diff options
author | kylep@chromium.org <kylep@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-10 21:04:44 +0000 |
---|---|---|
committer | kylep@chromium.org <kylep@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-10 21:04:44 +0000 |
commit | 4cdbad1fd0f03fc0db25955acacab5e0d9e8f5c4 (patch) | |
tree | 9e4fae5c2e250c1c31ce78c17eedd73b08588f75 /media | |
parent | 78f69a4f9f08d5e983639d5648386cfe0657110e (diff) | |
download | chromium_src-4cdbad1fd0f03fc0db25955acacab5e0d9e8f5c4.zip chromium_src-4cdbad1fd0f03fc0db25955acacab5e0d9e8f5c4.tar.gz chromium_src-4cdbad1fd0f03fc0db25955acacab5e0d9e8f5c4.tar.bz2 |
Modify OLA to use window size in seconds instead of bytes.
BUG=16011
TEST=none
Review URL: http://codereview.chromium.org/157001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20416 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/filters/audio_renderer_algorithm_base.cc | 14 | ||||
-rw-r--r-- | media/filters/audio_renderer_algorithm_base.h | 5 | ||||
-rw-r--r-- | media/filters/audio_renderer_algorithm_ola.cc | 34 | ||||
-rw-r--r-- | media/filters/audio_renderer_algorithm_ola.h | 3 | ||||
-rw-r--r-- | media/tools/wav_ola_test.cc | 22 |
5 files changed, 59 insertions, 19 deletions
diff --git a/media/filters/audio_renderer_algorithm_base.cc b/media/filters/audio_renderer_algorithm_base.cc index 013c716..ef6c0ec 100644 --- a/media/filters/audio_renderer_algorithm_base.cc +++ b/media/filters/audio_renderer_algorithm_base.cc @@ -15,6 +15,7 @@ const size_t kDefaultMaxQueueSizeInBytes = 65536; AudioRendererAlgorithmBase::AudioRendererAlgorithmBase() : channels_(0), + sample_rate_(0), sample_bytes_(0), playback_rate_(0.0f) { } @@ -22,15 +23,22 @@ AudioRendererAlgorithmBase::AudioRendererAlgorithmBase() AudioRendererAlgorithmBase::~AudioRendererAlgorithmBase() {} void AudioRendererAlgorithmBase::Initialize(int channels, + int sample_rate, int sample_bits, float initial_playback_rate, RequestReadCallback* callback) { DCHECK_GT(channels, 0); + DCHECK_LE(channels, 6) << "We only support <=6 channel audio."; + DCHECK_GT(sample_rate, 0); + DCHECK_LE(sample_rate, 256000) + << "We only support sample rates at or below 256000Hz."; DCHECK_GT(sample_bits, 0); - DCHECK(callback); + DCHECK_LE(sample_bits, 32) << "We only support 8, 16, 32 bit audio."; DCHECK_EQ(sample_bits % 8, 0) << "We only support 8, 16, 32 bit audio."; + DCHECK(callback); channels_ = channels; + sample_rate_ = sample_rate; sample_bytes_ = sample_bits / 8; request_read_callback_.reset(callback); @@ -88,6 +96,10 @@ int AudioRendererAlgorithmBase::channels() { return channels_; } +int AudioRendererAlgorithmBase::sample_rate() { + return sample_rate_; +} + int AudioRendererAlgorithmBase::sample_bytes() { return sample_bytes_; } diff --git a/media/filters/audio_renderer_algorithm_base.h b/media/filters/audio_renderer_algorithm_base.h index d817e3d..3fc8fde 100644 --- a/media/filters/audio_renderer_algorithm_base.h +++ b/media/filters/audio_renderer_algorithm_base.h @@ -45,6 +45,7 @@ class AudioRendererAlgorithmBase { // Checks validity of audio parameters and takes ownership of |callback|. virtual void Initialize(int channels, + int sample_rate, int sample_bits, float initial_playback_rate, RequestReadCallback* callback); @@ -82,12 +83,16 @@ class AudioRendererAlgorithmBase { // Number of audio channels. virtual int channels(); + // Sample rate in hertz. + virtual int sample_rate(); + // Number of bytes per sample per channel. virtual int sample_bytes(); private: // Audio properties. int channels_; + int sample_rate_; int sample_bytes_; // Used by algorithm to scale output. diff --git a/media/filters/audio_renderer_algorithm_ola.cc b/media/filters/audio_renderer_algorithm_ola.cc index da2992d..b32b27a 100644 --- a/media/filters/audio_renderer_algorithm_ola.cc +++ b/media/filters/audio_renderer_algorithm_ola.cc @@ -11,13 +11,14 @@ namespace media { -// Default window size in bytes. -// TODO(kylep): base the window size in seconds, not bytes. -const size_t kDefaultWindowSize = 4096; +// Default window and crossfade lengths in seconds. +const double kDefaultWindowLength = 0.08; +const double kDefaultCrossfadeLength = 0.008; AudioRendererAlgorithmOLA::AudioRendererAlgorithmOLA() : input_step_(0), - output_step_(0) { + output_step_(0), + window_size_(0) { } AudioRendererAlgorithmOLA::~AudioRendererAlgorithmOLA() { @@ -47,7 +48,7 @@ size_t AudioRendererAlgorithmOLA::FillBuffer(DataBuffer* buffer_out) { // on the UI side or in set_playback_rate(). while (dest_remaining >= output_step_ + crossfade_size_) { // If we don't have enough data to completely finish this loop, quit. - if (QueueSize() < kDefaultWindowSize) + if (QueueSize() < window_size_) break; // Copy bulk of data to output (including some to crossfade to the next @@ -89,7 +90,7 @@ size_t AudioRendererAlgorithmOLA::FillBuffer(DataBuffer* buffer_out) { // Advance pointers again. AdvanceInputPosition(crossfade_size); - dest += crossfade_size; + dest += crossfade_size_; } return dest_written; } @@ -97,21 +98,32 @@ size_t AudioRendererAlgorithmOLA::FillBuffer(DataBuffer* buffer_out) { void AudioRendererAlgorithmOLA::set_playback_rate(float new_rate) { AudioRendererAlgorithmBase::set_playback_rate(new_rate); + // Calculate the window size from our default length and our audio properties. + // Precision is not an issue because we will round this to a sample boundary. + // This will not overflow because each parameter is checked in Initialize(). + window_size_ = static_cast<size_t>(sample_rate() + * sample_bytes() + * channels() + * kDefaultWindowLength); + // Adjusting step sizes to accomodate requested playback rate. if (playback_rate() > 1.0f) { - input_step_ = kDefaultWindowSize; + input_step_ = window_size_; output_step_ = static_cast<size_t>(ceil( - static_cast<float>(kDefaultWindowSize / playback_rate()))); + static_cast<float>(window_size_ / playback_rate()))); } else { input_step_ = static_cast<size_t>(ceil( - static_cast<float>(kDefaultWindowSize * playback_rate()))); - output_step_ = kDefaultWindowSize; + static_cast<float>(window_size_ * playback_rate()))); + output_step_ = window_size_; } AlignToSampleBoundary(&input_step_); AlignToSampleBoundary(&output_step_); // Calculate length for crossfading. - crossfade_size_ = kDefaultWindowSize / 10; + crossfade_size_ = static_cast<size_t>(sample_rate() + * sample_bytes() + * channels() + * kDefaultCrossfadeLength); AlignToSampleBoundary(&crossfade_size_); // To keep true to playback rate, modify the steps. diff --git a/media/filters/audio_renderer_algorithm_ola.h b/media/filters/audio_renderer_algorithm_ola.h index 006400c..da5cbe4 100644 --- a/media/filters/audio_renderer_algorithm_ola.h +++ b/media/filters/audio_renderer_algorithm_ola.h @@ -48,6 +48,9 @@ class AudioRendererAlgorithmOLA : public AudioRendererAlgorithmBase { // Length for crossfade in bytes. size_t crossfade_size_; + // Window size, in bytes (calculated from audio properties). + size_t window_size_; + DISALLOW_COPY_AND_ASSIGN(AudioRendererAlgorithmOLA); }; diff --git a/media/tools/wav_ola_test.cc b/media/tools/wav_ola_test.cc index 9676861..5835bf2 100644 --- a/media/tools/wav_ola_test.cc +++ b/media/tools/wav_ola_test.cc @@ -23,7 +23,7 @@ using file_util::ScopedFILE; using media::AudioRendererAlgorithmOLA; using media::DataBuffer; -const size_t kDefaultWindowSize = 4096; +const double kDefaultWindowLength = 0.08; struct WavHeader { int32 riff; @@ -42,15 +42,16 @@ struct WavHeader { // Dummy class to feed data to OLA algorithm. Necessary to create callback. class Dummy { public: - Dummy(FILE* in, AudioRendererAlgorithmOLA* ola) + Dummy(FILE* in, AudioRendererAlgorithmOLA* ola, size_t window_size) : input_(in), - ola_(ola) { + ola_(ola), + window_size_(window_size) { } void ReadDataForAlg() { scoped_refptr<DataBuffer> b(new DataBuffer()); - uint8* buf = b->GetWritableData(kDefaultWindowSize); - if (fread(buf, 1, kDefaultWindowSize, input_) > 0) { + uint8* buf = b->GetWritableData(window_size_); + if (fread(buf, 1, window_size_, input_) > 0) { ola_->EnqueueBuffer(b.get()); } } @@ -58,6 +59,7 @@ class Dummy { private: FILE* input_; AudioRendererAlgorithmOLA* ola_; + size_t window_size_; DISALLOW_COPY_AND_ASSIGN(Dummy); }; @@ -104,11 +106,17 @@ int main(int argc, const char** argv) { return 1; } + size_t window_size = static_cast<size_t>(wav.sample_rate + * (wav.bit_rate / 8) + * wav.channels + * kDefaultWindowLength); + // Instantiate dummy class and callback to feed data to |ola|. - Dummy guy(input.get(), &ola); + Dummy guy(input.get(), &ola, window_size); AudioRendererAlgorithmOLA::RequestReadCallback* cb = NewCallback(&guy, &Dummy::ReadDataForAlg); ola.Initialize(wav.channels, + wav.sample_rate, wav.bit_rate, static_cast<float>(playback_rate), cb); @@ -129,7 +137,7 @@ int main(int argc, const char** argv) { // Create buffer to be filled by |ola|. scoped_refptr<DataBuffer> buffer(new DataBuffer()); - uint8* buf = buffer->GetWritableData(kDefaultWindowSize); + uint8* buf = buffer->GetWritableData(window_size); // Keep track of bytes written to disk and bytes copied to |b|. size_t bytes_written = 0; |