mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-04 23:45:14 +00:00
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
|