blob: 80349e25047d9794d3001f9a410fac1816eb7b6f [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
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000043void CngTest::SetUp() {
44 FILE* input_file;
45 const std::string file_name =
Yves Gerey665174f2018-06-19 15:03:05 +020046 webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000047 input_file = fopen(file_name.c_str(), "rb");
48 ASSERT_TRUE(input_file != NULL);
Yves Gerey665174f2018-06-19 15:03:05 +020049 ASSERT_EQ(640, static_cast<int32_t>(
50 fread(speech_data_, sizeof(int16_t), 640, input_file)));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000051 fclose(input_file);
52 input_file = NULL;
53}
54
ossu97ba30e2016-04-25 07:55:58 -070055void CngTest::TestCngEncode(int sample_rate_hz, int quality) {
56 const size_t num_samples_10ms = rtc::CheckedDivExact(sample_rate_hz, 100);
57 rtc::Buffer sid_data;
58
59 ComfortNoiseEncoder cng_encoder(sample_rate_hz, kSidNormalIntervalUpdate,
60 quality);
61 EXPECT_EQ(0U, cng_encoder.Encode(rtc::ArrayView<const int16_t>(
62 speech_data_, num_samples_10ms),
63 kNoSid, &sid_data));
64 EXPECT_EQ(static_cast<size_t>(quality + 1),
65 cng_encoder.Encode(
66 rtc::ArrayView<const int16_t>(speech_data_, num_samples_10ms),
67 kForceSid, &sid_data));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000068}
69
ossu97ba30e2016-04-25 07:55:58 -070070#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000071// Create CNG encoder, init with faulty values, free CNG encoder.
henrika1d34fe92015-06-16 10:04:20 +020072TEST_F(CngTest, CngInitFail) {
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000073 // Call with too few parameters.
Yves Gerey665174f2018-06-19 15:03:05 +020074 EXPECT_DEATH(
75 {
76 ComfortNoiseEncoder(8000, kSidNormalIntervalUpdate, kCNGNumParamsLow);
77 },
78 "");
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000079 // Call with too many parameters.
Yves Gerey665174f2018-06-19 15:03:05 +020080 EXPECT_DEATH(
81 {
82 ComfortNoiseEncoder(8000, kSidNormalIntervalUpdate,
83 kCNGNumParamsTooHigh);
84 },
85 "");
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000086}
87
88// Encode Cng with too long input vector.
henrika1d34fe92015-06-16 10:04:20 +020089TEST_F(CngTest, CngEncodeTooLong) {
ossu97ba30e2016-04-25 07:55:58 -070090 rtc::Buffer sid_data;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000091
ossu97ba30e2016-04-25 07:55:58 -070092 // Create encoder.
93 ComfortNoiseEncoder cng_encoder(8000, kSidNormalIntervalUpdate,
94 kCNGNumParamsNormal);
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +000095 // Run encoder with too much data.
ossu97ba30e2016-04-25 07:55:58 -070096 EXPECT_DEATH(
97 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 641),
98 kNoSid, &sid_data),
99 "");
100}
101#endif // GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000102
ossu97ba30e2016-04-25 07:55:58 -0700103TEST_F(CngTest, CngEncode8000) {
104 TestCngEncode(8000, kCNGNumParamsNormal);
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000105}
106
ossu97ba30e2016-04-25 07:55:58 -0700107TEST_F(CngTest, CngEncode16000) {
108 TestCngEncode(16000, kCNGNumParamsNormal);
109}
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000110
ossu97ba30e2016-04-25 07:55:58 -0700111TEST_F(CngTest, CngEncode32000) {
112 TestCngEncode(32000, kCNGNumParamsHigh);
113}
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000114
ossu97ba30e2016-04-25 07:55:58 -0700115TEST_F(CngTest, CngEncode48000) {
116 TestCngEncode(48000, kCNGNumParamsNormal);
117}
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000118
ossu97ba30e2016-04-25 07:55:58 -0700119TEST_F(CngTest, CngEncode64000) {
120 TestCngEncode(64000, kCNGNumParamsNormal);
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000121}
122
123// Update SID parameters, for both 9 and 16 parameters.
henrika1d34fe92015-06-16 10:04:20 +0200124TEST_F(CngTest, CngUpdateSid) {
ossu97ba30e2016-04-25 07:55:58 -0700125 rtc::Buffer sid_data;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000126
ossu97ba30e2016-04-25 07:55:58 -0700127 // Create and initialize encoder and decoder.
128 ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
129 kCNGNumParamsNormal);
130 ComfortNoiseDecoder cng_decoder;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000131
132 // Run normal Encode and UpdateSid.
ossu97ba30e2016-04-25 07:55:58 -0700133 EXPECT_EQ(kCNGNumParamsNormal + 1,
134 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
135 kForceSid, &sid_data));
136 cng_decoder.UpdateSid(sid_data);
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000137
138 // Reinit with new length.
ossu97ba30e2016-04-25 07:55:58 -0700139 cng_encoder.Reset(16000, kSidNormalIntervalUpdate, kCNGNumParamsHigh);
140 cng_decoder.Reset();
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000141
142 // Expect 0 because of unstable parameters after switching length.
ossu97ba30e2016-04-25 07:55:58 -0700143 EXPECT_EQ(0U,
144 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
145 kForceSid, &sid_data));
146 EXPECT_EQ(
147 kCNGNumParamsHigh + 1,
148 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_ + 160, 160),
149 kForceSid, &sid_data));
150 cng_decoder.UpdateSid(
151 rtc::ArrayView<const uint8_t>(sid_data.data(), kCNGNumParamsNormal + 1));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000152}
153
154// Update SID parameters, with wrong parameters or without calling decode.
henrika1d34fe92015-06-16 10:04:20 +0200155TEST_F(CngTest, CngUpdateSidErroneous) {
ossu97ba30e2016-04-25 07:55:58 -0700156 rtc::Buffer sid_data;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000157
158 // Encode.
ossu97ba30e2016-04-25 07:55:58 -0700159 ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
160 kCNGNumParamsNormal);
161 ComfortNoiseDecoder cng_decoder;
162 EXPECT_EQ(kCNGNumParamsNormal + 1,
163 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
164 kForceSid, &sid_data));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000165
166 // First run with valid parameters, then with too many CNG parameters.
167 // The function will operate correctly by only reading the maximum number of
168 // parameters, skipping the extra.
ossu97ba30e2016-04-25 07:55:58 -0700169 EXPECT_EQ(kCNGNumParamsNormal + 1, sid_data.size());
170 cng_decoder.UpdateSid(sid_data);
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000171
ossu97ba30e2016-04-25 07:55:58 -0700172 // Make sure the input buffer is large enough. Since Encode() appends data, we
173 // need to set the size manually only afterwards, or the buffer will be bigger
174 // than anticipated.
175 sid_data.SetSize(kCNGNumParamsTooHigh + 1);
176 cng_decoder.UpdateSid(sid_data);
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000177}
178
179// Test to generate cng data, by forcing SID. Both normal and faulty condition.
henrika1d34fe92015-06-16 10:04:20 +0200180TEST_F(CngTest, CngGenerate) {
ossu97ba30e2016-04-25 07:55:58 -0700181 rtc::Buffer sid_data;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000182 int16_t out_data[640];
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000183
ossu97ba30e2016-04-25 07:55:58 -0700184 // Create and initialize encoder and decoder.
185 ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
186 kCNGNumParamsNormal);
187 ComfortNoiseDecoder cng_decoder;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000188
189 // Normal Encode.
ossu97ba30e2016-04-25 07:55:58 -0700190 EXPECT_EQ(kCNGNumParamsNormal + 1,
191 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
192 kForceSid, &sid_data));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000193
194 // Normal UpdateSid.
ossu97ba30e2016-04-25 07:55:58 -0700195 cng_decoder.UpdateSid(sid_data);
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000196
197 // Two normal Generate, one with new_period.
ossu97ba30e2016-04-25 07:55:58 -0700198 EXPECT_TRUE(cng_decoder.Generate(rtc::ArrayView<int16_t>(out_data, 640), 1));
199 EXPECT_TRUE(cng_decoder.Generate(rtc::ArrayView<int16_t>(out_data, 640), 0));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000200
201 // Call Genereate with too much data.
ossu97ba30e2016-04-25 07:55:58 -0700202 EXPECT_FALSE(cng_decoder.Generate(rtc::ArrayView<int16_t>(out_data, 641), 0));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000203}
204
205// Test automatic SID.
henrika1d34fe92015-06-16 10:04:20 +0200206TEST_F(CngTest, CngAutoSid) {
ossu97ba30e2016-04-25 07:55:58 -0700207 rtc::Buffer sid_data;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000208
ossu97ba30e2016-04-25 07:55:58 -0700209 // Create and initialize encoder and decoder.
210 ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
211 kCNGNumParamsNormal);
212 ComfortNoiseDecoder cng_decoder;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000213
214 // Normal Encode, 100 msec, where no SID data should be generated.
215 for (int i = 0; i < 10; i++) {
Yves Gerey665174f2018-06-19 15:03:05 +0200216 EXPECT_EQ(
217 0U, cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
218 kNoSid, &sid_data));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000219 }
220
221 // We have reached 100 msec, and SID data should be generated.
Yves Gerey665174f2018-06-19 15:03:05 +0200222 EXPECT_EQ(kCNGNumParamsNormal + 1,
223 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
224 kNoSid, &sid_data));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000225}
226
227// Test automatic SID, with very short interval.
henrika1d34fe92015-06-16 10:04:20 +0200228TEST_F(CngTest, CngAutoSidShort) {
ossu97ba30e2016-04-25 07:55:58 -0700229 rtc::Buffer sid_data;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000230
ossu97ba30e2016-04-25 07:55:58 -0700231 // Create and initialize encoder and decoder.
232 ComfortNoiseEncoder cng_encoder(16000, kSidShortIntervalUpdate,
233 kCNGNumParamsNormal);
234 ComfortNoiseDecoder cng_decoder;
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000235
236 // First call will never generate SID, unless forced to.
Yves Gerey665174f2018-06-19 15:03:05 +0200237 EXPECT_EQ(0U,
238 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
239 kNoSid, &sid_data));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000240
241 // Normal Encode, 100 msec, SID data should be generated all the time.
242 for (int i = 0; i < 10; i++) {
Yves Gerey665174f2018-06-19 15:03:05 +0200243 EXPECT_EQ(
244 kCNGNumParamsNormal + 1,
245 cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
246 kNoSid, &sid_data));
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000247 }
tina.legrand@webrtc.orga4f9ba62012-09-28 07:12:00 +0000248}
249
250} // namespace webrtc