| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // MSVC++ requires this to be set before any other includes to get M_PI. | 5 // MSVC++ requires this to be set before any other includes to get M_PI. |
| 6 #define _USE_MATH_DEFINES | 6 #define _USE_MATH_DEFINES |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| 11 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
| 12 #include "base/memory/scoped_vector.h" | 12 #include "base/memory/scoped_vector.h" |
| 13 #include "base/synchronization/waitable_event.h" | 13 #include "base/synchronization/waitable_event.h" |
| 14 #include "base/threading/platform_thread.h" | 14 #include "base/threading/platform_thread.h" |
| 15 #include "media/base/audio_renderer_mixer.h" | 15 #include "media/base/audio_renderer_mixer.h" |
| 16 #include "media/base/audio_renderer_mixer_input.h" | 16 #include "media/base/audio_renderer_mixer_input.h" |
| 17 #include "media/base/fake_audio_render_callback.h" | 17 #include "media/base/fake_audio_render_callback.h" |
| 18 #include "media/base/mock_audio_renderer_sink.h" | 18 #include "media/base/mock_audio_renderer_sink.h" |
| 19 #include "testing/gmock/include/gmock/gmock.h" | 19 #include "testing/gmock/include/gmock/gmock.h" |
| 20 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
| 21 | 21 |
| 22 namespace media { | 22 namespace media { |
| 23 | 23 |
| 24 // Parameters which control the many input case tests. | 24 // Parameters which control the many input case tests. |
| 25 const int kMixerInputs = 8; | 25 const int kMixerInputs = 8; |
| 26 const int kOddMixerInputs = 7; |
| 26 const int kMixerCycles = 3; | 27 const int kMixerCycles = 3; |
| 27 | 28 |
| 28 // Parameters used for testing. | 29 // Parameters used for testing. |
| 29 const int kBitsPerChannel = 32; | 30 const int kBitsPerChannel = 32; |
| 30 const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO; | 31 const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO; |
| 31 const int kHighLatencyBufferSize = 8192; | 32 const int kHighLatencyBufferSize = 8192; |
| 32 const int kLowLatencyBufferSize = 256; | 33 const int kLowLatencyBufferSize = 256; |
| 33 | 34 |
| 34 // Number of full sine wave cycles for each Render() call. | 35 // Number of full sine wave cycles for each Render() call. |
| 35 const int kSineCycles = 4; | 36 const int kSineCycles = 4; |
| 36 | 37 |
| 37 // Default device ID | 38 // Default device ID. |
| 38 const std::string kDefaultDeviceId; | 39 const std::string kDefaultDeviceId; |
| 39 const url::Origin kDefaultSecurityOrigin; | 40 const url::Origin kDefaultSecurityOrigin; |
| 40 | 41 |
| 41 // Tuple of <input sampling rate, output sampling rate, epsilon>. | 42 // Input sample frequencies for testing. |
| 42 typedef std::tr1::tuple<int, int, double> AudioRendererMixerTestData; | 43 std::vector<int> kTestInputLower(1, 44100); |
| 44 std::vector<int> kTestInputHigher(1, 48000); |
| 45 const int kSampleRates[] = {22050, 44100, 48000}; |
| 46 std::vector<int> kTestInput3Rates(kSampleRates, |
| 47 kSampleRates + |
| 48 sizeof(kSampleRates) / |
| 49 sizeof(kSampleRates[0])); |
| 50 |
| 51 // Tuple of <input sampling rates, output sampling rate, epsilon>. |
| 52 typedef std::tr1::tuple<std::vector<int>, int, double> |
| 53 AudioRendererMixerTestData; |
| 54 |
| 43 class AudioRendererMixerTest | 55 class AudioRendererMixerTest |
| 44 : public testing::TestWithParam<AudioRendererMixerTestData> { | 56 : public testing::TestWithParam<AudioRendererMixerTestData> { |
| 45 public: | 57 public: |
| 46 AudioRendererMixerTest() | 58 AudioRendererMixerTest() |
| 47 : epsilon_(std::tr1::get<2>(GetParam())), | 59 : epsilon_(std::tr1::get<2>(GetParam())), |
| 48 half_fill_(false) { | 60 half_fill_(false) { |
| 49 // Create input and output parameters based on test parameters. | 61 // Create input parameters based on test parameters. |
| 50 input_parameters_ = AudioParameters( | 62 const std::vector<int>& sample_rates(std::tr1::get<0>(GetParam())); |
| 51 AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, | 63 for (size_t i = 0; i < sample_rates.size(); ++i) |
| 52 std::tr1::get<0>(GetParam()), kBitsPerChannel, kHighLatencyBufferSize); | 64 input_parameters_.push_back(AudioParameters( |
| 65 AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, sample_rates[i], |
| 66 kBitsPerChannel, kHighLatencyBufferSize)); |
| 67 |
| 68 // Create output parameters based on test parameters. |
| 53 output_parameters_ = AudioParameters( | 69 output_parameters_ = AudioParameters( |
| 54 AudioParameters::AUDIO_PCM_LOW_LATENCY, kChannelLayout, | 70 AudioParameters::AUDIO_PCM_LOW_LATENCY, kChannelLayout, |
| 55 std::tr1::get<1>(GetParam()), 16, kLowLatencyBufferSize); | 71 std::tr1::get<1>(GetParam()), 16, kLowLatencyBufferSize); |
| 56 | 72 |
| 57 sink_ = new MockAudioRendererSink(); | 73 sink_ = new MockAudioRendererSink(); |
| 58 EXPECT_CALL(*sink_.get(), Start()); | 74 EXPECT_CALL(*sink_.get(), Start()); |
| 59 EXPECT_CALL(*sink_.get(), Stop()); | 75 EXPECT_CALL(*sink_.get(), Stop()); |
| 60 | 76 |
| 61 mixer_.reset(new AudioRendererMixer( | 77 mixer_.reset(new AudioRendererMixer(output_parameters_, sink_)); |
| 62 input_parameters_, output_parameters_, sink_)); | |
| 63 mixer_callback_ = sink_->callback(); | 78 mixer_callback_ = sink_->callback(); |
| 64 | 79 |
| 65 audio_bus_ = AudioBus::Create(output_parameters_); | 80 audio_bus_ = AudioBus::Create(output_parameters_); |
| 66 expected_audio_bus_ = AudioBus::Create(output_parameters_); | 81 expected_audio_bus_ = AudioBus::Create(output_parameters_); |
| 67 | 82 |
| 68 // Allocate one callback for generating expected results. | 83 // Allocate one callback for generating expected results. |
| 69 double step = kSineCycles / static_cast<double>( | 84 double step = kSineCycles / static_cast<double>( |
| 70 output_parameters_.frames_per_buffer()); | 85 output_parameters_.frames_per_buffer()); |
| 71 expected_callback_.reset(new FakeAudioRenderCallback(step)); | 86 expected_callback_.reset(new FakeAudioRenderCallback(step)); |
| 72 } | 87 } |
| 73 | 88 |
| 74 AudioRendererMixer* GetMixer(const AudioParameters& params, | 89 AudioRendererMixer* GetMixer(const AudioParameters& params, |
| 75 const std::string& device_id, | 90 const std::string& device_id, |
| 76 const url::Origin& security_origin, | 91 const url::Origin& security_origin, |
| 77 OutputDeviceStatus* device_status) { | 92 OutputDeviceStatus* device_status) { |
| 78 return mixer_.get(); | 93 return mixer_.get(); |
| 79 } | 94 } |
| 80 | 95 |
| 81 MOCK_METHOD3(RemoveMixer, | 96 MOCK_METHOD3(RemoveMixer, |
| 82 void(const AudioParameters&, | 97 void(const AudioParameters&, |
| 83 const std::string&, | 98 const std::string&, |
| 84 const url::Origin&)); | 99 const url::Origin&)); |
| 85 | 100 |
| 86 void InitializeInputs(int count) { | 101 void InitializeInputs(int inputs_per_sample_rate) { |
| 87 mixer_inputs_.reserve(count); | 102 mixer_inputs_.reserve(inputs_per_sample_rate * input_parameters_.size()); |
| 88 fake_callbacks_.reserve(count); | 103 fake_callbacks_.reserve(inputs_per_sample_rate * input_parameters_.size()); |
| 89 | 104 |
| 90 // Setup FakeAudioRenderCallback step to compensate for resampling. | 105 for (size_t i = 0, input = 0; i < input_parameters_.size(); ++i) { |
| 91 double scale_factor = input_parameters_.sample_rate() / | 106 // Setup FakeAudioRenderCallback step to compensate for resampling. |
| 92 static_cast<double>(output_parameters_.sample_rate()); | 107 double scale_factor = |
| 93 double step = kSineCycles / (scale_factor * | 108 input_parameters_[i].sample_rate() / |
| 94 static_cast<double>(output_parameters_.frames_per_buffer())); | 109 static_cast<double>(output_parameters_.sample_rate()); |
| 110 double step = |
| 111 kSineCycles / |
| 112 (scale_factor * |
| 113 static_cast<double>(output_parameters_.frames_per_buffer())); |
| 95 | 114 |
| 96 for (int i = 0; i < count; ++i) { | 115 for (int j = 0; j < inputs_per_sample_rate; ++j, ++input) { |
| 97 fake_callbacks_.push_back(new FakeAudioRenderCallback(step)); | 116 fake_callbacks_.push_back(new FakeAudioRenderCallback(step)); |
| 98 mixer_inputs_.push_back(new AudioRendererMixerInput( | 117 mixer_inputs_.push_back(new AudioRendererMixerInput( |
| 99 base::Bind(&AudioRendererMixerTest::GetMixer, base::Unretained(this)), | 118 base::Bind(&AudioRendererMixerTest::GetMixer, |
| 100 base::Bind(&AudioRendererMixerTest::RemoveMixer, | 119 base::Unretained(this)), |
| 101 base::Unretained(this)), | 120 base::Bind(&AudioRendererMixerTest::RemoveMixer, |
| 102 kDefaultDeviceId, kDefaultSecurityOrigin)); | 121 base::Unretained(this)), |
| 103 mixer_inputs_[i]->Initialize(input_parameters_, fake_callbacks_[i]); | 122 kDefaultDeviceId, kDefaultSecurityOrigin)); |
| 104 mixer_inputs_[i]->SetVolume(1.0f); | 123 mixer_inputs_[input]->Initialize(input_parameters_[i], |
| 124 fake_callbacks_[input]); |
| 125 mixer_inputs_[input]->SetVolume(1.0f); |
| 126 } |
| 105 } | 127 } |
| 106 EXPECT_CALL(*this, RemoveMixer(testing::_, testing::_, testing::_)) | 128 EXPECT_CALL(*this, RemoveMixer(testing::_, testing::_, testing::_)) |
| 107 .Times(count); | 129 .Times(mixer_inputs_.size()); |
| 108 } | 130 } |
| 109 | 131 |
| 110 bool ValidateAudioData(int index, int frames, float scale, double epsilon) { | 132 bool ValidateAudioData(int index, int frames, float scale, double epsilon) { |
| 111 for (int i = 0; i < audio_bus_->channels(); ++i) { | 133 for (int i = 0; i < audio_bus_->channels(); ++i) { |
| 112 for (int j = index; j < frames; j++) { | 134 for (int j = index; j < frames; j++) { |
| 113 double error = fabs(audio_bus_->channel(i)[j] - | 135 double error = fabs(audio_bus_->channel(i)[j] - |
| 114 expected_audio_bus_->channel(i)[j] * scale); | 136 expected_audio_bus_->channel(i)[j] * scale); |
| 115 if (error > epsilon) { | 137 // The second comparison is for the case when scale is set to 0 |
| 138 // (and less that 1 in general) |
| 139 if ((error > epsilon * scale) && (error > epsilon)) { |
| 116 EXPECT_NEAR(expected_audio_bus_->channel(i)[j] * scale, | 140 EXPECT_NEAR(expected_audio_bus_->channel(i)[j] * scale, |
| 117 audio_bus_->channel(i)[j], epsilon) | 141 audio_bus_->channel(i)[j], epsilon * scale) |
| 118 << " i=" << i << ", j=" << j; | 142 << " i=" << i << ", j=" << j; |
| 119 return false; | 143 return false; |
| 120 } | 144 } |
| 121 } | 145 } |
| 122 } | 146 } |
| 123 return true; | 147 return true; |
| 124 } | 148 } |
| 125 | 149 |
| 126 bool ValidateAudioData(int index, int frames, float scale) { | 150 bool ValidateAudioData(int index, int frames, float scale) { |
| 127 return ValidateAudioData(index, frames, scale, epsilon_); | 151 return ValidateAudioData(index, frames, scale, epsilon_); |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { | 296 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { |
| 273 mixer_inputs_[i]->Start(); | 297 mixer_inputs_[i]->Start(); |
| 274 mixer_inputs_[i]->Stop(); | 298 mixer_inputs_[i]->Stop(); |
| 275 } | 299 } |
| 276 | 300 |
| 277 // Verify we get silence back; fill |audio_bus_| before hand to be sure. | 301 // Verify we get silence back; fill |audio_bus_| before hand to be sure. |
| 278 FillAudioData(1.0f); | 302 FillAudioData(1.0f); |
| 279 EXPECT_TRUE(RenderAndValidateAudioData(0.0f)); | 303 EXPECT_TRUE(RenderAndValidateAudioData(0.0f)); |
| 280 } | 304 } |
| 281 | 305 |
| 306 // Verify output when mixer inputs in mixed post-Stop() and post-Play() |
| 307 // states. |
| 308 void MixedStopPlayTest(int inputs) { |
| 309 InitializeInputs(inputs); |
| 310 |
| 311 // Start() all inputs. |
| 312 for (size_t i = 0; i < mixer_inputs_.size(); ++i) |
| 313 mixer_inputs_[i]->Start(); |
| 314 |
| 315 // Stop() all even numbered mixer inputs and Play() all odd numbered inputs |
| 316 // and ensure we get the right value. |
| 317 for (size_t i = 1; i < mixer_inputs_.size(); i += 2) { |
| 318 mixer_inputs_[i - 1]->Stop(); |
| 319 mixer_inputs_[i]->Play(); |
| 320 } |
| 321 |
| 322 // Stop the last input in case the number of inputs is odd |
| 323 if (mixer_inputs_.size() % 2) |
| 324 mixer_inputs_[mixer_inputs_.size() - 1]->Stop(); |
| 325 |
| 326 ASSERT_TRUE(RenderAndValidateAudioData( |
| 327 std::max(1.f, static_cast<float>(floor(mixer_inputs_.size() / 2.f))))); |
| 328 |
| 329 for (size_t i = 1; i < mixer_inputs_.size(); i += 2) |
| 330 mixer_inputs_[i]->Stop(); |
| 331 } |
| 332 |
| 282 protected: | 333 protected: |
| 283 virtual ~AudioRendererMixerTest() {} | 334 virtual ~AudioRendererMixerTest() {} |
| 284 | 335 |
| 285 scoped_refptr<MockAudioRendererSink> sink_; | 336 scoped_refptr<MockAudioRendererSink> sink_; |
| 286 scoped_ptr<AudioRendererMixer> mixer_; | 337 scoped_ptr<AudioRendererMixer> mixer_; |
| 287 AudioRendererSink::RenderCallback* mixer_callback_; | 338 AudioRendererSink::RenderCallback* mixer_callback_; |
| 288 AudioParameters input_parameters_; | 339 std::vector<AudioParameters> input_parameters_; |
| 289 AudioParameters output_parameters_; | 340 AudioParameters output_parameters_; |
| 290 scoped_ptr<AudioBus> audio_bus_; | 341 scoped_ptr<AudioBus> audio_bus_; |
| 291 scoped_ptr<AudioBus> expected_audio_bus_; | 342 scoped_ptr<AudioBus> expected_audio_bus_; |
| 292 std::vector< scoped_refptr<AudioRendererMixerInput> > mixer_inputs_; | 343 std::vector< scoped_refptr<AudioRendererMixerInput> > mixer_inputs_; |
| 293 ScopedVector<FakeAudioRenderCallback> fake_callbacks_; | 344 ScopedVector<FakeAudioRenderCallback> fake_callbacks_; |
| 294 scoped_ptr<FakeAudioRenderCallback> expected_callback_; | 345 scoped_ptr<FakeAudioRenderCallback> expected_callback_; |
| 295 double epsilon_; | 346 double epsilon_; |
| 296 bool half_fill_; | 347 bool half_fill_; |
| 297 | 348 |
| 298 private: | 349 private: |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 StopTest(1); | 417 StopTest(1); |
| 367 } | 418 } |
| 368 | 419 |
| 369 // Test mixer output with many inputs in the post-Stop() state. | 420 // Test mixer output with many inputs in the post-Stop() state. |
| 370 TEST_P(AudioRendererMixerTest, ManyInputStop) { | 421 TEST_P(AudioRendererMixerTest, ManyInputStop) { |
| 371 StopTest(kMixerInputs); | 422 StopTest(kMixerInputs); |
| 372 } | 423 } |
| 373 | 424 |
| 374 // Test mixer with many inputs in mixed post-Stop() and post-Play() states. | 425 // Test mixer with many inputs in mixed post-Stop() and post-Play() states. |
| 375 TEST_P(AudioRendererMixerTest, ManyInputMixedStopPlay) { | 426 TEST_P(AudioRendererMixerTest, ManyInputMixedStopPlay) { |
| 376 InitializeInputs(kMixerInputs); | 427 MixedStopPlayTest(kMixerInputs); |
| 428 } |
| 377 | 429 |
| 378 // Start() all inputs. | 430 // Test mixer with many inputs in mixed post-Stop() and post-Play() states. |
| 379 for (size_t i = 0; i < mixer_inputs_.size(); ++i) | 431 TEST_P(AudioRendererMixerTest, ManyInputMixedStopPlayOdd) { |
| 380 mixer_inputs_[i]->Start(); | 432 // Odd number of inputs per sample rate, to stop them unevenly. |
| 381 | 433 MixedStopPlayTest(kOddMixerInputs); |
| 382 // Stop() all even numbered mixer inputs and Play() all odd numbered inputs | |
| 383 // and ensure we get the right value. | |
| 384 for (size_t i = 1; i < mixer_inputs_.size(); i += 2) { | |
| 385 mixer_inputs_[i - 1]->Stop(); | |
| 386 mixer_inputs_[i]->Play(); | |
| 387 } | |
| 388 ASSERT_TRUE(RenderAndValidateAudioData(std::max( | |
| 389 mixer_inputs_.size() / 2, static_cast<size_t>(1)))); | |
| 390 | |
| 391 for (size_t i = 1; i < mixer_inputs_.size(); i += 2) | |
| 392 mixer_inputs_[i]->Stop(); | |
| 393 } | 434 } |
| 394 | 435 |
| 395 TEST_P(AudioRendererMixerBehavioralTest, OnRenderError) { | 436 TEST_P(AudioRendererMixerBehavioralTest, OnRenderError) { |
| 396 InitializeInputs(kMixerInputs); | 437 InitializeInputs(kMixerInputs); |
| 397 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { | 438 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { |
| 398 mixer_inputs_[i]->Start(); | 439 mixer_inputs_[i]->Start(); |
| 399 mixer_inputs_[i]->Play(); | 440 mixer_inputs_[i]->Play(); |
| 400 EXPECT_CALL(*fake_callbacks_[i], OnRenderError()).Times(1); | 441 EXPECT_CALL(*fake_callbacks_[i], OnRenderError()).Times(1); |
| 401 } | 442 } |
| 402 | 443 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 while (!pause_event.IsSignaled()) { | 508 while (!pause_event.IsSignaled()) { |
| 468 mixer_callback_->Render(audio_bus_.get(), 0); | 509 mixer_callback_->Render(audio_bus_.get(), 0); |
| 469 base::PlatformThread::Sleep(kSleepTime); | 510 base::PlatformThread::Sleep(kSleepTime); |
| 470 ASSERT_TRUE(base::TimeTicks::Now() - start_time < kTestTimeout); | 511 ASSERT_TRUE(base::TimeTicks::Now() - start_time < kTestTimeout); |
| 471 } | 512 } |
| 472 | 513 |
| 473 mixer_inputs_[0]->Stop(); | 514 mixer_inputs_[0]->Stop(); |
| 474 } | 515 } |
| 475 | 516 |
| 476 INSTANTIATE_TEST_CASE_P( | 517 INSTANTIATE_TEST_CASE_P( |
| 477 AudioRendererMixerTest, AudioRendererMixerTest, testing::Values( | 518 AudioRendererMixerTest, |
| 478 // No resampling. | 519 AudioRendererMixerTest, |
| 479 std::tr1::make_tuple(44100, 44100, 0.00000048), | 520 testing::Values( |
| 521 // No resampling, 1 input sample rate. |
| 522 std::tr1::make_tuple(kTestInputLower, kTestInputLower[0], 0.00000048), |
| 480 | 523 |
| 481 // Upsampling. | 524 // Upsampling, 1 input sample rate. |
| 482 std::tr1::make_tuple(44100, 48000, 0.033), | 525 std::tr1::make_tuple(kTestInputLower, kTestInputHigher[0], 0.01), |
| 483 | 526 |
| 484 // Downsampling. | 527 // Downsampling, 1 input sample rate. |
| 485 std::tr1::make_tuple(48000, 41000, 0.042))); | 528 std::tr1::make_tuple(kTestInputHigher, kTestInputLower[0], 0.01), |
| 529 |
| 530 // Downsampling, multuple input sample rates. |
| 531 std::tr1::make_tuple(kTestInput3Rates, kTestInput3Rates[0], 0.01), |
| 532 |
| 533 // Upsampling, multiple sinput sample rates. |
| 534 std::tr1::make_tuple(kTestInput3Rates, kTestInput3Rates[2], 0.01), |
| 535 |
| 536 // Both downsampling and upsampling, multiple input sample rates |
| 537 std::tr1::make_tuple(kTestInput3Rates, kTestInput3Rates[1], 0.01))); |
| 486 | 538 |
| 487 // Test cases for behavior which is independent of parameters. Values() doesn't | 539 // Test cases for behavior which is independent of parameters. Values() doesn't |
| 488 // support single item lists and we don't want these test cases to run for every | 540 // support single item lists and we don't want these test cases to run for every |
| 489 // parameter set. | 541 // parameter set. |
| 490 INSTANTIATE_TEST_CASE_P( | 542 INSTANTIATE_TEST_CASE_P( |
| 491 AudioRendererMixerBehavioralTest, AudioRendererMixerBehavioralTest, | 543 AudioRendererMixerBehavioralTest, |
| 544 AudioRendererMixerBehavioralTest, |
| 492 testing::ValuesIn(std::vector<AudioRendererMixerTestData>( | 545 testing::ValuesIn(std::vector<AudioRendererMixerTestData>( |
| 493 1, std::tr1::make_tuple(44100, 44100, 0)))); | 546 1, |
| 494 | 547 std::tr1::make_tuple(kTestInputLower, |
| 548 kTestInputLower[0], |
| 549 0.00000048)))); |
| 495 } // namespace media | 550 } // namespace media |
| OLD | NEW |