blob: 0e6ab793943749581e1cf695e3c5fedfc220e070 [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"
Steve Anton10542f22019-01-11 09:11:00 -080015#include "test/testsupport/file_utils.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
Yves Gerey665174f2018-06-19 15:03:05 +020032enum { kNoSid, kForceSid };
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000033
34class CngTest : public ::testing::Test {
35 protected:
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000036 virtual void SetUp();
37
ossu97ba30e2016-04-25 07:55:58 -070038 void TestCngEncode(int sample_rate_hz, int quality);
39
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000040 int16_t speech_data_[640]; // Max size of CNG internal buffers.
41};
42
Tommi909f3a52020-05-18 16:47:56 +020043class CngDeathTest : public CngTest {};
44
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000045void CngTest::SetUp() {
46 FILE* input_file;
47 const std::string file_name =
Yves Gerey665174f2018-06-19 15:03:05 +020048 webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000049 input_file = fopen(file_name.c_str(), "rb");
50 ASSERT_TRUE(input_file != NULL);
Yves Gerey665174f2018-06-19 15:03:05 +020051 ASSERT_EQ(640, static_cast<int32_t>(
52 fread(speech_data_, sizeof(int16_t), 640, input_file)));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000053 fclose(input_file);
54 input_file = NULL;
55}
56
ossu97ba30e2016-04-25 07:55:58 -070057void CngTest::TestCngEncode(int sample_rate_hz, int quality) {
58 const size_t num_samples_10ms = rtc::CheckedDivExact(sample_rate_hz, 100);
59 rtc::Buffer sid_data;
60
61 ComfortNoiseEncoder cng_encoder(sample_rate_hz, kSidNormalIntervalUpdate,
62 quality);
63 EXPECT_EQ(0U, cng_encoder.Encode(rtc::ArrayView<const int16_t>(
64 speech_data_, num_samples_10ms),
65 kNoSid, &sid_data));
66 EXPECT_EQ(static_cast<size_t>(quality + 1),
67 cng_encoder.Encode(
68 rtc::ArrayView<const int16_t>(speech_data_, num_samples_10ms),
69 kForceSid, &sid_data));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000070}
71
ossu97ba30e2016-04-25 07:55:58 -070072#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000073// Create CNG encoder, init with faulty values, free CNG encoder.
Tommi909f3a52020-05-18 16:47:56 +020074TEST_F(CngDeathTest, CngInitFail) {
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000075 // Call with too few parameters.
Yves Gerey665174f2018-06-19 15:03:05 +020076 EXPECT_DEATH(
77 {
78 ComfortNoiseEncoder(8000, kSidNormalIntervalUpdate, kCNGNumParamsLow);
79 },
80 "");
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000081 // Call with too many parameters.
Yves Gerey665174f2018-06-19 15:03:05 +020082 EXPECT_DEATH(
83 {
84 ComfortNoiseEncoder(8000, kSidNormalIntervalUpdate,
85 kCNGNumParamsTooHigh);
86 },
87 "");
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000088}
89
90// Encode Cng with too long input vector.
Tommi909f3a52020-05-18 16:47:56 +020091TEST_F(CngDeathTest, CngEncodeTooLong) {
ossu97ba30e2016-04-25 07:55:58 -070092 rtc::Buffer sid_data;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000093
ossu97ba30e2016-04-25 07:55:58 -070094 // Create encoder.
95 ComfortNoiseEncoder cng_encoder(8000, kSidNormalIntervalUpdate,
96 kCNGNumParamsNormal);
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000097 // Run encoder with too much data.
ossu97ba30e2016-04-25 07:55:58 -070098 EXPECT_DEATH(
99 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 641),
100 kNoSid, &sid_data),
101 "");
102}
103#endif // GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000104
ossu97ba30e2016-04-25 07:55:58 -0700105TEST_F(CngTest, CngEncode8000) {
106 TestCngEncode(8000, kCNGNumParamsNormal);
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000107}
108
ossu97ba30e2016-04-25 07:55:58 -0700109TEST_F(CngTest, CngEncode16000) {
110 TestCngEncode(16000, kCNGNumParamsNormal);
111}
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000112
ossu97ba30e2016-04-25 07:55:58 -0700113TEST_F(CngTest, CngEncode32000) {
114 TestCngEncode(32000, kCNGNumParamsHigh);
115}
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000116
ossu97ba30e2016-04-25 07:55:58 -0700117TEST_F(CngTest, CngEncode48000) {
118 TestCngEncode(48000, kCNGNumParamsNormal);
119}
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000120
ossu97ba30e2016-04-25 07:55:58 -0700121TEST_F(CngTest, CngEncode64000) {
122 TestCngEncode(64000, kCNGNumParamsNormal);
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000123}
124
125// Update SID parameters, for both 9 and 16 parameters.
henrika1d34fe92015-06-16 10:04:20 +0200126TEST_F(CngTest, CngUpdateSid) {
ossu97ba30e2016-04-25 07:55:58 -0700127 rtc::Buffer sid_data;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000128
ossu97ba30e2016-04-25 07:55:58 -0700129 // Create and initialize encoder and decoder.
130 ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
131 kCNGNumParamsNormal);
132 ComfortNoiseDecoder cng_decoder;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000133
134 // Run normal Encode and UpdateSid.
ossu97ba30e2016-04-25 07:55:58 -0700135 EXPECT_EQ(kCNGNumParamsNormal + 1,
136 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
137 kForceSid, &sid_data));
138 cng_decoder.UpdateSid(sid_data);
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000139
140 // Reinit with new length.
ossu97ba30e2016-04-25 07:55:58 -0700141 cng_encoder.Reset(16000, kSidNormalIntervalUpdate, kCNGNumParamsHigh);
142 cng_decoder.Reset();
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000143
144 // Expect 0 because of unstable parameters after switching length.
ossu97ba30e2016-04-25 07:55:58 -0700145 EXPECT_EQ(0U,
146 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
147 kForceSid, &sid_data));
148 EXPECT_EQ(
149 kCNGNumParamsHigh + 1,
150 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_ + 160, 160),
151 kForceSid, &sid_data));
152 cng_decoder.UpdateSid(
153 rtc::ArrayView<const uint8_t>(sid_data.data(), kCNGNumParamsNormal + 1));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000154}
155
156// Update SID parameters, with wrong parameters or without calling decode.
henrika1d34fe92015-06-16 10:04:20 +0200157TEST_F(CngTest, CngUpdateSidErroneous) {
ossu97ba30e2016-04-25 07:55:58 -0700158 rtc::Buffer sid_data;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000159
160 // Encode.
ossu97ba30e2016-04-25 07:55:58 -0700161 ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
162 kCNGNumParamsNormal);
163 ComfortNoiseDecoder cng_decoder;
164 EXPECT_EQ(kCNGNumParamsNormal + 1,
165 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
166 kForceSid, &sid_data));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000167
168 // First run with valid parameters, then with too many CNG parameters.
169 // The function will operate correctly by only reading the maximum number of
170 // parameters, skipping the extra.
ossu97ba30e2016-04-25 07:55:58 -0700171 EXPECT_EQ(kCNGNumParamsNormal + 1, sid_data.size());
172 cng_decoder.UpdateSid(sid_data);
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000173
ossu97ba30e2016-04-25 07:55:58 -0700174 // Make sure the input buffer is large enough. Since Encode() appends data, we
175 // need to set the size manually only afterwards, or the buffer will be bigger
176 // than anticipated.
177 sid_data.SetSize(kCNGNumParamsTooHigh + 1);
178 cng_decoder.UpdateSid(sid_data);
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000179}
180
181// Test to generate cng data, by forcing SID. Both normal and faulty condition.
henrika1d34fe92015-06-16 10:04:20 +0200182TEST_F(CngTest, CngGenerate) {
ossu97ba30e2016-04-25 07:55:58 -0700183 rtc::Buffer sid_data;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000184 int16_t out_data[640];
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000185
ossu97ba30e2016-04-25 07:55:58 -0700186 // Create and initialize encoder and decoder.
187 ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
188 kCNGNumParamsNormal);
189 ComfortNoiseDecoder cng_decoder;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000190
191 // Normal Encode.
ossu97ba30e2016-04-25 07:55:58 -0700192 EXPECT_EQ(kCNGNumParamsNormal + 1,
193 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
194 kForceSid, &sid_data));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000195
196 // Normal UpdateSid.
ossu97ba30e2016-04-25 07:55:58 -0700197 cng_decoder.UpdateSid(sid_data);
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000198
199 // Two normal Generate, one with new_period.
ossu97ba30e2016-04-25 07:55:58 -0700200 EXPECT_TRUE(cng_decoder.Generate(rtc::ArrayView<int16_t>(out_data, 640), 1));
201 EXPECT_TRUE(cng_decoder.Generate(rtc::ArrayView<int16_t>(out_data, 640), 0));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000202
203 // Call Genereate with too much data.
ossu97ba30e2016-04-25 07:55:58 -0700204 EXPECT_FALSE(cng_decoder.Generate(rtc::ArrayView<int16_t>(out_data, 641), 0));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000205}
206
207// Test automatic SID.
henrika1d34fe92015-06-16 10:04:20 +0200208TEST_F(CngTest, CngAutoSid) {
ossu97ba30e2016-04-25 07:55:58 -0700209 rtc::Buffer sid_data;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000210
ossu97ba30e2016-04-25 07:55:58 -0700211 // Create and initialize encoder and decoder.
212 ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
213 kCNGNumParamsNormal);
214 ComfortNoiseDecoder cng_decoder;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000215
216 // Normal Encode, 100 msec, where no SID data should be generated.
217 for (int i = 0; i < 10; i++) {
Yves Gerey665174f2018-06-19 15:03:05 +0200218 EXPECT_EQ(
219 0U, cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
220 kNoSid, &sid_data));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000221 }
222
223 // We have reached 100 msec, and SID data should be generated.
Yves Gerey665174f2018-06-19 15:03:05 +0200224 EXPECT_EQ(kCNGNumParamsNormal + 1,
225 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
226 kNoSid, &sid_data));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000227}
228
229// Test automatic SID, with very short interval.
henrika1d34fe92015-06-16 10:04:20 +0200230TEST_F(CngTest, CngAutoSidShort) {
ossu97ba30e2016-04-25 07:55:58 -0700231 rtc::Buffer sid_data;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000232
ossu97ba30e2016-04-25 07:55:58 -0700233 // Create and initialize encoder and decoder.
234 ComfortNoiseEncoder cng_encoder(16000, kSidShortIntervalUpdate,
235 kCNGNumParamsNormal);
236 ComfortNoiseDecoder cng_decoder;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000237
238 // First call will never generate SID, unless forced to.
Yves Gerey665174f2018-06-19 15:03:05 +0200239 EXPECT_EQ(0U,
240 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
241 kNoSid, &sid_data));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000242
243 // Normal Encode, 100 msec, SID data should be generated all the time.
244 for (int i = 0; i < 10; i++) {
Yves Gerey665174f2018-06-19 15:03:05 +0200245 EXPECT_EQ(
246 kCNGNumParamsNormal + 1,
247 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
248 kNoSid, &sid_data));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000249 }
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000250}
251
252} // namespace webrtc