1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "audio/utility/channel_mixer.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <memory>
14*d9f75844SAndroid Build Coastguard Worker
15*d9f75844SAndroid Build Coastguard Worker #include "api/audio/audio_frame.h"
16*d9f75844SAndroid Build Coastguard Worker #include "api/audio/channel_layout.h"
17*d9f75844SAndroid Build Coastguard Worker #include "audio/utility/channel_mixing_matrix.h"
18*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/arraysize.h"
19*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/strings/string_builder.h"
20*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
21*d9f75844SAndroid Build Coastguard Worker
22*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
23*d9f75844SAndroid Build Coastguard Worker
24*d9f75844SAndroid Build Coastguard Worker namespace {
25*d9f75844SAndroid Build Coastguard Worker
26*d9f75844SAndroid Build Coastguard Worker constexpr uint32_t kTimestamp = 27;
27*d9f75844SAndroid Build Coastguard Worker constexpr int kSampleRateHz = 16000;
28*d9f75844SAndroid Build Coastguard Worker constexpr size_t kSamplesPerChannel = kSampleRateHz / 100;
29*d9f75844SAndroid Build Coastguard Worker
30*d9f75844SAndroid Build Coastguard Worker class ChannelMixerTest : public ::testing::Test {
31*d9f75844SAndroid Build Coastguard Worker protected:
ChannelMixerTest()32*d9f75844SAndroid Build Coastguard Worker ChannelMixerTest() {
33*d9f75844SAndroid Build Coastguard Worker // Use 10ms audio frames by default. Don't set values yet.
34*d9f75844SAndroid Build Coastguard Worker frame_.samples_per_channel_ = kSamplesPerChannel;
35*d9f75844SAndroid Build Coastguard Worker frame_.sample_rate_hz_ = kSampleRateHz;
36*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(frame_.muted());
37*d9f75844SAndroid Build Coastguard Worker }
38*d9f75844SAndroid Build Coastguard Worker
~ChannelMixerTest()39*d9f75844SAndroid Build Coastguard Worker virtual ~ChannelMixerTest() {}
40*d9f75844SAndroid Build Coastguard Worker
41*d9f75844SAndroid Build Coastguard Worker AudioFrame frame_;
42*d9f75844SAndroid Build Coastguard Worker };
43*d9f75844SAndroid Build Coastguard Worker
SetFrameData(int16_t data,AudioFrame * frame)44*d9f75844SAndroid Build Coastguard Worker void SetFrameData(int16_t data, AudioFrame* frame) {
45*d9f75844SAndroid Build Coastguard Worker int16_t* frame_data = frame->mutable_data();
46*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < frame->samples_per_channel() * frame->num_channels();
47*d9f75844SAndroid Build Coastguard Worker i++) {
48*d9f75844SAndroid Build Coastguard Worker frame_data[i] = data;
49*d9f75844SAndroid Build Coastguard Worker }
50*d9f75844SAndroid Build Coastguard Worker }
51*d9f75844SAndroid Build Coastguard Worker
SetMonoData(int16_t center,AudioFrame * frame)52*d9f75844SAndroid Build Coastguard Worker void SetMonoData(int16_t center, AudioFrame* frame) {
53*d9f75844SAndroid Build Coastguard Worker frame->num_channels_ = 1;
54*d9f75844SAndroid Build Coastguard Worker int16_t* frame_data = frame->mutable_data();
55*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < frame->samples_per_channel(); ++i) {
56*d9f75844SAndroid Build Coastguard Worker frame_data[i] = center;
57*d9f75844SAndroid Build Coastguard Worker }
58*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(frame->muted());
59*d9f75844SAndroid Build Coastguard Worker }
60*d9f75844SAndroid Build Coastguard Worker
SetStereoData(int16_t left,int16_t right,AudioFrame * frame)61*d9f75844SAndroid Build Coastguard Worker void SetStereoData(int16_t left, int16_t right, AudioFrame* frame) {
62*d9f75844SAndroid Build Coastguard Worker ASSERT_LE(2 * frame->samples_per_channel(), frame->max_16bit_samples());
63*d9f75844SAndroid Build Coastguard Worker frame->num_channels_ = 2;
64*d9f75844SAndroid Build Coastguard Worker int16_t* frame_data = frame->mutable_data();
65*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < frame->samples_per_channel() * 2; i += 2) {
66*d9f75844SAndroid Build Coastguard Worker frame_data[i] = left;
67*d9f75844SAndroid Build Coastguard Worker frame_data[i + 1] = right;
68*d9f75844SAndroid Build Coastguard Worker }
69*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(frame->muted());
70*d9f75844SAndroid Build Coastguard Worker }
71*d9f75844SAndroid Build Coastguard Worker
SetFiveOneData(int16_t front_left,int16_t front_right,int16_t center,int16_t lfe,int16_t side_left,int16_t side_right,AudioFrame * frame)72*d9f75844SAndroid Build Coastguard Worker void SetFiveOneData(int16_t front_left,
73*d9f75844SAndroid Build Coastguard Worker int16_t front_right,
74*d9f75844SAndroid Build Coastguard Worker int16_t center,
75*d9f75844SAndroid Build Coastguard Worker int16_t lfe,
76*d9f75844SAndroid Build Coastguard Worker int16_t side_left,
77*d9f75844SAndroid Build Coastguard Worker int16_t side_right,
78*d9f75844SAndroid Build Coastguard Worker AudioFrame* frame) {
79*d9f75844SAndroid Build Coastguard Worker ASSERT_LE(6 * frame->samples_per_channel(), frame->max_16bit_samples());
80*d9f75844SAndroid Build Coastguard Worker frame->num_channels_ = 6;
81*d9f75844SAndroid Build Coastguard Worker int16_t* frame_data = frame->mutable_data();
82*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < frame->samples_per_channel() * 6; i += 6) {
83*d9f75844SAndroid Build Coastguard Worker frame_data[i] = front_left;
84*d9f75844SAndroid Build Coastguard Worker frame_data[i + 1] = front_right;
85*d9f75844SAndroid Build Coastguard Worker frame_data[i + 2] = center;
86*d9f75844SAndroid Build Coastguard Worker frame_data[i + 3] = lfe;
87*d9f75844SAndroid Build Coastguard Worker frame_data[i + 4] = side_left;
88*d9f75844SAndroid Build Coastguard Worker frame_data[i + 5] = side_right;
89*d9f75844SAndroid Build Coastguard Worker }
90*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(frame->muted());
91*d9f75844SAndroid Build Coastguard Worker }
92*d9f75844SAndroid Build Coastguard Worker
SetSevenOneData(int16_t front_left,int16_t front_right,int16_t center,int16_t lfe,int16_t side_left,int16_t side_right,int16_t back_left,int16_t back_right,AudioFrame * frame)93*d9f75844SAndroid Build Coastguard Worker void SetSevenOneData(int16_t front_left,
94*d9f75844SAndroid Build Coastguard Worker int16_t front_right,
95*d9f75844SAndroid Build Coastguard Worker int16_t center,
96*d9f75844SAndroid Build Coastguard Worker int16_t lfe,
97*d9f75844SAndroid Build Coastguard Worker int16_t side_left,
98*d9f75844SAndroid Build Coastguard Worker int16_t side_right,
99*d9f75844SAndroid Build Coastguard Worker int16_t back_left,
100*d9f75844SAndroid Build Coastguard Worker int16_t back_right,
101*d9f75844SAndroid Build Coastguard Worker AudioFrame* frame) {
102*d9f75844SAndroid Build Coastguard Worker ASSERT_LE(8 * frame->samples_per_channel(), frame->max_16bit_samples());
103*d9f75844SAndroid Build Coastguard Worker frame->num_channels_ = 8;
104*d9f75844SAndroid Build Coastguard Worker int16_t* frame_data = frame->mutable_data();
105*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < frame->samples_per_channel() * 8; i += 8) {
106*d9f75844SAndroid Build Coastguard Worker frame_data[i] = front_left;
107*d9f75844SAndroid Build Coastguard Worker frame_data[i + 1] = front_right;
108*d9f75844SAndroid Build Coastguard Worker frame_data[i + 2] = center;
109*d9f75844SAndroid Build Coastguard Worker frame_data[i + 3] = lfe;
110*d9f75844SAndroid Build Coastguard Worker frame_data[i + 4] = side_left;
111*d9f75844SAndroid Build Coastguard Worker frame_data[i + 5] = side_right;
112*d9f75844SAndroid Build Coastguard Worker frame_data[i + 6] = back_left;
113*d9f75844SAndroid Build Coastguard Worker frame_data[i + 7] = back_right;
114*d9f75844SAndroid Build Coastguard Worker }
115*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(frame->muted());
116*d9f75844SAndroid Build Coastguard Worker }
117*d9f75844SAndroid Build Coastguard Worker
AllSamplesEquals(int16_t sample,const AudioFrame * frame)118*d9f75844SAndroid Build Coastguard Worker bool AllSamplesEquals(int16_t sample, const AudioFrame* frame) {
119*d9f75844SAndroid Build Coastguard Worker const int16_t* frame_data = frame->data();
120*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < frame->samples_per_channel() * frame->num_channels();
121*d9f75844SAndroid Build Coastguard Worker i++) {
122*d9f75844SAndroid Build Coastguard Worker if (frame_data[i] != sample) {
123*d9f75844SAndroid Build Coastguard Worker return false;
124*d9f75844SAndroid Build Coastguard Worker }
125*d9f75844SAndroid Build Coastguard Worker }
126*d9f75844SAndroid Build Coastguard Worker return true;
127*d9f75844SAndroid Build Coastguard Worker }
128*d9f75844SAndroid Build Coastguard Worker
VerifyFramesAreEqual(const AudioFrame & frame1,const AudioFrame & frame2)129*d9f75844SAndroid Build Coastguard Worker void VerifyFramesAreEqual(const AudioFrame& frame1, const AudioFrame& frame2) {
130*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(frame1.num_channels(), frame2.num_channels());
131*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(frame1.samples_per_channel(), frame2.samples_per_channel());
132*d9f75844SAndroid Build Coastguard Worker const int16_t* frame1_data = frame1.data();
133*d9f75844SAndroid Build Coastguard Worker const int16_t* frame2_data = frame2.data();
134*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < frame1.samples_per_channel() * frame1.num_channels();
135*d9f75844SAndroid Build Coastguard Worker i++) {
136*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(frame1_data[i], frame2_data[i]);
137*d9f75844SAndroid Build Coastguard Worker }
138*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(frame1.muted(), frame2.muted());
139*d9f75844SAndroid Build Coastguard Worker }
140*d9f75844SAndroid Build Coastguard Worker
141*d9f75844SAndroid Build Coastguard Worker } // namespace
142*d9f75844SAndroid Build Coastguard Worker
143*d9f75844SAndroid Build Coastguard Worker // Test all possible layout conversions can be constructed and mixed. Don't
144*d9f75844SAndroid Build Coastguard Worker // care about the actual content, simply run through all mixing combinations
145*d9f75844SAndroid Build Coastguard Worker // and ensure that nothing fails.
TEST_F(ChannelMixerTest,ConstructAllPossibleLayouts)146*d9f75844SAndroid Build Coastguard Worker TEST_F(ChannelMixerTest, ConstructAllPossibleLayouts) {
147*d9f75844SAndroid Build Coastguard Worker for (ChannelLayout input_layout = CHANNEL_LAYOUT_MONO;
148*d9f75844SAndroid Build Coastguard Worker input_layout <= CHANNEL_LAYOUT_MAX;
149*d9f75844SAndroid Build Coastguard Worker input_layout = static_cast<ChannelLayout>(input_layout + 1)) {
150*d9f75844SAndroid Build Coastguard Worker for (ChannelLayout output_layout = CHANNEL_LAYOUT_MONO;
151*d9f75844SAndroid Build Coastguard Worker output_layout <= CHANNEL_LAYOUT_MAX;
152*d9f75844SAndroid Build Coastguard Worker output_layout = static_cast<ChannelLayout>(output_layout + 1)) {
153*d9f75844SAndroid Build Coastguard Worker // DISCRETE, BITSTREAM can't be tested here based on the current approach.
154*d9f75844SAndroid Build Coastguard Worker // CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC is not mixable.
155*d9f75844SAndroid Build Coastguard Worker // Stereo down mix should never be the output layout.
156*d9f75844SAndroid Build Coastguard Worker if (input_layout == CHANNEL_LAYOUT_BITSTREAM ||
157*d9f75844SAndroid Build Coastguard Worker input_layout == CHANNEL_LAYOUT_DISCRETE ||
158*d9f75844SAndroid Build Coastguard Worker input_layout == CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC ||
159*d9f75844SAndroid Build Coastguard Worker output_layout == CHANNEL_LAYOUT_BITSTREAM ||
160*d9f75844SAndroid Build Coastguard Worker output_layout == CHANNEL_LAYOUT_DISCRETE ||
161*d9f75844SAndroid Build Coastguard Worker output_layout == CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC ||
162*d9f75844SAndroid Build Coastguard Worker output_layout == CHANNEL_LAYOUT_STEREO_DOWNMIX) {
163*d9f75844SAndroid Build Coastguard Worker continue;
164*d9f75844SAndroid Build Coastguard Worker }
165*d9f75844SAndroid Build Coastguard Worker
166*d9f75844SAndroid Build Coastguard Worker rtc::StringBuilder ss;
167*d9f75844SAndroid Build Coastguard Worker ss << "Input Layout: " << input_layout
168*d9f75844SAndroid Build Coastguard Worker << ", Output Layout: " << output_layout;
169*d9f75844SAndroid Build Coastguard Worker SCOPED_TRACE(ss.str());
170*d9f75844SAndroid Build Coastguard Worker ChannelMixer mixer(input_layout, output_layout);
171*d9f75844SAndroid Build Coastguard Worker
172*d9f75844SAndroid Build Coastguard Worker frame_.UpdateFrame(kTimestamp, nullptr, kSamplesPerChannel, kSampleRateHz,
173*d9f75844SAndroid Build Coastguard Worker AudioFrame::kNormalSpeech, AudioFrame::kVadActive,
174*d9f75844SAndroid Build Coastguard Worker ChannelLayoutToChannelCount(input_layout));
175*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(frame_.muted());
176*d9f75844SAndroid Build Coastguard Worker mixer.Transform(&frame_);
177*d9f75844SAndroid Build Coastguard Worker }
178*d9f75844SAndroid Build Coastguard Worker }
179*d9f75844SAndroid Build Coastguard Worker }
180*d9f75844SAndroid Build Coastguard Worker
181*d9f75844SAndroid Build Coastguard Worker // Ensure that the audio frame is untouched when input and output channel
182*d9f75844SAndroid Build Coastguard Worker // layouts are identical, i.e., the transformation should have no effect.
183*d9f75844SAndroid Build Coastguard Worker // Exclude invalid mixing combinations.
TEST_F(ChannelMixerTest,NoMixingForIdenticalChannelLayouts)184*d9f75844SAndroid Build Coastguard Worker TEST_F(ChannelMixerTest, NoMixingForIdenticalChannelLayouts) {
185*d9f75844SAndroid Build Coastguard Worker for (ChannelLayout input_layout = CHANNEL_LAYOUT_MONO;
186*d9f75844SAndroid Build Coastguard Worker input_layout <= CHANNEL_LAYOUT_MAX;
187*d9f75844SAndroid Build Coastguard Worker input_layout = static_cast<ChannelLayout>(input_layout + 1)) {
188*d9f75844SAndroid Build Coastguard Worker for (ChannelLayout output_layout = CHANNEL_LAYOUT_MONO;
189*d9f75844SAndroid Build Coastguard Worker output_layout <= CHANNEL_LAYOUT_MAX;
190*d9f75844SAndroid Build Coastguard Worker output_layout = static_cast<ChannelLayout>(output_layout + 1)) {
191*d9f75844SAndroid Build Coastguard Worker if (input_layout != output_layout ||
192*d9f75844SAndroid Build Coastguard Worker input_layout == CHANNEL_LAYOUT_BITSTREAM ||
193*d9f75844SAndroid Build Coastguard Worker input_layout == CHANNEL_LAYOUT_DISCRETE ||
194*d9f75844SAndroid Build Coastguard Worker input_layout == CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC ||
195*d9f75844SAndroid Build Coastguard Worker output_layout == CHANNEL_LAYOUT_STEREO_DOWNMIX) {
196*d9f75844SAndroid Build Coastguard Worker continue;
197*d9f75844SAndroid Build Coastguard Worker }
198*d9f75844SAndroid Build Coastguard Worker ChannelMixer mixer(input_layout, output_layout);
199*d9f75844SAndroid Build Coastguard Worker frame_.num_channels_ = ChannelLayoutToChannelCount(input_layout);
200*d9f75844SAndroid Build Coastguard Worker SetFrameData(99, &frame_);
201*d9f75844SAndroid Build Coastguard Worker mixer.Transform(&frame_);
202*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(ChannelLayoutToChannelCount(input_layout),
203*d9f75844SAndroid Build Coastguard Worker static_cast<int>(frame_.num_channels()));
204*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(AllSamplesEquals(99, &frame_));
205*d9f75844SAndroid Build Coastguard Worker }
206*d9f75844SAndroid Build Coastguard Worker }
207*d9f75844SAndroid Build Coastguard Worker }
208*d9f75844SAndroid Build Coastguard Worker
TEST_F(ChannelMixerTest,StereoToMono)209*d9f75844SAndroid Build Coastguard Worker TEST_F(ChannelMixerTest, StereoToMono) {
210*d9f75844SAndroid Build Coastguard Worker ChannelMixer mixer(CHANNEL_LAYOUT_STEREO, CHANNEL_LAYOUT_MONO);
211*d9f75844SAndroid Build Coastguard Worker //
212*d9f75844SAndroid Build Coastguard Worker // Input: stereo
213*d9f75844SAndroid Build Coastguard Worker // LEFT RIGHT
214*d9f75844SAndroid Build Coastguard Worker // Output: mono CENTER 0.5 0.5
215*d9f75844SAndroid Build Coastguard Worker //
216*d9f75844SAndroid Build Coastguard Worker SetStereoData(7, 3, &frame_);
217*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2u, frame_.num_channels());
218*d9f75844SAndroid Build Coastguard Worker mixer.Transform(&frame_);
219*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1u, frame_.num_channels());
220*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(CHANNEL_LAYOUT_MONO, frame_.channel_layout());
221*d9f75844SAndroid Build Coastguard Worker
222*d9f75844SAndroid Build Coastguard Worker AudioFrame mono_frame;
223*d9f75844SAndroid Build Coastguard Worker mono_frame.samples_per_channel_ = frame_.samples_per_channel();
224*d9f75844SAndroid Build Coastguard Worker SetMonoData(5, &mono_frame);
225*d9f75844SAndroid Build Coastguard Worker VerifyFramesAreEqual(mono_frame, frame_);
226*d9f75844SAndroid Build Coastguard Worker
227*d9f75844SAndroid Build Coastguard Worker SetStereoData(-32768, -32768, &frame_);
228*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2u, frame_.num_channels());
229*d9f75844SAndroid Build Coastguard Worker mixer.Transform(&frame_);
230*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1u, frame_.num_channels());
231*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(CHANNEL_LAYOUT_MONO, frame_.channel_layout());
232*d9f75844SAndroid Build Coastguard Worker SetMonoData(-32768, &mono_frame);
233*d9f75844SAndroid Build Coastguard Worker VerifyFramesAreEqual(mono_frame, frame_);
234*d9f75844SAndroid Build Coastguard Worker }
235*d9f75844SAndroid Build Coastguard Worker
TEST_F(ChannelMixerTest,StereoToMonoMuted)236*d9f75844SAndroid Build Coastguard Worker TEST_F(ChannelMixerTest, StereoToMonoMuted) {
237*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(frame_.muted());
238*d9f75844SAndroid Build Coastguard Worker ChannelMixer mixer(CHANNEL_LAYOUT_STEREO, CHANNEL_LAYOUT_MONO);
239*d9f75844SAndroid Build Coastguard Worker mixer.Transform(&frame_);
240*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1u, frame_.num_channels());
241*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(CHANNEL_LAYOUT_MONO, frame_.channel_layout());
242*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(frame_.muted());
243*d9f75844SAndroid Build Coastguard Worker }
244*d9f75844SAndroid Build Coastguard Worker
TEST_F(ChannelMixerTest,FiveOneToSevenOneMuted)245*d9f75844SAndroid Build Coastguard Worker TEST_F(ChannelMixerTest, FiveOneToSevenOneMuted) {
246*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(frame_.muted());
247*d9f75844SAndroid Build Coastguard Worker ChannelMixer mixer(CHANNEL_LAYOUT_5_1, CHANNEL_LAYOUT_7_1);
248*d9f75844SAndroid Build Coastguard Worker mixer.Transform(&frame_);
249*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(8u, frame_.num_channels());
250*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(CHANNEL_LAYOUT_7_1, frame_.channel_layout());
251*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(frame_.muted());
252*d9f75844SAndroid Build Coastguard Worker }
253*d9f75844SAndroid Build Coastguard Worker
TEST_F(ChannelMixerTest,FiveOneToMono)254*d9f75844SAndroid Build Coastguard Worker TEST_F(ChannelMixerTest, FiveOneToMono) {
255*d9f75844SAndroid Build Coastguard Worker ChannelMixer mixer(CHANNEL_LAYOUT_5_1, CHANNEL_LAYOUT_MONO);
256*d9f75844SAndroid Build Coastguard Worker //
257*d9f75844SAndroid Build Coastguard Worker // Input: 5.1
258*d9f75844SAndroid Build Coastguard Worker // LEFT RIGHT CENTER LFE SIDE_LEFT SIDE_RIGHT
259*d9f75844SAndroid Build Coastguard Worker // Output: mono CENTER 0.707 0.707 1 0.707 0.707 0.707
260*d9f75844SAndroid Build Coastguard Worker //
261*d9f75844SAndroid Build Coastguard Worker // a = [10, 20, 15, 2, 5, 5]
262*d9f75844SAndroid Build Coastguard Worker // b = [1/sqrt(2), 1/sqrt(2), 1.0, 1/sqrt(2), 1/sqrt(2), 1/sqrt(2)] =>
263*d9f75844SAndroid Build Coastguard Worker // a * b (dot product) = 44.69848480983499,
264*d9f75844SAndroid Build Coastguard Worker // which is truncated into 44 using 16 bit representation.
265*d9f75844SAndroid Build Coastguard Worker //
266*d9f75844SAndroid Build Coastguard Worker SetFiveOneData(10, 20, 15, 2, 5, 5, &frame_);
267*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(6u, frame_.num_channels());
268*d9f75844SAndroid Build Coastguard Worker mixer.Transform(&frame_);
269*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1u, frame_.num_channels());
270*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(CHANNEL_LAYOUT_MONO, frame_.channel_layout());
271*d9f75844SAndroid Build Coastguard Worker
272*d9f75844SAndroid Build Coastguard Worker AudioFrame mono_frame;
273*d9f75844SAndroid Build Coastguard Worker mono_frame.samples_per_channel_ = frame_.samples_per_channel();
274*d9f75844SAndroid Build Coastguard Worker SetMonoData(44, &mono_frame);
275*d9f75844SAndroid Build Coastguard Worker VerifyFramesAreEqual(mono_frame, frame_);
276*d9f75844SAndroid Build Coastguard Worker
277*d9f75844SAndroid Build Coastguard Worker SetFiveOneData(-32768, -32768, -32768, -32768, -32768, -32768, &frame_);
278*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(6u, frame_.num_channels());
279*d9f75844SAndroid Build Coastguard Worker mixer.Transform(&frame_);
280*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1u, frame_.num_channels());
281*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(CHANNEL_LAYOUT_MONO, frame_.channel_layout());
282*d9f75844SAndroid Build Coastguard Worker SetMonoData(-32768, &mono_frame);
283*d9f75844SAndroid Build Coastguard Worker VerifyFramesAreEqual(mono_frame, frame_);
284*d9f75844SAndroid Build Coastguard Worker }
285*d9f75844SAndroid Build Coastguard Worker
TEST_F(ChannelMixerTest,FiveOneToSevenOne)286*d9f75844SAndroid Build Coastguard Worker TEST_F(ChannelMixerTest, FiveOneToSevenOne) {
287*d9f75844SAndroid Build Coastguard Worker ChannelMixer mixer(CHANNEL_LAYOUT_5_1, CHANNEL_LAYOUT_7_1);
288*d9f75844SAndroid Build Coastguard Worker //
289*d9f75844SAndroid Build Coastguard Worker // Input: 5.1
290*d9f75844SAndroid Build Coastguard Worker // LEFT RIGHT CENTER LFE SIDE_LEFT SIDE_RIGHT
291*d9f75844SAndroid Build Coastguard Worker // Output: 7.1 LEFT 1 0 0 0 0 0
292*d9f75844SAndroid Build Coastguard Worker // RIGHT 0 1 0 0 0 0
293*d9f75844SAndroid Build Coastguard Worker // CENTER 0 0 1 0 0 0
294*d9f75844SAndroid Build Coastguard Worker // LFE 0 0 0 1 0 0
295*d9f75844SAndroid Build Coastguard Worker // SIDE_LEFT 0 0 0 0 1 0
296*d9f75844SAndroid Build Coastguard Worker // SIDE_RIGHT 0 0 0 0 0 1
297*d9f75844SAndroid Build Coastguard Worker // BACK_LEFT 0 0 0 0 0 0
298*d9f75844SAndroid Build Coastguard Worker // BACK_RIGHT 0 0 0 0 0 0
299*d9f75844SAndroid Build Coastguard Worker //
300*d9f75844SAndroid Build Coastguard Worker SetFiveOneData(10, 20, 15, 2, 5, 5, &frame_);
301*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(6u, frame_.num_channels());
302*d9f75844SAndroid Build Coastguard Worker mixer.Transform(&frame_);
303*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(8u, frame_.num_channels());
304*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(CHANNEL_LAYOUT_7_1, frame_.channel_layout());
305*d9f75844SAndroid Build Coastguard Worker
306*d9f75844SAndroid Build Coastguard Worker AudioFrame seven_one_frame;
307*d9f75844SAndroid Build Coastguard Worker seven_one_frame.samples_per_channel_ = frame_.samples_per_channel();
308*d9f75844SAndroid Build Coastguard Worker SetSevenOneData(10, 20, 15, 2, 5, 5, 0, 0, &seven_one_frame);
309*d9f75844SAndroid Build Coastguard Worker VerifyFramesAreEqual(seven_one_frame, frame_);
310*d9f75844SAndroid Build Coastguard Worker
311*d9f75844SAndroid Build Coastguard Worker SetFiveOneData(-32768, 32767, -32768, 32767, -32768, 32767, &frame_);
312*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(6u, frame_.num_channels());
313*d9f75844SAndroid Build Coastguard Worker mixer.Transform(&frame_);
314*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(8u, frame_.num_channels());
315*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(CHANNEL_LAYOUT_7_1, frame_.channel_layout());
316*d9f75844SAndroid Build Coastguard Worker SetSevenOneData(-32768, 32767, -32768, 32767, -32768, 32767, 0, 0,
317*d9f75844SAndroid Build Coastguard Worker &seven_one_frame);
318*d9f75844SAndroid Build Coastguard Worker VerifyFramesAreEqual(seven_one_frame, frame_);
319*d9f75844SAndroid Build Coastguard Worker }
320*d9f75844SAndroid Build Coastguard Worker
TEST_F(ChannelMixerTest,FiveOneBackToStereo)321*d9f75844SAndroid Build Coastguard Worker TEST_F(ChannelMixerTest, FiveOneBackToStereo) {
322*d9f75844SAndroid Build Coastguard Worker ChannelMixer mixer(CHANNEL_LAYOUT_5_1_BACK, CHANNEL_LAYOUT_STEREO);
323*d9f75844SAndroid Build Coastguard Worker //
324*d9f75844SAndroid Build Coastguard Worker // Input: 5.1
325*d9f75844SAndroid Build Coastguard Worker // LEFT RIGHT CENTER LFE BACK_LEFT BACK_RIGHT
326*d9f75844SAndroid Build Coastguard Worker // Output: stereo LEFT 1 0 0.707 0.707 0.707 0
327*d9f75844SAndroid Build Coastguard Worker // RIGHT 0 1 0.707 0.707 0 0.707
328*d9f75844SAndroid Build Coastguard Worker //
329*d9f75844SAndroid Build Coastguard Worker SetFiveOneData(20, 30, 15, 2, 5, 5, &frame_);
330*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(6u, frame_.num_channels());
331*d9f75844SAndroid Build Coastguard Worker mixer.Transform(&frame_);
332*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2u, frame_.num_channels());
333*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(CHANNEL_LAYOUT_STEREO, frame_.channel_layout());
334*d9f75844SAndroid Build Coastguard Worker
335*d9f75844SAndroid Build Coastguard Worker AudioFrame stereo_frame;
336*d9f75844SAndroid Build Coastguard Worker stereo_frame.samples_per_channel_ = frame_.samples_per_channel();
337*d9f75844SAndroid Build Coastguard Worker SetStereoData(35, 45, &stereo_frame);
338*d9f75844SAndroid Build Coastguard Worker VerifyFramesAreEqual(stereo_frame, frame_);
339*d9f75844SAndroid Build Coastguard Worker
340*d9f75844SAndroid Build Coastguard Worker SetFiveOneData(-32768, -32768, -32768, -32768, -32768, -32768, &frame_);
341*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(6u, frame_.num_channels());
342*d9f75844SAndroid Build Coastguard Worker mixer.Transform(&frame_);
343*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2u, frame_.num_channels());
344*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(CHANNEL_LAYOUT_STEREO, frame_.channel_layout());
345*d9f75844SAndroid Build Coastguard Worker SetStereoData(-32768, -32768, &stereo_frame);
346*d9f75844SAndroid Build Coastguard Worker VerifyFramesAreEqual(stereo_frame, frame_);
347*d9f75844SAndroid Build Coastguard Worker }
348*d9f75844SAndroid Build Coastguard Worker
TEST_F(ChannelMixerTest,MonoToStereo)349*d9f75844SAndroid Build Coastguard Worker TEST_F(ChannelMixerTest, MonoToStereo) {
350*d9f75844SAndroid Build Coastguard Worker ChannelMixer mixer(CHANNEL_LAYOUT_MONO, CHANNEL_LAYOUT_STEREO);
351*d9f75844SAndroid Build Coastguard Worker //
352*d9f75844SAndroid Build Coastguard Worker // Input: mono
353*d9f75844SAndroid Build Coastguard Worker // CENTER
354*d9f75844SAndroid Build Coastguard Worker // Output: stereo LEFT 1
355*d9f75844SAndroid Build Coastguard Worker // RIGHT 1
356*d9f75844SAndroid Build Coastguard Worker //
357*d9f75844SAndroid Build Coastguard Worker SetMonoData(44, &frame_);
358*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1u, frame_.num_channels());
359*d9f75844SAndroid Build Coastguard Worker mixer.Transform(&frame_);
360*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2u, frame_.num_channels());
361*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(CHANNEL_LAYOUT_STEREO, frame_.channel_layout());
362*d9f75844SAndroid Build Coastguard Worker
363*d9f75844SAndroid Build Coastguard Worker AudioFrame stereo_frame;
364*d9f75844SAndroid Build Coastguard Worker stereo_frame.samples_per_channel_ = frame_.samples_per_channel();
365*d9f75844SAndroid Build Coastguard Worker SetStereoData(44, 44, &stereo_frame);
366*d9f75844SAndroid Build Coastguard Worker VerifyFramesAreEqual(stereo_frame, frame_);
367*d9f75844SAndroid Build Coastguard Worker }
368*d9f75844SAndroid Build Coastguard Worker
TEST_F(ChannelMixerTest,StereoToFiveOne)369*d9f75844SAndroid Build Coastguard Worker TEST_F(ChannelMixerTest, StereoToFiveOne) {
370*d9f75844SAndroid Build Coastguard Worker ChannelMixer mixer(CHANNEL_LAYOUT_STEREO, CHANNEL_LAYOUT_5_1);
371*d9f75844SAndroid Build Coastguard Worker //
372*d9f75844SAndroid Build Coastguard Worker // Input: Stereo
373*d9f75844SAndroid Build Coastguard Worker // LEFT RIGHT
374*d9f75844SAndroid Build Coastguard Worker // Output: 5.1 LEFT 1 0
375*d9f75844SAndroid Build Coastguard Worker // RIGHT 0 1
376*d9f75844SAndroid Build Coastguard Worker // CENTER 0 0
377*d9f75844SAndroid Build Coastguard Worker // LFE 0 0
378*d9f75844SAndroid Build Coastguard Worker // SIDE_LEFT 0 0
379*d9f75844SAndroid Build Coastguard Worker // SIDE_RIGHT 0 0
380*d9f75844SAndroid Build Coastguard Worker //
381*d9f75844SAndroid Build Coastguard Worker SetStereoData(50, 60, &frame_);
382*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2u, frame_.num_channels());
383*d9f75844SAndroid Build Coastguard Worker mixer.Transform(&frame_);
384*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(6u, frame_.num_channels());
385*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(CHANNEL_LAYOUT_5_1, frame_.channel_layout());
386*d9f75844SAndroid Build Coastguard Worker
387*d9f75844SAndroid Build Coastguard Worker AudioFrame five_one_frame;
388*d9f75844SAndroid Build Coastguard Worker five_one_frame.samples_per_channel_ = frame_.samples_per_channel();
389*d9f75844SAndroid Build Coastguard Worker SetFiveOneData(50, 60, 0, 0, 0, 0, &five_one_frame);
390*d9f75844SAndroid Build Coastguard Worker VerifyFramesAreEqual(five_one_frame, frame_);
391*d9f75844SAndroid Build Coastguard Worker }
392*d9f75844SAndroid Build Coastguard Worker
393*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
394