blob: 080a11d2bee20c8100e79644d9036c39525314bb [file] [log] [blame]
// 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_