Drive: Add BatchableRequest subclass.
[chromium-blink-merge.git] / media / base / channel_mixer_unittest.cc
blob89b4eeedc44397281c1b03fa466d008c1127bffc
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.
5 // MSVC++ requires this to be set before any other includes to get M_SQRT1_2.
6 #define _USE_MATH_DEFINES
8 #include <cmath>
10 #include "base/strings/stringprintf.h"
11 #include "media/audio/audio_parameters.h"
12 #include "media/base/audio_bus.h"
13 #include "media/base/channel_mixer.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 namespace media {
18 // Number of frames to test with.
19 enum { kFrames = 16 };
21 // Test all possible layout conversions can be constructed and mixed.
22 TEST(ChannelMixerTest, ConstructAllPossibleLayouts) {
23 for (ChannelLayout input_layout = CHANNEL_LAYOUT_MONO;
24 input_layout <= CHANNEL_LAYOUT_MAX;
25 input_layout = static_cast<ChannelLayout>(input_layout + 1)) {
26 for (ChannelLayout output_layout = CHANNEL_LAYOUT_MONO;
27 output_layout <= CHANNEL_LAYOUT_MAX;
28 output_layout = static_cast<ChannelLayout>(output_layout + 1)) {
29 // DISCRETE can't be tested here based on the current approach.
30 // CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC is not mixable.
31 // Stereo down mix should never be the output layout.
32 if (input_layout == CHANNEL_LAYOUT_DISCRETE ||
33 input_layout == CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC ||
34 output_layout == CHANNEL_LAYOUT_DISCRETE ||
35 output_layout == CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC ||
36 output_layout == CHANNEL_LAYOUT_STEREO_DOWNMIX) {
37 continue;
40 SCOPED_TRACE(base::StringPrintf(
41 "Input Layout: %d, Output Layout: %d", input_layout, output_layout));
42 ChannelMixer mixer(input_layout, output_layout);
43 scoped_ptr<AudioBus> input_bus = AudioBus::Create(
44 ChannelLayoutToChannelCount(input_layout), kFrames);
45 scoped_ptr<AudioBus> output_bus = AudioBus::Create(
46 ChannelLayoutToChannelCount(output_layout), kFrames);
47 for (int ch = 0; ch < input_bus->channels(); ++ch)
48 std::fill(input_bus->channel(ch), input_bus->channel(ch) + kFrames, 1);
50 mixer.Transform(input_bus.get(), output_bus.get());
55 struct ChannelMixerTestData {
56 ChannelMixerTestData(ChannelLayout input_layout, ChannelLayout output_layout,
57 const float* channel_values, int num_channel_values,
58 float scale)
59 : input_layout(input_layout),
60 output_layout(output_layout),
61 channel_values(channel_values),
62 num_channel_values(num_channel_values),
63 scale(scale) {
64 input_channels = ChannelLayoutToChannelCount(input_layout);
65 output_channels = ChannelLayoutToChannelCount(output_layout);
68 ChannelMixerTestData(ChannelLayout input_layout, int input_channels,
69 ChannelLayout output_layout, int output_channels,
70 const float* channel_values, int num_channel_values)
71 : input_layout(input_layout),
72 input_channels(input_channels),
73 output_layout(output_layout),
74 output_channels(output_channels),
75 channel_values(channel_values),
76 num_channel_values(num_channel_values),
77 scale(1.0f) {
80 std::string DebugString() const {
81 return base::StringPrintf(
82 "Input Layout: %d, Output Layout %d, Scale: %f", input_layout,
83 output_layout, scale);
86 ChannelLayout input_layout;
87 int input_channels;
88 ChannelLayout output_layout;
89 int output_channels;
90 const float* channel_values;
91 int num_channel_values;
92 float scale;
95 std::ostream& operator<<(std::ostream& os, const ChannelMixerTestData& data) {
96 return os << data.DebugString();
99 class ChannelMixerTest : public testing::TestWithParam<ChannelMixerTestData> {};
101 // Verify channels are mixed and scaled correctly. The test only works if all
102 // output channels have the same value.
103 TEST_P(ChannelMixerTest, Mixing) {
104 ChannelLayout input_layout = GetParam().input_layout;
105 int input_channels = GetParam().input_channels;
106 scoped_ptr<AudioBus> input_bus = AudioBus::Create(input_channels, kFrames);
107 AudioParameters input_audio(AudioParameters::AUDIO_PCM_LINEAR,
108 input_layout,
109 input_layout == CHANNEL_LAYOUT_DISCRETE ?
110 input_channels :
111 ChannelLayoutToChannelCount(input_layout),
112 AudioParameters::kAudioCDSampleRate, 16,
113 kFrames,
114 AudioParameters::NO_EFFECTS);
116 ChannelLayout output_layout = GetParam().output_layout;
117 int output_channels = GetParam().output_channels;
118 scoped_ptr<AudioBus> output_bus = AudioBus::Create(output_channels, kFrames);
119 AudioParameters output_audio(AudioParameters::AUDIO_PCM_LINEAR,
120 output_layout,
121 output_layout == CHANNEL_LAYOUT_DISCRETE ?
122 output_channels :
123 ChannelLayoutToChannelCount(output_layout),
124 AudioParameters::kAudioCDSampleRate, 16,
125 kFrames,
126 AudioParameters::NO_EFFECTS);
128 const float* channel_values = GetParam().channel_values;
129 ASSERT_EQ(input_bus->channels(), GetParam().num_channel_values);
131 float expected_value = 0;
132 float scale = GetParam().scale;
133 for (int ch = 0; ch < input_bus->channels(); ++ch) {
134 std::fill(input_bus->channel(ch), input_bus->channel(ch) + kFrames,
135 channel_values[ch]);
136 expected_value += channel_values[ch] * scale;
139 ChannelMixer mixer(input_audio, output_audio);
140 mixer.Transform(input_bus.get(), output_bus.get());
142 // Validate the output channel
143 if (input_layout != CHANNEL_LAYOUT_DISCRETE) {
144 for (int ch = 0; ch < output_bus->channels(); ++ch) {
145 for (int frame = 0; frame < output_bus->frames(); ++frame) {
146 ASSERT_FLOAT_EQ(expected_value, output_bus->channel(ch)[frame]);
149 } else {
150 // Processing discrete mixing. If there is a matching input channel,
151 // then the output channel should be set. If no input channel,
152 // output channel should be 0
153 for (int ch = 0; ch < output_bus->channels(); ++ch) {
154 expected_value = (ch < input_channels) ? channel_values[ch] : 0;
155 for (int frame = 0; frame < output_bus->frames(); ++frame) {
156 ASSERT_FLOAT_EQ(expected_value, output_bus->channel(ch)[frame]);
162 static float kStereoToMonoValues[] = { 0.5f, 0.75f };
163 static float kMonoToStereoValues[] = { 0.5f };
164 // Zero the center channel since it will be mixed at scale 1 vs M_SQRT1_2.
165 static float kFiveOneToMonoValues[] = { 0.1f, 0.2f, 0.0f, 0.4f, 0.5f, 0.6f };
166 static float kFiveDiscreteValues[] = { 0.1f, 0.2f, 0.3f, 0.4f, 0.5f };
168 // Run through basic sanity tests for some common conversions.
169 INSTANTIATE_TEST_CASE_P(ChannelMixerTest, ChannelMixerTest, testing::Values(
170 ChannelMixerTestData(CHANNEL_LAYOUT_STEREO, CHANNEL_LAYOUT_MONO,
171 kStereoToMonoValues, arraysize(kStereoToMonoValues),
172 0.5f),
173 ChannelMixerTestData(CHANNEL_LAYOUT_MONO, CHANNEL_LAYOUT_STEREO,
174 kMonoToStereoValues, arraysize(kMonoToStereoValues),
175 1.0f),
176 ChannelMixerTestData(CHANNEL_LAYOUT_5_1, CHANNEL_LAYOUT_MONO,
177 kFiveOneToMonoValues, arraysize(kFiveOneToMonoValues),
178 static_cast<float>(M_SQRT1_2)),
179 ChannelMixerTestData(CHANNEL_LAYOUT_DISCRETE, 2,
180 CHANNEL_LAYOUT_DISCRETE, 2,
181 kStereoToMonoValues, arraysize(kStereoToMonoValues)),
182 ChannelMixerTestData(CHANNEL_LAYOUT_DISCRETE, 2,
183 CHANNEL_LAYOUT_DISCRETE, 5,
184 kStereoToMonoValues, arraysize(kStereoToMonoValues)),
185 ChannelMixerTestData(CHANNEL_LAYOUT_DISCRETE, 5,
186 CHANNEL_LAYOUT_DISCRETE, 2,
187 kFiveDiscreteValues, arraysize(kFiveDiscreteValues))
190 } // namespace media