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

Unified 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, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/base/seekable_buffer.cc ('k') | media/filters/audio_renderer_algorithm_base.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/filters/audio_renderer_algorithm_base.h
diff --git a/media/filters/audio_renderer_algorithm_base.h b/media/filters/audio_renderer_algorithm_base.h
index a7325dac2ba4392a5a5354fbb250c5a683ac4b06..9e7d8a805f1c60154c884c210e6d3d08807b70e0 100644
--- a/media/filters/audio_renderer_algorithm_base.h
+++ b/media/filters/audio_renderer_algorithm_base.h
@@ -30,6 +30,8 @@ namespace media {
class Buffer;
+// TODO(vrk): Remove all the uint32s from AudioRendererAlgorithmBase and
+// replace them with ints.
class MEDIA_EXPORT AudioRendererAlgorithmBase {
public:
AudioRendererAlgorithmBase();
@@ -51,22 +53,15 @@ class MEDIA_EXPORT AudioRendererAlgorithmBase {
float initial_playback_rate,
const base::Closure& request_read_cb);
- // Tries to fill |length| bytes of |dest| with possibly scaled data from our
- // |audio_buffer_|. Data is scaled based on the playback rate, using a
- // variation of the Overlap-Add method to combine sample windows.
+ // Tries to fill |requested_frames| frames into |dest| with possibly scaled
+ // data from our |audio_buffer_|. Data is scaled based on the playback rate,
+ // using a variation of the Overlap-Add method to combine sample windows.
//
// Data from |audio_buffer_| is consumed in proportion to the playback rate.
- // FillBuffer() will fit |playback_rate_| * |length| bytes of raw data from
- // |audio_buffer| into |length| bytes of output data in |dest| by chopping up
- // the buffered data into windows and crossfading from one window to the next.
- // For speeds greater than 1.0f, FillBuffer() "squish" the windows, dropping
- // some data in between windows to meet the sped-up playback. For speeds less
- // than 1.0f, FillBuffer() will "stretch" the window by copying and
- // overlapping data at the window boundaries, crossfading in between.
//
- // Returns the number of bytes copied into |dest|.
+ // Returns the number of frames copied into |dest|.
// May request more reads via |request_read_cb_| before returning.
- uint32 FillBuffer(uint8* dest, uint32 length);
+ uint32 FillBuffer(uint8* dest, uint32 requested_frames);
// Clears |audio_buffer_|.
void FlushBuffers();
@@ -82,8 +77,8 @@ class MEDIA_EXPORT AudioRendererAlgorithmBase {
float playback_rate() const { return playback_rate_; }
void SetPlaybackRate(float new_rate);
- // Returns whether |audio_buffer_| is empty.
- bool IsQueueEmpty();
+ // Returns whether the algorithm needs more data to continue filling buffers.
+ bool NeedsMoreData();
// Returns true if |audio_buffer_| is at or exceeds capacity.
bool IsQueueFull();
@@ -99,21 +94,65 @@ class MEDIA_EXPORT AudioRendererAlgorithmBase {
// than |audio_buffer_| was intending to hold.
uint32 bytes_buffered() { return audio_buffer_.forward_bytes(); }
- uint32 window_size() { return window_size_; }
+ uint32 bytes_per_frame() { return bytes_per_frame_; }
- private:
- // Advances |audio_buffer_|'s internal pointer by |bytes|.
- void AdvanceBufferPosition(uint32 bytes);
+ uint32 bytes_per_channel() { return bytes_per_channel_; }
- // Tries to copy |bytes| bytes from |audio_buffer_| to |dest|.
- // Returns the number of bytes successfully copied.
- uint32 CopyFromAudioBuffer(uint8* dest, uint32 bytes);
+ bool is_muted() { return muted_; }
- // Aligns |value| to a channel and sample boundary.
- void AlignToSampleBoundary(uint32* value);
+ private:
+ // Returns true if |audio_buffer_| is empty.
+ bool IsQueueEmpty();
- // Attempts to write |length| bytes of muted audio into |dest|.
- uint32 MuteBuffer(uint8* dest, uint32 length);
+ // Fills |dest| with one frame of audio data at normal speed. Returns true if
+ // a frame was rendered, false otherwise.
+ bool OutputNormalPlayback(uint8* dest);
+
+ // Fills |dest| with one frame of audio data at faster than normal speed.
+ // Returns true if a frame was rendered, false otherwise.
+ //
+ // When the audio playback is > 1.0, we use a variant of Overlap-Add to squish
+ // audio output while preserving pitch. Essentially, we play a bit of audio
+ // data at normal speed, then we "fast forward" by dropping the next bit of
+ // audio data, and then we stich the pieces together by crossfading from one
+ // audio chunk to the next.
+ bool OutputFasterPlayback(uint8* dest);
+
+ // Fills |dest| with one frame of audio data at slower than normal speed.
+ // Returns true if a frame was rendered, false otherwise.
+ //
+ // When the audio playback is < 1.0, we use a variant of Overlap-Add to
+ // stretch audio output while preserving pitch. This works by outputting a
+ // segment of audio data at normal speed. The next audio segment then starts
+ // by repeating some of the audio data from the previous audio segment.
+ // Segments are stiched together by crossfading from one audio chunk to the
+ // next.
+ bool OutputSlowerPlayback(uint8* dest);
+
+ // Resets the window state to the start of a new window.
+ void ResetWindow();
+
+ // Copies a raw frame from |audio_buffer_| into |dest| without progressing
+ // |audio_buffer_|'s internal "current" cursor. Optionally peeks at a forward
+ // byte |offset|.
+ void CopyWithoutAdvance(uint8* dest);
+ void CopyWithoutAdvance(uint8* dest, uint32 offset);
+
+ // Copies a raw frame from |audio_buffer_| into |dest| and progresses the
+ // |audio_buffer_| forward.
+ void CopyWithAdvance(uint8* dest);
+
+ // Moves the |audio_buffer_| forward by one frame.
+ void DropFrame();
+
+ // Does a linear crossfade from |intro| into |outtro| for one frame.
+ // Assumes pointers are valid and are at least size of |bytes_per_frame_|.
+ void OutputCrossfadedFrame(uint8* outtro, const uint8* intro);
+ template <class Type>
+ void CrossfadeFrame(uint8* outtro, const uint8* intro);
+
+ // Rounds |*value| down to the nearest frame boundary.
+ void AlignToFrameBoundary(uint32* value);
// Number of channels in audio stream.
int channels_;
@@ -134,7 +173,26 @@ class MEDIA_EXPORT AudioRendererAlgorithmBase {
SeekableBuffer audio_buffer_;
// Length for crossfade in bytes.
- uint32 crossfade_size_;
+ uint32 bytes_in_crossfade_;
+
+ // Length of frame in bytes.
+ uint32 bytes_per_frame_;
+
+ // The current location in the audio window, between 0 and |window_size_|.
+ // When |index_into_window_| reaches |window_size_|, the window resets.
+ // Indexed by byte.
+ uint32 index_into_window_;
+
+ // The frame number in the crossfade.
+ uint32 crossfade_frame_number_;
+
+ // True if the audio should be muted.
+ bool muted_;
+
+ bool needs_more_data_;
+
+ // Temporary buffer to hold crossfade data.
+ scoped_array<uint8> crossfade_buffer_;
// Window size, in bytes (calculated from audio properties).
uint32 window_size_;
« 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