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 #include "media/base/channel_mixing_matrix.h"
6
7 #include <stddef.h>
8
9 #include "base/stl_util.h"
10 #include "base/strings/stringprintf.h"
11 #include "media/base/channel_mixer.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace media {
15
16 // Test all possible layout conversions can be constructed and mixed.
TEST(ChannelMixingMatrixTest,ConstructAllPossibleLayouts)17 TEST(ChannelMixingMatrixTest, ConstructAllPossibleLayouts) {
18 for (ChannelLayout input_layout = CHANNEL_LAYOUT_MONO;
19 input_layout <= CHANNEL_LAYOUT_MAX;
20 input_layout = static_cast<ChannelLayout>(input_layout + 1)) {
21 for (ChannelLayout output_layout = CHANNEL_LAYOUT_MONO;
22 output_layout <= CHANNEL_LAYOUT_MAX;
23 output_layout = static_cast<ChannelLayout>(output_layout + 1)) {
24 // DISCRETE, BITSTREAM can't be tested here based on the current approach.
25 // CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC is not mixable.
26 // Stereo down mix should never be the output layout.
27 if (input_layout == CHANNEL_LAYOUT_BITSTREAM ||
28 input_layout == CHANNEL_LAYOUT_DISCRETE ||
29 input_layout == CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC ||
30 output_layout == CHANNEL_LAYOUT_BITSTREAM ||
31 output_layout == CHANNEL_LAYOUT_DISCRETE ||
32 output_layout == CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC ||
33 output_layout == CHANNEL_LAYOUT_STEREO_DOWNMIX) {
34 continue;
35 }
36
37 SCOPED_TRACE(base::StringPrintf(
38 "Input Layout: %d, Output Layout: %d", input_layout, output_layout));
39 ChannelMixingMatrix matrix_builder(
40 input_layout,
41 ChannelLayoutToChannelCount(input_layout),
42 output_layout,
43 ChannelLayoutToChannelCount(output_layout));
44 std::vector<std::vector<float>> matrix;
45 matrix_builder.CreateTransformationMatrix(&matrix);
46 }
47 }
48 }
49
50 // Verify channels are mixed and scaled correctly.
TEST(ChannelMixingMatrixTest,StereoToMono)51 TEST(ChannelMixingMatrixTest, StereoToMono) {
52 ChannelLayout input_layout = CHANNEL_LAYOUT_STEREO;
53 ChannelLayout output_layout = CHANNEL_LAYOUT_MONO;
54 ChannelMixingMatrix matrix_builder(
55 input_layout,
56 ChannelLayoutToChannelCount(input_layout),
57 output_layout,
58 ChannelLayoutToChannelCount(output_layout));
59 std::vector<std::vector<float>> matrix;
60 bool remapping = matrix_builder.CreateTransformationMatrix(&matrix);
61
62 // Input: stereo
63 // LEFT RIGHT
64 // Output: mono CENTER 0.5 0.5
65 //
66 EXPECT_FALSE(remapping);
67 EXPECT_EQ(1u, matrix.size());
68 EXPECT_EQ(2u, matrix[0].size());
69 EXPECT_EQ(0.5f, matrix[0][0]);
70 EXPECT_EQ(0.5f, matrix[0][1]);
71 }
72
TEST(ChannelMixingMatrixTest,MonoToStereo)73 TEST(ChannelMixingMatrixTest, MonoToStereo) {
74 ChannelLayout input_layout = CHANNEL_LAYOUT_MONO;
75 ChannelLayout output_layout = CHANNEL_LAYOUT_STEREO;
76 ChannelMixingMatrix matrix_builder(
77 input_layout,
78 ChannelLayoutToChannelCount(input_layout),
79 output_layout,
80 ChannelLayoutToChannelCount(output_layout));
81 std::vector<std::vector<float>> matrix;
82 bool remapping = matrix_builder.CreateTransformationMatrix(&matrix);
83
84 // Input: mono
85 // CENTER
86 // Output: stereo LEFT 1
87 // RIGHT 1
88 //
89 EXPECT_TRUE(remapping);
90 EXPECT_EQ(2u, matrix.size());
91 EXPECT_EQ(1u, matrix[0].size());
92 EXPECT_EQ(1.0f, matrix[0][0]);
93 EXPECT_EQ(1u, matrix[1].size());
94 EXPECT_EQ(1.0f, matrix[1][0]);
95 }
96
TEST(ChannelMixingMatrixTest,MonoToSurround)97 TEST(ChannelMixingMatrixTest, MonoToSurround) {
98 ChannelLayout input_layout = CHANNEL_LAYOUT_MONO;
99 ChannelLayout output_layout = CHANNEL_LAYOUT_5_1;
100 ChannelMixingMatrix matrix_builder(
101 input_layout, ChannelLayoutToChannelCount(input_layout), output_layout,
102 ChannelLayoutToChannelCount(output_layout));
103 std::vector<std::vector<float>> matrix;
104 bool remapping = matrix_builder.CreateTransformationMatrix(&matrix);
105
106 // Input: mono
107 // CENTER
108 // Output: surround LEFT 1
109 // RIGHT 1
110 // CENTER 0
111 // LFE 0
112 // SL 0
113 // SR 0
114 //
115 EXPECT_FALSE(remapping);
116 EXPECT_EQ(6u, matrix.size());
117 EXPECT_EQ(1u, matrix[0].size());
118 EXPECT_EQ(1.0f, matrix[0][0]);
119 EXPECT_EQ(1u, matrix[1].size());
120 EXPECT_EQ(1.0f, matrix[1][0]);
121 for (size_t i = 2; i < 6; i++) {
122 EXPECT_EQ(1u, matrix[i].size());
123 EXPECT_EQ(0.0f, matrix[i][0]);
124 }
125 }
126
TEST(ChannelMixingMatrixTest,FiveOneToMono)127 TEST(ChannelMixingMatrixTest, FiveOneToMono) {
128 ChannelLayout input_layout = CHANNEL_LAYOUT_5_1;
129 ChannelLayout output_layout = CHANNEL_LAYOUT_MONO;
130 ChannelMixingMatrix matrix_builder(
131 input_layout,
132 ChannelLayoutToChannelCount(input_layout),
133 output_layout,
134 ChannelLayoutToChannelCount(output_layout));
135 std::vector<std::vector<float>> matrix;
136 bool remapping = matrix_builder.CreateTransformationMatrix(&matrix);
137
138 // Note: 1/sqrt(2) is shown as 0.707.
139 //
140 // Input: 5.1
141 // LEFT RIGHT CENTER LFE SIDE_LEFT SIDE_RIGHT
142 // Output: mono CENTER 0.707 0.707 1 0.707 0.707 0.707
143 //
144 EXPECT_FALSE(remapping);
145 EXPECT_EQ(1u, matrix.size());
146 EXPECT_EQ(6u, matrix[0].size());
147 EXPECT_FLOAT_EQ(ChannelMixer::kHalfPower, matrix[0][0]);
148 EXPECT_FLOAT_EQ(ChannelMixer::kHalfPower, matrix[0][1]);
149 // The center channel will be mixed at scale 1.
150 EXPECT_EQ(1.0f, matrix[0][2]);
151 EXPECT_FLOAT_EQ(ChannelMixer::kHalfPower, matrix[0][3]);
152 EXPECT_FLOAT_EQ(ChannelMixer::kHalfPower, matrix[0][4]);
153 EXPECT_FLOAT_EQ(ChannelMixer::kHalfPower, matrix[0][5]);
154 }
155
TEST(ChannelMixingMatrixTest,DiscreteToDiscrete)156 TEST(ChannelMixingMatrixTest, DiscreteToDiscrete) {
157 const struct {
158 int input_channels;
159 int output_channels;
160 } test_case[] = {
161 {2, 2}, {2, 5}, {5, 2},
162 };
163
164 for (size_t n = 0; n < base::size(test_case); n++) {
165 int input_channels = test_case[n].input_channels;
166 int output_channels = test_case[n].output_channels;
167 ChannelMixingMatrix matrix_builder(CHANNEL_LAYOUT_DISCRETE,
168 input_channels,
169 CHANNEL_LAYOUT_DISCRETE,
170 output_channels);
171 std::vector<std::vector<float>> matrix;
172 bool remapping = matrix_builder.CreateTransformationMatrix(&matrix);
173 EXPECT_TRUE(remapping);
174 EXPECT_EQ(static_cast<size_t>(output_channels), matrix.size());
175 for (int i = 0; i < output_channels; i++) {
176 EXPECT_EQ(static_cast<size_t>(input_channels), matrix[i].size());
177 for (int j = 0; j < input_channels; j++) {
178 if (i == j) {
179 EXPECT_EQ(1.0f, matrix[i][j]);
180 } else {
181 EXPECT_EQ(0.0f, matrix[i][j]);
182 }
183 }
184 }
185 }
186 }
187
188 } // namespace media
189