| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // AudioRendererAlgorithm buffers and transforms audio data. The owner of |
| // this object provides audio data to the object through EnqueueBuffer() and |
| // requests data from the buffer via FillBuffer(). The owner also sets the |
| // playback rate, and the AudioRendererAlgorithm will stretch or compress the |
| // buffered audio as necessary to match the playback rate when fulfilling |
| // FillBuffer() requests. AudioRendererAlgorithm can request more data to be |
| // buffered via a read callback passed in during initialization. |
| // |
| // This class is *not* thread-safe. Calls to enqueue and retrieve data must be |
| // locked if called from multiple threads. |
| // |
| // AudioRendererAlgorithm uses a simple pitch-preservation algorithm to |
| // stretch and compress audio data to meet playback speeds less than and |
| // greater than the natural playback of the audio stream. |
| // |
| // Audio at very low or very high playback rates are muted to preserve quality. |
| |
| #ifndef MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_H_ |
| #define MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_H_ |
| |
| #include "base/callback.h" |
| #include "media/audio/audio_parameters.h" |
| #include "media/base/seekable_buffer.h" |
| |
| namespace media { |
| |
| class Buffer; |
| |
| class MEDIA_EXPORT AudioRendererAlgorithm { |
| public: |
| AudioRendererAlgorithm(); |
| ~AudioRendererAlgorithm(); |
| |
| // Initializes this object with information about the audio stream. |
| // |request_read_cb| is called to request more data from the client, requests |
| // that are fulfilled through calls to EnqueueBuffer(). |
| void Initialize(float initial_playback_rate, |
| const AudioParameters& params, |
| const base::Closure& request_read_cb); |
| |
| // 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. |
| // |
| // Returns the number of frames copied into |dest|. |
| // May request more reads via |request_read_cb_| before returning. |
| int FillBuffer(uint8* dest, int requested_frames); |
| |
| // Clears |audio_buffer_|. |
| void FlushBuffers(); |
| |
| // Returns the time of the next byte in our data or kNoTimestamp() if current |
| // time is unknown. |
| base::TimeDelta GetTime(); |
| |
| // Enqueues a buffer. It is called from the owner of the algorithm after a |
| // read completes. |
| void EnqueueBuffer(Buffer* buffer_in); |
| |
| float playback_rate() const { return playback_rate_; } |
| void SetPlaybackRate(float new_rate); |
| |
| // Returns whether the algorithm has enough data at the current playback rate |
| // such that it can write data on the next call to FillBuffer(). |
| bool CanFillBuffer(); |
| |
| // Returns true if |audio_buffer_| is at or exceeds capacity. |
| bool IsQueueFull(); |
| |
| // Returns the capacity of |audio_buffer_|. |
| int QueueCapacity(); |
| |
| // Increase the capacity of |audio_buffer_| if possible. |
| void IncreaseQueueCapacity(); |
| |
| // Returns the number of bytes left in |audio_buffer_|, which may be larger |
| // than QueueCapacity() in the event that a read callback delivered more data |
| // than |audio_buffer_| was intending to hold. |
| int bytes_buffered() { return audio_buffer_.forward_bytes(); } |
| |
| int bytes_per_frame() { return bytes_per_frame_; } |
| |
| int bytes_per_channel() { return bytes_per_channel_; } |
| |
| int samples_per_second() { return samples_per_second_; } |
| |
| bool is_muted() { return muted_; } |
| |
| private: |
| // 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, int input_step, int output_step); |
| |
| // 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, int input_step, int output_step); |
| |
| // 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, int 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(int* value); |
| |
| // Number of channels in audio stream. |
| int channels_; |
| |
| // Sample rate of audio stream. |
| int samples_per_second_; |
| |
| // Byte depth of audio. |
| int bytes_per_channel_; |
| |
| // Used by algorithm to scale output. |
| float playback_rate_; |
| |
| // Used to request more data. |
| base::Closure request_read_cb_; |
| |
| // Buffered audio data. |
| SeekableBuffer audio_buffer_; |
| |
| // Length for crossfade in bytes. |
| int bytes_in_crossfade_; |
| |
| // Length of frame in bytes. |
| int 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. |
| int index_into_window_; |
| |
| // The frame number in the crossfade. |
| int 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). |
| int window_size_; |
| |
| DISALLOW_COPY_AND_ASSIGN(AudioRendererAlgorithm); |
| }; |
| |
| } // namespace media |
| |
| #endif // MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_H_ |