1 /*
2 * Copyright (c) 2011 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 #include <string>
11
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "webrtc/test/testsupport/fileutils.h"
14 #include "webrtc_cng.h"
15
16 namespace webrtc {
17
18 enum {
19 kSidShortIntervalUpdate = 1,
20 kSidNormalIntervalUpdate = 100,
21 kSidLongIntervalUpdate = 10000
22 };
23
24 enum {
25 kCNGNumParamsLow = 0,
26 kCNGNumParamsNormal = 8,
27 kCNGNumParamsHigh = WEBRTC_CNG_MAX_LPC_ORDER,
28 kCNGNumParamsTooHigh = WEBRTC_CNG_MAX_LPC_ORDER + 1
29 };
30
31 enum {
32 kNoSid,
33 kForceSid
34 };
35
36 class CngTest : public ::testing::Test {
37 protected:
38 CngTest();
39 virtual void SetUp();
40
41 CNG_enc_inst* cng_enc_inst_;
42 CNG_dec_inst* cng_dec_inst_;
43 int16_t speech_data_[640]; // Max size of CNG internal buffers.
44 };
45
CngTest()46 CngTest::CngTest()
47 : cng_enc_inst_(NULL),
48 cng_dec_inst_(NULL) {
49 }
50
SetUp()51 void CngTest::SetUp() {
52 FILE* input_file;
53 const std::string file_name =
54 webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
55 input_file = fopen(file_name.c_str(), "rb");
56 ASSERT_TRUE(input_file != NULL);
57 ASSERT_EQ(640, static_cast<int32_t>(fread(speech_data_, sizeof(int16_t),
58 640, input_file)));
59 fclose(input_file);
60 input_file = NULL;
61 }
62
63 // Test failing Create.
TEST_F(CngTest,CngCreateFail)64 TEST_F(CngTest, CngCreateFail) {
65 // Test to see that an invalid pointer is caught.
66 EXPECT_EQ(-1, WebRtcCng_CreateEnc(NULL));
67 EXPECT_EQ(-1, WebRtcCng_CreateDec(NULL));
68 }
69
70 // Test normal Create.
TEST_F(CngTest,CngCreate)71 TEST_F(CngTest, CngCreate) {
72 EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
73 EXPECT_EQ(0, WebRtcCng_CreateDec(&cng_dec_inst_));
74 EXPECT_TRUE(cng_enc_inst_ != NULL);
75 EXPECT_TRUE(cng_dec_inst_ != NULL);
76 // Free encoder and decoder memory.
77 EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
78 EXPECT_EQ(0, WebRtcCng_FreeDec(cng_dec_inst_));
79 }
80
81 // Create CNG encoder, init with faulty values, free CNG encoder.
TEST_F(CngTest,CngInitFail)82 TEST_F(CngTest, CngInitFail) {
83 // Create encoder memory.
84 EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
85
86 // Call with too few parameters.
87 EXPECT_EQ(-1, WebRtcCng_InitEnc(cng_enc_inst_, 8000, kSidNormalIntervalUpdate,
88 kCNGNumParamsLow));
89 EXPECT_EQ(6130, WebRtcCng_GetErrorCodeEnc(cng_enc_inst_));
90
91 // Call with too many parameters.
92 EXPECT_EQ(-1, WebRtcCng_InitEnc(cng_enc_inst_, 8000, kSidNormalIntervalUpdate,
93 kCNGNumParamsTooHigh));
94 EXPECT_EQ(6130, WebRtcCng_GetErrorCodeEnc(cng_enc_inst_));
95
96 // Free encoder memory.
97 EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
98 }
99
TEST_F(CngTest,CngEncode)100 TEST_F(CngTest, CngEncode) {
101 uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
102 size_t number_bytes;
103
104 // Create encoder memory.
105 EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
106
107 // 8 kHz, Normal number of parameters
108 EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 8000, kSidNormalIntervalUpdate,
109 kCNGNumParamsNormal));
110 EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 80, sid_data,
111 &number_bytes, kNoSid));
112 EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
113 cng_enc_inst_, speech_data_, 80, sid_data, &number_bytes, kForceSid));
114
115 // 16 kHz, Normal number of parameters
116 EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 16000, kSidNormalIntervalUpdate,
117 kCNGNumParamsNormal));
118 EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 160, sid_data,
119 &number_bytes, kNoSid));
120 EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
121 cng_enc_inst_, speech_data_, 160, sid_data, &number_bytes, kForceSid));
122
123 // 32 kHz, Max number of parameters
124 EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 32000, kSidNormalIntervalUpdate,
125 kCNGNumParamsHigh));
126 EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 320, sid_data,
127 &number_bytes, kNoSid));
128 EXPECT_EQ(kCNGNumParamsHigh + 1, WebRtcCng_Encode(
129 cng_enc_inst_, speech_data_, 320, sid_data, &number_bytes, kForceSid));
130
131 // 48 kHz, Normal number of parameters
132 EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 48000, kSidNormalIntervalUpdate,
133 kCNGNumParamsNormal));
134 EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 480, sid_data,
135 &number_bytes, kNoSid));
136 EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
137 cng_enc_inst_, speech_data_, 480, sid_data, &number_bytes, kForceSid));
138
139 // 64 kHz, Normal number of parameters
140 EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 64000, kSidNormalIntervalUpdate,
141 kCNGNumParamsNormal));
142 EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 640, sid_data,
143 &number_bytes, kNoSid));
144 EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
145 cng_enc_inst_, speech_data_, 640, sid_data, &number_bytes, kForceSid));
146
147 // Free encoder memory.
148 EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
149 }
150
151 // Encode Cng with too long input vector.
TEST_F(CngTest,CngEncodeTooLong)152 TEST_F(CngTest, CngEncodeTooLong) {
153 uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
154 size_t number_bytes;
155
156 // Create and init encoder memory.
157 EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
158 EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 8000, kSidNormalIntervalUpdate,
159 kCNGNumParamsNormal));
160
161 // Run encoder with too much data.
162 EXPECT_EQ(-1, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 641, sid_data,
163 &number_bytes, kNoSid));
164 EXPECT_EQ(6140, WebRtcCng_GetErrorCodeEnc(cng_enc_inst_));
165
166 // Free encoder memory.
167 EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
168 }
169
170 // Call encode without calling init.
TEST_F(CngTest,CngEncodeNoInit)171 TEST_F(CngTest, CngEncodeNoInit) {
172 uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
173 size_t number_bytes;
174
175 // Create encoder memory.
176 EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
177
178 // Run encoder without calling init.
179 EXPECT_EQ(-1, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 640, sid_data,
180 &number_bytes, kNoSid));
181 EXPECT_EQ(6120, WebRtcCng_GetErrorCodeEnc(cng_enc_inst_));
182
183 // Free encoder memory.
184 EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
185 }
186
187 // Update SID parameters, for both 9 and 16 parameters.
TEST_F(CngTest,CngUpdateSid)188 TEST_F(CngTest, CngUpdateSid) {
189 uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
190 size_t number_bytes;
191
192 // Create and initialize encoder and decoder memory.
193 EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
194 EXPECT_EQ(0, WebRtcCng_CreateDec(&cng_dec_inst_));
195 EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 16000, kSidNormalIntervalUpdate,
196 kCNGNumParamsNormal));
197 WebRtcCng_InitDec(cng_dec_inst_);
198
199 // Run normal Encode and UpdateSid.
200 EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
201 cng_enc_inst_, speech_data_, 160, sid_data, &number_bytes, kForceSid));
202 EXPECT_EQ(0, WebRtcCng_UpdateSid(cng_dec_inst_, sid_data,
203 kCNGNumParamsNormal + 1));
204
205 // Reinit with new length.
206 EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 16000, kSidNormalIntervalUpdate,
207 kCNGNumParamsHigh));
208 WebRtcCng_InitDec(cng_dec_inst_);
209
210 // Expect 0 because of unstable parameters after switching length.
211 EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 160, sid_data,
212 &number_bytes, kForceSid));
213 EXPECT_EQ(kCNGNumParamsHigh + 1, WebRtcCng_Encode(
214 cng_enc_inst_, speech_data_ + 160, 160, sid_data, &number_bytes,
215 kForceSid));
216 EXPECT_EQ(0, WebRtcCng_UpdateSid(cng_dec_inst_, sid_data,
217 kCNGNumParamsNormal + 1));
218
219 // Free encoder and decoder memory.
220 EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
221 EXPECT_EQ(0, WebRtcCng_FreeDec(cng_dec_inst_));
222 }
223
224 // Update SID parameters, with wrong parameters or without calling decode.
TEST_F(CngTest,CngUpdateSidErroneous)225 TEST_F(CngTest, CngUpdateSidErroneous) {
226 uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
227 size_t number_bytes;
228
229 // Create encoder and decoder memory.
230 EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
231 EXPECT_EQ(0, WebRtcCng_CreateDec(&cng_dec_inst_));
232
233 // Encode.
234 EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 16000, kSidNormalIntervalUpdate,
235 kCNGNumParamsNormal));
236 EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
237 cng_enc_inst_, speech_data_, 160, sid_data, &number_bytes, kForceSid));
238
239 // Update Sid before initializing decoder.
240 EXPECT_EQ(-1, WebRtcCng_UpdateSid(cng_dec_inst_, sid_data,
241 kCNGNumParamsNormal + 1));
242 EXPECT_EQ(6220, WebRtcCng_GetErrorCodeDec(cng_dec_inst_));
243
244 // Initialize decoder.
245 WebRtcCng_InitDec(cng_dec_inst_);
246
247 // First run with valid parameters, then with too many CNG parameters.
248 // The function will operate correctly by only reading the maximum number of
249 // parameters, skipping the extra.
250 EXPECT_EQ(0, WebRtcCng_UpdateSid(cng_dec_inst_, sid_data,
251 kCNGNumParamsNormal + 1));
252 EXPECT_EQ(0, WebRtcCng_UpdateSid(cng_dec_inst_, sid_data,
253 kCNGNumParamsTooHigh + 1));
254
255 // Free encoder and decoder memory.
256 EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
257 EXPECT_EQ(0, WebRtcCng_FreeDec(cng_dec_inst_));
258 }
259
260 // Test to generate cng data, by forcing SID. Both normal and faulty condition.
TEST_F(CngTest,CngGenerate)261 TEST_F(CngTest, CngGenerate) {
262 uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
263 int16_t out_data[640];
264 size_t number_bytes;
265
266 // Create and initialize encoder and decoder memory.
267 EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
268 EXPECT_EQ(0, WebRtcCng_CreateDec(&cng_dec_inst_));
269 EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 16000, kSidNormalIntervalUpdate,
270 kCNGNumParamsNormal));
271 WebRtcCng_InitDec(cng_dec_inst_);
272
273 // Normal Encode.
274 EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
275 cng_enc_inst_, speech_data_, 160, sid_data, &number_bytes, kForceSid));
276
277 // Normal UpdateSid.
278 EXPECT_EQ(0, WebRtcCng_UpdateSid(cng_dec_inst_, sid_data,
279 kCNGNumParamsNormal + 1));
280
281 // Two normal Generate, one with new_period.
282 EXPECT_EQ(0, WebRtcCng_Generate(cng_dec_inst_, out_data, 640, 1));
283 EXPECT_EQ(0, WebRtcCng_Generate(cng_dec_inst_, out_data, 640, 0));
284
285 // Call Genereate with too much data.
286 EXPECT_EQ(-1, WebRtcCng_Generate(cng_dec_inst_, out_data, 641, 0));
287 EXPECT_EQ(6140, WebRtcCng_GetErrorCodeDec(cng_dec_inst_));
288
289 // Free encoder and decoder memory.
290 EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
291 EXPECT_EQ(0, WebRtcCng_FreeDec(cng_dec_inst_));
292 }
293
294 // Test automatic SID.
TEST_F(CngTest,CngAutoSid)295 TEST_F(CngTest, CngAutoSid) {
296 uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
297 size_t number_bytes;
298
299 // Create and initialize encoder and decoder memory.
300 EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
301 EXPECT_EQ(0, WebRtcCng_CreateDec(&cng_dec_inst_));
302 EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 16000, kSidNormalIntervalUpdate,
303 kCNGNumParamsNormal));
304 WebRtcCng_InitDec(cng_dec_inst_);
305
306 // Normal Encode, 100 msec, where no SID data should be generated.
307 for (int i = 0; i < 10; i++) {
308 EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 160, sid_data,
309 &number_bytes, kNoSid));
310 }
311
312 // We have reached 100 msec, and SID data should be generated.
313 EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
314 cng_enc_inst_, speech_data_, 160, sid_data, &number_bytes, kNoSid));
315
316 // Free encoder and decoder memory.
317 EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
318 EXPECT_EQ(0, WebRtcCng_FreeDec(cng_dec_inst_));
319 }
320
321 // Test automatic SID, with very short interval.
TEST_F(CngTest,CngAutoSidShort)322 TEST_F(CngTest, CngAutoSidShort) {
323 uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
324 size_t number_bytes;
325
326 // Create and initialize encoder and decoder memory.
327 EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
328 EXPECT_EQ(0, WebRtcCng_CreateDec(&cng_dec_inst_));
329 EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 16000, kSidShortIntervalUpdate,
330 kCNGNumParamsNormal));
331 WebRtcCng_InitDec(cng_dec_inst_);
332
333 // First call will never generate SID, unless forced to.
334 EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 160, sid_data,
335 &number_bytes, kNoSid));
336
337 // Normal Encode, 100 msec, SID data should be generated all the time.
338 for (int i = 0; i < 10; i++) {
339 EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
340 cng_enc_inst_, speech_data_, 160, sid_data, &number_bytes, kNoSid));
341 }
342
343 // Free encoder and decoder memory.
344 EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
345 EXPECT_EQ(0, WebRtcCng_FreeDec(cng_dec_inst_));
346 }
347
348 } // namespace webrtc
349