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 |