blob: 54e5189d30a200cb1415dd7c1c6755d2ac89d4af [file] [log] [blame]
kjellander@webrtc.org64a897a2011-11-17 13:33:11 +00001/*
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 */
ossu97ba30e2016-04-25 07:55:58 -070010#include <memory>
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000011#include <string>
kjellander@webrtc.org64a897a2011-11-17 13:33:11 +000012
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "modules/audio_coding/codecs/cng/webrtc_cng.h"
14#include "test/gtest.h"
15#include "test/testsupport/fileutils.h"
kjellander@webrtc.org64a897a2011-11-17 13:33:11 +000016
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000017namespace webrtc {
18
19enum {
20 kSidShortIntervalUpdate = 1,
21 kSidNormalIntervalUpdate = 100,
22 kSidLongIntervalUpdate = 10000
23};
24
ossu97ba30e2016-04-25 07:55:58 -070025enum : size_t {
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000026 kCNGNumParamsLow = 0,
27 kCNGNumParamsNormal = 8,
28 kCNGNumParamsHigh = WEBRTC_CNG_MAX_LPC_ORDER,
29 kCNGNumParamsTooHigh = WEBRTC_CNG_MAX_LPC_ORDER + 1
30};
31
32enum {
33 kNoSid,
34 kForceSid
35};
36
37class CngTest : public ::testing::Test {
38 protected:
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000039 virtual void SetUp();
40
ossu97ba30e2016-04-25 07:55:58 -070041 void TestCngEncode(int sample_rate_hz, int quality);
42
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000043 int16_t speech_data_[640]; // Max size of CNG internal buffers.
44};
45
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000046void CngTest::SetUp() {
47 FILE* input_file;
48 const std::string file_name =
49 webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
50 input_file = fopen(file_name.c_str(), "rb");
51 ASSERT_TRUE(input_file != NULL);
tina.legrand@webrtc.org95c23642012-09-28 10:49:59 +000052 ASSERT_EQ(640, static_cast<int32_t>(fread(speech_data_, sizeof(int16_t),
53 640, input_file)));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000054 fclose(input_file);
55 input_file = NULL;
56}
57
ossu97ba30e2016-04-25 07:55:58 -070058void CngTest::TestCngEncode(int sample_rate_hz, int quality) {
59 const size_t num_samples_10ms = rtc::CheckedDivExact(sample_rate_hz, 100);
60 rtc::Buffer sid_data;
61
62 ComfortNoiseEncoder cng_encoder(sample_rate_hz, kSidNormalIntervalUpdate,
63 quality);
64 EXPECT_EQ(0U, cng_encoder.Encode(rtc::ArrayView<const int16_t>(
65 speech_data_, num_samples_10ms),
66 kNoSid, &sid_data));
67 EXPECT_EQ(static_cast<size_t>(quality + 1),
68 cng_encoder.Encode(
69 rtc::ArrayView<const int16_t>(speech_data_, num_samples_10ms),
70 kForceSid, &sid_data));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000071}
72
ossu97ba30e2016-04-25 07:55:58 -070073#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000074// Create CNG encoder, init with faulty values, free CNG encoder.
henrika1d34fe92015-06-16 10:04:20 +020075TEST_F(CngTest, CngInitFail) {
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000076 // Call with too few parameters.
ossu97ba30e2016-04-25 07:55:58 -070077 EXPECT_DEATH({ ComfortNoiseEncoder(8000, kSidNormalIntervalUpdate,
78 kCNGNumParamsLow); }, "");
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000079 // Call with too many parameters.
ossu97ba30e2016-04-25 07:55:58 -070080 EXPECT_DEATH({ ComfortNoiseEncoder(8000, kSidNormalIntervalUpdate,
81 kCNGNumParamsTooHigh); }, "");
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000082}
83
84// Encode Cng with too long input vector.
henrika1d34fe92015-06-16 10:04:20 +020085TEST_F(CngTest, CngEncodeTooLong) {
ossu97ba30e2016-04-25 07:55:58 -070086 rtc::Buffer sid_data;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000087
ossu97ba30e2016-04-25 07:55:58 -070088 // Create encoder.
89 ComfortNoiseEncoder cng_encoder(8000, kSidNormalIntervalUpdate,
90 kCNGNumParamsNormal);
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000091 // Run encoder with too much data.
ossu97ba30e2016-04-25 07:55:58 -070092 EXPECT_DEATH(
93 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 641),
94 kNoSid, &sid_data),
95 "");
96}
97#endif // GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000098
ossu97ba30e2016-04-25 07:55:58 -070099TEST_F(CngTest, CngEncode8000) {
100 TestCngEncode(8000, kCNGNumParamsNormal);
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000101}
102
ossu97ba30e2016-04-25 07:55:58 -0700103TEST_F(CngTest, CngEncode16000) {
104 TestCngEncode(16000, kCNGNumParamsNormal);
105}
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000106
ossu97ba30e2016-04-25 07:55:58 -0700107TEST_F(CngTest, CngEncode32000) {
108 TestCngEncode(32000, kCNGNumParamsHigh);
109}
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000110
ossu97ba30e2016-04-25 07:55:58 -0700111TEST_F(CngTest, CngEncode48000) {
112 TestCngEncode(48000, kCNGNumParamsNormal);
113}
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000114
ossu97ba30e2016-04-25 07:55:58 -0700115TEST_F(CngTest, CngEncode64000) {
116 TestCngEncode(64000, kCNGNumParamsNormal);
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000117}
118
119// Update SID parameters, for both 9 and 16 parameters.
henrika1d34fe92015-06-16 10:04:20 +0200120TEST_F(CngTest, CngUpdateSid) {
ossu97ba30e2016-04-25 07:55:58 -0700121 rtc::Buffer sid_data;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000122
ossu97ba30e2016-04-25 07:55:58 -0700123 // Create and initialize encoder and decoder.
124 ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
125 kCNGNumParamsNormal);
126 ComfortNoiseDecoder cng_decoder;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000127
128 // Run normal Encode and UpdateSid.
ossu97ba30e2016-04-25 07:55:58 -0700129 EXPECT_EQ(kCNGNumParamsNormal + 1,
130 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
131 kForceSid, &sid_data));
132 cng_decoder.UpdateSid(sid_data);
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000133
134 // Reinit with new length.
ossu97ba30e2016-04-25 07:55:58 -0700135 cng_encoder.Reset(16000, kSidNormalIntervalUpdate, kCNGNumParamsHigh);
136 cng_decoder.Reset();
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000137
138 // Expect 0 because of unstable parameters after switching length.
ossu97ba30e2016-04-25 07:55:58 -0700139 EXPECT_EQ(0U,
140 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
141 kForceSid, &sid_data));
142 EXPECT_EQ(
143 kCNGNumParamsHigh + 1,
144 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_ + 160, 160),
145 kForceSid, &sid_data));
146 cng_decoder.UpdateSid(
147 rtc::ArrayView<const uint8_t>(sid_data.data(), kCNGNumParamsNormal + 1));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000148}
149
150// Update SID parameters, with wrong parameters or without calling decode.
henrika1d34fe92015-06-16 10:04:20 +0200151TEST_F(CngTest, CngUpdateSidErroneous) {
ossu97ba30e2016-04-25 07:55:58 -0700152 rtc::Buffer sid_data;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000153
154 // Encode.
ossu97ba30e2016-04-25 07:55:58 -0700155 ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
156 kCNGNumParamsNormal);
157 ComfortNoiseDecoder cng_decoder;
158 EXPECT_EQ(kCNGNumParamsNormal + 1,
159 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
160 kForceSid, &sid_data));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000161
162 // First run with valid parameters, then with too many CNG parameters.
163 // The function will operate correctly by only reading the maximum number of
164 // parameters, skipping the extra.
ossu97ba30e2016-04-25 07:55:58 -0700165 EXPECT_EQ(kCNGNumParamsNormal + 1, sid_data.size());
166 cng_decoder.UpdateSid(sid_data);
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000167
ossu97ba30e2016-04-25 07:55:58 -0700168 // Make sure the input buffer is large enough. Since Encode() appends data, we
169 // need to set the size manually only afterwards, or the buffer will be bigger
170 // than anticipated.
171 sid_data.SetSize(kCNGNumParamsTooHigh + 1);
172 cng_decoder.UpdateSid(sid_data);
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000173}
174
175// Test to generate cng data, by forcing SID. Both normal and faulty condition.
henrika1d34fe92015-06-16 10:04:20 +0200176TEST_F(CngTest, CngGenerate) {
ossu97ba30e2016-04-25 07:55:58 -0700177 rtc::Buffer sid_data;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000178 int16_t out_data[640];
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000179
ossu97ba30e2016-04-25 07:55:58 -0700180 // Create and initialize encoder and decoder.
181 ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
182 kCNGNumParamsNormal);
183 ComfortNoiseDecoder cng_decoder;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000184
185 // Normal Encode.
ossu97ba30e2016-04-25 07:55:58 -0700186 EXPECT_EQ(kCNGNumParamsNormal + 1,
187 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
188 kForceSid, &sid_data));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000189
190 // Normal UpdateSid.
ossu97ba30e2016-04-25 07:55:58 -0700191 cng_decoder.UpdateSid(sid_data);
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000192
193 // Two normal Generate, one with new_period.
ossu97ba30e2016-04-25 07:55:58 -0700194 EXPECT_TRUE(cng_decoder.Generate(rtc::ArrayView<int16_t>(out_data, 640), 1));
195 EXPECT_TRUE(cng_decoder.Generate(rtc::ArrayView<int16_t>(out_data, 640), 0));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000196
197 // Call Genereate with too much data.
ossu97ba30e2016-04-25 07:55:58 -0700198 EXPECT_FALSE(cng_decoder.Generate(rtc::ArrayView<int16_t>(out_data, 641), 0));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000199}
200
201// Test automatic SID.
henrika1d34fe92015-06-16 10:04:20 +0200202TEST_F(CngTest, CngAutoSid) {
ossu97ba30e2016-04-25 07:55:58 -0700203 rtc::Buffer sid_data;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000204
ossu97ba30e2016-04-25 07:55:58 -0700205 // Create and initialize encoder and decoder.
206 ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
207 kCNGNumParamsNormal);
208 ComfortNoiseDecoder cng_decoder;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000209
210 // Normal Encode, 100 msec, where no SID data should be generated.
211 for (int i = 0; i < 10; i++) {
ossu97ba30e2016-04-25 07:55:58 -0700212 EXPECT_EQ(0U, cng_encoder.Encode(
213 rtc::ArrayView<const int16_t>(speech_data_, 160), kNoSid, &sid_data));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000214 }
215
216 // We have reached 100 msec, and SID data should be generated.
ossu97ba30e2016-04-25 07:55:58 -0700217 EXPECT_EQ(kCNGNumParamsNormal + 1, cng_encoder.Encode(
218 rtc::ArrayView<const int16_t>(speech_data_, 160), kNoSid, &sid_data));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000219}
220
221// Test automatic SID, with very short interval.
henrika1d34fe92015-06-16 10:04:20 +0200222TEST_F(CngTest, CngAutoSidShort) {
ossu97ba30e2016-04-25 07:55:58 -0700223 rtc::Buffer sid_data;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000224
ossu97ba30e2016-04-25 07:55:58 -0700225 // Create and initialize encoder and decoder.
226 ComfortNoiseEncoder cng_encoder(16000, kSidShortIntervalUpdate,
227 kCNGNumParamsNormal);
228 ComfortNoiseDecoder cng_decoder;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000229
230 // First call will never generate SID, unless forced to.
ossu97ba30e2016-04-25 07:55:58 -0700231 EXPECT_EQ(0U, cng_encoder.Encode(
232 rtc::ArrayView<const int16_t>(speech_data_, 160), kNoSid, &sid_data));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000233
234 // Normal Encode, 100 msec, SID data should be generated all the time.
235 for (int i = 0; i < 10; i++) {
ossu97ba30e2016-04-25 07:55:58 -0700236 EXPECT_EQ(kCNGNumParamsNormal + 1, cng_encoder.Encode(
237 rtc::ArrayView<const int16_t>(speech_data_, 160), kNoSid, &sid_data));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000238 }
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000239}
240
241} // namespace webrtc