OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // AudioRendererAlgorithmBase buffers and transforms audio data. The owner of | 5 // AudioRendererAlgorithmBase buffers and transforms audio data. The owner of |
6 // this object provides audio data to the object through EnqueueBuffer() and | 6 // this object provides audio data to the object through EnqueueBuffer() and |
7 // requests data from the buffer via FillBuffer(). The owner also sets the | 7 // requests data from the buffer via FillBuffer(). The owner also sets the |
8 // playback rate, and the AudioRendererAlgorithm will stretch or compress the | 8 // playback rate, and the AudioRendererAlgorithm will stretch or compress the |
9 // buffered audio as necessary to match the playback rate when fulfilling | 9 // buffered audio as necessary to match the playback rate when fulfilling |
10 // FillBuffer() requests. AudioRendererAlgorithm can request more data to be | 10 // FillBuffer() requests. AudioRendererAlgorithm can request more data to be |
(...skipping 12 matching lines...) Expand all Loading... |
23 #define MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_BASE_H_ | 23 #define MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_BASE_H_ |
24 | 24 |
25 #include "base/callback.h" | 25 #include "base/callback.h" |
26 #include "base/gtest_prod_util.h" | 26 #include "base/gtest_prod_util.h" |
27 #include "media/base/seekable_buffer.h" | 27 #include "media/base/seekable_buffer.h" |
28 | 28 |
29 namespace media { | 29 namespace media { |
30 | 30 |
31 class Buffer; | 31 class Buffer; |
32 | 32 |
| 33 // TODO(vrk): Remove all the uint32s from AudioRendererAlgorithmBase and |
| 34 // replace them with ints. |
33 class MEDIA_EXPORT AudioRendererAlgorithmBase { | 35 class MEDIA_EXPORT AudioRendererAlgorithmBase { |
34 public: | 36 public: |
35 AudioRendererAlgorithmBase(); | 37 AudioRendererAlgorithmBase(); |
36 ~AudioRendererAlgorithmBase(); | 38 ~AudioRendererAlgorithmBase(); |
37 | 39 |
38 // Call prior to Initialize() to validate configuration. Returns false if the | 40 // Call prior to Initialize() to validate configuration. Returns false if the |
39 // configuration is invalid. Detailed error information will be DVLOG'd. | 41 // configuration is invalid. Detailed error information will be DVLOG'd. |
40 static bool ValidateConfig(int channels, | 42 static bool ValidateConfig(int channels, |
41 int samples_per_second, | 43 int samples_per_second, |
42 int bits_per_channel); | 44 int bits_per_channel); |
43 | 45 |
44 // Initializes this object with information about the audio stream. | 46 // Initializes this object with information about the audio stream. |
45 // |samples_per_second| is in Hz. |read_request_callback| is called to | 47 // |samples_per_second| is in Hz. |read_request_callback| is called to |
46 // request more data from the client, requests that are fulfilled through | 48 // request more data from the client, requests that are fulfilled through |
47 // calls to EnqueueBuffer(). | 49 // calls to EnqueueBuffer(). |
48 void Initialize(int channels, | 50 void Initialize(int channels, |
49 int samples_per_second, | 51 int samples_per_second, |
50 int bits_per_channel, | 52 int bits_per_channel, |
51 float initial_playback_rate, | 53 float initial_playback_rate, |
52 const base::Closure& request_read_cb); | 54 const base::Closure& request_read_cb); |
53 | 55 |
54 // Tries to fill |length| bytes of |dest| with possibly scaled data from our | 56 // Tries to fill |requested_frames| frames into |dest| with possibly scaled |
55 // |audio_buffer_|. Data is scaled based on the playback rate, using a | 57 // data from our |audio_buffer_|. Data is scaled based on the playback rate, |
56 // variation of the Overlap-Add method to combine sample windows. | 58 // using a variation of the Overlap-Add method to combine sample windows. |
57 // | 59 // |
58 // Data from |audio_buffer_| is consumed in proportion to the playback rate. | 60 // Data from |audio_buffer_| is consumed in proportion to the playback rate. |
59 // FillBuffer() will fit |playback_rate_| * |length| bytes of raw data from | |
60 // |audio_buffer| into |length| bytes of output data in |dest| by chopping up | |
61 // the buffered data into windows and crossfading from one window to the next. | |
62 // For speeds greater than 1.0f, FillBuffer() "squish" the windows, dropping | |
63 // some data in between windows to meet the sped-up playback. For speeds less | |
64 // than 1.0f, FillBuffer() will "stretch" the window by copying and | |
65 // overlapping data at the window boundaries, crossfading in between. | |
66 // | 61 // |
67 // Returns the number of bytes copied into |dest|. | 62 // Returns the number of frames copied into |dest|. |
68 // May request more reads via |request_read_cb_| before returning. | 63 // May request more reads via |request_read_cb_| before returning. |
69 uint32 FillBuffer(uint8* dest, uint32 length); | 64 uint32 FillBuffer(uint8* dest, uint32 requested_frames); |
70 | 65 |
71 // Clears |audio_buffer_|. | 66 // Clears |audio_buffer_|. |
72 void FlushBuffers(); | 67 void FlushBuffers(); |
73 | 68 |
74 // Returns the time of the next byte in our data or kNoTimestamp() if current | 69 // Returns the time of the next byte in our data or kNoTimestamp() if current |
75 // time is unknown. | 70 // time is unknown. |
76 base::TimeDelta GetTime(); | 71 base::TimeDelta GetTime(); |
77 | 72 |
78 // Enqueues a buffer. It is called from the owner of the algorithm after a | 73 // Enqueues a buffer. It is called from the owner of the algorithm after a |
79 // read completes. | 74 // read completes. |
80 void EnqueueBuffer(Buffer* buffer_in); | 75 void EnqueueBuffer(Buffer* buffer_in); |
81 | 76 |
82 float playback_rate() const { return playback_rate_; } | 77 float playback_rate() const { return playback_rate_; } |
83 void SetPlaybackRate(float new_rate); | 78 void SetPlaybackRate(float new_rate); |
84 | 79 |
85 // Returns whether |audio_buffer_| is empty. | 80 // Returns whether the algorithm needs more data to continue filling buffers. |
86 bool IsQueueEmpty(); | 81 bool NeedsMoreData(); |
87 | 82 |
88 // Returns true if |audio_buffer_| is at or exceeds capacity. | 83 // Returns true if |audio_buffer_| is at or exceeds capacity. |
89 bool IsQueueFull(); | 84 bool IsQueueFull(); |
90 | 85 |
91 // Returns the capacity of |audio_buffer_|. | 86 // Returns the capacity of |audio_buffer_|. |
92 uint32 QueueCapacity(); | 87 uint32 QueueCapacity(); |
93 | 88 |
94 // Increase the capacity of |audio_buffer_| if possible. | 89 // Increase the capacity of |audio_buffer_| if possible. |
95 void IncreaseQueueCapacity(); | 90 void IncreaseQueueCapacity(); |
96 | 91 |
97 // Returns the number of bytes left in |audio_buffer_|, which may be larger | 92 // Returns the number of bytes left in |audio_buffer_|, which may be larger |
98 // than QueueCapacity() in the event that a read callback delivered more data | 93 // than QueueCapacity() in the event that a read callback delivered more data |
99 // than |audio_buffer_| was intending to hold. | 94 // than |audio_buffer_| was intending to hold. |
100 uint32 bytes_buffered() { return audio_buffer_.forward_bytes(); } | 95 uint32 bytes_buffered() { return audio_buffer_.forward_bytes(); } |
101 | 96 |
102 uint32 window_size() { return window_size_; } | 97 uint32 bytes_per_frame() { return bytes_per_frame_; } |
| 98 |
| 99 uint32 bytes_per_channel() { return bytes_per_channel_; } |
| 100 |
| 101 bool is_muted() { return muted_; } |
103 | 102 |
104 private: | 103 private: |
105 // Advances |audio_buffer_|'s internal pointer by |bytes|. | 104 // Returns true if |audio_buffer_| is empty. |
106 void AdvanceBufferPosition(uint32 bytes); | 105 bool IsQueueEmpty(); |
107 | 106 |
108 // Tries to copy |bytes| bytes from |audio_buffer_| to |dest|. | 107 // Fills |dest| with one frame of audio data at normal speed. Returns true if |
109 // Returns the number of bytes successfully copied. | 108 // a frame was rendered, false otherwise. |
110 uint32 CopyFromAudioBuffer(uint8* dest, uint32 bytes); | 109 bool OutputNormalPlayback(uint8* dest); |
111 | 110 |
112 // Aligns |value| to a channel and sample boundary. | 111 // Fills |dest| with one frame of audio data at faster than normal speed. |
113 void AlignToSampleBoundary(uint32* value); | 112 // Returns true if a frame was rendered, false otherwise. |
| 113 // |
| 114 // When the audio playback is > 1.0, we use a variant of Overlap-Add to squish |
| 115 // audio output while preserving pitch. Essentially, we play a bit of audio |
| 116 // data at normal speed, then we "fast forward" by dropping the next bit of |
| 117 // audio data, and then we stich the pieces together by crossfading from one |
| 118 // audio chunk to the next. |
| 119 bool OutputFasterPlayback(uint8* dest); |
114 | 120 |
115 // Attempts to write |length| bytes of muted audio into |dest|. | 121 // Fills |dest| with one frame of audio data at slower than normal speed. |
116 uint32 MuteBuffer(uint8* dest, uint32 length); | 122 // Returns true if a frame was rendered, false otherwise. |
| 123 // |
| 124 // When the audio playback is < 1.0, we use a variant of Overlap-Add to |
| 125 // stretch audio output while preserving pitch. This works by outputting a |
| 126 // segment of audio data at normal speed. The next audio segment then starts |
| 127 // by repeating some of the audio data from the previous audio segment. |
| 128 // Segments are stiched together by crossfading from one audio chunk to the |
| 129 // next. |
| 130 bool OutputSlowerPlayback(uint8* dest); |
| 131 |
| 132 // Resets the window state to the start of a new window. |
| 133 void ResetWindow(); |
| 134 |
| 135 // Copies a raw frame from |audio_buffer_| into |dest| without progressing |
| 136 // |audio_buffer_|'s internal "current" cursor. Optionally peeks at a forward |
| 137 // byte |offset|. |
| 138 void CopyWithoutAdvance(uint8* dest); |
| 139 void CopyWithoutAdvance(uint8* dest, uint32 offset); |
| 140 |
| 141 // Copies a raw frame from |audio_buffer_| into |dest| and progresses the |
| 142 // |audio_buffer_| forward. |
| 143 void CopyWithAdvance(uint8* dest); |
| 144 |
| 145 // Moves the |audio_buffer_| forward by one frame. |
| 146 void DropFrame(); |
| 147 |
| 148 // Does a linear crossfade from |intro| into |outtro| for one frame. |
| 149 // Assumes pointers are valid and are at least size of |bytes_per_frame_|. |
| 150 void OutputCrossfadedFrame(uint8* outtro, const uint8* intro); |
| 151 template <class Type> |
| 152 void CrossfadeFrame(uint8* outtro, const uint8* intro); |
| 153 |
| 154 // Rounds |*value| down to the nearest frame boundary. |
| 155 void AlignToFrameBoundary(uint32* value); |
117 | 156 |
118 // Number of channels in audio stream. | 157 // Number of channels in audio stream. |
119 int channels_; | 158 int channels_; |
120 | 159 |
121 // Sample rate of audio stream. | 160 // Sample rate of audio stream. |
122 int samples_per_second_; | 161 int samples_per_second_; |
123 | 162 |
124 // Byte depth of audio. | 163 // Byte depth of audio. |
125 int bytes_per_channel_; | 164 int bytes_per_channel_; |
126 | 165 |
127 // Used by algorithm to scale output. | 166 // Used by algorithm to scale output. |
128 float playback_rate_; | 167 float playback_rate_; |
129 | 168 |
130 // Used to request more data. | 169 // Used to request more data. |
131 base::Closure request_read_cb_; | 170 base::Closure request_read_cb_; |
132 | 171 |
133 // Buffered audio data. | 172 // Buffered audio data. |
134 SeekableBuffer audio_buffer_; | 173 SeekableBuffer audio_buffer_; |
135 | 174 |
136 // Length for crossfade in bytes. | 175 // Length for crossfade in bytes. |
137 uint32 crossfade_size_; | 176 uint32 bytes_in_crossfade_; |
| 177 |
| 178 // Length of frame in bytes. |
| 179 uint32 bytes_per_frame_; |
| 180 |
| 181 // The current location in the audio window, between 0 and |window_size_|. |
| 182 // When |index_into_window_| reaches |window_size_|, the window resets. |
| 183 // Indexed by byte. |
| 184 uint32 index_into_window_; |
| 185 |
| 186 // The frame number in the crossfade. |
| 187 uint32 crossfade_frame_number_; |
| 188 |
| 189 // True if the audio should be muted. |
| 190 bool muted_; |
| 191 |
| 192 bool needs_more_data_; |
| 193 |
| 194 // Temporary buffer to hold crossfade data. |
| 195 scoped_array<uint8> crossfade_buffer_; |
138 | 196 |
139 // Window size, in bytes (calculated from audio properties). | 197 // Window size, in bytes (calculated from audio properties). |
140 uint32 window_size_; | 198 uint32 window_size_; |
141 | 199 |
142 DISALLOW_COPY_AND_ASSIGN(AudioRendererAlgorithmBase); | 200 DISALLOW_COPY_AND_ASSIGN(AudioRendererAlgorithmBase); |
143 }; | 201 }; |
144 | 202 |
145 } // namespace media | 203 } // namespace media |
146 | 204 |
147 #endif // MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_BASE_H_ | 205 #endif // MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_BASE_H_ |
OLD | NEW |