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