Chromium Code Reviews| 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. | |
| 6 #define _USE_MATH_DEFINES | |
| 5 #include <cmath> | 7 #include <cmath> |
| 6 | 8 |
| 7 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 8 #include "media/audio/audio_util.h" | 10 #include "base/memory/scoped_vector.h" |
| 9 #include "media/base/audio_renderer_mixer.h" | 11 #include "media/base/audio_renderer_mixer.h" |
| 10 #include "media/base/audio_renderer_mixer_input.h" | 12 #include "media/base/audio_renderer_mixer_input.h" |
| 11 #include "media/base/fake_audio_render_callback.h" | 13 #include "media/base/fake_audio_render_callback.h" |
| 14 #include "media/base/mock_audio_renderer_sink.h" | |
| 12 #include "testing/gmock/include/gmock/gmock.h" | 15 #include "testing/gmock/include/gmock/gmock.h" |
| 13 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 14 | 17 |
| 15 namespace media { | 18 namespace media { |
| 16 | 19 |
| 17 // Parameters which control the many input case tests. | 20 // Parameters which control the many input case tests. |
| 18 static const int kMixerInputs = 64; | 21 static const int kMixerInputs = 8; |
| 19 static const int kMixerCycles = 32; | 22 static const int kMixerCycles = 3; |
| 20 | 23 |
| 24 // Parameters used for testing. | |
| 21 static const int kBitsPerChannel = 16; | 25 static const int kBitsPerChannel = 16; |
| 22 static const int kSampleRate = 48000; | |
| 23 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO; | 26 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO; |
| 27 static const int kHighLatencyBufferSize = 8192; | |
| 28 static const int kLowLatencyBufferSize = 256; | |
| 24 | 29 |
| 25 // Multiple rounds of addition result in precision loss with float values, so we | 30 // Number of full sine wave cycles for each Render() call. |
| 26 // need an epsilon such that if for all x f(x) = sum(x, m) and g(x) = m * x then | 31 static const int kSineCycles = 4; |
| 27 // fabs(f - g) < kEpsilon. The kEpsilon below has been tested with m < 128. | |
| 28 static const float kEpsilon = 0.00015f; | |
| 29 | 32 |
| 30 class MockAudioRendererSink : public AudioRendererSink { | 33 typedef std::tr1::tuple<int, int, double> AudioRendererMixerTestData; |
|
scherkus (not reviewing)
2012/07/12 23:02:52
AFAIK a struct *should* work here instead, which m
DaleCurtis
2012/07/12 23:16:29
I don't think we'd get nice error messages then. I
DaleCurtis
2012/07/13 00:01:25
Confirmed. I'll need to add an ostream() operator
scherkus (not reviewing)
2012/07/14 01:45:02
yeah that's what I figured -- your call
I wonder
| |
| 34 class AudioRendererMixerTestCase | |
| 35 : public testing::TestWithParam<AudioRendererMixerTestData> { | |
| 31 public: | 36 public: |
| 32 MOCK_METHOD0(Start, void()); | 37 AudioRendererMixerTestCase() |
| 33 MOCK_METHOD0(Stop, void()); | 38 : epsilon_(std::tr1::get<2>(GetParam())), |
| 34 MOCK_METHOD1(Pause, void(bool flush)); | 39 half_fill_(false) { |
| 35 MOCK_METHOD0(Play, void()); | 40 // Create input and output parameters based on test parameters. |
| 36 MOCK_METHOD1(SetPlaybackRate, void(float rate)); | 41 input_parameters_ = AudioParameters( |
| 37 MOCK_METHOD1(SetVolume, bool(double volume)); | 42 AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, |
| 38 MOCK_METHOD1(GetVolume, void(double* volume)); | 43 std::tr1::get<0>(GetParam()), kBitsPerChannel, kHighLatencyBufferSize); |
| 44 output_parameters_ = AudioParameters( | |
| 45 AudioParameters::AUDIO_PCM_LOW_LATENCY, kChannelLayout, | |
| 46 std::tr1::get<1>(GetParam()), 16, kLowLatencyBufferSize); | |
| 39 | 47 |
| 40 void Initialize(const media::AudioParameters& params, | |
| 41 AudioRendererSink::RenderCallback* renderer) OVERRIDE { | |
| 42 // TODO(dalecurtis): Once we have resampling we need to ensure we are given | |
| 43 // an AudioParameters which reflects the hardware settings. | |
| 44 callback_ = renderer; | |
| 45 }; | |
| 46 | |
| 47 AudioRendererSink::RenderCallback* callback() { | |
| 48 return callback_; | |
| 49 } | |
| 50 | |
| 51 void SimulateRenderError() { | |
| 52 callback_->OnRenderError(); | |
| 53 } | |
| 54 | |
| 55 protected: | |
| 56 virtual ~MockAudioRendererSink() {} | |
| 57 | |
| 58 AudioRendererSink::RenderCallback* callback_; | |
| 59 }; | |
| 60 | |
| 61 class AudioRendererMixerTest : public ::testing::Test { | |
| 62 public: | |
| 63 AudioRendererMixerTest() { | |
| 64 audio_parameters_ = AudioParameters( | |
| 65 AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate, | |
| 66 kBitsPerChannel, GetHighLatencyOutputBufferSize(kSampleRate)); | |
| 67 sink_ = new MockAudioRendererSink(); | 48 sink_ = new MockAudioRendererSink(); |
| 68 EXPECT_CALL(*sink_, Start()); | 49 EXPECT_CALL(*sink_, Start()); |
| 69 EXPECT_CALL(*sink_, Stop()); | 50 EXPECT_CALL(*sink_, Stop()); |
| 70 | 51 |
| 71 mixer_ = new AudioRendererMixer(audio_parameters_, sink_); | 52 mixer_ = new AudioRendererMixer( |
| 53 input_parameters_, output_parameters_, sink_); | |
| 72 mixer_callback_ = sink_->callback(); | 54 mixer_callback_ = sink_->callback(); |
| 73 | 55 |
| 74 // TODO(dalecurtis): If we switch to AVX/SSE optimization, we'll need to | 56 // 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. | 57 // allocate these on 32-byte boundaries and ensure they're sized % 32 bytes. |
| 76 audio_data_.reserve(audio_parameters_.channels()); | 58 audio_data_.reserve(output_parameters_.channels()); |
| 77 for (int i = 0; i < audio_parameters_.channels(); ++i) | 59 for (int i = 0; i < output_parameters_.channels(); ++i) |
| 78 audio_data_.push_back(new float[audio_parameters_.frames_per_buffer()]); | 60 audio_data_.push_back(new float[output_parameters_.frames_per_buffer()]); |
| 79 | 61 |
| 80 fake_callback_.reset(new FakeAudioRenderCallback(audio_parameters_)); | 62 // TODO(dalecurtis): If we switch to AVX/SSE optimization, we'll need to |
| 63 // allocate these on 32-byte boundaries and ensure they're sized % 32 bytes. | |
| 64 expected_audio_data_.reserve(output_parameters_.channels()); | |
| 65 for (int i = 0; i < output_parameters_.channels(); ++i) { | |
| 66 expected_audio_data_.push_back( | |
| 67 new float[output_parameters_.frames_per_buffer()]); | |
| 68 } | |
| 69 | |
| 70 // Allocate one callback for generating expected results. | |
| 71 double step = kSineCycles / static_cast<double>( | |
| 72 output_parameters_.frames_per_buffer()); | |
| 73 expected_callback_.reset(new FakeAudioRenderCallback(step)); | |
| 81 } | 74 } |
| 82 | 75 |
| 83 void InitializeInputs(int count) { | 76 void InitializeInputs(int count) { |
| 77 mixer_inputs_.reserve(count); | |
| 78 fake_callbacks_.reserve(count); | |
| 79 | |
| 80 // Setup FakeAudioRenderCallback step to compensate for resampling. | |
| 81 double scale_factor = input_parameters_.sample_rate() | |
| 82 / static_cast<double>(output_parameters_.sample_rate()); | |
| 83 double step = kSineCycles / (scale_factor * | |
| 84 static_cast<double>(output_parameters_.frames_per_buffer())); | |
| 85 | |
| 84 for (int i = 0; i < count; ++i) { | 86 for (int i = 0; i < count; ++i) { |
| 85 scoped_refptr<AudioRendererMixerInput> mixer_input( | 87 fake_callbacks_.push_back(new FakeAudioRenderCallback(step)); |
| 86 new AudioRendererMixerInput(mixer_)); | 88 mixer_inputs_.push_back(new AudioRendererMixerInput(mixer_)); |
| 87 mixer_input->Initialize(audio_parameters_, fake_callback_.get()); | 89 mixer_inputs_[i]->Initialize(input_parameters_, fake_callbacks_[i]); |
| 88 mixer_input->SetVolume(1.0f); | 90 mixer_inputs_[i]->SetVolume(1.0f); |
| 89 mixer_inputs_.push_back(mixer_input); | |
| 90 } | 91 } |
| 91 } | 92 } |
| 92 | 93 |
| 93 bool ValidateAudioData(int start_index, int frames, float check_value) { | 94 bool ValidateAudioData(int index, int frames, float scale) { |
| 94 for (size_t i = 0; i < audio_data_.size(); ++i) { | 95 for (size_t i = 0; i < audio_data_.size(); ++i) { |
| 95 for (int j = start_index; j < frames; j++) { | 96 for (int j = index; j < frames; j++) { |
| 96 if (fabs(audio_data_[i][j] - check_value) > kEpsilon) { | 97 double error = fabs( |
| 97 EXPECT_NEAR(check_value, audio_data_[i][j], kEpsilon) | 98 audio_data_[i][j] - expected_audio_data_[i][j] * scale); |
| 99 if (error > epsilon_) { | |
| 100 EXPECT_NEAR( | |
| 101 expected_audio_data_[i][j] * scale, audio_data_[i][j], epsilon_) | |
| 98 << " i=" << i << ", j=" << j; | 102 << " i=" << i << ", j=" << j; |
| 99 return false; | 103 return false; |
| 100 } | 104 } |
| 101 } | 105 } |
| 102 } | 106 } |
| 103 return true; | 107 return true; |
| 104 } | 108 } |
| 105 | 109 |
| 106 // Render audio_parameters_.frames_per_buffer() frames into |audio_data_| and | 110 bool RenderAndValidateAudioData(float scale) { |
| 107 // verify the result against |check_value|. | 111 int request_frames = output_parameters_.frames_per_buffer(); |
| 108 bool RenderAndValidateAudioData(float check_value) { | 112 |
| 109 int frames = mixer_callback_->Render( | 113 // Half fill won't be exactly half when resampling since the resampler |
| 110 audio_data_, audio_parameters_.frames_per_buffer(), 0); | 114 // will have enough data to fill out more of the buffer based on its |
| 111 return frames == audio_parameters_.frames_per_buffer() && ValidateAudioData( | 115 // internal buffer and kernel size. So special case some of the checks. |
| 112 0, audio_parameters_.frames_per_buffer(), check_value); | 116 bool resampling = input_parameters_.sample_rate() |
| 117 != output_parameters_.sample_rate(); | |
| 118 | |
| 119 if (half_fill_) { | |
| 120 for (size_t i = 0; i < fake_callbacks_.size(); ++i) | |
| 121 fake_callbacks_[i]->set_half_fill(true); | |
| 122 expected_callback_->set_half_fill(true); | |
| 123 } | |
| 124 | |
| 125 // Render actual audio data. | |
| 126 int frames = mixer_callback_->Render(audio_data_, request_frames, 0); | |
| 127 if (frames != request_frames) | |
| 128 return false; | |
| 129 | |
| 130 // Render expected audio data (without scaling). | |
| 131 expected_callback_->Render(expected_audio_data_, request_frames, 0); | |
| 132 | |
| 133 if (half_fill_) { | |
| 134 // Verify first half of audio data for both resampling and non-resampling. | |
| 135 if (!ValidateAudioData(0, frames / 2, scale)) | |
| 136 return false; | |
| 137 // Verify silence in the second half if we're not resampling. | |
| 138 if (!resampling) | |
| 139 return ValidateAudioData(frames / 2, frames, 0); | |
| 140 return true; | |
| 141 } else { | |
| 142 return ValidateAudioData(0, frames, scale); | |
| 143 } | |
| 113 } | 144 } |
| 114 | 145 |
| 115 // Fill |audio_data_| fully with |value|. | 146 // Fill |audio_data_| fully with |value|. |
| 116 void FillAudioData(float value) { | 147 void FillAudioData(float value) { |
| 117 for (size_t i = 0; i < audio_data_.size(); ++i) | 148 for (size_t i = 0; i < audio_data_.size(); ++i) |
| 118 std::fill(audio_data_[i], | 149 std::fill(audio_data_[i], |
| 119 audio_data_[i] + audio_parameters_.frames_per_buffer(), value); | 150 audio_data_[i] + output_parameters_.frames_per_buffer(), value); |
| 120 } | 151 } |
| 121 | 152 |
| 122 // Verify silence when mixer inputs are in pre-Start() and post-Start(). | 153 // Verify silence when mixer inputs are in pre-Start() and post-Start(). |
| 123 void StartTest(int inputs) { | 154 void StartTest(int inputs) { |
| 124 InitializeInputs(inputs); | 155 InitializeInputs(inputs); |
| 125 | 156 |
| 126 // Verify silence before any inputs have been started. Fill the buffer | 157 // Verify silence before any inputs have been started. Fill the buffer |
| 127 // before hand with non-zero data to ensure we get zeros back. | 158 // before hand with non-zero data to ensure we get zeros back. |
| 128 FillAudioData(1.0f); | 159 FillAudioData(1.0f); |
| 129 EXPECT_TRUE(RenderAndValidateAudioData(0.0f)); | 160 EXPECT_TRUE(RenderAndValidateAudioData(0.0f)); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 141 EXPECT_TRUE(RenderAndValidateAudioData(0.0f)); | 172 EXPECT_TRUE(RenderAndValidateAudioData(0.0f)); |
| 142 | 173 |
| 143 for (size_t i = 0; i < mixer_inputs_.size(); ++i) | 174 for (size_t i = 0; i < mixer_inputs_.size(); ++i) |
| 144 mixer_inputs_[i]->Stop(); | 175 mixer_inputs_[i]->Stop(); |
| 145 } | 176 } |
| 146 | 177 |
| 147 // Verify output when mixer inputs are in post-Play() state. | 178 // Verify output when mixer inputs are in post-Play() state. |
| 148 void PlayTest(int inputs) { | 179 void PlayTest(int inputs) { |
| 149 InitializeInputs(inputs); | 180 InitializeInputs(inputs); |
| 150 | 181 |
| 151 for (size_t i = 0; i < mixer_inputs_.size(); ++i) | 182 // Play() all mixer inputs and ensure we get the right values. |
| 183 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { | |
| 152 mixer_inputs_[i]->Start(); | 184 mixer_inputs_[i]->Start(); |
| 153 | |
| 154 // Play() all even numbered mixer inputs and ensure we get the right value. | |
| 155 for (size_t i = 0; i < mixer_inputs_.size(); i += 2) | |
| 156 mixer_inputs_[i]->Play(); | 185 mixer_inputs_[i]->Play(); |
| 157 for (int i = 0; i < kMixerCycles; ++i) { | |
| 158 fake_callback_->NextFillValue(); | |
| 159 ASSERT_TRUE(RenderAndValidateAudioData( | |
| 160 fake_callback_->fill_value() * std::max( | |
| 161 mixer_inputs_.size() / 2, static_cast<size_t>(1)))); | |
| 162 } | 186 } |
| 163 | 187 |
| 164 // Play() all mixer inputs and ensure we still get the right values. | 188 for (int i = 0; i < kMixerCycles; ++i) |
| 165 for (size_t i = 1; i < mixer_inputs_.size(); i += 2) | 189 ASSERT_TRUE(RenderAndValidateAudioData(mixer_inputs_.size())); |
| 166 mixer_inputs_[i]->Play(); | |
| 167 for (int i = 0; i < kMixerCycles; ++i) { | |
| 168 fake_callback_->NextFillValue(); | |
| 169 ASSERT_TRUE(RenderAndValidateAudioData( | |
| 170 fake_callback_->fill_value() * mixer_inputs_.size())); | |
| 171 } | |
| 172 | 190 |
| 173 for (size_t i = 0; i < mixer_inputs_.size(); ++i) | 191 for (size_t i = 0; i < mixer_inputs_.size(); ++i) |
| 174 mixer_inputs_[i]->Stop(); | 192 mixer_inputs_[i]->Stop(); |
| 175 } | 193 } |
| 176 | 194 |
| 177 // Verify volume adjusted output when mixer inputs are in post-Play() state. | 195 // Verify volume adjusted output when mixer inputs are in post-Play() state. |
| 178 void PlayVolumeAdjustedTest(int inputs) { | 196 void PlayVolumeAdjustedTest(int inputs) { |
| 179 InitializeInputs(inputs); | 197 InitializeInputs(inputs); |
| 180 | 198 |
| 181 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { | 199 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { |
| 182 mixer_inputs_[i]->Start(); | 200 mixer_inputs_[i]->Start(); |
| 183 mixer_inputs_[i]->Play(); | 201 mixer_inputs_[i]->Play(); |
| 184 } | 202 } |
| 185 | 203 |
| 186 // Set a different volume for each mixer input and verify the results. | 204 // Set a different volume for each mixer input and verify the results. |
| 187 float total_scale = 0; | 205 float total_scale = 0; |
| 188 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { | 206 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { |
| 189 float volume = static_cast<float>(i) / mixer_inputs_.size(); | 207 float volume = static_cast<float>(i) / mixer_inputs_.size(); |
| 190 total_scale += volume; | 208 total_scale += volume; |
| 191 EXPECT_TRUE(mixer_inputs_[i]->SetVolume(volume)); | 209 EXPECT_TRUE(mixer_inputs_[i]->SetVolume(volume)); |
| 192 } | 210 } |
| 193 for (int i = 0; i < kMixerCycles; ++i) { | 211 for (int i = 0; i < kMixerCycles; ++i) |
| 194 fake_callback_->NextFillValue(); | 212 ASSERT_TRUE(RenderAndValidateAudioData(total_scale)); |
| 195 ASSERT_TRUE(RenderAndValidateAudioData( | |
| 196 fake_callback_->fill_value() * total_scale)); | |
| 197 } | |
| 198 | 213 |
| 199 for (size_t i = 0; i < mixer_inputs_.size(); ++i) | 214 for (size_t i = 0; i < mixer_inputs_.size(); ++i) |
| 200 mixer_inputs_[i]->Stop(); | 215 mixer_inputs_[i]->Stop(); |
| 201 } | 216 } |
| 202 | 217 |
| 203 // Verify output when mixer inputs can only partially fulfill a Render(). | 218 // Verify output when mixer inputs can only partially fulfill a Render(). |
| 204 void PlayPartialRenderTest(int inputs) { | 219 void PlayPartialRenderTest(int inputs) { |
| 205 InitializeInputs(inputs); | 220 InitializeInputs(inputs); |
| 206 int frames = audio_parameters_.frames_per_buffer(); | |
| 207 | 221 |
| 208 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { | 222 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { |
| 209 mixer_inputs_[i]->Start(); | 223 mixer_inputs_[i]->Start(); |
| 210 mixer_inputs_[i]->Play(); | 224 mixer_inputs_[i]->Play(); |
| 211 } | 225 } |
| 212 | 226 |
| 213 // Verify a properly filled buffer when half filled (remainder zeroed). | 227 // Verify a properly filled buffer when half filled (remainder zeroed). |
| 214 fake_callback_->set_half_fill(true); | 228 half_fill_ = true; |
| 215 for (int i = 0; i < kMixerCycles; ++i) { | 229 ASSERT_TRUE(RenderAndValidateAudioData(mixer_inputs_.size())); |
| 216 fake_callback_->NextFillValue(); | |
| 217 ASSERT_EQ(mixer_callback_->Render(audio_data_, frames, 0), frames); | |
| 218 ASSERT_TRUE(ValidateAudioData( | |
| 219 0, frames / 2, fake_callback_->fill_value() * mixer_inputs_.size())); | |
| 220 ASSERT_TRUE(ValidateAudioData( | |
| 221 frames / 2, frames, 0.0f)); | |
| 222 } | |
| 223 fake_callback_->set_half_fill(false); | |
| 224 | 230 |
| 225 for (size_t i = 0; i < mixer_inputs_.size(); ++i) | 231 for (size_t i = 0; i < mixer_inputs_.size(); ++i) |
| 226 mixer_inputs_[i]->Stop(); | 232 mixer_inputs_[i]->Stop(); |
| 227 } | 233 } |
| 228 | 234 |
| 229 // Verify output when mixer inputs are in Pause() state. | 235 // Verify output when mixer inputs are in Pause() state. |
| 230 void PauseTest(int inputs) { | 236 void PauseTest(int inputs) { |
| 231 InitializeInputs(inputs); | 237 InitializeInputs(inputs); |
| 232 | 238 |
| 233 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { | 239 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { |
| 234 mixer_inputs_[i]->Start(); | 240 mixer_inputs_[i]->Start(); |
| 235 mixer_inputs_[i]->Play(); | 241 mixer_inputs_[i]->Play(); |
| 236 } | 242 } |
| 237 | 243 |
| 238 // Pause() all even numbered mixer inputs and ensure we get the right value. | 244 // Pause() all even numbered mixer inputs and ensure we get the right value. |
| 239 for (size_t i = 0; i < mixer_inputs_.size(); i += 2) | 245 for (size_t i = 0; i < mixer_inputs_.size(); i += 2) |
| 240 mixer_inputs_[i]->Pause(false); | 246 mixer_inputs_[i]->Pause(false); |
| 241 for (int i = 0; i < kMixerCycles; ++i) { | 247 for (int i = 0; i < kMixerCycles; ++i) |
| 242 fake_callback_->NextFillValue(); | 248 ASSERT_TRUE(RenderAndValidateAudioData(mixer_inputs_.size() / 2)); |
| 243 ASSERT_TRUE(RenderAndValidateAudioData( | |
| 244 fake_callback_->fill_value() * (mixer_inputs_.size() / 2))); | |
| 245 } | |
| 246 | |
| 247 // Pause() all the inputs and verify we get silence back. | |
| 248 for (size_t i = 1; i < mixer_inputs_.size(); i += 2) | |
| 249 mixer_inputs_[i]->Pause(false); | |
| 250 FillAudioData(1.0f); | |
| 251 EXPECT_TRUE(RenderAndValidateAudioData(0.0f)); | |
| 252 | 249 |
| 253 for (size_t i = 0; i < mixer_inputs_.size(); ++i) | 250 for (size_t i = 0; i < mixer_inputs_.size(); ++i) |
| 254 mixer_inputs_[i]->Stop(); | 251 mixer_inputs_[i]->Stop(); |
| 255 } | 252 } |
| 256 | 253 |
| 257 // Verify output when mixer inputs are in post-Stop() state. | 254 // Verify output when mixer inputs are in post-Stop() state. |
| 258 void StopTest(int inputs) { | 255 void StopTest(int inputs) { |
| 259 InitializeInputs(inputs); | 256 InitializeInputs(inputs); |
| 260 | 257 |
| 261 // Start() and Stop() all inputs. | 258 // Start() and Stop() all inputs. |
| 262 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { | 259 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { |
| 263 mixer_inputs_[i]->Start(); | 260 mixer_inputs_[i]->Start(); |
| 264 mixer_inputs_[i]->Stop(); | 261 mixer_inputs_[i]->Stop(); |
| 265 } | 262 } |
| 266 | 263 |
| 267 // Verify we get silence back; fill |audio_data_| before hand to be sure. | 264 // Verify we get silence back; fill |audio_data_| before hand to be sure. |
| 268 FillAudioData(1.0f); | 265 FillAudioData(1.0f); |
| 269 EXPECT_TRUE(RenderAndValidateAudioData(0.0f)); | 266 EXPECT_TRUE(RenderAndValidateAudioData(0.0f)); |
| 270 } | 267 } |
| 271 | 268 |
| 272 protected: | 269 protected: |
| 273 virtual ~AudioRendererMixerTest() { | 270 virtual ~AudioRendererMixerTestCase() { |
| 274 for (size_t i = 0; i < audio_data_.size(); ++i) | 271 for (size_t i = 0; i < audio_data_.size(); ++i) |
| 275 delete [] audio_data_[i]; | 272 delete [] audio_data_[i]; |
| 276 } | 273 } |
| 277 | 274 |
| 278 scoped_refptr<MockAudioRendererSink> sink_; | 275 scoped_refptr<MockAudioRendererSink> sink_; |
| 279 scoped_refptr<AudioRendererMixer> mixer_; | 276 scoped_refptr<AudioRendererMixer> mixer_; |
| 280 AudioRendererSink::RenderCallback* mixer_callback_; | 277 AudioRendererSink::RenderCallback* mixer_callback_; |
| 281 scoped_ptr<FakeAudioRenderCallback> fake_callback_; | 278 AudioParameters input_parameters_; |
| 282 AudioParameters audio_parameters_; | 279 AudioParameters output_parameters_; |
| 283 std::vector<float*> audio_data_; | 280 std::vector<float*> audio_data_; |
| 281 std::vector<float*> expected_audio_data_; | |
| 284 std::vector< scoped_refptr<AudioRendererMixerInput> > mixer_inputs_; | 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_; | |
| 285 | 287 |
| 286 DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerTest); | 288 DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerTestCase); |
| 287 }; | 289 }; |
| 288 | 290 |
| 289 // Verify a mixer with no inputs returns silence for all requested frames. | 291 // Verify a mixer with no inputs returns silence for all requested frames. |
| 290 TEST_F(AudioRendererMixerTest, NoInputs) { | 292 TEST_P(AudioRendererMixerTestCase, NoInputs) { |
| 291 FillAudioData(1.0f); | 293 FillAudioData(1.0f); |
| 292 EXPECT_TRUE(RenderAndValidateAudioData(0.0f)); | 294 EXPECT_TRUE(RenderAndValidateAudioData(0.0f)); |
| 293 } | 295 } |
| 294 | 296 |
| 295 // Test mixer output with one input in the pre-Start() and post-Start() state. | 297 // Test mixer output with one input in the pre-Start() and post-Start() state. |
| 296 TEST_F(AudioRendererMixerTest, OneInputStart) { | 298 TEST_P(AudioRendererMixerTestCase, OneInputStart) { |
| 297 StartTest(1); | 299 StartTest(1); |
| 298 } | 300 } |
| 299 | 301 |
| 300 // Test mixer output with many inputs in the pre-Start() and post-Start() state. | 302 // Test mixer output with many inputs in the pre-Start() and post-Start() state. |
| 301 TEST_F(AudioRendererMixerTest, ManyInputStart) { | 303 TEST_P(AudioRendererMixerTestCase, ManyInputStart) { |
| 302 StartTest(kMixerInputs); | 304 StartTest(kMixerInputs); |
| 303 } | 305 } |
| 304 | 306 |
| 305 // Test mixer output with one input in the post-Play() state. | 307 // Test mixer output with one input in the post-Play() state. |
| 306 TEST_F(AudioRendererMixerTest, OneInputPlay) { | 308 TEST_P(AudioRendererMixerTestCase, OneInputPlay) { |
| 307 PlayTest(1); | 309 PlayTest(1); |
| 308 } | 310 } |
| 309 | 311 |
| 310 // Test mixer output with many inputs in the post-Play() state. | 312 // Test mixer output with many inputs in the post-Play() state. |
| 311 TEST_F(AudioRendererMixerTest, ManyInputPlay) { | 313 TEST_P(AudioRendererMixerTestCase, ManyInputPlay) { |
| 312 PlayTest(kMixerInputs); | 314 PlayTest(kMixerInputs); |
| 313 } | 315 } |
| 314 | 316 |
| 315 // Test volume adjusted mixer output with one input in the post-Play() state. | 317 // Test volume adjusted mixer output with one input in the post-Play() state. |
| 316 TEST_F(AudioRendererMixerTest, OneInputPlayVolumeAdjusted) { | 318 TEST_P(AudioRendererMixerTestCase, OneInputPlayVolumeAdjusted) { |
| 317 PlayVolumeAdjustedTest(1); | 319 PlayVolumeAdjustedTest(1); |
| 318 } | 320 } |
| 319 | 321 |
| 320 // Test volume adjusted mixer output with many inputs in the post-Play() state. | 322 // Test volume adjusted mixer output with many inputs in the post-Play() state. |
| 321 TEST_F(AudioRendererMixerTest, ManyInputPlayVolumeAdjusted) { | 323 TEST_P(AudioRendererMixerTestCase, ManyInputPlayVolumeAdjusted) { |
| 322 PlayVolumeAdjustedTest(kMixerInputs); | 324 PlayVolumeAdjustedTest(kMixerInputs); |
| 323 } | 325 } |
| 324 | 326 |
| 325 // Test mixer output with one input and partial Render() in post-Play() state. | 327 // Test mixer output with one input and partial Render() in post-Play() state. |
| 326 TEST_F(AudioRendererMixerTest, OneInputPlayPartialRender) { | 328 TEST_P(AudioRendererMixerTestCase, OneInputPlayPartialRender) { |
| 327 PlayPartialRenderTest(1); | 329 PlayPartialRenderTest(1); |
| 328 } | 330 } |
| 329 | 331 |
| 330 // Test mixer output with many inputs and partial Render() in post-Play() state. | 332 // Test mixer output with many inputs and partial Render() in post-Play() state. |
| 331 TEST_F(AudioRendererMixerTest, ManyInputPlayPartialRender) { | 333 TEST_P(AudioRendererMixerTestCase, ManyInputPlayPartialRender) { |
| 332 PlayPartialRenderTest(kMixerInputs); | 334 PlayPartialRenderTest(kMixerInputs); |
| 333 } | 335 } |
| 334 | 336 |
| 335 // Test mixer output with one input in the post-Pause() state. | 337 // Test mixer output with one input in the post-Pause() state. |
| 336 TEST_F(AudioRendererMixerTest, OneInputPause) { | 338 TEST_P(AudioRendererMixerTestCase, OneInputPause) { |
| 337 PauseTest(1); | 339 PauseTest(1); |
| 338 } | 340 } |
| 339 | 341 |
| 340 // Test mixer output with many inputs in the post-Pause() state. | 342 // Test mixer output with many inputs in the post-Pause() state. |
| 341 TEST_F(AudioRendererMixerTest, ManyInputPause) { | 343 TEST_P(AudioRendererMixerTestCase, ManyInputPause) { |
| 342 PauseTest(kMixerInputs); | 344 PauseTest(kMixerInputs); |
| 343 } | 345 } |
| 344 | 346 |
| 345 // Test mixer output with one input in the post-Stop() state. | 347 // Test mixer output with one input in the post-Stop() state. |
| 346 TEST_F(AudioRendererMixerTest, OneInputStop) { | 348 TEST_P(AudioRendererMixerTestCase, OneInputStop) { |
| 347 StopTest(1); | 349 StopTest(1); |
| 348 } | 350 } |
| 349 | 351 |
| 350 // Test mixer output with many inputs in the post-Stop() state. | 352 // Test mixer output with many inputs in the post-Stop() state. |
| 351 TEST_F(AudioRendererMixerTest, ManyInputStop) { | 353 TEST_P(AudioRendererMixerTestCase, ManyInputStop) { |
| 352 StopTest(kMixerInputs); | 354 StopTest(kMixerInputs); |
| 353 } | 355 } |
| 354 | 356 |
| 355 // Test mixer with many inputs in mixed post-Stop() and post-Play() states. | 357 // Test mixer with many inputs in mixed post-Stop() and post-Play() states. |
| 356 TEST_F(AudioRendererMixerTest, ManyInputMixedStopPlay) { | 358 TEST_P(AudioRendererMixerTestCase, ManyInputMixedStopPlay) { |
| 357 InitializeInputs(kMixerInputs); | 359 InitializeInputs(kMixerInputs); |
| 358 | 360 |
| 359 // Start() all inputs. | 361 // Start() all inputs. |
| 360 for (size_t i = 0; i < mixer_inputs_.size(); ++i) | 362 for (size_t i = 0; i < mixer_inputs_.size(); ++i) |
| 361 mixer_inputs_[i]->Start(); | 363 mixer_inputs_[i]->Start(); |
| 362 | 364 |
| 363 // Stop() all even numbered mixer inputs and Play() all odd numbered inputs | 365 // Stop() all even numbered mixer inputs and Play() all odd numbered inputs |
| 364 // and ensure we get the right value. | 366 // and ensure we get the right value. |
| 365 for (size_t i = 1; i < mixer_inputs_.size(); i += 2) { | 367 for (size_t i = 1; i < mixer_inputs_.size(); i += 2) { |
| 366 mixer_inputs_[i - 1]->Stop(); | 368 mixer_inputs_[i - 1]->Stop(); |
| 367 mixer_inputs_[i]->Play(); | 369 mixer_inputs_[i]->Play(); |
| 368 } | 370 } |
| 369 for (int i = 0; i < kMixerCycles; ++i) { | 371 ASSERT_TRUE(RenderAndValidateAudioData(std::max( |
| 370 fake_callback_->NextFillValue(); | 372 mixer_inputs_.size() / 2, static_cast<size_t>(1)))); |
| 371 ASSERT_TRUE(RenderAndValidateAudioData( | |
| 372 fake_callback_->fill_value() * std::max( | |
| 373 mixer_inputs_.size() / 2, static_cast<size_t>(1)))); | |
| 374 } | |
| 375 | 373 |
| 376 for (size_t i = 1; i < mixer_inputs_.size(); i += 2) | 374 for (size_t i = 1; i < mixer_inputs_.size(); i += 2) |
| 377 mixer_inputs_[i]->Stop(); | 375 mixer_inputs_[i]->Stop(); |
| 378 } | 376 } |
| 379 | 377 |
| 380 TEST_F(AudioRendererMixerTest, OnRenderError) { | 378 TEST_P(AudioRendererMixerTestCase, OnRenderError) { |
| 381 std::vector< scoped_refptr<AudioRendererMixerInput> > mixer_inputs; | 379 InitializeInputs(kMixerInputs); |
| 382 for (int i = 0; i < kMixerInputs; ++i) { | 380 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { |
| 383 scoped_refptr<AudioRendererMixerInput> mixer_input( | 381 mixer_inputs_[i]->Start(); |
| 384 new AudioRendererMixerInput(mixer_)); | 382 EXPECT_CALL(*fake_callbacks_[i], OnRenderError()).Times(1); |
| 385 mixer_input->Initialize(audio_parameters_, fake_callback_.get()); | |
| 386 mixer_input->SetVolume(1.0f); | |
| 387 mixer_input->Start(); | |
| 388 mixer_inputs_.push_back(mixer_input); | |
| 389 } | 383 } |
| 390 | 384 |
| 391 EXPECT_CALL(*fake_callback_, OnRenderError()).Times(kMixerInputs); | 385 mixer_callback_->OnRenderError(); |
| 392 sink_->SimulateRenderError(); | 386 for (size_t i = 0; i < mixer_inputs_.size(); ++i) |
| 393 for (int i = 0; i < kMixerInputs; ++i) | |
| 394 mixer_inputs_[i]->Stop(); | 387 mixer_inputs_[i]->Stop(); |
| 395 } | 388 } |
| 396 | 389 |
| 390 INSTANTIATE_TEST_CASE_P( | |
| 391 AudioRendererMixerTest, AudioRendererMixerTestCase, testing::Values( | |
| 392 // No resampling. | |
| 393 std::tr1::make_tuple(44100, 44100, 0.000000477), | |
| 394 | |
| 395 // Upsampling. | |
| 396 std::tr1::make_tuple(44100, 48000, 0.0329405), | |
| 397 | |
| 398 // Downsampling. | |
| 399 std::tr1::make_tuple(48000, 41000, 0.0410239))); | |
| 400 | |
| 397 } // namespace media | 401 } // namespace media |
| OLD | NEW |