audio_renderer_mixer_unittest.cc revision 868fa2fe829687343ffae624259930155e16dbd8
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
3// found in the LICENSE file.
4
5// MSVC++ requires this to be set before any other includes to get M_PI.
6#define _USE_MATH_DEFINES
7#include <cmath>
8
9#include "base/bind.h"
10#include "base/bind_helpers.h"
11#include "base/memory/scoped_ptr.h"
12#include "base/memory/scoped_vector.h"
13#include "base/synchronization/waitable_event.h"
14#include "base/threading/platform_thread.h"
15#include "media/base/audio_renderer_mixer.h"
16#include "media/base/audio_renderer_mixer_input.h"
17#include "media/base/fake_audio_render_callback.h"
18#include "media/base/mock_audio_renderer_sink.h"
19#include "testing/gmock/include/gmock/gmock.h"
20#include "testing/gtest/include/gtest/gtest.h"
21
22namespace media {
23
24// Parameters which control the many input case tests.
25static const int kMixerInputs = 8;
26static const int kMixerCycles = 3;
27
28// Parameters used for testing.
29static const int kBitsPerChannel = 32;
30static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
31static const int kHighLatencyBufferSize = 8192;
32static const int kLowLatencyBufferSize = 256;
33static const int kSampleRate = 48000;
34
35// Number of full sine wave cycles for each Render() call.
36static const int kSineCycles = 4;
37
38// Tuple of <input sampling rate, output sampling rate, epsilon>.
39typedef std::tr1::tuple<int, int, double> AudioRendererMixerTestData;
40class AudioRendererMixerTest
41    : public testing::TestWithParam<AudioRendererMixerTestData> {
42 public:
43  AudioRendererMixerTest()
44      : epsilon_(std::tr1::get<2>(GetParam())),
45        half_fill_(false) {
46    // Create input and output parameters based on test parameters.
47    input_parameters_ = AudioParameters(
48        AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
49        std::tr1::get<0>(GetParam()), kBitsPerChannel, kHighLatencyBufferSize);
50    output_parameters_ = AudioParameters(
51        AudioParameters::AUDIO_PCM_LOW_LATENCY, kChannelLayout,
52        std::tr1::get<1>(GetParam()), 16, kLowLatencyBufferSize);
53
54    sink_ = new MockAudioRendererSink();
55    EXPECT_CALL(*sink_.get(), Start());
56    EXPECT_CALL(*sink_.get(), Stop());
57
58    mixer_.reset(new AudioRendererMixer(
59        input_parameters_, output_parameters_, sink_));
60    mixer_callback_ = sink_->callback();
61
62    audio_bus_ = AudioBus::Create(output_parameters_);
63    expected_audio_bus_ = AudioBus::Create(output_parameters_);
64
65    // Allocate one callback for generating expected results.
66    double step = kSineCycles / static_cast<double>(
67        output_parameters_.frames_per_buffer());
68    expected_callback_.reset(new FakeAudioRenderCallback(step));
69  }
70
71  AudioRendererMixer* GetMixer(const AudioParameters& params) {
72    return mixer_.get();
73  }
74
75  MOCK_METHOD1(RemoveMixer, void(const AudioParameters&));
76
77  void InitializeInputs(int count) {
78    mixer_inputs_.reserve(count);
79    fake_callbacks_.reserve(count);
80
81    // Setup FakeAudioRenderCallback step to compensate for resampling.
82    double scale_factor = input_parameters_.sample_rate() /
83        static_cast<double>(output_parameters_.sample_rate());
84    double step = kSineCycles / (scale_factor *
85        static_cast<double>(output_parameters_.frames_per_buffer()));
86
87    for (int i = 0; i < count; ++i) {
88      fake_callbacks_.push_back(new FakeAudioRenderCallback(step));
89      mixer_inputs_.push_back(new AudioRendererMixerInput(
90          base::Bind(&AudioRendererMixerTest::GetMixer,
91                     base::Unretained(this)),
92          base::Bind(&AudioRendererMixerTest::RemoveMixer,
93                     base::Unretained(this))));
94      mixer_inputs_[i]->Initialize(input_parameters_, fake_callbacks_[i]);
95      mixer_inputs_[i]->SetVolume(1.0f);
96    }
97    EXPECT_CALL(*this, RemoveMixer(testing::_)).Times(count);
98  }
99
100  bool ValidateAudioData(int index, int frames, float scale, double epsilon) {
101    for (int i = 0; i < audio_bus_->channels(); ++i) {
102      for (int j = index; j < frames; j++) {
103        double error = fabs(audio_bus_->channel(i)[j] -
104            expected_audio_bus_->channel(i)[j] * scale);
105        if (error > epsilon) {
106          EXPECT_NEAR(expected_audio_bus_->channel(i)[j] * scale,
107                      audio_bus_->channel(i)[j], epsilon)
108              << " i=" << i << ", j=" << j;
109          return false;
110        }
111      }
112    }
113    return true;
114  }
115
116  bool ValidateAudioData(int index, int frames, float scale) {
117    return ValidateAudioData(index, frames, scale, epsilon_);
118  }
119
120  bool RenderAndValidateAudioData(float scale) {
121    if (half_fill_) {
122      for (size_t i = 0; i < fake_callbacks_.size(); ++i)
123        fake_callbacks_[i]->set_half_fill(true);
124      expected_callback_->set_half_fill(true);
125      // Initialize the AudioBus completely or we'll run into Valgrind problems
126      // during the verification step below.
127      expected_audio_bus_->Zero();
128    }
129
130    // Render actual audio data.
131    int frames = mixer_callback_->Render(audio_bus_.get(), 0);
132    if (frames != audio_bus_->frames())
133      return false;
134
135    // Render expected audio data (without scaling).
136    expected_callback_->Render(expected_audio_bus_.get(), 0);
137
138    if (half_fill_) {
139      // In this case, just verify that every frame was initialized, this will
140      // only fail under tooling such as valgrind.
141      return ValidateAudioData(
142          0, frames, 0, std::numeric_limits<double>::max());
143    } else {
144      return ValidateAudioData(0, frames, scale);
145    }
146  }
147
148  // Fill |audio_bus_| fully with |value|.
149  void FillAudioData(float value) {
150    for (int i = 0; i < audio_bus_->channels(); ++i) {
151      std::fill(audio_bus_->channel(i),
152                audio_bus_->channel(i) + audio_bus_->frames(), value);
153    }
154  }
155
156  // Verify silence when mixer inputs are in pre-Start() and post-Start().
157  void StartTest(int inputs) {
158    InitializeInputs(inputs);
159
160    // Verify silence before any inputs have been started.  Fill the buffer
161    // before hand with non-zero data to ensure we get zeros back.
162    FillAudioData(1.0f);
163    EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
164
165    // Start() all even numbered mixer inputs and ensure we still get silence.
166    for (size_t i = 0; i < mixer_inputs_.size(); i += 2)
167      mixer_inputs_[i]->Start();
168    FillAudioData(1.0f);
169    EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
170
171    // Start() all mixer inputs and ensure we still get silence.
172    for (size_t i = 1; i < mixer_inputs_.size(); i += 2)
173      mixer_inputs_[i]->Start();
174    FillAudioData(1.0f);
175    EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
176
177    for (size_t i = 0; i < mixer_inputs_.size(); ++i)
178      mixer_inputs_[i]->Stop();
179  }
180
181  // Verify output when mixer inputs are in post-Play() state.
182  void PlayTest(int inputs) {
183    InitializeInputs(inputs);
184
185    // Play() all mixer inputs and ensure we get the right values.
186    for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
187      mixer_inputs_[i]->Start();
188      mixer_inputs_[i]->Play();
189    }
190
191    for (int i = 0; i < kMixerCycles; ++i)
192      ASSERT_TRUE(RenderAndValidateAudioData(mixer_inputs_.size()));
193
194    for (size_t i = 0; i < mixer_inputs_.size(); ++i)
195      mixer_inputs_[i]->Stop();
196  }
197
198  // Verify volume adjusted output when mixer inputs are in post-Play() state.
199  void PlayVolumeAdjustedTest(int inputs) {
200    InitializeInputs(inputs);
201
202    for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
203      mixer_inputs_[i]->Start();
204      mixer_inputs_[i]->Play();
205    }
206
207    // Set a different volume for each mixer input and verify the results.
208    float total_scale = 0;
209    for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
210      float volume = static_cast<float>(i) / mixer_inputs_.size();
211      total_scale += volume;
212      EXPECT_TRUE(mixer_inputs_[i]->SetVolume(volume));
213    }
214    for (int i = 0; i < kMixerCycles; ++i)
215      ASSERT_TRUE(RenderAndValidateAudioData(total_scale));
216
217    for (size_t i = 0; i < mixer_inputs_.size(); ++i)
218      mixer_inputs_[i]->Stop();
219  }
220
221  // Verify output when mixer inputs can only partially fulfill a Render().
222  void PlayPartialRenderTest(int inputs) {
223    InitializeInputs(inputs);
224
225    for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
226      mixer_inputs_[i]->Start();
227      mixer_inputs_[i]->Play();
228    }
229
230    // Verify a properly filled buffer when half filled (remainder zeroed).
231    half_fill_ = true;
232    ASSERT_TRUE(RenderAndValidateAudioData(mixer_inputs_.size()));
233
234    for (size_t i = 0; i < mixer_inputs_.size(); ++i)
235      mixer_inputs_[i]->Stop();
236  }
237
238  // Verify output when mixer inputs are in Pause() state.
239  void PauseTest(int inputs) {
240    InitializeInputs(inputs);
241
242    for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
243      mixer_inputs_[i]->Start();
244      mixer_inputs_[i]->Play();
245    }
246
247    // Pause() all even numbered mixer inputs and ensure we get the right value.
248    for (size_t i = 0; i < mixer_inputs_.size(); i += 2)
249      mixer_inputs_[i]->Pause();
250    for (int i = 0; i < kMixerCycles; ++i)
251      ASSERT_TRUE(RenderAndValidateAudioData(mixer_inputs_.size() / 2));
252
253    for (size_t i = 0; i < mixer_inputs_.size(); ++i)
254      mixer_inputs_[i]->Stop();
255  }
256
257  // Verify output when mixer inputs are in post-Stop() state.
258  void StopTest(int inputs) {
259    InitializeInputs(inputs);
260
261    // Start() and Stop() all inputs.
262    for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
263      mixer_inputs_[i]->Start();
264      mixer_inputs_[i]->Stop();
265    }
266
267    // Verify we get silence back; fill |audio_bus_| before hand to be sure.
268    FillAudioData(1.0f);
269    EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
270  }
271
272 protected:
273  virtual ~AudioRendererMixerTest() {}
274
275  scoped_refptr<MockAudioRendererSink> sink_;
276  scoped_ptr<AudioRendererMixer> mixer_;
277  AudioRendererSink::RenderCallback* mixer_callback_;
278  AudioParameters input_parameters_;
279  AudioParameters output_parameters_;
280  scoped_ptr<AudioBus> audio_bus_;
281  scoped_ptr<AudioBus> expected_audio_bus_;
282  std::vector< scoped_refptr<AudioRendererMixerInput> > mixer_inputs_;
283  ScopedVector<FakeAudioRenderCallback> fake_callbacks_;
284  scoped_ptr<FakeAudioRenderCallback> expected_callback_;
285  double epsilon_;
286  bool half_fill_;
287
288  DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerTest);
289};
290
291class AudioRendererMixerBehavioralTest : public AudioRendererMixerTest {};
292
293ACTION_P(SignalEvent, event) {
294  event->Signal();
295}
296
297// Verify a mixer with no inputs returns silence for all requested frames.
298TEST_P(AudioRendererMixerTest, NoInputs) {
299  FillAudioData(1.0f);
300  EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
301}
302
303// Test mixer output with one input in the pre-Start() and post-Start() state.
304TEST_P(AudioRendererMixerTest, OneInputStart) {
305  StartTest(1);
306}
307
308// Test mixer output with many inputs in the pre-Start() and post-Start() state.
309TEST_P(AudioRendererMixerTest, ManyInputStart) {
310  StartTest(kMixerInputs);
311}
312
313// Test mixer output with one input in the post-Play() state.
314TEST_P(AudioRendererMixerTest, OneInputPlay) {
315  PlayTest(1);
316}
317
318// Test mixer output with many inputs in the post-Play() state.
319TEST_P(AudioRendererMixerTest, ManyInputPlay) {
320  PlayTest(kMixerInputs);
321}
322
323// Test volume adjusted mixer output with one input in the post-Play() state.
324TEST_P(AudioRendererMixerTest, OneInputPlayVolumeAdjusted) {
325  PlayVolumeAdjustedTest(1);
326}
327
328// Test volume adjusted mixer output with many inputs in the post-Play() state.
329TEST_P(AudioRendererMixerTest, ManyInputPlayVolumeAdjusted) {
330  PlayVolumeAdjustedTest(kMixerInputs);
331}
332
333// Test mixer output with one input and partial Render() in post-Play() state.
334TEST_P(AudioRendererMixerTest, OneInputPlayPartialRender) {
335  PlayPartialRenderTest(1);
336}
337
338// Test mixer output with many inputs and partial Render() in post-Play() state.
339TEST_P(AudioRendererMixerTest, ManyInputPlayPartialRender) {
340  PlayPartialRenderTest(kMixerInputs);
341}
342
343// Test mixer output with one input in the post-Pause() state.
344TEST_P(AudioRendererMixerTest, OneInputPause) {
345  PauseTest(1);
346}
347
348// Test mixer output with many inputs in the post-Pause() state.
349TEST_P(AudioRendererMixerTest, ManyInputPause) {
350  PauseTest(kMixerInputs);
351}
352
353// Test mixer output with one input in the post-Stop() state.
354TEST_P(AudioRendererMixerTest, OneInputStop) {
355  StopTest(1);
356}
357
358// Test mixer output with many inputs in the post-Stop() state.
359TEST_P(AudioRendererMixerTest, ManyInputStop) {
360  StopTest(kMixerInputs);
361}
362
363// Test mixer with many inputs in mixed post-Stop() and post-Play() states.
364TEST_P(AudioRendererMixerTest, ManyInputMixedStopPlay) {
365  InitializeInputs(kMixerInputs);
366
367  // Start() all inputs.
368  for (size_t i = 0; i < mixer_inputs_.size(); ++i)
369    mixer_inputs_[i]->Start();
370
371  // Stop() all even numbered mixer inputs and Play() all odd numbered inputs
372  // and ensure we get the right value.
373  for (size_t i = 1; i < mixer_inputs_.size(); i += 2) {
374    mixer_inputs_[i - 1]->Stop();
375    mixer_inputs_[i]->Play();
376  }
377  ASSERT_TRUE(RenderAndValidateAudioData(std::max(
378      mixer_inputs_.size() / 2, static_cast<size_t>(1))));
379
380  for (size_t i = 1; i < mixer_inputs_.size(); i += 2)
381    mixer_inputs_[i]->Stop();
382}
383
384TEST_P(AudioRendererMixerBehavioralTest, OnRenderError) {
385  InitializeInputs(kMixerInputs);
386  for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
387    mixer_inputs_[i]->Start();
388    mixer_inputs_[i]->Play();
389    EXPECT_CALL(*fake_callbacks_[i], OnRenderError()).Times(1);
390  }
391
392  mixer_callback_->OnRenderError();
393  for (size_t i = 0; i < mixer_inputs_.size(); ++i)
394    mixer_inputs_[i]->Stop();
395}
396
397// Ensure constructing an AudioRendererMixerInput, but not initializing it does
398// not call RemoveMixer().
399TEST_P(AudioRendererMixerBehavioralTest, NoInitialize) {
400  EXPECT_CALL(*this, RemoveMixer(testing::_)).Times(0);
401  scoped_refptr<AudioRendererMixerInput> audio_renderer_mixer =
402      new AudioRendererMixerInput(
403          base::Bind(&AudioRendererMixerTest::GetMixer,
404                     base::Unretained(this)),
405          base::Bind(&AudioRendererMixerTest::RemoveMixer,
406                     base::Unretained(this)));
407}
408
409// Ensure the physical stream is paused after a certain amount of time with no
410// inputs playing.  The test will hang if the behavior is incorrect.
411TEST_P(AudioRendererMixerBehavioralTest, MixerPausesStream) {
412  const base::TimeDelta kPauseTime = base::TimeDelta::FromMilliseconds(500);
413  // This value can't be too low or valgrind, tsan will timeout on the bots.
414  const base::TimeDelta kTestTimeout = 10 * kPauseTime;
415  mixer_->set_pause_delay_for_testing(kPauseTime);
416
417  base::WaitableEvent pause_event(true, false);
418  EXPECT_CALL(*sink_.get(), Pause()).Times(2)
419      .WillRepeatedly(SignalEvent(&pause_event));
420  InitializeInputs(1);
421
422  // Ensure never playing the input results in a sink pause.
423  const base::TimeDelta kSleepTime = base::TimeDelta::FromMilliseconds(100);
424  base::Time start_time = base::Time::Now();
425  while (!pause_event.IsSignaled()) {
426    mixer_callback_->Render(audio_bus_.get(), 0);
427    base::PlatformThread::Sleep(kSleepTime);
428    ASSERT_TRUE(base::Time::Now() - start_time < kTestTimeout);
429  }
430  pause_event.Reset();
431
432  // Playing the input for the first time should cause a sink play.
433  mixer_inputs_[0]->Start();
434  EXPECT_CALL(*sink_.get(), Play());
435  mixer_inputs_[0]->Play();
436  mixer_inputs_[0]->Pause();
437
438  // Ensure once the input is paused the sink eventually pauses.
439  start_time = base::Time::Now();
440  while (!pause_event.IsSignaled()) {
441    mixer_callback_->Render(audio_bus_.get(), 0);
442    base::PlatformThread::Sleep(kSleepTime);
443    ASSERT_TRUE(base::Time::Now() - start_time < kTestTimeout);
444  }
445
446  mixer_inputs_[0]->Stop();
447}
448
449INSTANTIATE_TEST_CASE_P(
450    AudioRendererMixerTest, AudioRendererMixerTest, testing::Values(
451        // No resampling.
452        std::tr1::make_tuple(44100, 44100, 0.00000048),
453
454        // Upsampling.
455        std::tr1::make_tuple(44100, 48000, 0.033),
456
457        // Downsampling.
458        std::tr1::make_tuple(48000, 41000, 0.042)));
459
460// Test cases for behavior which is independent of parameters.  Values() doesn't
461// support single item lists and we don't want these test cases to run for every
462// parameter set.
463INSTANTIATE_TEST_CASE_P(
464    AudioRendererMixerBehavioralTest, AudioRendererMixerBehavioralTest,
465    testing::ValuesIn(std::vector<AudioRendererMixerTestData>(
466        1, std::tr1::make_tuple(44100, 44100, 0))));
467
468}  // namespace media
469