You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			349 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
			
		
		
	
	
			349 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
| /*
 | |
|  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 | |
|  *
 | |
|  *  Use of this source code is governed by a BSD-style license
 | |
|  *  that can be found in the LICENSE file in the root of the source
 | |
|  *  tree. An additional intellectual property rights grant can be found
 | |
|  *  in the file PATENTS.  All contributing project authors may
 | |
|  *  be found in the AUTHORS file in the root of the source tree.
 | |
|  */
 | |
| #include <string>
 | |
| 
 | |
| #include "gtest/gtest.h"
 | |
| #include "webrtc/test/testsupport/fileutils.h"
 | |
| #include "webrtc_cng.h"
 | |
| 
 | |
| namespace webrtc {
 | |
| 
 | |
| enum {
 | |
|   kSidShortIntervalUpdate = 1,
 | |
|   kSidNormalIntervalUpdate = 100,
 | |
|   kSidLongIntervalUpdate = 10000
 | |
| };
 | |
| 
 | |
| enum {
 | |
|   kCNGNumParamsLow = 0,
 | |
|   kCNGNumParamsNormal = 8,
 | |
|   kCNGNumParamsHigh = WEBRTC_CNG_MAX_LPC_ORDER,
 | |
|   kCNGNumParamsTooHigh = WEBRTC_CNG_MAX_LPC_ORDER + 1
 | |
| };
 | |
| 
 | |
| enum {
 | |
|   kNoSid,
 | |
|   kForceSid
 | |
| };
 | |
| 
 | |
| class CngTest : public ::testing::Test {
 | |
|  protected:
 | |
|   CngTest();
 | |
|   virtual void SetUp();
 | |
| 
 | |
|   CNG_enc_inst* cng_enc_inst_;
 | |
|   CNG_dec_inst* cng_dec_inst_;
 | |
|   int16_t speech_data_[640];  // Max size of CNG internal buffers.
 | |
| };
 | |
| 
 | |
| CngTest::CngTest()
 | |
|     : cng_enc_inst_(NULL),
 | |
|       cng_dec_inst_(NULL) {
 | |
| }
 | |
| 
 | |
| void CngTest::SetUp() {
 | |
|   FILE* input_file;
 | |
|   const std::string file_name =
 | |
|         webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
 | |
|   input_file = fopen(file_name.c_str(), "rb");
 | |
|   ASSERT_TRUE(input_file != NULL);
 | |
|   ASSERT_EQ(640, static_cast<int32_t>(fread(speech_data_, sizeof(int16_t),
 | |
|                                              640, input_file)));
 | |
|   fclose(input_file);
 | |
|   input_file = NULL;
 | |
| }
 | |
| 
 | |
| // Test failing Create.
 | |
| TEST_F(CngTest, CngCreateFail) {
 | |
|   // Test to see that an invalid pointer is caught.
 | |
|   EXPECT_EQ(-1, WebRtcCng_CreateEnc(NULL));
 | |
|   EXPECT_EQ(-1, WebRtcCng_CreateDec(NULL));
 | |
| }
 | |
| 
 | |
| // Test normal Create.
 | |
| TEST_F(CngTest, CngCreate) {
 | |
|   EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
 | |
|   EXPECT_EQ(0, WebRtcCng_CreateDec(&cng_dec_inst_));
 | |
|   EXPECT_TRUE(cng_enc_inst_ != NULL);
 | |
|   EXPECT_TRUE(cng_dec_inst_ != NULL);
 | |
|   // Free encoder and decoder memory.
 | |
|   EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
 | |
|   EXPECT_EQ(0, WebRtcCng_FreeDec(cng_dec_inst_));
 | |
| }
 | |
| 
 | |
| // Create CNG encoder, init with faulty values, free CNG encoder.
 | |
| TEST_F(CngTest, CngInitFail) {
 | |
|   // Create encoder memory.
 | |
|   EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
 | |
| 
 | |
|   // Call with too few parameters.
 | |
|   EXPECT_EQ(-1, WebRtcCng_InitEnc(cng_enc_inst_, 8000, kSidNormalIntervalUpdate,
 | |
|                                   kCNGNumParamsLow));
 | |
|   EXPECT_EQ(6130, WebRtcCng_GetErrorCodeEnc(cng_enc_inst_));
 | |
| 
 | |
|   // Call with too many parameters.
 | |
|   EXPECT_EQ(-1, WebRtcCng_InitEnc(cng_enc_inst_, 8000, kSidNormalIntervalUpdate,
 | |
|                                   kCNGNumParamsTooHigh));
 | |
|   EXPECT_EQ(6130, WebRtcCng_GetErrorCodeEnc(cng_enc_inst_));
 | |
| 
 | |
|   // Free encoder memory.
 | |
|   EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
 | |
| }
 | |
| 
 | |
| TEST_F(CngTest, CngEncode) {
 | |
|   uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
 | |
|   int16_t number_bytes;
 | |
| 
 | |
|   // Create encoder memory.
 | |
|   EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
 | |
| 
 | |
|   // 8 kHz, Normal number of parameters
 | |
|   EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 8000, kSidNormalIntervalUpdate,
 | |
|                                  kCNGNumParamsNormal));
 | |
|   EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 80, sid_data,
 | |
|                                 &number_bytes, kNoSid));
 | |
|   EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
 | |
|       cng_enc_inst_, speech_data_, 80, sid_data, &number_bytes, kForceSid));
 | |
| 
 | |
|   // 16 kHz, Normal number of parameters
 | |
|   EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 16000, kSidNormalIntervalUpdate,
 | |
|                                  kCNGNumParamsNormal));
 | |
|   EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 160, sid_data,
 | |
|                                 &number_bytes, kNoSid));
 | |
|   EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
 | |
|       cng_enc_inst_, speech_data_, 160, sid_data, &number_bytes, kForceSid));
 | |
| 
 | |
|   // 32 kHz, Max number of parameters
 | |
|   EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 32000, kSidNormalIntervalUpdate,
 | |
|                                  kCNGNumParamsHigh));
 | |
|   EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 320, sid_data,
 | |
|                                 &number_bytes, kNoSid));
 | |
|   EXPECT_EQ(kCNGNumParamsHigh + 1, WebRtcCng_Encode(
 | |
|       cng_enc_inst_, speech_data_, 320, sid_data, &number_bytes, kForceSid));
 | |
| 
 | |
|   // 48 kHz, Normal number of parameters
 | |
|   EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 48000, kSidNormalIntervalUpdate,
 | |
|                                  kCNGNumParamsNormal));
 | |
|   EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 480, sid_data,
 | |
|                                 &number_bytes, kNoSid));
 | |
|   EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
 | |
|       cng_enc_inst_, speech_data_, 480, sid_data, &number_bytes, kForceSid));
 | |
| 
 | |
|   // 64 kHz, Normal number of parameters
 | |
|   EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 64000, kSidNormalIntervalUpdate,
 | |
|                                  kCNGNumParamsNormal));
 | |
|   EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 640, sid_data,
 | |
|                                 &number_bytes, kNoSid));
 | |
|   EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
 | |
|       cng_enc_inst_, speech_data_, 640, sid_data, &number_bytes, kForceSid));
 | |
| 
 | |
|   // Free encoder memory.
 | |
|   EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
 | |
| }
 | |
| 
 | |
| // Encode Cng with too long input vector.
 | |
| TEST_F(CngTest, CngEncodeTooLong) {
 | |
|   uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
 | |
|   int16_t number_bytes;
 | |
| 
 | |
|   // Create and init encoder memory.
 | |
|   EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
 | |
|   EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 8000, kSidNormalIntervalUpdate,
 | |
|                                  kCNGNumParamsNormal));
 | |
| 
 | |
|   // Run encoder with too much data.
 | |
|   EXPECT_EQ(-1, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 641, sid_data,
 | |
|                                  &number_bytes, kNoSid));
 | |
|   EXPECT_EQ(6140, WebRtcCng_GetErrorCodeEnc(cng_enc_inst_));
 | |
| 
 | |
|   // Free encoder memory.
 | |
|   EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
 | |
| }
 | |
| 
 | |
| // Call encode without calling init.
 | |
| TEST_F(CngTest, CngEncodeNoInit) {
 | |
|   uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
 | |
|   int16_t number_bytes;
 | |
| 
 | |
|   // Create encoder memory.
 | |
|   EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
 | |
| 
 | |
|   // Run encoder without calling init.
 | |
|   EXPECT_EQ(-1, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 640, sid_data,
 | |
|                                  &number_bytes, kNoSid));
 | |
|   EXPECT_EQ(6120, WebRtcCng_GetErrorCodeEnc(cng_enc_inst_));
 | |
| 
 | |
|   // Free encoder memory.
 | |
|   EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
 | |
| }
 | |
| 
 | |
| // Update SID parameters, for both 9 and 16 parameters.
 | |
| TEST_F(CngTest, CngUpdateSid) {
 | |
|   uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
 | |
|   int16_t number_bytes;
 | |
| 
 | |
|   // Create and initialize encoder and decoder memory.
 | |
|   EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
 | |
|   EXPECT_EQ(0, WebRtcCng_CreateDec(&cng_dec_inst_));
 | |
|   EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 16000, kSidNormalIntervalUpdate,
 | |
|                                  kCNGNumParamsNormal));
 | |
|   EXPECT_EQ(0, WebRtcCng_InitDec(cng_dec_inst_));
 | |
| 
 | |
|   // Run normal Encode and UpdateSid.
 | |
|   EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
 | |
|       cng_enc_inst_, speech_data_, 160, sid_data, &number_bytes, kForceSid));
 | |
|   EXPECT_EQ(0, WebRtcCng_UpdateSid(cng_dec_inst_, sid_data,
 | |
|                                    kCNGNumParamsNormal + 1));
 | |
| 
 | |
|   // Reinit with new length.
 | |
|   EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 16000, kSidNormalIntervalUpdate,
 | |
|                                  kCNGNumParamsHigh));
 | |
|   EXPECT_EQ(0, WebRtcCng_InitDec(cng_dec_inst_));
 | |
| 
 | |
|   // Expect 0 because of unstable parameters after switching length.
 | |
|   EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 160, sid_data,
 | |
|                                 &number_bytes, kForceSid));
 | |
|   EXPECT_EQ(kCNGNumParamsHigh + 1, WebRtcCng_Encode(
 | |
|       cng_enc_inst_, speech_data_ + 160, 160, sid_data, &number_bytes,
 | |
|       kForceSid));
 | |
|   EXPECT_EQ(0, WebRtcCng_UpdateSid(cng_dec_inst_, sid_data,
 | |
|                                    kCNGNumParamsNormal + 1));
 | |
| 
 | |
|   // Free encoder and decoder memory.
 | |
|   EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
 | |
|   EXPECT_EQ(0, WebRtcCng_FreeDec(cng_dec_inst_));
 | |
| }
 | |
| 
 | |
| // Update SID parameters, with wrong parameters or without calling decode.
 | |
| TEST_F(CngTest, CngUpdateSidErroneous) {
 | |
|   uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
 | |
|   int16_t number_bytes;
 | |
| 
 | |
|   // Create encoder and decoder memory.
 | |
|   EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
 | |
|   EXPECT_EQ(0, WebRtcCng_CreateDec(&cng_dec_inst_));
 | |
| 
 | |
|   // Encode.
 | |
|   EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 16000, kSidNormalIntervalUpdate,
 | |
|                                  kCNGNumParamsNormal));
 | |
|   EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
 | |
|       cng_enc_inst_, speech_data_, 160, sid_data, &number_bytes, kForceSid));
 | |
| 
 | |
|   // Update Sid before initializing decoder.
 | |
|   EXPECT_EQ(-1, WebRtcCng_UpdateSid(cng_dec_inst_, sid_data,
 | |
|                                     kCNGNumParamsNormal + 1));
 | |
|   EXPECT_EQ(6220, WebRtcCng_GetErrorCodeDec(cng_dec_inst_));
 | |
| 
 | |
|   // Initialize decoder.
 | |
|   EXPECT_EQ(0, WebRtcCng_InitDec(cng_dec_inst_));
 | |
| 
 | |
|   // First run with valid parameters, then with too many CNG parameters.
 | |
|   // The function will operate correctly by only reading the maximum number of
 | |
|   // parameters, skipping the extra.
 | |
|   EXPECT_EQ(0, WebRtcCng_UpdateSid(cng_dec_inst_, sid_data,
 | |
|                                    kCNGNumParamsNormal + 1));
 | |
|   EXPECT_EQ(0, WebRtcCng_UpdateSid(cng_dec_inst_, sid_data,
 | |
|                                    kCNGNumParamsTooHigh + 1));
 | |
| 
 | |
|   // Free encoder and decoder memory.
 | |
|   EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
 | |
|   EXPECT_EQ(0, WebRtcCng_FreeDec(cng_dec_inst_));
 | |
| }
 | |
| 
 | |
| // Test to generate cng data, by forcing SID. Both normal and faulty condition.
 | |
| TEST_F(CngTest, CngGenerate) {
 | |
|   uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
 | |
|   int16_t out_data[640];
 | |
|   int16_t number_bytes;
 | |
| 
 | |
|   // Create and initialize encoder and decoder memory.
 | |
|   EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
 | |
|   EXPECT_EQ(0, WebRtcCng_CreateDec(&cng_dec_inst_));
 | |
|   EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 16000, kSidNormalIntervalUpdate,
 | |
|                                  kCNGNumParamsNormal));
 | |
|   EXPECT_EQ(0, WebRtcCng_InitDec(cng_dec_inst_));
 | |
| 
 | |
|   // Normal Encode.
 | |
|   EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
 | |
|       cng_enc_inst_, speech_data_, 160, sid_data, &number_bytes, kForceSid));
 | |
| 
 | |
|   // Normal UpdateSid.
 | |
|   EXPECT_EQ(0, WebRtcCng_UpdateSid(cng_dec_inst_, sid_data,
 | |
|                                    kCNGNumParamsNormal + 1));
 | |
| 
 | |
|   // Two normal Generate, one with new_period.
 | |
|   EXPECT_EQ(0, WebRtcCng_Generate(cng_dec_inst_, out_data, 640, 1));
 | |
|   EXPECT_EQ(0, WebRtcCng_Generate(cng_dec_inst_, out_data, 640, 0));
 | |
| 
 | |
|   // Call Genereate with too much data.
 | |
|   EXPECT_EQ(-1, WebRtcCng_Generate(cng_dec_inst_, out_data, 641, 0));
 | |
|   EXPECT_EQ(6140, WebRtcCng_GetErrorCodeDec(cng_dec_inst_));
 | |
| 
 | |
|   // Free encoder and decoder memory.
 | |
|   EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
 | |
|   EXPECT_EQ(0, WebRtcCng_FreeDec(cng_dec_inst_));
 | |
| }
 | |
| 
 | |
| // Test automatic SID.
 | |
| TEST_F(CngTest, CngAutoSid) {
 | |
|   uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
 | |
|   int16_t number_bytes;
 | |
| 
 | |
|   // Create and initialize encoder and decoder memory.
 | |
|   EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
 | |
|   EXPECT_EQ(0, WebRtcCng_CreateDec(&cng_dec_inst_));
 | |
|   EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 16000, kSidNormalIntervalUpdate,
 | |
|                                  kCNGNumParamsNormal));
 | |
|   EXPECT_EQ(0, WebRtcCng_InitDec(cng_dec_inst_));
 | |
| 
 | |
|   // Normal Encode, 100 msec, where no SID data should be generated.
 | |
|   for (int i = 0; i < 10; i++) {
 | |
|     EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 160, sid_data,
 | |
|                                   &number_bytes, kNoSid));
 | |
|   }
 | |
| 
 | |
|   // We have reached 100 msec, and SID data should be generated.
 | |
|   EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
 | |
|       cng_enc_inst_, speech_data_, 160, sid_data, &number_bytes, kNoSid));
 | |
| 
 | |
|   // Free encoder and decoder memory.
 | |
|   EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
 | |
|   EXPECT_EQ(0, WebRtcCng_FreeDec(cng_dec_inst_));
 | |
| }
 | |
| 
 | |
| // Test automatic SID, with very short interval.
 | |
| TEST_F(CngTest, CngAutoSidShort) {
 | |
|   uint8_t sid_data[WEBRTC_CNG_MAX_LPC_ORDER + 1];
 | |
|   int16_t number_bytes;
 | |
| 
 | |
|   // Create and initialize encoder and decoder memory.
 | |
|   EXPECT_EQ(0, WebRtcCng_CreateEnc(&cng_enc_inst_));
 | |
|   EXPECT_EQ(0, WebRtcCng_CreateDec(&cng_dec_inst_));
 | |
|   EXPECT_EQ(0, WebRtcCng_InitEnc(cng_enc_inst_, 16000, kSidShortIntervalUpdate,
 | |
|                                  kCNGNumParamsNormal));
 | |
|   EXPECT_EQ(0, WebRtcCng_InitDec(cng_dec_inst_));
 | |
| 
 | |
|   // First call will never generate SID, unless forced to.
 | |
|   EXPECT_EQ(0, WebRtcCng_Encode(cng_enc_inst_, speech_data_, 160, sid_data,
 | |
|                                 &number_bytes, kNoSid));
 | |
| 
 | |
|   // Normal Encode, 100 msec, SID data should be generated all the time.
 | |
|   for (int i = 0; i < 10; i++) {
 | |
|     EXPECT_EQ(kCNGNumParamsNormal + 1, WebRtcCng_Encode(
 | |
|         cng_enc_inst_, speech_data_, 160, sid_data, &number_bytes, kNoSid));
 | |
|   }
 | |
| 
 | |
|   // Free encoder and decoder memory.
 | |
|   EXPECT_EQ(0, WebRtcCng_FreeEnc(cng_enc_inst_));
 | |
|   EXPECT_EQ(0, WebRtcCng_FreeDec(cng_dec_inst_));
 | |
| }
 | |
| 
 | |
| }  // namespace webrtc
 |