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

Unified 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 side-by-side diff with in-line comments
Download patch
« 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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/base/audio_renderer_mixer_unittest.cc
diff --git a/media/base/audio_renderer_mixer_unittest.cc b/media/base/audio_renderer_mixer_unittest.cc
index b218fa0410070d9d2c765f49bff06453eaa48f1f..8d2b5d43a80309f44e24b75ac5a3493ee96c3ea5 100644
--- a/media/base/audio_renderer_mixer_unittest.cc
+++ b/media/base/audio_renderer_mixer_unittest.cc
@@ -23,6 +23,7 @@ namespace media {
// Parameters which control the many input case tests.
const int kMixerInputs = 8;
+const int kOddMixerInputs = 7;
const int kMixerCycles = 3;
// Parameters used for testing.
@@ -34,22 +35,37 @@ const int kLowLatencyBufferSize = 256;
// Number of full sine wave cycles for each Render() call.
const int kSineCycles = 4;
-// Default device ID
+// Default device ID.
const std::string kDefaultDeviceId;
const url::Origin kDefaultSecurityOrigin;
-// Tuple of <input sampling rate, output sampling rate, epsilon>.
-typedef std::tr1::tuple<int, int, double> AudioRendererMixerTestData;
+// Input sample frequencies for testing.
+std::vector<int> kTestInputLower(1, 44100);
+std::vector<int> kTestInputHigher(1, 48000);
+const int kSampleRates[] = {22050, 44100, 48000};
+std::vector<int> kTestInput3Rates(kSampleRates,
+ kSampleRates +
+ sizeof(kSampleRates) /
+ sizeof(kSampleRates[0]));
+
+// Tuple of <input sampling rates, output sampling rate, epsilon>.
+typedef std::tr1::tuple<std::vector<int>, int, double>
+ AudioRendererMixerTestData;
+
class AudioRendererMixerTest
: public testing::TestWithParam<AudioRendererMixerTestData> {
public:
AudioRendererMixerTest()
: epsilon_(std::tr1::get<2>(GetParam())),
half_fill_(false) {
- // Create input and output parameters based on test parameters.
- input_parameters_ = AudioParameters(
- AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
- std::tr1::get<0>(GetParam()), kBitsPerChannel, kHighLatencyBufferSize);
+ // Create input parameters based on test parameters.
+ const std::vector<int>& sample_rates(std::tr1::get<0>(GetParam()));
+ for (size_t i = 0; i < sample_rates.size(); ++i)
+ input_parameters_.push_back(AudioParameters(
+ AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, sample_rates[i],
+ kBitsPerChannel, kHighLatencyBufferSize));
+
+ // Create output parameters based on test parameters.
output_parameters_ = AudioParameters(
AudioParameters::AUDIO_PCM_LOW_LATENCY, kChannelLayout,
std::tr1::get<1>(GetParam()), 16, kLowLatencyBufferSize);
@@ -58,8 +74,7 @@ class AudioRendererMixerTest
EXPECT_CALL(*sink_.get(), Start());
EXPECT_CALL(*sink_.get(), Stop());
- mixer_.reset(new AudioRendererMixer(
- input_parameters_, output_parameters_, sink_));
+ mixer_.reset(new AudioRendererMixer(output_parameters_, sink_));
mixer_callback_ = sink_->callback();
audio_bus_ = AudioBus::Create(output_parameters_);
@@ -83,28 +98,35 @@ class AudioRendererMixerTest
const std::string&,
const url::Origin&));
- void InitializeInputs(int count) {
- mixer_inputs_.reserve(count);
- fake_callbacks_.reserve(count);
-
- // Setup FakeAudioRenderCallback step to compensate for resampling.
- double scale_factor = input_parameters_.sample_rate() /
- static_cast<double>(output_parameters_.sample_rate());
- double step = kSineCycles / (scale_factor *
- static_cast<double>(output_parameters_.frames_per_buffer()));
-
- for (int i = 0; i < count; ++i) {
- fake_callbacks_.push_back(new FakeAudioRenderCallback(step));
- mixer_inputs_.push_back(new AudioRendererMixerInput(
- base::Bind(&AudioRendererMixerTest::GetMixer, base::Unretained(this)),
- base::Bind(&AudioRendererMixerTest::RemoveMixer,
- base::Unretained(this)),
- kDefaultDeviceId, kDefaultSecurityOrigin));
- mixer_inputs_[i]->Initialize(input_parameters_, fake_callbacks_[i]);
- mixer_inputs_[i]->SetVolume(1.0f);
+ void InitializeInputs(int inputs_per_sample_rate) {
+ mixer_inputs_.reserve(inputs_per_sample_rate * input_parameters_.size());
+ fake_callbacks_.reserve(inputs_per_sample_rate * input_parameters_.size());
+
+ for (size_t i = 0, input = 0; i < input_parameters_.size(); ++i) {
+ // Setup FakeAudioRenderCallback step to compensate for resampling.
+ double scale_factor =
+ input_parameters_[i].sample_rate() /
+ static_cast<double>(output_parameters_.sample_rate());
+ double step =
+ kSineCycles /
+ (scale_factor *
+ static_cast<double>(output_parameters_.frames_per_buffer()));
+
+ for (int j = 0; j < inputs_per_sample_rate; ++j, ++input) {
+ fake_callbacks_.push_back(new FakeAudioRenderCallback(step));
+ mixer_inputs_.push_back(new AudioRendererMixerInput(
+ base::Bind(&AudioRendererMixerTest::GetMixer,
+ base::Unretained(this)),
+ base::Bind(&AudioRendererMixerTest::RemoveMixer,
+ base::Unretained(this)),
+ kDefaultDeviceId, kDefaultSecurityOrigin));
+ mixer_inputs_[input]->Initialize(input_parameters_[i],
+ fake_callbacks_[input]);
+ mixer_inputs_[input]->SetVolume(1.0f);
+ }
}
EXPECT_CALL(*this, RemoveMixer(testing::_, testing::_, testing::_))
- .Times(count);
+ .Times(mixer_inputs_.size());
}
bool ValidateAudioData(int index, int frames, float scale, double epsilon) {
@@ -112,9 +134,11 @@ class AudioRendererMixerTest
for (int j = index; j < frames; j++) {
double error = fabs(audio_bus_->channel(i)[j] -
expected_audio_bus_->channel(i)[j] * scale);
- if (error > epsilon) {
+ // The second comparison is for the case when scale is set to 0
+ // (and less that 1 in general)
+ if ((error > epsilon * scale) && (error > epsilon)) {
EXPECT_NEAR(expected_audio_bus_->channel(i)[j] * scale,
- audio_bus_->channel(i)[j], epsilon)
+ audio_bus_->channel(i)[j], epsilon * scale)
<< " i=" << i << ", j=" << j;
return false;
}
@@ -279,13 +303,40 @@ class AudioRendererMixerTest
EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
}
+ // Verify output when mixer inputs in mixed post-Stop() and post-Play()
+ // states.
+ void MixedStopPlayTest(int inputs) {
+ InitializeInputs(inputs);
+
+ // Start() all inputs.
+ for (size_t i = 0; i < mixer_inputs_.size(); ++i)
+ mixer_inputs_[i]->Start();
+
+ // Stop() all even numbered mixer inputs and Play() all odd numbered inputs
+ // and ensure we get the right value.
+ for (size_t i = 1; i < mixer_inputs_.size(); i += 2) {
+ mixer_inputs_[i - 1]->Stop();
+ mixer_inputs_[i]->Play();
+ }
+
+ // Stop the last input in case the number of inputs is odd
+ if (mixer_inputs_.size() % 2)
+ mixer_inputs_[mixer_inputs_.size() - 1]->Stop();
+
+ ASSERT_TRUE(RenderAndValidateAudioData(
+ std::max(1.f, static_cast<float>(floor(mixer_inputs_.size() / 2.f)))));
+
+ for (size_t i = 1; i < mixer_inputs_.size(); i += 2)
+ mixer_inputs_[i]->Stop();
+ }
+
protected:
virtual ~AudioRendererMixerTest() {}
scoped_refptr<MockAudioRendererSink> sink_;
scoped_ptr<AudioRendererMixer> mixer_;
AudioRendererSink::RenderCallback* mixer_callback_;
- AudioParameters input_parameters_;
+ std::vector<AudioParameters> input_parameters_;
AudioParameters output_parameters_;
scoped_ptr<AudioBus> audio_bus_;
scoped_ptr<AudioBus> expected_audio_bus_;
@@ -373,23 +424,13 @@ TEST_P(AudioRendererMixerTest, ManyInputStop) {
// Test mixer with many inputs in mixed post-Stop() and post-Play() states.
TEST_P(AudioRendererMixerTest, ManyInputMixedStopPlay) {
- InitializeInputs(kMixerInputs);
-
- // Start() all inputs.
- for (size_t i = 0; i < mixer_inputs_.size(); ++i)
- mixer_inputs_[i]->Start();
-
- // Stop() all even numbered mixer inputs and Play() all odd numbered inputs
- // and ensure we get the right value.
- for (size_t i = 1; i < mixer_inputs_.size(); i += 2) {
- mixer_inputs_[i - 1]->Stop();
- mixer_inputs_[i]->Play();
- }
- ASSERT_TRUE(RenderAndValidateAudioData(std::max(
- mixer_inputs_.size() / 2, static_cast<size_t>(1))));
+ MixedStopPlayTest(kMixerInputs);
+}
- for (size_t i = 1; i < mixer_inputs_.size(); i += 2)
- mixer_inputs_[i]->Stop();
+// Test mixer with many inputs in mixed post-Stop() and post-Play() states.
+TEST_P(AudioRendererMixerTest, ManyInputMixedStopPlayOdd) {
+ // Odd number of inputs per sample rate, to stop them unevenly.
+ MixedStopPlayTest(kOddMixerInputs);
}
TEST_P(AudioRendererMixerBehavioralTest, OnRenderError) {
@@ -474,22 +515,36 @@ TEST_P(AudioRendererMixerBehavioralTest, MixerPausesStream) {
}
INSTANTIATE_TEST_CASE_P(
- AudioRendererMixerTest, AudioRendererMixerTest, testing::Values(
- // No resampling.
- std::tr1::make_tuple(44100, 44100, 0.00000048),
+ AudioRendererMixerTest,
+ AudioRendererMixerTest,
+ testing::Values(
+ // No resampling, 1 input sample rate.
+ std::tr1::make_tuple(kTestInputLower, kTestInputLower[0], 0.00000048),
- // Upsampling.
- std::tr1::make_tuple(44100, 48000, 0.033),
+ // Upsampling, 1 input sample rate.
+ std::tr1::make_tuple(kTestInputLower, kTestInputHigher[0], 0.01),
- // Downsampling.
- std::tr1::make_tuple(48000, 41000, 0.042)));
+ // Downsampling, 1 input sample rate.
+ std::tr1::make_tuple(kTestInputHigher, kTestInputLower[0], 0.01),
+
+ // Downsampling, multuple input sample rates.
+ std::tr1::make_tuple(kTestInput3Rates, kTestInput3Rates[0], 0.01),
+
+ // Upsampling, multiple sinput sample rates.
+ std::tr1::make_tuple(kTestInput3Rates, kTestInput3Rates[2], 0.01),
+
+ // Both downsampling and upsampling, multiple input sample rates
+ std::tr1::make_tuple(kTestInput3Rates, kTestInput3Rates[1], 0.01)));
// Test cases for behavior which is independent of parameters. Values() doesn't
// support single item lists and we don't want these test cases to run for every
// parameter set.
INSTANTIATE_TEST_CASE_P(
- AudioRendererMixerBehavioralTest, AudioRendererMixerBehavioralTest,
+ AudioRendererMixerBehavioralTest,
+ AudioRendererMixerBehavioralTest,
testing::ValuesIn(std::vector<AudioRendererMixerTestData>(
- 1, std::tr1::make_tuple(44100, 44100, 0))));
-
+ 1,
+ std::tr1::make_tuple(kTestInputLower,
+ kTestInputLower[0],
+ 0.00000048))));
} // namespace media
« 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