Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1216)

Side by Side Diff: media/base/audio_renderer_mixer_unittest.cc

Issue 1483433003: Second layer of mixing for audio elements. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: That fix Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « media/base/audio_renderer_mixer_input_unittest.cc ('k') | media/base/loopback_audio_converter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698