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 window_size() { return window_size_; } |
103 | 98 |
104 private: | 99 private: |
105 // Advances |audio_buffer_|'s internal pointer by |bytes|. | 100 // Returns true if |audio_buffer_| is empty. |
106 void AdvanceBufferPosition(uint32 bytes); | 101 bool IsQueueEmpty(); |
107 | 102 |
108 // Tries to copy |bytes| bytes from |audio_buffer_| to |dest|. | 103 // Fills |dest| with one frame of audio data at normal speed. Returns true if |
109 // Returns the number of bytes successfully copied. | 104 // a frame was rendered, false otherwise. |
110 uint32 CopyFromAudioBuffer(uint8* dest, uint32 bytes); | 105 bool OutputNormalPlayback(uint8* dest); |
111 | 106 |
112 // Aligns |value| to a channel and sample boundary. | 107 // Fills |dest| with one frame of audio data at faster than normal speed. |
113 void AlignToSampleBoundary(uint32* value); | 108 // Returns true if a frame was rendered, false otherwise. |
| 109 // |
| 110 // When the audio playback is > 1.0, we use a variant of Overlap-Add to squish |
| 111 // audio output while preserving pitch. Essentially, we play a bit of audio |
| 112 // data at normal speed, then we "fast forward" by dropping the next bit of |
| 113 // audio data, and then we stich the pieces together by crossfading from one |
| 114 // audio chunk to the next. |
| 115 bool OutputFasterPlayback(uint8* dest); |
114 | 116 |
115 // Attempts to write |length| bytes of muted audio into |dest|. | 117 // Fills |dest| with one frame of audio data at slower than normal speed. |
116 uint32 MuteBuffer(uint8* dest, uint32 length); | 118 // Returns true if a frame was rendered, false otherwise. |
| 119 // |
| 120 // When the audio playback is < 1.0, we use a variant of Overlap-Add to |
| 121 // stretch audio output while preserving pitch. This works by outputting a |
| 122 // segment of audio data at normal speed. The next audio segment then starts |
| 123 // by repeating some of the audio data from the previous audio segment. |
| 124 // Segments are stiched together by crossfading from one audio chunk to the |
| 125 // next. |
| 126 bool OutputSlowerPlayback(uint8* dest); |
| 127 |
| 128 // Resets the window state to the start of a new window. |
| 129 void ResetWindow(); |
| 130 |
| 131 // Copies a raw frame from |audio_buffer_| into |dest| without progressing |
| 132 // |audio_buffer_|'s internal "current" cursor. Optionally peeks at a forward |
| 133 // byte |offset|. |
| 134 void CopyWithoutAdvance(uint8* dest); |
| 135 void CopyWithoutAdvance(uint8* dest, uint32 offset); |
| 136 |
| 137 // Copies a raw frame from |audio_buffer_| into |dest| and progresses the |
| 138 // |audio_buffer_| forward. |
| 139 void CopyWithAdvance(uint8* dest); |
| 140 |
| 141 // Moves the |audio_buffer_| forward by one frame. |
| 142 void DropFrame(); |
| 143 |
| 144 // Does a linear crossfade from |intro| into |outtro| for one frame. |
| 145 // Assumes pointers are valid and are at least size of |bytes_per_frame_|. |
| 146 void OutputCrossfadedFrame(uint8* outtro, const uint8* intro); |
| 147 template <class Type> |
| 148 void CrossfadeFrame(Type* outtro, const Type* intro); |
| 149 |
| 150 // Rounds |*value| down to the nearest frame boundary. |
| 151 void AlignToFrameBoundary(uint32* value); |
117 | 152 |
118 // Number of channels in audio stream. | 153 // Number of channels in audio stream. |
119 int channels_; | 154 int channels_; |
120 | 155 |
121 // Sample rate of audio stream. | 156 // Sample rate of audio stream. |
122 int samples_per_second_; | 157 int samples_per_second_; |
123 | 158 |
124 // Byte depth of audio. | 159 // Byte depth of audio. |
125 int bytes_per_channel_; | 160 int bytes_per_channel_; |
126 | 161 |
127 // Used by algorithm to scale output. | 162 // Used by algorithm to scale output. |
128 float playback_rate_; | 163 float playback_rate_; |
129 | 164 |
130 // Used to request more data. | 165 // Used to request more data. |
131 base::Closure request_read_cb_; | 166 base::Closure request_read_cb_; |
132 | 167 |
133 // Buffered audio data. | 168 // Buffered audio data. |
134 SeekableBuffer audio_buffer_; | 169 SeekableBuffer audio_buffer_; |
135 | 170 |
136 // Length for crossfade in bytes. | 171 // Length for crossfade in bytes. |
137 uint32 crossfade_size_; | 172 uint32 bytes_in_crossfade_; |
| 173 |
| 174 // Length of frame in bytes. |
| 175 uint32 bytes_per_frame_; |
| 176 |
| 177 // The current location in the audio window, between 0 and |window_size_|. |
| 178 // When |index_into_window_| reaches |window_size_|, the window resets. |
| 179 // Indexed by byte. |
| 180 uint32 index_into_window_; |
| 181 |
| 182 // The frame number in the crossfade. |
| 183 uint32 crossfade_frame_number_; |
| 184 |
| 185 // True if the audio should be muted. |
| 186 bool muted_; |
| 187 |
| 188 bool needs_more_data_; |
| 189 |
| 190 // Temporary buffer to hold crossfade data. |
| 191 scoped_array<uint8> crossfade_buffer_; |
138 | 192 |
139 // Window size, in bytes (calculated from audio properties). | 193 // Window size, in bytes (calculated from audio properties). |
140 uint32 window_size_; | 194 uint32 window_size_; |
141 | 195 |
142 DISALLOW_COPY_AND_ASSIGN(AudioRendererAlgorithmBase); | 196 DISALLOW_COPY_AND_ASSIGN(AudioRendererAlgorithmBase); |
143 }; | 197 }; |
144 | 198 |
145 } // namespace media | 199 } // namespace media |
146 | 200 |
147 #endif // MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_BASE_H_ | 201 #endif // MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_BASE_H_ |
OLD | NEW |