1/*
2 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "testing/gmock/include/gmock/gmock.h"
12#include "testing/gtest/include/gtest/gtest.h"
13#include "webrtc/common_audio/include/audio_util.h"
14#include "webrtc/typedefs.h"
15
16namespace webrtc {
17namespace {
18
19using ::testing::ElementsAreArray;
20
21void ExpectArraysEq(const int16_t* ref, const int16_t* test, size_t length) {
22  for (size_t i = 0; i < length; ++i) {
23    EXPECT_EQ(ref[i], test[i]);
24  }
25}
26
27void ExpectArraysEq(const float* ref, const float* test, size_t length) {
28  for (size_t i = 0; i < length; ++i) {
29    EXPECT_FLOAT_EQ(ref[i], test[i]);
30  }
31}
32
33TEST(AudioUtilTest, FloatToS16) {
34  const size_t kSize = 9;
35  const float kInput[kSize] = {0.f,
36                               0.4f / 32767.f,
37                               0.6f / 32767.f,
38                               -0.4f / 32768.f,
39                               -0.6f / 32768.f,
40                               1.f,
41                               -1.f,
42                               1.1f,
43                               -1.1f};
44  const int16_t kReference[kSize] = {0,     0,      1,     0,     -1,
45                                     32767, -32768, 32767, -32768};
46  int16_t output[kSize];
47  FloatToS16(kInput, kSize, output);
48  ExpectArraysEq(kReference, output, kSize);
49}
50
51TEST(AudioUtilTest, S16ToFloat) {
52  const size_t kSize = 7;
53  const int16_t kInput[kSize] = {0, 1, -1, 16384, -16384, 32767, -32768};
54  const float kReference[kSize] = {
55      0.f, 1.f / 32767.f, -1.f / 32768.f, 16384.f / 32767.f, -0.5f, 1.f, -1.f};
56  float output[kSize];
57  S16ToFloat(kInput, kSize, output);
58  ExpectArraysEq(kReference, output, kSize);
59}
60
61TEST(AudioUtilTest, FloatS16ToS16) {
62  const size_t kSize = 7;
63  const float kInput[kSize] = {0.f,   0.4f,    0.5f,    -0.4f,
64                               -0.5f, 32768.f, -32769.f};
65  const int16_t kReference[kSize] = {0, 0, 1, 0, -1, 32767, -32768};
66  int16_t output[kSize];
67  FloatS16ToS16(kInput, kSize, output);
68  ExpectArraysEq(kReference, output, kSize);
69}
70
71TEST(AudioUtilTest, FloatToFloatS16) {
72  const size_t kSize = 9;
73  const float kInput[kSize] = {0.f,
74                               0.4f / 32767.f,
75                               0.6f / 32767.f,
76                               -0.4f / 32768.f,
77                               -0.6f / 32768.f,
78                               1.f,
79                               -1.f,
80                               1.1f,
81                               -1.1f};
82  const float kReference[kSize] = {0.f,     0.4f,     0.6f,     -0.4f,    -0.6f,
83                                   32767.f, -32768.f, 36043.7f, -36044.8f};
84  float output[kSize];
85  FloatToFloatS16(kInput, kSize, output);
86  ExpectArraysEq(kReference, output, kSize);
87}
88
89TEST(AudioUtilTest, FloatS16ToFloat) {
90  const size_t kSize = 9;
91  const float kInput[kSize] = {0.f,     0.4f,     0.6f,     -0.4f,    -0.6f,
92                               32767.f, -32768.f, 36043.7f, -36044.8f};
93  const float kReference[kSize] = {0.f,
94                                   0.4f / 32767.f,
95                                   0.6f / 32767.f,
96                                   -0.4f / 32768.f,
97                                   -0.6f / 32768.f,
98                                   1.f,
99                                   -1.f,
100                                   1.1f,
101                                   -1.1f};
102  float output[kSize];
103  FloatS16ToFloat(kInput, kSize, output);
104  ExpectArraysEq(kReference, output, kSize);
105}
106
107TEST(AudioUtilTest, InterleavingStereo) {
108  const int16_t kInterleaved[] = {2, 3, 4, 9, 8, 27, 16, 81};
109  const size_t kSamplesPerChannel = 4;
110  const int kNumChannels = 2;
111  const size_t kLength = kSamplesPerChannel * kNumChannels;
112  int16_t left[kSamplesPerChannel], right[kSamplesPerChannel];
113  int16_t* deinterleaved[] = {left, right};
114  Deinterleave(kInterleaved, kSamplesPerChannel, kNumChannels, deinterleaved);
115  const int16_t kRefLeft[] = {2, 4, 8, 16};
116  const int16_t kRefRight[] = {3, 9, 27, 81};
117  ExpectArraysEq(kRefLeft, left, kSamplesPerChannel);
118  ExpectArraysEq(kRefRight, right, kSamplesPerChannel);
119
120  int16_t interleaved[kLength];
121  Interleave(deinterleaved, kSamplesPerChannel, kNumChannels, interleaved);
122  ExpectArraysEq(kInterleaved, interleaved, kLength);
123}
124
125TEST(AudioUtilTest, InterleavingMonoIsIdentical) {
126  const int16_t kInterleaved[] = {1, 2, 3, 4, 5};
127  const size_t kSamplesPerChannel = 5;
128  const int kNumChannels = 1;
129  int16_t mono[kSamplesPerChannel];
130  int16_t* deinterleaved[] = {mono};
131  Deinterleave(kInterleaved, kSamplesPerChannel, kNumChannels, deinterleaved);
132  ExpectArraysEq(kInterleaved, mono, kSamplesPerChannel);
133
134  int16_t interleaved[kSamplesPerChannel];
135  Interleave(deinterleaved, kSamplesPerChannel, kNumChannels, interleaved);
136  ExpectArraysEq(mono, interleaved, kSamplesPerChannel);
137}
138
139TEST(AudioUtilTest, DownmixInterleavedToMono) {
140  {
141    const size_t kNumFrames = 4;
142    const int kNumChannels = 1;
143    const int16_t interleaved[kNumChannels * kNumFrames] = {1, 2, -1, -3};
144    int16_t deinterleaved[kNumFrames];
145
146    DownmixInterleavedToMono(interleaved, kNumFrames, kNumChannels,
147                             deinterleaved);
148
149    EXPECT_THAT(deinterleaved, ElementsAreArray(interleaved));
150  }
151  {
152    const size_t kNumFrames = 2;
153    const int kNumChannels = 2;
154    const int16_t interleaved[kNumChannels * kNumFrames] = {10, 20, -10, -30};
155    int16_t deinterleaved[kNumFrames];
156
157    DownmixInterleavedToMono(interleaved, kNumFrames, kNumChannels,
158                             deinterleaved);
159    const int16_t expected[kNumFrames] = {15, -20};
160
161    EXPECT_THAT(deinterleaved, ElementsAreArray(expected));
162  }
163  {
164    const size_t kNumFrames = 3;
165    const int kNumChannels = 3;
166    const int16_t interleaved[kNumChannels * kNumFrames] = {
167        30000, 30000, 24001, -5, -10, -20, -30000, -30999, -30000};
168    int16_t deinterleaved[kNumFrames];
169
170    DownmixInterleavedToMono(interleaved, kNumFrames, kNumChannels,
171                             deinterleaved);
172    const int16_t expected[kNumFrames] = {28000, -11, -30333};
173
174    EXPECT_THAT(deinterleaved, ElementsAreArray(expected));
175  }
176}
177
178TEST(AudioUtilTest, DownmixToMonoTest) {
179  {
180    const size_t kNumFrames = 4;
181    const int kNumChannels = 1;
182    const float input_data[kNumChannels][kNumFrames] = {{1.f, 2.f, -1.f, -3.f}};
183    const float* input[kNumChannels];
184    for (int i = 0; i < kNumChannels; ++i) {
185      input[i] = input_data[i];
186    }
187
188    float downmixed[kNumFrames];
189
190    DownmixToMono<float, float>(input, kNumFrames, kNumChannels, downmixed);
191
192    EXPECT_THAT(downmixed, ElementsAreArray(input_data[0]));
193  }
194  {
195    const size_t kNumFrames = 3;
196    const int kNumChannels = 2;
197    const float input_data[kNumChannels][kNumFrames] = {{1.f, 2.f, -1.f},
198                                                        {3.f, 0.f, 1.f}};
199    const float* input[kNumChannels];
200    for (int i = 0; i < kNumChannels; ++i) {
201      input[i] = input_data[i];
202    }
203
204    float downmixed[kNumFrames];
205    const float expected[kNumFrames] = {2.f, 1.f, 0.f};
206
207    DownmixToMono<float, float>(input, kNumFrames, kNumChannels, downmixed);
208
209    EXPECT_THAT(downmixed, ElementsAreArray(expected));
210  }
211  {
212    const size_t kNumFrames = 3;
213    const int kNumChannels = 3;
214    const int16_t input_data[kNumChannels][kNumFrames] = {
215        {30000, -5, -30000}, {30000, -10, -30999}, {24001, -20, -30000}};
216    const int16_t* input[kNumChannels];
217    for (int i = 0; i < kNumChannels; ++i) {
218      input[i] = input_data[i];
219    }
220
221    int16_t downmixed[kNumFrames];
222    const int16_t expected[kNumFrames] = {28000, -11, -30333};
223
224    DownmixToMono<int16_t, int32_t>(input, kNumFrames, kNumChannels, downmixed);
225
226    EXPECT_THAT(downmixed, ElementsAreArray(expected));
227  }
228}
229
230}  // namespace
231}  // namespace webrtc
232