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
16namespace webrtc {
17
18enum {
19  kSidShortIntervalUpdate = 1,
20  kSidNormalIntervalUpdate = 100,
21  kSidLongIntervalUpdate = 10000
22};
23
24enum {
25  kCNGNumParamsLow = 0,
26  kCNGNumParamsNormal = 8,
27  kCNGNumParamsHigh = WEBRTC_CNG_MAX_LPC_ORDER,
28  kCNGNumParamsTooHigh = WEBRTC_CNG_MAX_LPC_ORDER + 1
29};
30
31enum {
32  kNoSid,
33  kForceSid
34};
35
36class 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
46CngTest::CngTest()
47    : cng_enc_inst_(NULL),
48      cng_dec_inst_(NULL) {
49}
50
51void 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.
64TEST_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.
71TEST_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.
82TEST_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
100TEST_F(CngTest, CngEncode) {
101  uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
102  int16_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.
152TEST_F(CngTest, CngEncodeTooLong) {
153  uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
154  int16_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.
171TEST_F(CngTest, CngEncodeNoInit) {
172  uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
173  int16_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.
188TEST_F(CngTest, CngUpdateSid) {
189  uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
190  int16_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  EXPECT_EQ(0, 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  EXPECT_EQ(0, 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.
225TEST_F(CngTest, CngUpdateSidErroneous) {
226  uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
227  int16_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  EXPECT_EQ(0, 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.
261TEST_F(CngTest, CngGenerate) {
262  uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
263  int16_t out_data[640];
264  int16_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  EXPECT_EQ(0, 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.
295TEST_F(CngTest, CngAutoSid) {
296  uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
297  int16_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  EXPECT_EQ(0, 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.
322TEST_F(CngTest, CngAutoSidShort) {
323  uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
324  int16_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  EXPECT_EQ(0, 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