Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / media / base / channel_mixer_unittest.cc
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_SQRT1_2.
6 #define _USE_MATH_DEFINES
7
8 #include <cmath>
9
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"
15
16 namespace media {
17
18 // Number of frames to test with.
19 enum { kFrames = 16 };
20
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_STEREO_DOWNMIX;
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       if (input_layout == CHANNEL_LAYOUT_DISCRETE ||
32           input_layout == CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC ||
33           output_layout == CHANNEL_LAYOUT_DISCRETE ||
34           output_layout == CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) {
35         continue;
36       }
37
38       SCOPED_TRACE(base::StringPrintf(
39           "Input Layout: %d, Output Layout: %d", input_layout, output_layout));
40       ChannelMixer mixer(input_layout, output_layout);
41       scoped_ptr<AudioBus> input_bus = AudioBus::Create(
42           ChannelLayoutToChannelCount(input_layout), kFrames);
43       scoped_ptr<AudioBus> output_bus = AudioBus::Create(
44           ChannelLayoutToChannelCount(output_layout), kFrames);
45       for (int ch = 0; ch < input_bus->channels(); ++ch)
46         std::fill(input_bus->channel(ch), input_bus->channel(ch) + kFrames, 1);
47
48       mixer.Transform(input_bus.get(), output_bus.get());
49     }
50   }
51 }
52
53 struct ChannelMixerTestData {
54   ChannelMixerTestData(ChannelLayout input_layout, ChannelLayout output_layout,
55                        float* channel_values, int num_channel_values,
56                        float scale)
57       : input_layout(input_layout),
58         output_layout(output_layout),
59         channel_values(channel_values),
60         num_channel_values(num_channel_values),
61         scale(scale) {
62     input_channels = ChannelLayoutToChannelCount(input_layout);
63     output_channels = ChannelLayoutToChannelCount(output_layout);
64   }
65
66   ChannelMixerTestData(ChannelLayout input_layout, int input_channels,
67                        ChannelLayout output_layout, int output_channels,
68                        float* channel_values, int num_channel_values)
69       : input_layout(input_layout),
70         input_channels(input_channels),
71         output_layout(output_layout),
72         output_channels(output_channels),
73         channel_values(channel_values),
74         num_channel_values(num_channel_values),
75         scale(1.0f) {
76   }
77
78   std::string DebugString() const {
79     return base::StringPrintf(
80         "Input Layout: %d, Output Layout %d, Scale: %f", input_layout,
81         output_layout, scale);
82   }
83
84   ChannelLayout input_layout;
85   int input_channels;
86   ChannelLayout output_layout;
87   int output_channels;
88   float* channel_values;
89   int num_channel_values;
90   float scale;
91 };
92
93 std::ostream& operator<<(std::ostream& os, const ChannelMixerTestData& data) {
94   return os << data.DebugString();
95 }
96
97 class ChannelMixerTest : public testing::TestWithParam<ChannelMixerTestData> {};
98
99 // Verify channels are mixed and scaled correctly.  The test only works if all
100 // output channels have the same value.
101 TEST_P(ChannelMixerTest, Mixing) {
102   ChannelLayout input_layout = GetParam().input_layout;
103   int input_channels = GetParam().input_channels;
104   scoped_ptr<AudioBus> input_bus = AudioBus::Create(input_channels, kFrames);
105   AudioParameters input_audio(AudioParameters::AUDIO_PCM_LINEAR,
106                               input_layout,
107                               input_layout == CHANNEL_LAYOUT_DISCRETE ?
108                                   input_channels :
109                                   ChannelLayoutToChannelCount(input_layout),
110                               AudioParameters::kAudioCDSampleRate, 16,
111                               kFrames,
112                               AudioParameters::NO_EFFECTS);
113
114   ChannelLayout output_layout = GetParam().output_layout;
115   int output_channels = GetParam().output_channels;
116   scoped_ptr<AudioBus> output_bus = AudioBus::Create(output_channels, kFrames);
117   AudioParameters output_audio(AudioParameters::AUDIO_PCM_LINEAR,
118                                output_layout,
119                                output_layout == CHANNEL_LAYOUT_DISCRETE ?
120                                    output_channels :
121                                    ChannelLayoutToChannelCount(output_layout),
122                                AudioParameters::kAudioCDSampleRate, 16,
123                                kFrames,
124                                AudioParameters::NO_EFFECTS);
125
126   const float* channel_values = GetParam().channel_values;
127   ASSERT_EQ(input_bus->channels(), GetParam().num_channel_values);
128
129   float expected_value = 0;
130   float scale = GetParam().scale;
131   for (int ch = 0; ch < input_bus->channels(); ++ch) {
132     std::fill(input_bus->channel(ch), input_bus->channel(ch) + kFrames,
133               channel_values[ch]);
134     expected_value += channel_values[ch] * scale;
135   }
136
137   ChannelMixer mixer(input_audio, output_audio);
138   mixer.Transform(input_bus.get(), output_bus.get());
139
140   // Validate the output channel
141   if (input_layout != CHANNEL_LAYOUT_DISCRETE) {
142     for (int ch = 0; ch < output_bus->channels(); ++ch) {
143       for (int frame = 0; frame < output_bus->frames(); ++frame) {
144         ASSERT_FLOAT_EQ(output_bus->channel(ch)[frame], expected_value);
145       }
146     }
147   } else {
148     // Processing discrete mixing. If there is a matching input channel,
149     // then the output channel should be set. If no input channel,
150     // output channel should be 0
151     for (int ch = 0; ch < output_bus->channels(); ++ch) {
152       expected_value = (ch < input_channels) ? channel_values[ch] : 0;
153       for (int frame = 0; frame < output_bus->frames(); ++frame) {
154         ASSERT_FLOAT_EQ(output_bus->channel(ch)[frame], expected_value);
155       }
156     }
157   }
158 }
159
160 static float kStereoToMonoValues[] = { 0.5f, 0.75f };
161 static float kMonoToStereoValues[] = { 0.5f };
162 // Zero the center channel since it will be mixed at scale 1 vs M_SQRT1_2.
163 static float kFiveOneToMonoValues[] = { 0.1f, 0.2f, 0.0f, 0.4f, 0.5f, 0.6f };
164 static float kFiveDiscreteValues[] = { 0.1f, 0.2f, 0.3f, 0.4f, 0.5f };
165
166 // Run through basic sanity tests for some common conversions.
167 INSTANTIATE_TEST_CASE_P(ChannelMixerTest, ChannelMixerTest, testing::Values(
168     ChannelMixerTestData(CHANNEL_LAYOUT_STEREO, CHANNEL_LAYOUT_MONO,
169                          kStereoToMonoValues, arraysize(kStereoToMonoValues),
170                          0.5f),
171     ChannelMixerTestData(CHANNEL_LAYOUT_MONO, CHANNEL_LAYOUT_STEREO,
172                          kMonoToStereoValues, arraysize(kMonoToStereoValues),
173                          1.0f),
174     ChannelMixerTestData(CHANNEL_LAYOUT_5_1, CHANNEL_LAYOUT_MONO,
175                          kFiveOneToMonoValues, arraysize(kFiveOneToMonoValues),
176                          static_cast<float>(M_SQRT1_2)),
177     ChannelMixerTestData(CHANNEL_LAYOUT_DISCRETE, 2,
178                          CHANNEL_LAYOUT_DISCRETE, 2,
179                          kStereoToMonoValues, arraysize(kStereoToMonoValues)),
180     ChannelMixerTestData(CHANNEL_LAYOUT_DISCRETE, 2,
181                          CHANNEL_LAYOUT_DISCRETE, 5,
182                          kStereoToMonoValues, arraysize(kStereoToMonoValues)),
183     ChannelMixerTestData(CHANNEL_LAYOUT_DISCRETE, 5,
184                          CHANNEL_LAYOUT_DISCRETE, 2,
185                          kFiveDiscreteValues, arraysize(kFiveDiscreteValues))
186 ));
187
188 }  // namespace media