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

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

Issue 10698066: Switch to pcm_low_latency and enable resampling. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: First Look! Created 8 years, 5 months 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 | Annotate | Revision Log
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 #include <cmath> 5 #include <cmath>
6 6
7 #include "base/memory/scoped_ptr.h" 7 #include "base/memory/scoped_ptr.h"
8 #include "media/audio/audio_util.h" 8 #include "media/audio/audio_util.h"
9 #include "media/base/audio_renderer_mixer.h" 9 #include "media/base/audio_renderer_mixer.h"
10 #include "media/base/audio_renderer_mixer_input.h" 10 #include "media/base/audio_renderer_mixer_input.h"
11 #include "media/base/fake_audio_render_callback.h" 11 #include "media/base/fake_audio_render_callback.h"
12 #include "testing/gmock/include/gmock/gmock.h" 12 #include "testing/gmock/include/gmock/gmock.h"
13 #include "testing/gtest/include/gtest/gtest.h" 13 #include "testing/gtest/include/gtest/gtest.h"
14 14
15 namespace media { 15 namespace media {
16 16
17 // Parameters which control the many input case tests. 17 // Parameters which control the many input case tests.
18 static const int kMixerInputs = 64; 18 static const int kMixerInputs = 64;
19 static const int kMixerCycles = 32; 19 static const int kMixerCycles = 32;
20 20
21 static const int kBitsPerChannel = 16; 21 static const int kBitsPerChannel = 16;
22 static const int kSampleRate = 48000; 22 static const int kSampleRate = GetAudioHardwareSampleRate();
23 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO; 23 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
24 24
25 // Multiple rounds of addition result in precision loss with float values, so we 25 // Multiple rounds of addition result in precision loss with float values, so we
26 // need an epsilon such that if for all x f(x) = sum(x, m) and g(x) = m * x then 26 // need an epsilon such that if for all x f(x) = sum(x, m) and g(x) = m * x then
27 // fabs(f - g) < kEpsilon. The kEpsilon below has been tested with m < 128. 27 // fabs(f - g) < kEpsilon. The kEpsilon below has been tested with m < 128.
28 static const float kEpsilon = 0.00015f; 28 static const float kEpsilon = 0.00015f;
29 29
30 class MockAudioRendererSink : public AudioRendererSink { 30 class MockAudioRendererSink : public AudioRendererSink {
31 public: 31 public:
32 MOCK_METHOD0(Start, void()); 32 MOCK_METHOD0(Start, void());
33 MOCK_METHOD0(Stop, void()); 33 MOCK_METHOD0(Stop, void());
34 MOCK_METHOD1(Pause, void(bool flush)); 34 MOCK_METHOD1(Pause, void(bool flush));
35 MOCK_METHOD0(Play, void()); 35 MOCK_METHOD0(Play, void());
36 MOCK_METHOD1(SetPlaybackRate, void(float rate)); 36 MOCK_METHOD1(SetPlaybackRate, void(float rate));
37 MOCK_METHOD1(SetVolume, bool(double volume)); 37 MOCK_METHOD1(SetVolume, bool(double volume));
38 MOCK_METHOD1(GetVolume, void(double* volume)); 38 MOCK_METHOD1(GetVolume, void(double* volume));
39 39
40 void Initialize(const media::AudioParameters& params, 40 void Initialize(const AudioParameters& params,
41 AudioRendererSink::RenderCallback* renderer) OVERRIDE { 41 AudioRendererSink::RenderCallback* renderer) OVERRIDE {
42 // TODO(dalecurtis): Once we have resampling we need to ensure we are given 42 // TODO(dalecurtis): Once we have resampling we need to ensure we are given
43 // an AudioParameters which reflects the hardware settings. 43 // an AudioParameters which reflects the hardware settings.
44 callback_ = renderer; 44 callback_ = renderer;
45 params_ = params;
45 }; 46 };
46 47
47 AudioRendererSink::RenderCallback* callback() { 48 AudioRendererSink::RenderCallback* callback() {
48 return callback_; 49 return callback_;
49 } 50 }
50 51
52 const AudioParameters& params() {
53 return params_;
54 }
55
51 void SimulateRenderError() { 56 void SimulateRenderError() {
52 callback_->OnRenderError(); 57 callback_->OnRenderError();
53 } 58 }
54 59
55 protected: 60 protected:
56 virtual ~MockAudioRendererSink() {} 61 virtual ~MockAudioRendererSink() {}
57 62
58 AudioRendererSink::RenderCallback* callback_; 63 AudioRendererSink::RenderCallback* callback_;
64 AudioParameters params_;
59 }; 65 };
60 66
61 class AudioRendererMixerTest : public ::testing::Test { 67 class AudioRendererMixerTest : public ::testing::Test {
62 public: 68 public:
63 AudioRendererMixerTest() { 69 AudioRendererMixerTest() {
64 audio_parameters_ = AudioParameters( 70 input_parameters_ = AudioParameters(
65 AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate, 71 AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate,
66 kBitsPerChannel, GetHighLatencyOutputBufferSize(kSampleRate)); 72 kBitsPerChannel, GetHighLatencyOutputBufferSize(kSampleRate));
67 sink_ = new MockAudioRendererSink(); 73 sink_ = new MockAudioRendererSink();
68 EXPECT_CALL(*sink_, Start()); 74 EXPECT_CALL(*sink_, Start());
69 EXPECT_CALL(*sink_, Stop()); 75 EXPECT_CALL(*sink_, Stop());
70 76
71 mixer_ = new AudioRendererMixer(audio_parameters_, sink_); 77 mixer_ = new AudioRendererMixer(input_parameters_, sink_);
72 mixer_callback_ = sink_->callback(); 78 mixer_callback_ = sink_->callback();
79 output_parameters_ = sink_->params();
73 80
74 // TODO(dalecurtis): If we switch to AVX/SSE optimization, we'll need to 81 // TODO(dalecurtis): If we switch to AVX/SSE optimization, we'll need to
75 // allocate these on 32-byte boundaries and ensure they're sized % 32 bytes. 82 // allocate these on 32-byte boundaries and ensure they're sized % 32 bytes.
76 audio_data_.reserve(audio_parameters_.channels()); 83 audio_data_.reserve(output_parameters_.channels());
77 for (int i = 0; i < audio_parameters_.channels(); ++i) 84 for (int i = 0; i < output_parameters_.channels(); ++i)
78 audio_data_.push_back(new float[audio_parameters_.frames_per_buffer()]); 85 audio_data_.push_back(new float[output_parameters_.frames_per_buffer()]);
79 86
80 fake_callback_.reset(new FakeAudioRenderCallback(audio_parameters_)); 87 fake_callback_.reset(new FakeAudioRenderCallback(output_parameters_));
81 } 88 }
82 89
83 void InitializeInputs(int count) { 90 void InitializeInputs(int count) {
84 for (int i = 0; i < count; ++i) { 91 for (int i = 0; i < count; ++i) {
85 scoped_refptr<AudioRendererMixerInput> mixer_input( 92 scoped_refptr<AudioRendererMixerInput> mixer_input(
86 new AudioRendererMixerInput(mixer_)); 93 new AudioRendererMixerInput(mixer_));
87 mixer_input->Initialize(audio_parameters_, fake_callback_.get()); 94 mixer_input->Initialize(input_parameters_, fake_callback_.get());
88 mixer_input->SetVolume(1.0f); 95 mixer_input->SetVolume(1.0f);
89 mixer_inputs_.push_back(mixer_input); 96 mixer_inputs_.push_back(mixer_input);
90 } 97 }
91 } 98 }
92 99
93 bool ValidateAudioData(int start_index, int frames, float check_value) { 100 bool ValidateAudioData(int start_index, int frames, float check_value) {
94 for (size_t i = 0; i < audio_data_.size(); ++i) { 101 for (size_t i = 0; i < audio_data_.size(); ++i) {
95 for (int j = start_index; j < frames; j++) { 102 for (int j = start_index; j < frames; j++) {
96 if (fabs(audio_data_[i][j] - check_value) > kEpsilon) { 103 if (fabs(audio_data_[i][j] - check_value) > kEpsilon) {
97 EXPECT_NEAR(check_value, audio_data_[i][j], kEpsilon) 104 EXPECT_NEAR(check_value, audio_data_[i][j], kEpsilon)
98 << " i=" << i << ", j=" << j; 105 << " i=" << i << ", j=" << j;
99 return false; 106 return false;
100 } 107 }
101 } 108 }
102 } 109 }
103 return true; 110 return true;
104 } 111 }
105 112
106 // Render audio_parameters_.frames_per_buffer() frames into |audio_data_| and 113 // Render input_parameters_.frames_per_buffer() frames into |audio_data_| and
107 // verify the result against |check_value|. 114 // verify the result against |check_value|.
108 bool RenderAndValidateAudioData(float check_value) { 115 bool RenderAndValidateAudioData(float check_value) {
109 int frames = mixer_callback_->Render( 116 int request_frames = output_parameters_.frames_per_buffer();
110 audio_data_, audio_parameters_.frames_per_buffer(), 0); 117 int frames = mixer_callback_->Render(audio_data_, request_frames, 0);
111 return frames == audio_parameters_.frames_per_buffer() && ValidateAudioData( 118 return frames == request_frames && ValidateAudioData(
112 0, audio_parameters_.frames_per_buffer(), check_value); 119 0, request_frames, check_value);
113 } 120 }
114 121
115 // Fill |audio_data_| fully with |value|. 122 // Fill |audio_data_| fully with |value|.
116 void FillAudioData(float value) { 123 void FillAudioData(float value) {
117 for (size_t i = 0; i < audio_data_.size(); ++i) 124 for (size_t i = 0; i < audio_data_.size(); ++i)
118 std::fill(audio_data_[i], 125 std::fill(audio_data_[i],
119 audio_data_[i] + audio_parameters_.frames_per_buffer(), value); 126 audio_data_[i] + output_parameters_.frames_per_buffer(), value);
120 } 127 }
121 128
122 // Verify silence when mixer inputs are in pre-Start() and post-Start(). 129 // Verify silence when mixer inputs are in pre-Start() and post-Start().
123 void StartTest(int inputs) { 130 void StartTest(int inputs) {
124 InitializeInputs(inputs); 131 InitializeInputs(inputs);
125 132
126 // Verify silence before any inputs have been started. Fill the buffer 133 // Verify silence before any inputs have been started. Fill the buffer
127 // before hand with non-zero data to ensure we get zeros back. 134 // before hand with non-zero data to ensure we get zeros back.
128 FillAudioData(1.0f); 135 FillAudioData(1.0f);
129 EXPECT_TRUE(RenderAndValidateAudioData(0.0f)); 136 EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 fake_callback_->fill_value() * total_scale)); 203 fake_callback_->fill_value() * total_scale));
197 } 204 }
198 205
199 for (size_t i = 0; i < mixer_inputs_.size(); ++i) 206 for (size_t i = 0; i < mixer_inputs_.size(); ++i)
200 mixer_inputs_[i]->Stop(); 207 mixer_inputs_[i]->Stop();
201 } 208 }
202 209
203 // Verify output when mixer inputs can only partially fulfill a Render(). 210 // Verify output when mixer inputs can only partially fulfill a Render().
204 void PlayPartialRenderTest(int inputs) { 211 void PlayPartialRenderTest(int inputs) {
205 InitializeInputs(inputs); 212 InitializeInputs(inputs);
206 int frames = audio_parameters_.frames_per_buffer(); 213 int frames = output_parameters_.frames_per_buffer();
207 214
208 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { 215 for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
209 mixer_inputs_[i]->Start(); 216 mixer_inputs_[i]->Start();
210 mixer_inputs_[i]->Play(); 217 mixer_inputs_[i]->Play();
211 } 218 }
212 219
213 // Verify a properly filled buffer when half filled (remainder zeroed). 220 // Verify a properly filled buffer when half filled (remainder zeroed).
214 fake_callback_->set_half_fill(true); 221 fake_callback_->set_half_fill(true);
215 for (int i = 0; i < kMixerCycles; ++i) { 222 for (int i = 0; i < kMixerCycles; ++i) {
216 fake_callback_->NextFillValue(); 223 fake_callback_->NextFillValue();
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 protected: 279 protected:
273 virtual ~AudioRendererMixerTest() { 280 virtual ~AudioRendererMixerTest() {
274 for (size_t i = 0; i < audio_data_.size(); ++i) 281 for (size_t i = 0; i < audio_data_.size(); ++i)
275 delete [] audio_data_[i]; 282 delete [] audio_data_[i];
276 } 283 }
277 284
278 scoped_refptr<MockAudioRendererSink> sink_; 285 scoped_refptr<MockAudioRendererSink> sink_;
279 scoped_refptr<AudioRendererMixer> mixer_; 286 scoped_refptr<AudioRendererMixer> mixer_;
280 AudioRendererSink::RenderCallback* mixer_callback_; 287 AudioRendererSink::RenderCallback* mixer_callback_;
281 scoped_ptr<FakeAudioRenderCallback> fake_callback_; 288 scoped_ptr<FakeAudioRenderCallback> fake_callback_;
282 AudioParameters audio_parameters_; 289 AudioParameters input_parameters_;
290 AudioParameters output_parameters_;
283 std::vector<float*> audio_data_; 291 std::vector<float*> audio_data_;
284 std::vector< scoped_refptr<AudioRendererMixerInput> > mixer_inputs_; 292 std::vector< scoped_refptr<AudioRendererMixerInput> > mixer_inputs_;
285 293
286 DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerTest); 294 DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerTest);
287 }; 295 };
288 296
289 // Verify a mixer with no inputs returns silence for all requested frames. 297 // Verify a mixer with no inputs returns silence for all requested frames.
290 TEST_F(AudioRendererMixerTest, NoInputs) { 298 TEST_F(AudioRendererMixerTest, NoInputs) {
291 FillAudioData(1.0f); 299 FillAudioData(1.0f);
292 EXPECT_TRUE(RenderAndValidateAudioData(0.0f)); 300 EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 383
376 for (size_t i = 1; i < mixer_inputs_.size(); i += 2) 384 for (size_t i = 1; i < mixer_inputs_.size(); i += 2)
377 mixer_inputs_[i]->Stop(); 385 mixer_inputs_[i]->Stop();
378 } 386 }
379 387
380 TEST_F(AudioRendererMixerTest, OnRenderError) { 388 TEST_F(AudioRendererMixerTest, OnRenderError) {
381 std::vector< scoped_refptr<AudioRendererMixerInput> > mixer_inputs; 389 std::vector< scoped_refptr<AudioRendererMixerInput> > mixer_inputs;
382 for (int i = 0; i < kMixerInputs; ++i) { 390 for (int i = 0; i < kMixerInputs; ++i) {
383 scoped_refptr<AudioRendererMixerInput> mixer_input( 391 scoped_refptr<AudioRendererMixerInput> mixer_input(
384 new AudioRendererMixerInput(mixer_)); 392 new AudioRendererMixerInput(mixer_));
385 mixer_input->Initialize(audio_parameters_, fake_callback_.get()); 393 mixer_input->Initialize(input_parameters_, fake_callback_.get());
386 mixer_input->SetVolume(1.0f); 394 mixer_input->SetVolume(1.0f);
387 mixer_input->Start(); 395 mixer_input->Start();
388 mixer_inputs_.push_back(mixer_input); 396 mixer_inputs_.push_back(mixer_input);
389 } 397 }
390 398
391 EXPECT_CALL(*fake_callback_, OnRenderError()).Times(kMixerInputs); 399 EXPECT_CALL(*fake_callback_, OnRenderError()).Times(kMixerInputs);
392 sink_->SimulateRenderError(); 400 sink_->SimulateRenderError();
393 for (int i = 0; i < kMixerInputs; ++i) 401 for (int i = 0; i < kMixerInputs; ++i)
394 mixer_inputs_[i]->Stop(); 402 mixer_inputs_[i]->Stop();
395 } 403 }
396 404
397 } // namespace media 405 } // namespace media
OLDNEW
« media/base/audio_renderer_mixer.cc ('K') | « media/base/audio_renderer_mixer_input_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698