Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(299)

Side by Side Diff: media/filters/audio_renderer_algorithm_base.h

Issue 9395057: Fix muted audio when playback rate != 1.0 or 0.0 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase ToT Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/base/seekable_buffer.cc ('k') | media/filters/audio_renderer_algorithm_base.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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_
OLDNEW
« no previous file with comments | « media/base/seekable_buffer.cc ('k') | media/filters/audio_renderer_algorithm_base.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698