Home | History | Annotate | Download | only in cng
      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 
     46 CngTest::CngTest()
     47     : cng_enc_inst_(NULL),
     48       cng_dec_inst_(NULL) {
     49 }
     50 
     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.
     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.
     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.
     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 
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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