diff options
author | dalecurtis@chromium.org <dalecurtis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-22 23:21:14 +0000 |
---|---|---|
committer | dalecurtis@chromium.org <dalecurtis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-22 23:21:14 +0000 |
commit | 3167a14f5a2a73afa9774b92faf4016b633f6366 (patch) | |
tree | 7eb39bb4f6f64a93df8977271b37e1295e5319a2 | |
parent | 86c65310708e4de9c4b552302d665427a6a53d3f (diff) | |
download | chromium_src-3167a14f5a2a73afa9774b92faf4016b633f6366.zip chromium_src-3167a14f5a2a73afa9774b92faf4016b633f6366.tar.gz chromium_src-3167a14f5a2a73afa9774b92faf4016b633f6366.tar.bz2 |
Scale audio delay information in AudioRendererMixer.
Converts the audio delay information into the scale expected by
the underlying audio renderer mixer input. Similar to what is
already done in AudioOutputResampler.
bytes_per_ms = channels * bytes_per_channel * frames_per_second / 1000;
bytes_per_buffer = channels * bytes_per_channel * frames_per_buffer;
delay_ms = bytes_per_buffer / bytes_per_ms
...
delay_ms = frames_per_buffer * 1000 / frames_per_second
Which means we just want to include the sample rate in the scaling.
BUG=133637
TEST=playback is in sync, tests work fine.
Review URL: https://chromiumcodereview.appspot.com/11231031
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@163435 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | media/base/audio_renderer_mixer.cc | 28 | ||||
-rw-r--r-- | media/base/audio_renderer_mixer.h | 4 | ||||
-rw-r--r-- | media/base/audio_renderer_mixer_unittest.cc | 22 | ||||
-rw-r--r-- | media/base/fake_audio_render_callback.cc | 4 | ||||
-rw-r--r-- | media/base/fake_audio_render_callback.h | 5 |
5 files changed, 51 insertions, 12 deletions
diff --git a/media/base/audio_renderer_mixer.cc b/media/base/audio_renderer_mixer.cc index e48b171..4df2eea 100644 --- a/media/base/audio_renderer_mixer.cc +++ b/media/base/audio_renderer_mixer.cc @@ -17,19 +17,23 @@ AudioRendererMixer::AudioRendererMixer( const AudioParameters& input_params, const AudioParameters& output_params, const scoped_refptr<AudioRendererSink>& sink) : audio_sink_(sink), - current_audio_delay_milliseconds_(0) { - // Sanity check sample rates. - DCHECK_LE(input_params.sample_rate(), limits::kMaxSampleRate); - DCHECK_GE(input_params.sample_rate(), limits::kMinSampleRate); - DCHECK_LE(output_params.sample_rate(), limits::kMaxSampleRate); - DCHECK_GE(output_params.sample_rate(), limits::kMinSampleRate); + current_audio_delay_milliseconds_(0), + io_ratio_(1), + input_ms_per_frame_( + static_cast<double>(base::Time::kMillisecondsPerSecond) / + input_params.sample_rate()) { + DCHECK(input_params.IsValid()); + DCHECK(output_params.IsValid()); + + // Channel mixing is handled by the browser side currently. + DCHECK_EQ(input_params.channels(), output_params.channels()); // Only resample if necessary since it's expensive. if (input_params.sample_rate() != output_params.sample_rate()) { + io_ratio_ = input_params.sample_rate() / + static_cast<double>(output_params.sample_rate()); resampler_.reset(new MultiChannelResampler( - output_params.channels(), - input_params.sample_rate() / static_cast<double>( - output_params.sample_rate()), + output_params.channels(), io_ratio_, base::Bind(&AudioRendererMixer::ProvideInput, base::Unretained(this)))); } @@ -60,7 +64,7 @@ void AudioRendererMixer::RemoveMixerInput( int AudioRendererMixer::Render(AudioBus* audio_bus, int audio_delay_milliseconds) { - current_audio_delay_milliseconds_ = audio_delay_milliseconds; + current_audio_delay_milliseconds_ = audio_delay_milliseconds / io_ratio_; if (resampler_.get()) resampler_->Resample(audio_bus, audio_bus->frames()); @@ -117,6 +121,10 @@ void AudioRendererMixer::ProvideInput(AudioBus* audio_bus) { audio_bus->channel(i)); } } + + // Update the delay estimate. + current_audio_delay_milliseconds_ += + audio_bus->frames() * input_ms_per_frame_; } void AudioRendererMixer::OnRenderError() { diff --git a/media/base/audio_renderer_mixer.h b/media/base/audio_renderer_mixer.h index c595c0d..7bb85af 100644 --- a/media/base/audio_renderer_mixer.h +++ b/media/base/audio_renderer_mixer.h @@ -61,6 +61,10 @@ class MEDIA_EXPORT AudioRendererMixer // The audio delay in milliseconds received by the last Render() call. int current_audio_delay_milliseconds_; + // Ratio of input data to output data. Used to scale audio delay information. + double io_ratio_; + double input_ms_per_frame_; + DISALLOW_COPY_AND_ASSIGN(AudioRendererMixer); }; diff --git a/media/base/audio_renderer_mixer_unittest.cc b/media/base/audio_renderer_mixer_unittest.cc index a37cd69..09fe8d4 100644 --- a/media/base/audio_renderer_mixer_unittest.cc +++ b/media/base/audio_renderer_mixer_unittest.cc @@ -24,7 +24,7 @@ static const int kMixerInputs = 8; static const int kMixerCycles = 3; // Parameters used for testing. -static const int kBitsPerChannel = 16; +static const int kBitsPerChannel = 32; static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO; static const int kHighLatencyBufferSize = 8192; static const int kLowLatencyBufferSize = 256; @@ -388,6 +388,26 @@ TEST_P(AudioRendererMixerTest, OnRenderError) { mixer_inputs_[i]->Stop(); } +// Verify that audio delay information is scaled to the input parameters. +TEST_P(AudioRendererMixerTest, DelayTest) { + InitializeInputs(1); + static const int kAudioDelayMilliseconds = 100; + ASSERT_EQ(mixer_inputs_.size(), 1u); + + // Start the input and issue a single render callback. + mixer_inputs_[0]->Start(); + mixer_inputs_[0]->Play(); + mixer_callback_->Render(audio_bus_.get(), kAudioDelayMilliseconds); + + // The input to output ratio should only include the sample rate difference. + double io_ratio = input_parameters_.sample_rate() / + static_cast<double>(output_parameters_.sample_rate()); + + EXPECT_EQ(static_cast<int>(kAudioDelayMilliseconds / io_ratio), + fake_callbacks_[0]->last_audio_delay_milliseconds()); + mixer_inputs_[0]->Stop(); +} + INSTANTIATE_TEST_CASE_P( AudioRendererMixerTest, AudioRendererMixerTest, testing::Values( // No resampling. diff --git a/media/base/fake_audio_render_callback.cc b/media/base/fake_audio_render_callback.cc index 6adf569..65b6ac9 100644 --- a/media/base/fake_audio_render_callback.cc +++ b/media/base/fake_audio_render_callback.cc @@ -13,7 +13,8 @@ namespace media { FakeAudioRenderCallback::FakeAudioRenderCallback(double step) : half_fill_(false), - step_(step) { + step_(step), + last_audio_delay_milliseconds_(-1) { reset(); } @@ -21,6 +22,7 @@ FakeAudioRenderCallback::~FakeAudioRenderCallback() {} int FakeAudioRenderCallback::Render(AudioBus* audio_bus, int audio_delay_milliseconds) { + last_audio_delay_milliseconds_ = audio_delay_milliseconds; int number_of_frames = audio_bus->frames(); if (half_fill_) number_of_frames /= 2; diff --git a/media/base/fake_audio_render_callback.h b/media/base/fake_audio_render_callback.h index f6ce104..760e39d 100644 --- a/media/base/fake_audio_render_callback.h +++ b/media/base/fake_audio_render_callback.h @@ -31,10 +31,15 @@ class FakeAudioRenderCallback : public AudioRendererSink::RenderCallback { // Reset the sine state to initial value. void reset() { x_ = 0; } + // Returns the last |audio_delay_milliseconds| provided to Render() or -1 if + // no Render() call occurred. + int last_audio_delay_milliseconds() { return last_audio_delay_milliseconds_; } + private: bool half_fill_; double x_; double step_; + int last_audio_delay_milliseconds_; DISALLOW_COPY_AND_ASSIGN(FakeAudioRenderCallback); }; |