├── CMakeLists.txt
├── LICENSE
├── README.md
├── cng.cpp
├── cng.h
├── dr_wav.h
└── main.cpp
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.9)
2 | project(cng)
3 | add_compile_options(-std=c++11)
4 | add_executable(cng main.cpp
5 | cng.cpp
6 | )
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | ============================
2 | Copyright (c) 2011, The WebRTC project authors. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are
6 | met:
7 |
8 | * Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 |
11 | * Redistributions in binary form must reproduce the above copyright
12 | notice, this list of conditions and the following disclaimer in
13 | the documentation and/or other materials provided with the
14 | distribution.
15 |
16 | * Neither the name of Google nor the names of its contributors may
17 | be used to endorse or promote products derived from this software
18 | without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WebRTC_CNG
2 | Comfort Noise Generator Module Port From WebRTC
3 |
4 | # Donating
5 |
6 | If you found this project useful, consider buying me a coffee
7 |
8 |
9 |
--------------------------------------------------------------------------------
/cng.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 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 | */
10 |
11 | #include "cng.h"
12 | #include
13 |
14 | #define WEBRTC_SPL_ABS_W16(a) \
15 | (((int16_t)a >= 0) ? ((int16_t)a) : -((int16_t)a))
16 | #define WEBRTC_SPL_MUL(a, b) \
17 | ((int32_t) ((int32_t)(a) * (int32_t)(b)))
18 | #define WEBRTC_SPL_MUL_16_16(a, b) \
19 | ((int32_t) (((int16_t)(a)) * ((int16_t)(b))))
20 | #define WEBRTC_SPL_MUL_16_16_RSFT(a, b, c) \
21 | (WEBRTC_SPL_MUL_16_16(a, b) >> (c))
22 | #define WEBRTC_SPL_ABS_W32(a) \
23 | (((int32_t)a >= 0) ? ((int32_t)a) : -((int32_t)a))
24 |
25 | // Shifting with negative numbers not allowed
26 | // We cannot do casting here due to signed/unsigned problem
27 | #define WEBRTC_SPL_LSHIFT_W32(x, c) ((x) << (c))
28 |
29 | int32_t WebRtcSpl_DivW32W16(int32_t num, int16_t den) {
30 | // Guard against division with 0
31 | if (den != 0) {
32 | return (int32_t) (num / den);
33 | } else {
34 | return (int32_t) 0x7FFFFFFF;
35 | }
36 | }
37 |
38 | void WebRtcSpl_ScaleVector(const int16_t *in_vector, int16_t *out_vector,
39 | int16_t gain, size_t in_vector_length,
40 | int16_t right_shifts) {
41 | // Performs vector operation: out_vector = (gain*in_vector)>>right_shifts
42 | size_t i;
43 | const int16_t *inptr;
44 | int16_t *outptr;
45 |
46 | inptr = in_vector;
47 | outptr = out_vector;
48 |
49 | for (i = 0; i < in_vector_length; i++) {
50 | *outptr++ = (int16_t) ((*inptr++ * gain) >> right_shifts);
51 | }
52 | }
53 |
54 | static const uint32_t kMaxSeedUsed = 0x80000000;
55 |
56 | static const int16_t kRandNTable[] = {
57 | 9178, -7260, 40, 10189, 4894, -3531, -13779, 14764,
58 | -4008, -8884, -8990, 1008, 7368, 5184, 3251, -5817,
59 | -9786, 5963, 1770, 8066, -7135, 10772, -2298, 1361,
60 | 6484, 2241, -8633, 792, 199, -3344, 6553, -10079,
61 | -15040, 95, 11608, -12469, 14161, -4176, 2476, 6403,
62 | 13685, -16005, 6646, 2239, 10916, -3004, -602, -3141,
63 | 2142, 14144, -5829, 5305, 8209, 4713, 2697, -5112,
64 | 16092, -1210, -2891, -6631, -5360, -11878, -6781, -2739,
65 | -6392, 536, 10923, 10872, 5059, -4748, -7770, 5477,
66 | 38, -1025, -2892, 1638, 6304, 14375, -11028, 1553,
67 | -1565, 10762, -393, 4040, 5257, 12310, 6554, -4799,
68 | 4899, -6354, 1603, -1048, -2220, 8247, -186, -8944,
69 | -12004, 2332, 4801, -4933, 6371, 131, 8614, -5927,
70 | -8287, -22760, 4033, -15162, 3385, 3246, 3153, -5250,
71 | 3766, 784, 6494, -62, 3531, -1582, 15572, 662,
72 | -3952, -330, -3196, 669, 7236, -2678, -6569, 23319,
73 | -8645, -741, 14830, -15976, 4903, 315, -11342, 10311,
74 | 1858, -7777, 2145, 5436, 5677, -113, -10033, 826,
75 | -1353, 17210, 7768, 986, -1471, 8291, -4982, 8207,
76 | -14911, -6255, -2449, -11881, -7059, -11703, -4338, 8025,
77 | 7538, -2823, -12490, 9470, -1613, -2529, -10092, -7807,
78 | 9480, 6970, -12844, 5123, 3532, 4816, 4803, -8455,
79 | -5045, 14032, -4378, -1643, 5756, -11041, -2732, -16618,
80 | -6430, -18375, -3320, 6098, 5131, -4269, -8840, 2482,
81 | -7048, 1547, -21890, -6505, -7414, -424, -11722, 7955,
82 | 1653, -17299, 1823, 473, -9232, 3337, 1111, 873,
83 | 4018, -8982, 9889, 3531, -11763, -3799, 7373, -4539,
84 | 3231, 7054, -8537, 7616, 6244, 16635, 447, -2915,
85 | 13967, 705, -2669, -1520, -1771, -16188, 5956, 5117,
86 | 6371, -9936, -1448, 2480, 5128, 7550, -8130, 5236,
87 | 8213, -6443, 7707, -1950, -13811, 7218, 7031, -3883,
88 | 67, 5731, -2874, 13480, -3743, 9298, -3280, 3552,
89 | -4425, -18, -3785, -9988, -5357, 5477, -11794, 2117,
90 | 1416, -9935, 3376, 802, -5079, -8243, 12652, 66,
91 | 3653, -2368, 6781, -21895, -7227, 2487, 7839, -385,
92 | 6646, -7016, -4658, 5531, -1705, 834, 129, 3694,
93 | -1343, 2238, -22640, -6417, -11139, 11301, -2945, -3494,
94 | -5626, 185, -3615, -2041, -7972, -3106, -60, -23497,
95 | -1566, 17064, 3519, 2518, 304, -6805, -10269, 2105,
96 | 1936, -426, -736, -8122, -1467, 4238, -6939, -13309,
97 | 360, 7402, -7970, 12576, 3287, 12194, -6289, -16006,
98 | 9171, 4042, -9193, 9123, -2512, 6388, -4734, -8739,
99 | 1028, -5406, -1696, 5889, -666, -4736, 4971, 3565,
100 | 9362, -6292, 3876, -3652, -19666, 7523, -4061, 391,
101 | -11773, 7502, -3763, 4929, -9478, 13278, 2805, 4496,
102 | 7814, 16419, 12455, -14773, 2127, -2746, 3763, 4847,
103 | 3698, 6978, 4751, -6957, -3581, -45, 6252, 1513,
104 | -4797, -7925, 11270, 16188, -2359, -5269, 9376, -10777,
105 | 7262, 20031, -6515, -2208, -5353, 8085, -1341, -1303,
106 | 7333, 5576, 3625, 5763, -7931, 9833, -3371, -10305,
107 | 6534, -13539, -9971, 997, 8464, -4064, -1495, 1857,
108 | 13624, 5458, 9490, -11086, -4524, 12022, -550, -198,
109 | 408, -8455, -7068, 10289, 9712, -3366, 9028, -7621,
110 | -5243, 2362, 6909, 4672, -4933, -1799, 4709, -4563,
111 | -62, -566, 1624, -7010, 14730, -17791, -3697, -2344,
112 | -1741, 7099, -9509, -6855, -1989, 3495, -2289, 2031,
113 | 12784, 891, 14189, -3963, -5683, 421, -12575, 1724,
114 | -12682, -5970, -8169, 3143, -1824, -5488, -5130, 8536,
115 | 12799, 794, 5738, 3459, -11689, -258, -3738, -3775,
116 | -8742, 2333, 8312, -9383, 10331, 13119, 8398, 10644,
117 | -19433, -6446, -16277, -11793, 16284, 9345, 15222, 15834,
118 | 2009, -7349, 130, -14547, 338, -5998, 3337, 21492,
119 | 2406, 7703, -951, 11196, -564, 3406, 2217, 4806,
120 | 2374, -5797, 11839, 8940, -11874, 18213, 2855, 10492
121 | };
122 |
123 | static uint32_t IncreaseSeed(uint32_t *seed) {
124 | seed[0] = (seed[0] * ((int32_t) 69069) + 1) & (kMaxSeedUsed - 1);
125 | return seed[0];
126 | }
127 |
128 | int16_t WebRtcSpl_RandN(uint32_t *seed) {
129 | return kRandNTable[IncreaseSeed(seed) >> 23];
130 | }
131 |
132 |
133 | #define WEBRTC_SPL_MEMCPY_W16(v1, v2, length) \
134 | memcpy(v1, v2, (length) * sizeof(int16_t))
135 |
136 | void WebRtcSpl_CopyFromEndW16(const int16_t *vector_in,
137 | size_t length,
138 | size_t samples,
139 | int16_t *vector_out) {
140 | // Copy the last of the input vector to vector_out
141 | WEBRTC_SPL_MEMCPY_W16(vector_out, &vector_in[length - samples], samples);
142 | }
143 |
144 | size_t WebRtcSpl_FilterAR(const int16_t *a,
145 | size_t a_length,
146 | const int16_t *x,
147 | size_t x_length,
148 | int16_t *state,
149 | size_t state_length,
150 | int16_t *state_low,
151 | size_t state_low_length,
152 | int16_t *filtered,
153 | int16_t *filtered_low,
154 | size_t filtered_low_length) {
155 | int64_t o;
156 | int32_t oLOW;
157 | size_t i, j, stop;
158 | const int16_t *x_ptr = &x[0];
159 | int16_t *filteredFINAL_ptr = filtered;
160 | int16_t *filteredFINAL_LOW_ptr = filtered_low;
161 |
162 | for (i = 0; i < x_length; i++) {
163 | // Calculate filtered[i] and filtered_low[i]
164 | const int16_t *a_ptr = &a[1];
165 | // The index can become negative, but the arrays will never be indexed
166 | // with it when negative. Nevertheless, the index cannot be a size_t
167 | // because of this.
168 | int filtered_ix = (int) i - 1;
169 | int16_t *state_ptr = &state[state_length - 1];
170 | int16_t *state_low_ptr = &state_low[state_length - 1];
171 |
172 | o = (int32_t) (*x_ptr++) * (1 << 12);
173 | oLOW = (int32_t) 0;
174 |
175 | stop = (i < a_length) ? i + 1 : a_length;
176 | for (j = 1; j < stop; j++) {
177 | // RTC_DCHECK_GE(filtered_ix, 0);
178 | o -= *a_ptr * filtered[filtered_ix];
179 | oLOW -= *a_ptr++ * filtered_low[filtered_ix];
180 | --filtered_ix;
181 | }
182 | for (j = i + 1; j < a_length; j++) {
183 | o -= *a_ptr * *state_ptr--;
184 | oLOW -= *a_ptr++ * *state_low_ptr--;
185 | }
186 |
187 | o += (oLOW >> 12);
188 | *filteredFINAL_ptr = (int16_t) ((o + (int32_t) 2048) >> 12);
189 | *filteredFINAL_LOW_ptr++ =
190 | (int16_t) (o - ((int32_t) (*filteredFINAL_ptr++) * (1 << 12)));
191 | }
192 |
193 | // Save the filter state
194 | if (x_length >= state_length) {
195 | WebRtcSpl_CopyFromEndW16(filtered, x_length, a_length - 1, state);
196 | WebRtcSpl_CopyFromEndW16(filtered_low, x_length, a_length - 1, state_low);
197 | } else {
198 | for (i = 0; i < state_length - x_length; i++) {
199 | state[i] = state[i + x_length];
200 | state_low[i] = state_low[i + x_length];
201 | }
202 | for (i = 0; i < x_length; i++) {
203 | state[state_length - x_length + i] = filtered[i];
204 | state[state_length - x_length + i] = filtered_low[i];
205 | }
206 | }
207 |
208 | return x_length;
209 | }
210 |
211 |
212 | const size_t kCngMaxOutsizeOrder = 640;
213 |
214 | // TODO(ossu): Rename the left-over WebRtcCng according to style guide.
215 | void WebRtcCng_K2a16(int16_t *k, int useOrder, int16_t *a);
216 |
217 | const int32_t WebRtcCng_kDbov[94] = {
218 | 1081109975, 858756178, 682134279, 541838517, 430397633, 341876992,
219 | 271562548, 215709799, 171344384, 136103682, 108110997, 85875618,
220 | 68213428, 54183852, 43039763, 34187699, 27156255, 21570980,
221 | 17134438, 13610368, 10811100, 8587562, 6821343, 5418385,
222 | 4303976, 3418770, 2715625, 2157098, 1713444, 1361037,
223 | 1081110, 858756, 682134, 541839, 430398, 341877,
224 | 271563, 215710, 171344, 136104, 108111, 85876,
225 | 68213, 54184, 43040, 34188, 27156, 21571,
226 | 17134, 13610, 10811, 8588, 6821, 5418,
227 | 4304, 3419, 2716, 2157, 1713, 1361,
228 | 1081, 859, 682, 542, 430, 342,
229 | 272, 216, 171, 136, 108, 86,
230 | 68, 54, 43, 34, 27, 22,
231 | 17, 14, 11, 9, 7, 5,
232 | 4, 3, 3, 2, 2, 1,
233 | 1, 1, 1, 1
234 | };
235 |
236 | const int16_t WebRtcCng_kCorrWindow[WEBRTC_CNG_MAX_LPC_ORDER] = {
237 | 32702, 32636, 32570, 32505, 32439, 32374,
238 | 32309, 32244, 32179, 32114, 32049, 31985
239 | };
240 |
241 | ComfortNoiseDecoder::ComfortNoiseDecoder() {
242 | /* Needed to get the right function pointers in SPLIB. */
243 | Reset();
244 | }
245 |
246 | void ComfortNoiseDecoder::Reset() {
247 | dec_seed_ = 7777; /* For debugging only. */
248 | dec_target_energy_ = 0;
249 | dec_used_energy_ = 0;
250 | for (auto &c : dec_target_reflCoefs_)
251 | c = 0;
252 | for (auto &c : dec_used_reflCoefs_)
253 | c = 0;
254 | for (auto &c : dec_filtstate_)
255 | c = 0;
256 | for (auto &c : dec_filtstateLow_)
257 | c = 0;
258 | dec_order_ = 5;
259 | dec_target_scale_factor_ = 0;
260 | dec_used_scale_factor_ = 0;
261 | }
262 |
263 | void ComfortNoiseDecoder::UpdateSid(ArrayView sid) {
264 | int16_t refCs[WEBRTC_CNG_MAX_LPC_ORDER];
265 | int32_t targetEnergy;
266 | size_t length = sid.size();
267 | /* Throw away reflection coefficients of higher order than we can handle. */
268 | if (length > (WEBRTC_CNG_MAX_LPC_ORDER + 1))
269 | length = WEBRTC_CNG_MAX_LPC_ORDER + 1;
270 |
271 | dec_order_ = static_cast(length - 1);
272 |
273 | uint8_t sid0 = std::min(sid[0], 93);
274 | targetEnergy = WebRtcCng_kDbov[sid0];
275 | /* Take down target energy to 75%. */
276 | targetEnergy = targetEnergy >> 1;
277 | targetEnergy += targetEnergy >> 2;
278 |
279 | dec_target_energy_ = targetEnergy;
280 |
281 | /* Reconstruct coeffs with tweak for WebRtc implementation of RFC3389. */
282 | if (dec_order_ == WEBRTC_CNG_MAX_LPC_ORDER) {
283 | for (size_t i = 0; i < (dec_order_); i++) {
284 | refCs[i] = sid[i + 1] << 8; /* Q7 to Q15*/
285 | dec_target_reflCoefs_[i] = refCs[i];
286 | }
287 | } else {
288 | for (size_t i = 0; i < (dec_order_); i++) {
289 | refCs[i] = (sid[i + 1] - 127) * (1 << 8); /* Q7 to Q15. */
290 | dec_target_reflCoefs_[i] = refCs[i];
291 | }
292 | }
293 |
294 | for (size_t i = (dec_order_); i < WEBRTC_CNG_MAX_LPC_ORDER; i++) {
295 | refCs[i] = 0;
296 | dec_target_reflCoefs_[i] = refCs[i];
297 | }
298 | }
299 |
300 | bool ComfortNoiseDecoder::Generate(ArrayView out_data,
301 | bool new_period) {
302 | int16_t excitation[kCngMaxOutsizeOrder];
303 | int16_t low[kCngMaxOutsizeOrder];
304 | int16_t lpPoly[WEBRTC_CNG_MAX_LPC_ORDER + 1];
305 | int16_t ReflBetaStd = 26214; /* 0.8 in q15. */
306 | int16_t ReflBetaCompStd = 6553; /* 0.2 in q15. */
307 | int16_t ReflBetaNewP = 19661; /* 0.6 in q15. */
308 | int16_t ReflBetaCompNewP = 13107; /* 0.4 in q15. */
309 | int16_t Beta, BetaC; /* These are in Q15. */
310 | int32_t targetEnergy;
311 | int16_t En;
312 | int16_t temp16;
313 | const size_t num_samples = out_data.size();
314 |
315 | if (num_samples > kCngMaxOutsizeOrder) {
316 | return false;
317 | }
318 |
319 | if (new_period) {
320 | dec_used_scale_factor_ = dec_target_scale_factor_;
321 | Beta = ReflBetaNewP;
322 | BetaC = ReflBetaCompNewP;
323 | } else {
324 | Beta = ReflBetaStd;
325 | BetaC = ReflBetaCompStd;
326 | }
327 |
328 | /* Calculate new scale factor in Q13 */
329 | dec_used_scale_factor_ = (int16_t) (
330 | WEBRTC_SPL_MUL_16_16_RSFT(dec_used_scale_factor_, Beta >> 2, 13) +
331 | WEBRTC_SPL_MUL_16_16_RSFT(dec_target_scale_factor_, BetaC >> 2, 13));
332 |
333 | dec_used_energy_ = dec_used_energy_ >> 1;
334 | dec_used_energy_ += dec_target_energy_ >> 1;
335 |
336 | /* Do the same for the reflection coeffs, albeit in Q15. */
337 | for (size_t i = 0; i < WEBRTC_CNG_MAX_LPC_ORDER; i++) {
338 | dec_used_reflCoefs_[i] = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(
339 | dec_used_reflCoefs_[i], Beta, 15);
340 | dec_used_reflCoefs_[i] += (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(
341 | dec_target_reflCoefs_[i], BetaC, 15);
342 | }
343 |
344 | /* Compute the polynomial coefficients. */
345 | WebRtcCng_K2a16(dec_used_reflCoefs_, WEBRTC_CNG_MAX_LPC_ORDER, lpPoly);
346 |
347 |
348 | targetEnergy = dec_used_energy_;
349 |
350 | /* Calculate scaling factor based on filter energy. */
351 | En = 8192; /* 1.0 in Q13. */
352 | for (size_t i = 0; i < (WEBRTC_CNG_MAX_LPC_ORDER); i++) {
353 | /* Floating point value for reference.
354 | E *= 1.0 - (dec_used_reflCoefs_[i] / 32768.0) *
355 | (dec_used_reflCoefs_[i] / 32768.0);
356 | */
357 |
358 | /* Same in fixed point. */
359 | /* K(i).^2 in Q15. */
360 | temp16 = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(
361 | dec_used_reflCoefs_[i], dec_used_reflCoefs_[i], 15);
362 | /* 1 - K(i).^2 in Q15. */
363 | temp16 = 0x7fff - temp16;
364 | En = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(En, temp16, 15);
365 | }
366 |
367 | /* float scaling= sqrt(E * dec_target_energy_ / (1 << 24)); */
368 |
369 | /* Calculate sqrt(En * target_energy / excitation energy) */
370 | targetEnergy = sqrtf(dec_used_energy_);
371 |
372 | En = (int16_t) sqrtf(En) << 6;
373 | En = (En * 3) >> 1; /* 1.5 estimates sqrt(2). */
374 | dec_used_scale_factor_ = (int16_t) ((En * targetEnergy) >> 12);
375 |
376 | /* Generate excitation. */
377 | /* Excitation energy per sample is 2.^24 - Q13 N(0,1). */
378 | for (size_t i = 0; i < num_samples; i++) {
379 | excitation[i] = WebRtcSpl_RandN(&dec_seed_) >> 1;
380 | }
381 |
382 | /* Scale to correct energy. */
383 | WebRtcSpl_ScaleVector(excitation, excitation, dec_used_scale_factor_,
384 | num_samples, 13);
385 |
386 | /* |lpPoly| - Coefficients in Q12.
387 | * |excitation| - Speech samples.
388 | * |nst->dec_filtstate| - State preservation.
389 | * |out_data| - Filtered speech samples. */
390 | WebRtcSpl_FilterAR(lpPoly, WEBRTC_CNG_MAX_LPC_ORDER + 1, excitation,
391 | num_samples, dec_filtstate_, WEBRTC_CNG_MAX_LPC_ORDER,
392 | dec_filtstateLow_, WEBRTC_CNG_MAX_LPC_ORDER,
393 | out_data.data(), low, num_samples);
394 |
395 | return true;
396 | }
397 |
398 | ComfortNoiseEncoder::ComfortNoiseEncoder(int fs, int interval, int quality)
399 | : enc_nrOfCoefs_(quality),
400 | enc_sampfreq_(fs),
401 | enc_interval_(interval),
402 | enc_msSinceSid_(0),
403 | enc_Energy_(0),
404 | enc_reflCoefs_{0},
405 | enc_corrVector_{0},
406 | enc_seed_(7777) /* For debugging only. */ {
407 | RTC_CHECK_GT(quality, 0);
408 | RTC_CHECK_LE(quality, WEBRTC_CNG_MAX_LPC_ORDER);
409 | /* Needed to get the right function pointers in SPLIB. */
410 |
411 | }
412 |
413 | void ComfortNoiseEncoder::Reset(int fs, int interval, int quality) {
414 | RTC_CHECK_GT(quality, 0);
415 | RTC_CHECK_LE(quality, WEBRTC_CNG_MAX_LPC_ORDER);
416 | enc_nrOfCoefs_ = quality;
417 | enc_sampfreq_ = fs;
418 | enc_interval_ = interval;
419 | enc_msSinceSid_ = 0;
420 | enc_Energy_ = 0;
421 | for (auto &c : enc_reflCoefs_)
422 | c = 0;
423 | for (auto &c : enc_corrVector_)
424 | c = 0;
425 | enc_seed_ = 7777; /* For debugging only. */
426 | }
427 |
428 | const int8_t kWebRtcSpl_CountLeadingZeros32_Table[64] = {
429 | 32, 8, 17, -1, -1, 14, -1, -1, -1, 20, -1, -1, -1, 28, -1, 18,
430 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 26, 25, 24,
431 | 4, 11, 23, 31, 3, 7, 10, 16, 22, 30, -1, -1, 2, 6, 13, 9,
432 | -1, 15, -1, 21, -1, 29, 19, -1, -1, -1, -1, -1, 1, 27, 5, 12,
433 | };
434 |
435 |
436 | // Don't call this directly except in tests!
437 | static __inline int WebRtcSpl_CountLeadingZeros32_NotBuiltin(uint32_t n) {
438 | // Normalize n by rounding up to the nearest number that is a sequence of 0
439 | // bits followed by a sequence of 1 bits. This number has the same number of
440 | // leading zeros as the original n. There are exactly 33 such values.
441 | n |= n >> 1;
442 | n |= n >> 2;
443 | n |= n >> 4;
444 | n |= n >> 8;
445 | n |= n >> 16;
446 |
447 | // Multiply the modified n with a constant selected (by exhaustive search)
448 | // such that each of the 33 possible values of n give a product whose 6 most
449 | // significant bits are unique. Then look up the answer in the table.
450 | return kWebRtcSpl_CountLeadingZeros32_Table[(n * 0x8c0b2891) >> 26];
451 | }
452 |
453 | // Don't call this directly except in tests!
454 | static __inline int WebRtcSpl_CountLeadingZeros64_NotBuiltin(uint64_t n) {
455 | const int leading_zeros = n >> 32 == 0 ? 32 : 0;
456 | return leading_zeros + WebRtcSpl_CountLeadingZeros32_NotBuiltin(
457 | (uint32_t) (n >> (32 - leading_zeros)));
458 | }
459 |
460 | // Returns the number of leading zero bits in the argument.
461 | static __inline int WebRtcSpl_CountLeadingZeros32(uint32_t n) {
462 | return WebRtcSpl_CountLeadingZeros32_NotBuiltin(n);
463 | }
464 |
465 | static __inline int16_t WebRtcSpl_GetSizeInBits(uint32_t n) {
466 | return 32 - WebRtcSpl_CountLeadingZeros32(n);
467 | }
468 |
469 | // Return the number of steps a can be left-shifted without overflow,
470 | // or 0 if a == 0.
471 | static __inline int16_t WebRtcSpl_NormW32(int32_t a) {
472 | return a == 0 ? 0 : WebRtcSpl_CountLeadingZeros32(a < 0 ? ~a : a) - 1;
473 | }
474 |
475 | int16_t WebRtcSpl_GetScalingSquare(int16_t *in_vector,
476 | size_t in_vector_length,
477 | size_t times) {
478 | int16_t nbits = WebRtcSpl_GetSizeInBits((uint32_t) times);
479 | size_t i;
480 | int16_t smax = -1;
481 | int16_t sabs;
482 | int16_t *sptr = in_vector;
483 | int16_t t;
484 | size_t looptimes = in_vector_length;
485 |
486 | for (i = looptimes; i > 0; i--) {
487 | sabs = (*sptr > 0 ? *sptr++ : -*sptr++);
488 | smax = (sabs > smax ? sabs : smax);
489 | }
490 | t = WebRtcSpl_NormW32(WEBRTC_SPL_MUL(smax, smax));
491 |
492 | if (smax == 0) {
493 | return 0; // Since norm(0) returns 0
494 | } else {
495 | return (t > nbits) ? 0 : nbits - t;
496 | }
497 | }
498 |
499 | int32_t WebRtcSpl_Energy(int16_t *vector,
500 | size_t vector_length,
501 | int *scale_factor) {
502 | int32_t en = 0;
503 | size_t i;
504 | int scaling =
505 | WebRtcSpl_GetScalingSquare(vector, vector_length, vector_length);
506 | size_t looptimes = vector_length;
507 | int16_t *vectorptr = vector;
508 |
509 | for (i = 0; i < looptimes; i++) {
510 | en += (*vectorptr * *vectorptr) >> scaling;
511 | vectorptr++;
512 | }
513 | *scale_factor = scaling;
514 |
515 | return en;
516 | }
517 |
518 | // Hanning table with 256 entries
519 | static const int16_t kHanningTable[] = {
520 | 1, 2, 6, 10, 15, 22, 30, 39,
521 | 50, 62, 75, 89, 104, 121, 138, 157,
522 | 178, 199, 222, 246, 271, 297, 324, 353,
523 | 383, 413, 446, 479, 513, 549, 586, 624,
524 | 663, 703, 744, 787, 830, 875, 920, 967,
525 | 1015, 1064, 1114, 1165, 1218, 1271, 1325, 1381,
526 | 1437, 1494, 1553, 1612, 1673, 1734, 1796, 1859,
527 | 1924, 1989, 2055, 2122, 2190, 2259, 2329, 2399,
528 | 2471, 2543, 2617, 2691, 2765, 2841, 2918, 2995,
529 | 3073, 3152, 3232, 3312, 3393, 3475, 3558, 3641,
530 | 3725, 3809, 3895, 3980, 4067, 4154, 4242, 4330,
531 | 4419, 4509, 4599, 4689, 4781, 4872, 4964, 5057,
532 | 5150, 5244, 5338, 5432, 5527, 5622, 5718, 5814,
533 | 5910, 6007, 6104, 6202, 6299, 6397, 6495, 6594,
534 | 6693, 6791, 6891, 6990, 7090, 7189, 7289, 7389,
535 | 7489, 7589, 7690, 7790, 7890, 7991, 8091, 8192,
536 | 8293, 8393, 8494, 8594, 8694, 8795, 8895, 8995,
537 | 9095, 9195, 9294, 9394, 9493, 9593, 9691, 9790,
538 | 9889, 9987, 10085, 10182, 10280, 10377, 10474, 10570,
539 | 10666, 10762, 10857, 10952, 11046, 11140, 11234, 11327,
540 | 11420, 11512, 11603, 11695, 11785, 11875, 11965, 12054,
541 | 12142, 12230, 12317, 12404, 12489, 12575, 12659, 12743,
542 | 12826, 12909, 12991, 13072, 13152, 13232, 13311, 13389,
543 | 13466, 13543, 13619, 13693, 13767, 13841, 13913, 13985,
544 | 14055, 14125, 14194, 14262, 14329, 14395, 14460, 14525,
545 | 14588, 14650, 14711, 14772, 14831, 14890, 14947, 15003,
546 | 15059, 15113, 15166, 15219, 15270, 15320, 15369, 15417,
547 | 15464, 15509, 15554, 15597, 15640, 15681, 15721, 15760,
548 | 15798, 15835, 15871, 15905, 15938, 15971, 16001, 16031,
549 | 16060, 16087, 16113, 16138, 16162, 16185, 16206, 16227,
550 | 16246, 16263, 16280, 16295, 16309, 16322, 16334, 16345,
551 | 16354, 16362, 16369, 16374, 16378, 16382, 16383, 16384
552 | };
553 |
554 | void WebRtcSpl_GetHanningWindow(int16_t *v, size_t size) {
555 | size_t jj;
556 | int16_t *vptr1;
557 |
558 | int32_t index;
559 | int32_t factor = ((int32_t) 0x40000000);
560 |
561 | factor = WebRtcSpl_DivW32W16(factor, (int16_t) size);
562 | if (size < 513)
563 | index = (int32_t) -0x200000;
564 | else
565 | index = (int32_t) -0x100000;
566 | vptr1 = v;
567 |
568 | for (jj = 0; jj < size; jj++) {
569 | index += factor;
570 | (*vptr1++) = kHanningTable[index >> 22];
571 | }
572 |
573 | }
574 |
575 | int16_t WebRtcSpl_MaxAbsValueW16C(const int16_t *vector, size_t length) {
576 | size_t i = 0;
577 | int absolute = 0, maximum = 0;
578 |
579 | RTC_DCHECK_GT(length, 0);
580 |
581 | for (i = 0; i < length; i++) {
582 | absolute = abs((int) vector[i]);
583 |
584 | if (absolute > maximum) {
585 | maximum = absolute;
586 | }
587 | }
588 |
589 | // Guard the case for abs(-32768).
590 | if (maximum > WEBRTC_SPL_WORD16_MAX) {
591 | maximum = WEBRTC_SPL_WORD16_MAX;
592 | }
593 |
594 | return (int16_t) maximum;
595 | }
596 |
597 | void WebRtcSpl_ElementwiseVectorMult(int16_t *out, const int16_t *in,
598 | const int16_t *win, size_t vector_length,
599 | int16_t right_shifts) {
600 | size_t i;
601 | int16_t *outptr = out;
602 | const int16_t *inptr = in;
603 | const int16_t *winptr = win;
604 | for (i = 0; i < vector_length; i++) {
605 | *outptr++ = (int16_t) ((*inptr++ * *winptr++) >> right_shifts);
606 | }
607 | }
608 |
609 | size_t WebRtcSpl_AutoCorrelation(const int16_t *in_vector,
610 | size_t in_vector_length,
611 | size_t order,
612 | int32_t *result,
613 | int *scale) {
614 | int32_t sum = 0;
615 | size_t i = 0, j = 0;
616 | int16_t smax = 0;
617 | int scaling = 0;
618 |
619 | RTC_DCHECK_LE(order, in_vector_length);
620 |
621 | // Find the maximum absolute value of the samples.
622 | smax = WebRtcSpl_MaxAbsValueW16C(in_vector, in_vector_length);
623 |
624 | // In order to avoid overflow when computing the sum we should scale the
625 | // samples so that (in_vector_length * smax * smax) will not overflow.
626 | if (smax == 0) {
627 | scaling = 0;
628 | } else {
629 | // Number of bits in the sum loop.
630 | int nbits = WebRtcSpl_GetSizeInBits((uint32_t) in_vector_length);
631 | // Number of bits to normalize smax.
632 | int t = WebRtcSpl_NormW32(WEBRTC_SPL_MUL(smax, smax));
633 |
634 | if (t > nbits) {
635 | scaling = 0;
636 | } else {
637 | scaling = nbits - t;
638 | }
639 | }
640 |
641 | // Perform the actual correlation calculation.
642 | for (i = 0; i < order + 1; i++) {
643 | sum = 0;
644 | /* Unroll the loop to improve performance. */
645 | for (j = 0; i + j + 3 < in_vector_length; j += 4) {
646 | sum += (in_vector[j + 0] * in_vector[i + j + 0]) >> scaling;
647 | sum += (in_vector[j + 1] * in_vector[i + j + 1]) >> scaling;
648 | sum += (in_vector[j + 2] * in_vector[i + j + 2]) >> scaling;
649 | sum += (in_vector[j + 3] * in_vector[i + j + 3]) >> scaling;
650 | }
651 | for (; j < in_vector_length - i; j++) {
652 | sum += (in_vector[j] * in_vector[i + j]) >> scaling;
653 | }
654 | *result++ = sum;
655 | }
656 |
657 | *scale = scaling;
658 | return order + 1;
659 | }
660 |
661 | int WebRtcSpl_DivW32HiLow(int32_t num, int16_t den_hi, int16_t den_low) {
662 | int16_t approx, tmp_hi, tmp_low, num_hi, num_low;
663 | int32_t tmpW32;
664 |
665 | approx = (int16_t) WebRtcSpl_DivW32W16((int32_t) 0x1FFFFFFF, den_hi);
666 | // result in Q14 (Note: 3FFFFFFF = 0.5 in Q30)
667 |
668 | // tmpW32 = 1/den = approx * (2.0 - den * approx) (in Q30)
669 | tmpW32 = (den_hi * approx << 1) + ((den_low * approx >> 15) << 1);
670 | // tmpW32 = den * approx
671 |
672 | tmpW32 = (int32_t) 0x7fffffffL - tmpW32; // result in Q30 (tmpW32 = 2.0-(den*approx))
673 | // UBSan: 2147483647 - -2 cannot be represented in type 'int'
674 |
675 | // Store tmpW32 in hi and low format
676 | tmp_hi = (int16_t) (tmpW32 >> 16);
677 | tmp_low = (int16_t) ((tmpW32 - ((int32_t) tmp_hi << 16)) >> 1);
678 |
679 | // tmpW32 = 1/den in Q29
680 | tmpW32 = (tmp_hi * approx + (tmp_low * approx >> 15)) << 1;
681 |
682 | // 1/den in hi and low format
683 | tmp_hi = (int16_t) (tmpW32 >> 16);
684 | tmp_low = (int16_t) ((tmpW32 - ((int32_t) tmp_hi << 16)) >> 1);
685 |
686 | // Store num in hi and low format
687 | num_hi = (int16_t) (num >> 16);
688 | num_low = (int16_t) ((num - ((int32_t) num_hi << 16)) >> 1);
689 |
690 | // num * (1/den) by 32 bit multiplication (result in Q28)
691 |
692 | tmpW32 = num_hi * tmp_hi + (num_hi * tmp_low >> 15) +
693 | (num_low * tmp_hi >> 15);
694 |
695 | // Put result in Q31 (convert from Q28)
696 | tmpW32 = WEBRTC_SPL_LSHIFT_W32(tmpW32, 3);
697 |
698 | return tmpW32;
699 | }
700 |
701 | #define SPL_LEVINSON_MAXORDER 20
702 |
703 |
704 | WebRtcSpl_LevinsonDurbin(const int32_t *R, int16_t *A, int16_t *K,
705 | size_t order) {
706 | size_t i, j;
707 | // Auto-correlation coefficients in high precision
708 | int16_t R_hi[SPL_LEVINSON_MAXORDER + 1], R_low[SPL_LEVINSON_MAXORDER + 1];
709 | // LPC coefficients in high precision
710 | int16_t A_hi[SPL_LEVINSON_MAXORDER + 1], A_low[SPL_LEVINSON_MAXORDER + 1];
711 | // LPC coefficients for next iteration
712 | int16_t A_upd_hi[SPL_LEVINSON_MAXORDER + 1], A_upd_low[SPL_LEVINSON_MAXORDER + 1];
713 | // Reflection coefficient in high precision
714 | int16_t K_hi, K_low;
715 | // Prediction gain Alpha in high precision and with scale factor
716 | int16_t Alpha_hi, Alpha_low, Alpha_exp;
717 | int16_t tmp_hi, tmp_low;
718 | int32_t temp1W32, temp2W32, temp3W32;
719 | int16_t norm;
720 |
721 | // Normalize the autocorrelation R[0]...R[order+1]
722 |
723 | norm = WebRtcSpl_NormW32(R[0]);
724 |
725 | for (i = 0; i <= order; ++i) {
726 | temp1W32 = R[i] * (1 << norm);
727 | // UBSan: 12 * 268435456 cannot be represented in type 'int'
728 |
729 | // Put R in hi and low format
730 | R_hi[i] = (int16_t) (temp1W32 >> 16);
731 | R_low[i] = (int16_t) ((temp1W32 - ((int32_t) R_hi[i] * 65536)) >> 1);
732 | }
733 |
734 | // K = A[1] = -R[1] / R[0]
735 |
736 | temp2W32 = R[1] * (1 << norm); // R[1] in Q31
737 | temp3W32 = WEBRTC_SPL_ABS_W32(temp2W32); // abs R[1]
738 | temp1W32 = WebRtcSpl_DivW32HiLow(temp3W32, R_hi[0], R_low[0]); // abs(R[1])/R[0] in Q31
739 | // Put back the sign on R[1]
740 | if (temp2W32 > 0) {
741 | temp1W32 = -temp1W32;
742 | }
743 |
744 | // Put K in hi and low format
745 | K_hi = (int16_t) (temp1W32 >> 16);
746 | K_low = (int16_t) ((temp1W32 - ((int32_t) K_hi * 65536)) >> 1);
747 |
748 | // Store first reflection coefficient
749 | K[0] = K_hi;
750 |
751 | temp1W32 >>= 4; // A[1] in Q27.
752 |
753 | // Put A[1] in hi and low format
754 | A_hi[1] = (int16_t) (temp1W32 >> 16);
755 | A_low[1] = (int16_t) ((temp1W32 - ((int32_t) A_hi[1] * 65536)) >> 1);
756 |
757 | // Alpha = R[0] * (1-K^2)
758 |
759 | temp1W32 = ((K_hi * K_low >> 14) + K_hi * K_hi) * 2; // = k^2 in Q31
760 |
761 | temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32); // Guard against <0
762 | temp1W32 = (int32_t) 0x7fffffffL - temp1W32; // temp1W32 = (1 - K[0]*K[0]) in Q31
763 |
764 | // Store temp1W32 = 1 - K[0]*K[0] on hi and low format
765 | tmp_hi = (int16_t) (temp1W32 >> 16);
766 | tmp_low = (int16_t) ((temp1W32 - ((int32_t) tmp_hi << 16)) >> 1);
767 |
768 | // Calculate Alpha in Q31
769 | temp1W32 = (R_hi[0] * tmp_hi + (R_hi[0] * tmp_low >> 15) +
770 | (R_low[0] * tmp_hi >> 15)) << 1;
771 |
772 | // Normalize Alpha and put it in hi and low format
773 |
774 | Alpha_exp = WebRtcSpl_NormW32(temp1W32);
775 | temp1W32 = WEBRTC_SPL_LSHIFT_W32(temp1W32, Alpha_exp);
776 | Alpha_hi = (int16_t) (temp1W32 >> 16);
777 | Alpha_low = (int16_t) ((temp1W32 - ((int32_t) Alpha_hi << 16)) >> 1);
778 |
779 | // Perform the iterative calculations in the Levinson-Durbin algorithm
780 |
781 | for (i = 2; i <= order; i++) {
782 | /* ----
783 | temp1W32 = R[i] + > R[j]*A[i-j]
784 | /
785 | ----
786 | j=1..i-1
787 | */
788 |
789 | temp1W32 = 0;
790 |
791 | for (j = 1; j < i; j++) {
792 | // temp1W32 is in Q31
793 | temp1W32 += (R_hi[j] * A_hi[i - j] * 2) +
794 | (((R_hi[j] * A_low[i - j] >> 15) +
795 | (R_low[j] * A_hi[i - j] >> 15)) * 2);
796 | }
797 |
798 | temp1W32 = temp1W32 * 16;
799 | temp1W32 += ((int32_t) R_hi[i] * 65536)
800 | + WEBRTC_SPL_LSHIFT_W32((int32_t) R_low[i], 1);
801 |
802 | // K = -temp1W32 / Alpha
803 | temp2W32 = WEBRTC_SPL_ABS_W32(temp1W32); // abs(temp1W32)
804 | temp3W32 = WebRtcSpl_DivW32HiLow(temp2W32, Alpha_hi, Alpha_low); // abs(temp1W32)/Alpha
805 |
806 | // Put the sign of temp1W32 back again
807 | if (temp1W32 > 0) {
808 | temp3W32 = -temp3W32;
809 | }
810 |
811 | // Use the Alpha shifts from earlier to de-normalize
812 | norm = WebRtcSpl_NormW32(temp3W32);
813 | if ((Alpha_exp <= norm) || (temp3W32 == 0)) {
814 | temp3W32 = temp3W32 * (1 << Alpha_exp);
815 | } else {
816 | if (temp3W32 > 0) {
817 | temp3W32 = (int32_t) 0x7fffffffL;
818 | } else {
819 | temp3W32 = (int32_t) 0x80000000L;
820 | }
821 | }
822 |
823 | // Put K on hi and low format
824 | K_hi = (int16_t) (temp3W32 >> 16);
825 | K_low = (int16_t) ((temp3W32 - ((int32_t) K_hi * 65536)) >> 1);
826 |
827 | // Store Reflection coefficient in Q15
828 | K[i - 1] = K_hi;
829 |
830 | // Test for unstable filter.
831 | // If unstable return 0 and let the user decide what to do in that case
832 |
833 | if ((int32_t) WEBRTC_SPL_ABS_W16(K_hi) > (int32_t) 32750) {
834 | return 0; // Unstable filter
835 | }
836 |
837 | /*
838 | Compute updated LPC coefficient: Anew[i]
839 | Anew[j]= A[j] + K*A[i-j] for j=1..i-1
840 | Anew[i]= K
841 | */
842 |
843 | for (j = 1; j < i; j++) {
844 | // temp1W32 = A[j] in Q27
845 | temp1W32 = (int32_t) A_hi[j] * 65536
846 | + WEBRTC_SPL_LSHIFT_W32((int32_t) A_low[j], 1);
847 |
848 | // temp1W32 += K*A[i-j] in Q27
849 | temp1W32 += (K_hi * A_hi[i - j] + (K_hi * A_low[i - j] >> 15) +
850 | (K_low * A_hi[i - j] >> 15)) * 2;
851 |
852 | // Put Anew in hi and low format
853 | A_upd_hi[j] = (int16_t) (temp1W32 >> 16);
854 | A_upd_low[j] = (int16_t) (
855 | (temp1W32 - ((int32_t) A_upd_hi[j] * 65536)) >> 1);
856 | }
857 |
858 | // temp3W32 = K in Q27 (Convert from Q31 to Q27)
859 | temp3W32 >>= 4;
860 |
861 | // Store Anew in hi and low format
862 | A_upd_hi[i] = (int16_t) (temp3W32 >> 16);
863 | A_upd_low[i] = (int16_t) (
864 | (temp3W32 - ((int32_t) A_upd_hi[i] * 65536)) >> 1);
865 |
866 | // Alpha = Alpha * (1-K^2)
867 |
868 | temp1W32 = ((K_hi * K_low >> 14) + K_hi * K_hi) * 2; // K*K in Q31
869 |
870 | temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32); // Guard against <0
871 | temp1W32 = (int32_t) 0x7fffffffL - temp1W32; // 1 - K*K in Q31
872 |
873 | // Convert 1- K^2 in hi and low format
874 | tmp_hi = (int16_t) (temp1W32 >> 16);
875 | tmp_low = (int16_t) ((temp1W32 - ((int32_t) tmp_hi << 16)) >> 1);
876 |
877 | // Calculate Alpha = Alpha * (1-K^2) in Q31
878 | temp1W32 = (Alpha_hi * tmp_hi + (Alpha_hi * tmp_low >> 15) +
879 | (Alpha_low * tmp_hi >> 15)) << 1;
880 |
881 | // Normalize Alpha and store it on hi and low format
882 |
883 | norm = WebRtcSpl_NormW32(temp1W32);
884 | temp1W32 = WEBRTC_SPL_LSHIFT_W32(temp1W32, norm);
885 |
886 | Alpha_hi = (int16_t) (temp1W32 >> 16);
887 | Alpha_low = (int16_t) ((temp1W32 - ((int32_t) Alpha_hi << 16)) >> 1);
888 |
889 | // Update the total normalization of Alpha
890 | Alpha_exp = Alpha_exp + norm;
891 |
892 | // Update A[]
893 |
894 | for (j = 1; j <= i; j++) {
895 | A_hi[j] = A_upd_hi[j];
896 | A_low[j] = A_upd_low[j];
897 | }
898 | }
899 |
900 | /*
901 | Set A[0] to 1.0 and store the A[i] i=1...order in Q12
902 | (Convert from Q27 and use rounding)
903 | */
904 |
905 | A[0] = 4096;
906 |
907 | for (i = 1; i <= order; i++) {
908 | // temp1W32 in Q27
909 | temp1W32 = (int32_t) A_hi[i] * 65536
910 | + WEBRTC_SPL_LSHIFT_W32((int32_t) A_low[i], 1);
911 | // Round and store upper word
912 | A[i] = (int16_t) (((temp1W32 * 2) + 32768) >> 16);
913 | }
914 | return 1; // Stable filters
915 | }
916 |
917 | size_t ComfortNoiseEncoder::Encode(ArrayView speech,
918 | bool force_sid,
919 | Buffer *output) {
920 | int16_t arCoefs[WEBRTC_CNG_MAX_LPC_ORDER + 1];
921 | int32_t corrVector[WEBRTC_CNG_MAX_LPC_ORDER + 1];
922 | int16_t refCs[WEBRTC_CNG_MAX_LPC_ORDER + 1];
923 | int16_t hanningW[kCngMaxOutsizeOrder];
924 | int16_t ReflBeta = 19661; /* 0.6 in q15. */
925 | int16_t ReflBetaComp = 13107; /* 0.4 in q15. */
926 | int32_t outEnergy;
927 | int outShifts;
928 | size_t i;
929 | int stab;
930 | int acorrScale;
931 | size_t index;
932 | size_t ind, factor;
933 | int32_t *bptr;
934 | int32_t blo, bhi;
935 | int16_t negate;
936 | const int16_t *aptr;
937 | int16_t speechBuf[kCngMaxOutsizeOrder];
938 |
939 | const size_t num_samples = speech.size();
940 | RTC_CHECK_LE(num_samples, kCngMaxOutsizeOrder);
941 |
942 | for (i = 0; i < num_samples; i++) {
943 | speechBuf[i] = speech[i];
944 | }
945 |
946 | factor = num_samples;
947 |
948 | /* Calculate energy and a coefficients. */
949 | outEnergy = WebRtcSpl_Energy(speechBuf, num_samples, &outShifts);
950 | while (outShifts > 0) {
951 | /* We can only do 5 shifts without destroying accuracy in
952 | * division factor. */
953 | if (outShifts > 5) {
954 | outEnergy <<= (outShifts - 5);
955 | outShifts = 5;
956 | } else {
957 | factor /= 2;
958 | outShifts--;
959 | }
960 | }
961 | outEnergy = WebRtcSpl_DivW32W16(outEnergy, (int16_t) factor);
962 |
963 | if (outEnergy > 1) {
964 | /* Create Hanning Window. */
965 | WebRtcSpl_GetHanningWindow(hanningW, num_samples / 2);
966 | for (i = 0; i < (num_samples / 2); i++)
967 | hanningW[num_samples - i - 1] = hanningW[i];
968 |
969 | WebRtcSpl_ElementwiseVectorMult(speechBuf, hanningW, speechBuf, num_samples,
970 | 14);
971 |
972 | WebRtcSpl_AutoCorrelation(speechBuf, num_samples, enc_nrOfCoefs_,
973 | corrVector, &acorrScale);
974 |
975 | if (*corrVector == 0)
976 | *corrVector = WEBRTC_SPL_WORD16_MAX;
977 |
978 | /* Adds the bandwidth expansion. */
979 | aptr = WebRtcCng_kCorrWindow;
980 | bptr = corrVector;
981 |
982 | /* (zzz) lpc16_1 = 17+1+820+2+2 = 842 (ordo2=700). */
983 | for (ind = 0; ind < enc_nrOfCoefs_; ind++) {
984 | /* The below code multiplies the 16 b corrWindow values (Q15) with
985 | * the 32 b corrvector (Q0) and shifts the result down 15 steps. */
986 | negate = *bptr < 0;
987 | if (negate)
988 | *bptr = -*bptr;
989 |
990 | blo = (int32_t) *aptr * (*bptr & 0xffff);
991 | bhi = ((blo >> 16) & 0xffff)
992 | + ((int32_t) (*aptr++) * ((*bptr >> 16) & 0xffff));
993 | blo = (blo & 0xffff) | ((bhi & 0xffff) << 16);
994 |
995 | *bptr = (((bhi >> 16) & 0x7fff) << 17) | ((uint32_t) blo >> 15);
996 | if (negate)
997 | *bptr = -*bptr;
998 | bptr++;
999 | }
1000 | /* End of bandwidth expansion. */
1001 |
1002 | stab = WebRtcSpl_LevinsonDurbin(corrVector, arCoefs, refCs,
1003 | enc_nrOfCoefs_);
1004 |
1005 | if (!stab) {
1006 | /* Disregard from this frame */
1007 | return 0;
1008 | }
1009 |
1010 | } else {
1011 | for (i = 0; i < enc_nrOfCoefs_; i++)
1012 | refCs[i] = 0;
1013 | }
1014 |
1015 | if (force_sid) {
1016 | /* Read instantaneous values instead of averaged. */
1017 | for (i = 0; i < enc_nrOfCoefs_; i++)
1018 | enc_reflCoefs_[i] = refCs[i];
1019 | enc_Energy_ = outEnergy;
1020 | } else {
1021 | /* Average history with new values. */
1022 | for (i = 0; i < enc_nrOfCoefs_; i++) {
1023 | enc_reflCoefs_[i] = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(
1024 | enc_reflCoefs_[i], ReflBeta, 15);
1025 | enc_reflCoefs_[i] +=
1026 | (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(refCs[i], ReflBetaComp, 15);
1027 | }
1028 | enc_Energy_ =
1029 | (outEnergy >> 2) + (enc_Energy_ >> 1) + (enc_Energy_ >> 2);
1030 | }
1031 |
1032 | if (enc_Energy_ < 1) {
1033 | enc_Energy_ = 1;
1034 | }
1035 |
1036 | if ((enc_msSinceSid_ > (enc_interval_ - 1)) || force_sid) {
1037 | /* Search for best dbov value. */
1038 | index = 0;
1039 | for (i = 1; i < 93; i++) {
1040 | /* Always round downwards. */
1041 | if ((enc_Energy_ - WebRtcCng_kDbov[i]) > 0) {
1042 | index = i;
1043 | break;
1044 | }
1045 | }
1046 | if ((i == 93) && (index == 0))
1047 | index = 94;
1048 |
1049 | const size_t output_coefs = enc_nrOfCoefs_ + 1;
1050 | output->AppendData(output_coefs, [&](ArrayView output) {
1051 | output[0] = (uint8_t) index;
1052 |
1053 | /* Quantize coefficients with tweak for WebRtc implementation of
1054 | * RFC3389. */
1055 | if (enc_nrOfCoefs_ == WEBRTC_CNG_MAX_LPC_ORDER) {
1056 | for (i = 0; i < enc_nrOfCoefs_; i++) {
1057 | /* Q15 to Q7 with rounding. */
1058 | output[i + 1] = ((enc_reflCoefs_[i] + 128) >> 8);
1059 | }
1060 | } else {
1061 | for (i = 0; i < enc_nrOfCoefs_; i++) {
1062 | /* Q15 to Q7 with rounding. */
1063 | output[i + 1] = (127 + ((enc_reflCoefs_[i] + 128) >> 8));
1064 | }
1065 | }
1066 |
1067 | return output_coefs;
1068 | });
1069 |
1070 | enc_msSinceSid_ =
1071 | static_cast((1000 * num_samples) / enc_sampfreq_);
1072 | return output_coefs;
1073 | } else {
1074 | enc_msSinceSid_ +=
1075 | static_cast((1000 * num_samples) / enc_sampfreq_);
1076 | return 0;
1077 | }
1078 | }
1079 |
1080 | #define WEBRTC_SPL_MAX_LPC_ORDER 14
1081 |
1082 | /* Values in |k| are Q15, and |a| Q12. */
1083 | void WebRtcCng_K2a16(int16_t *k, int useOrder, int16_t *a) {
1084 | int16_t any[WEBRTC_SPL_MAX_LPC_ORDER + 1];
1085 | int16_t *aptr;
1086 | int16_t *aptr2;
1087 | int16_t *anyptr;
1088 | const int16_t *kptr;
1089 | int m, i;
1090 |
1091 | kptr = k;
1092 | *a = 4096; /* i.e., (Word16_MAX >> 3) + 1 */
1093 | *any = *a;
1094 | a[1] = (*k + 4) >> 3;
1095 | for (m = 1; m < useOrder; m++) {
1096 | kptr++;
1097 | aptr = a;
1098 | aptr++;
1099 | aptr2 = &a[m];
1100 | anyptr = any;
1101 | anyptr++;
1102 |
1103 | any[m + 1] = (*kptr + 4) >> 3;
1104 | for (i = 0; i < m; i++) {
1105 | *anyptr++ =
1106 | (*aptr++) +
1107 | (int16_t) ((((int32_t) (*aptr2--) * (int32_t) *kptr) + 16384) >> 15);
1108 | }
1109 |
1110 | aptr = a;
1111 | anyptr = any;
1112 | for (i = 0; i < (m + 2); i++) {
1113 | *aptr++ = *anyptr++;
1114 | }
1115 | }
1116 | }
1117 |
--------------------------------------------------------------------------------
/cng.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 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 | */
10 | #ifndef MODULES_AUDIO_CODING_CODECS_CNG_WEBRTC_CNG_H_
11 | #define MODULES_AUDIO_CODING_CODECS_CNG_WEBRTC_CNG_H_
12 |
13 | #include
14 | #include
15 | #include
16 |
17 | #define WEBRTC_SPL_WORD16_MAX 32767
18 | #ifdef __cplusplus
19 | extern "C" {
20 | #endif
21 | static void rtc_FatalMessage(const char *file, int line, const char *msg) {
22 | printf("file:%s line %d: %s", file, line, msg);
23 | }
24 | #ifdef __cplusplus
25 | } // extern "C"
26 | #endif
27 | #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
28 | #define RTC_DCHECK_IS_ON 1
29 | #else
30 | #define RTC_DCHECK_IS_ON 0
31 | #endif
32 | #define RTC_CHECK(condition) \
33 | do { \
34 | if (!(condition)) { \
35 | rtc_FatalMessage(__FILE__, __LINE__, "CHECK failed: " #condition); \
36 | } \
37 | } while (0)
38 |
39 | #define RTC_DCHECK(condition) \
40 | do { \
41 | if (RTC_DCHECK_IS_ON && !(condition)) { \
42 | rtc_FatalMessage(__FILE__, __LINE__, "DCHECK failed: " #condition); \
43 | } \
44 | } while (0)
45 | #define RTC_DCHECK_LT(a, b) RTC_DCHECK((a) < (b))
46 | #define RTC_CHECK_EQ(a, b) RTC_CHECK((a) == (b))
47 | #define RTC_DCHECK_EQ(v1, v2) RTC_CHECK_EQ(v1, v2)
48 | #define RTC_CHECK_LE(a, b) RTC_CHECK((a) <= (b))
49 | #define RTC_DCHECK_LE(a, b) RTC_DCHECK((a) <= (b))
50 | #define RTC_CHECK_GT(a, b) RTC_CHECK((a) > (b))
51 | #define RTC_DCHECK_GT(v1, v2) RTC_CHECK_GT(v1, v2)
52 |
53 | #include
54 |
55 | #include // NOLINT(build/include)
56 |
57 | #define WEBRTC_CNG_MAX_LPC_ORDER 12
58 | #ifndef API_ARRAY_VIEW_H_
59 | #define API_ARRAY_VIEW_H_
60 |
61 | #include
62 | #include
63 |
64 |
65 | #ifndef RTC_BASE_TYPE_TRAITS_H_
66 | #define RTC_BASE_TYPE_TRAITS_H_
67 |
68 | #include
69 | #include
70 |
71 |
72 | // Determines if the given class has zero-argument .data() and .size() methods
73 | // whose return values are convertible to T* and size_t, respectively.
74 | template
75 | class HasDataAndSize {
76 | private:
77 | template<
78 | typename C,
79 | typename std::enable_if<
80 | std::is_convertible().data()), T *>::value &&
81 | std::is_convertible().size()),
82 | std::size_t>::value>::type * = nullptr>
83 | static int Test(int);
84 |
85 | template
86 | static char Test(...);
87 |
88 | public:
89 | static constexpr bool value = std::is_same(0)), int>::value;
90 | };
91 |
92 | namespace test_has_data_and_size {
93 |
94 | template
95 | struct Test1 {
96 | DR data();
97 |
98 | SR size();
99 | };
100 |
101 | static_assert(HasDataAndSize, int>::value, "");
102 | static_assert(HasDataAndSize, const int>::value, "");
103 | static_assert(HasDataAndSize, const int>::value, "");
104 | static_assert(!HasDataAndSize, int>::value,
105 | "implicit cast of const int* to int*");
106 | static_assert(!HasDataAndSize, int>::value,
107 | "implicit cast of char* to int*");
108 |
109 | struct Test2 {
110 | int *data;
111 | size_t size;
112 | };
113 | static_assert(!HasDataAndSize::value,
114 | ".data and .size aren't functions");
115 |
116 | struct Test3 {
117 | int *data();
118 | };
119 |
120 | static_assert(!HasDataAndSize::value, ".size() is missing");
121 |
122 | class Test4 {
123 | int *data();
124 |
125 | size_t size();
126 | };
127 |
128 | static_assert(!HasDataAndSize::value,
129 | ".data() and .size() are private");
130 |
131 | } // namespace test_has_data_and_size
132 |
133 | namespace type_traits_impl {
134 |
135 | // Determines if the given type is an enum that converts implicitly to
136 | // an integral type.
137 | template
138 | struct IsIntEnum {
139 | private:
140 | // This overload is used if the type is an enum, and unary plus
141 | // compiles and turns it into an integral type.
142 | template::value &&
145 | std::is_integral())>::value>::type * =
146 | nullptr>
147 | static int Test(int);
148 |
149 | // Otherwise, this overload is used.
150 | template
151 | static char Test(...);
152 |
153 | public:
154 | static constexpr bool value =
155 | std::is_same::type>(0)),
156 | int>::value;
157 | };
158 |
159 | } // namespace type_traits_impl
160 |
161 | // Determines if the given type is integral, or an enum that
162 | // converts implicitly to an integral type.
163 | template
164 | struct IsIntlike {
165 | private:
166 | using X = typename std::remove_reference::type;
167 |
168 | public:
169 | static constexpr bool value =
170 | std::is_integral::value || type_traits_impl::IsIntEnum::value;
171 | };
172 |
173 | namespace test_enum_intlike {
174 |
175 | enum E1 {
176 | e1
177 | };
178 | enum {
179 | e2
180 | };
181 | enum class E3 {
182 | e3
183 | };
184 | struct S {
185 | };
186 |
187 | static_assert(type_traits_impl::IsIntEnum::value, "");
188 | static_assert(type_traits_impl::IsIntEnum::value, "");
189 | static_assert(!type_traits_impl::IsIntEnum::value, "");
190 | static_assert(!type_traits_impl::IsIntEnum::value, "");
191 | static_assert(!type_traits_impl::IsIntEnum::value, "");
192 | static_assert(!type_traits_impl::IsIntEnum::value, "");
193 |
194 | static_assert(IsIntlike::value, "");
195 | static_assert(IsIntlike::value, "");
196 | static_assert(!IsIntlike::value, "");
197 | static_assert(IsIntlike::value, "");
198 | static_assert(!IsIntlike::value, "");
199 | static_assert(!IsIntlike::value, "");
200 |
201 | } // test_enum_intlike
202 |
203 |
204 | #endif // RTC_BASE_TYPE_TRAITS_H_
205 |
206 |
207 | // tl;dr: ArrayView is the same thing as gsl::span from the Guideline
208 | // Support Library.
209 | //
210 | // Many functions read from or write to arrays. The obvious way to do this is
211 | // to use two arguments, a pointer to the first element and an element count:
212 | //
213 | // bool Contains17(const int* arr, size_t size) {
214 | // for (size_t i = 0; i < size; ++i) {
215 | // if (arr[i] == 17)
216 | // return true;
217 | // }
218 | // return false;
219 | // }
220 | //
221 | // This is flexible, since it doesn't matter how the array is stored (C array,
222 | // std::vector, Buffer, ...), but it's error-prone because the caller has
223 | // to correctly specify the array length:
224 | //
225 | // Contains17(arr, arraysize(arr)); // C array
226 | // Contains17(arr.data(), arr.size()); // std::vector
227 | // Contains17(arr, size); // pointer + size
228 | // ...
229 | //
230 | // It's also kind of messy to have two separate arguments for what is
231 | // conceptually a single thing.
232 | //
233 | // Enter ArrayView. It contains a T pointer (to an array it doesn't
234 | // own) and a count, and supports the basic things you'd expect, such as
235 | // indexing and iteration. It allows us to write our function like this:
236 | //
237 | // bool Contains17(ArrayView arr) {
238 | // for (auto e : arr) {
239 | // if (e == 17)
240 | // return true;
241 | // }
242 | // return false;
243 | // }
244 | //
245 | // And even better, because a bunch of things will implicitly convert to
246 | // ArrayView, we can call it like this:
247 | //
248 | // Contains17(arr); // C array
249 | // Contains17(arr); // std::vector
250 | // Contains17(ArrayView(arr, size)); // pointer + size
251 | // Contains17(nullptr); // nullptr -> empty ArrayView
252 | // ...
253 | //
254 | // ArrayView stores both a pointer and a size, but you may also use
255 | // ArrayView, which has a size that's fixed at compile time (which means
256 | // it only has to store the pointer).
257 | //
258 | // One important point is that ArrayView and ArrayView are
259 | // different types, which allow and don't allow mutation of the array elements,
260 | // respectively. The implicit conversions work just like you'd hope, so that
261 | // e.g. vector will convert to either ArrayView or ArrayView, but const vector will convert only to ArrayView.
263 | // (ArrayView itself can be the source type in such conversions, so
264 | // ArrayView will convert to ArrayView.)
265 | //
266 | // Note: ArrayView is tiny (just a pointer and a count if variable-sized, just
267 | // a pointer if fix-sized) and trivially copyable, so it's probably cheaper to
268 | // pass it by value than by const reference.
269 |
270 | namespace impl {
271 |
272 | // Magic constant for indicating that the size of an ArrayView is variable
273 | // instead of fixed.
274 | enum : std::ptrdiff_t {
275 | kArrayViewVarSize = -4711
276 | };
277 |
278 | // Base class for ArrayViews of fixed nonzero size.
279 | template
280 | class ArrayViewBase {
281 | static_assert(Size > 0, "ArrayView size must be variable or non-negative");
282 |
283 | public:
284 | ArrayViewBase(T *data, size_t size) : data_(data) {}
285 |
286 | static constexpr size_t size() { return Size; }
287 |
288 | static constexpr bool empty() { return false; }
289 |
290 | T *data() const { return data_; }
291 |
292 | protected:
293 | static constexpr bool fixed_size() { return true; }
294 |
295 | private:
296 | T *data_;
297 | };
298 |
299 | // Specialized base class for ArrayViews of fixed zero size.
300 | template
301 | class ArrayViewBase {
302 | public:
303 | explicit ArrayViewBase(T *data, size_t size) {}
304 |
305 | static constexpr size_t size() { return 0; }
306 |
307 | static constexpr bool empty() { return true; }
308 |
309 | T *data() const { return nullptr; }
310 |
311 | protected:
312 | static constexpr bool fixed_size() { return true; }
313 | };
314 |
315 | // Specialized base class for ArrayViews of variable size.
316 | template
317 | class ArrayViewBase {
318 | public:
319 | ArrayViewBase(T *data, size_t size)
320 | : data_(size == 0 ? nullptr : data), size_(size) {}
321 |
322 | size_t size() const { return size_; }
323 |
324 | bool empty() const { return size_ == 0; }
325 |
326 | T *data() const { return data_; }
327 |
328 | protected:
329 | static constexpr bool fixed_size() { return false; }
330 |
331 | private:
332 | T *data_;
333 | size_t size_;
334 | };
335 |
336 | } // namespace impl
337 |
338 | template
339 | class ArrayView final : public impl::ArrayViewBase {
340 | public:
341 | using value_type = T;
342 | using const_iterator = const T *;
343 |
344 | // Construct an ArrayView from a pointer and a length.
345 | template
346 | ArrayView(U *data, size_t size)
347 | : impl::ArrayViewBase::ArrayViewBase(data, size) {
348 | RTC_DCHECK_EQ(size == 0 ? nullptr : data, this->data());
349 | RTC_DCHECK_EQ(size, this->size());
350 | RTC_DCHECK_EQ(!this->data(),
351 | this->size() == 0); // data is null iff size == 0.
352 | }
353 |
354 | // Construct an empty ArrayView. Note that fixed-size ArrayViews of size > 0
355 | // cannot be empty.
356 | ArrayView() : ArrayView(nullptr, 0) {}
357 |
358 | ArrayView(std::nullptr_t) // NOLINT
359 | : ArrayView() {}
360 |
361 | ArrayView(std::nullptr_t, size_t size)
362 | : ArrayView(static_cast(nullptr), size) {
363 | static_assert(Size == 0 || Size == impl::kArrayViewVarSize, "");
364 | RTC_DCHECK_EQ(0, size);
365 | }
366 |
367 | // Construct an ArrayView from an array.
368 | template
369 | ArrayView(U (&array)[N]) // NOLINT
370 | : ArrayView(array, N) {
371 | static_assert(Size == N || Size == impl::kArrayViewVarSize,
372 | "Array size must match ArrayView size");
373 | }
374 |
375 | // (Only if size is fixed.) Construct an ArrayView from any type U that has a
376 | // static constexpr size() method whose return value is equal to Size, and a
377 | // data() method whose return value converts implicitly to T*. In particular,
378 | // this means we allow conversion from ArrayView to ArrayView, but not the other way around. We also don't allow conversion from
380 | // ArrayView to ArrayView, or from ArrayView to ArrayView when M != N.
382 | template<
383 | typename U,
384 | typename std::enable_if::value>::type * = nullptr>
386 | ArrayView(U &u) // NOLINT
387 | : ArrayView(u.data(), u.size()) {
388 | static_assert(U::size() == Size, "Sizes must match exactly");
389 | }
390 |
391 | // (Only if size is variable.) Construct an ArrayView from any type U that
392 | // has a size() method whose return value converts implicitly to size_t, and
393 | // a data() method whose return value converts implicitly to T*. In
394 | // particular, this means we allow conversion from ArrayView to
395 | // ArrayView, but not the other way around. Other allowed
396 | // conversions include
397 | // ArrayView to ArrayView or ArrayView,
398 | // std::vector to ArrayView or ArrayView,
399 | // const std::vector to ArrayView,
400 | // Buffer to ArrayView or ArrayView, and
401 | // const Buffer to ArrayView.
402 | template<
403 | typename U,
404 | typename std::enable_if::value>::type * = nullptr>
406 | ArrayView(U &u) // NOLINT
407 | : ArrayView(u.data(), u.size()) {}
408 |
409 | // Indexing and iteration. These allow mutation even if the ArrayView is
410 | // const, because the ArrayView doesn't own the array. (To prevent mutation,
411 | // use a const element type.)
412 | T &operator[](size_t idx) const {
413 | RTC_DCHECK_LT(idx, this->size());
414 | RTC_DCHECK(this->data());
415 | return this->data()[idx];
416 | }
417 |
418 | T *begin() const { return this->data(); }
419 |
420 | T *end() const { return this->data() + this->size(); }
421 |
422 | const T *cbegin() const { return this->data(); }
423 |
424 | const T *cend() const { return this->data() + this->size(); }
425 |
426 | ArrayView subview(size_t offset, size_t size) const {
427 | return offset < this->size()
428 | ? ArrayView(this->data() + offset,
429 | std::min(size, this->size() - offset))
430 | : ArrayView();
431 | }
432 |
433 | ArrayView subview(size_t offset) const {
434 | return subview(offset, this->size());
435 | }
436 | };
437 |
438 | // Comparing two ArrayViews compares their (pointer,size) pairs; it does *not*
439 | // dereference the pointers.
440 | template
441 | bool operator==(const ArrayView &a, const ArrayView &b) {
442 | return a.data() == b.data() && a.size() == b.size();
443 | }
444 |
445 | template
446 | bool operator!=(const ArrayView &a, const ArrayView &b) {
447 | return !(a == b);
448 | }
449 |
450 | // Variable-size ArrayViews are the size of two pointers; fixed-size ArrayViews
451 | // are the size of one pointer. (And as a special case, fixed-size ArrayViews
452 | // of size 0 require no storage.)
453 | static_assert(sizeof(ArrayView) == 2 * sizeof(int *), "");
454 | static_assert(sizeof(ArrayView) == sizeof(int *), "");
455 | static_assert(std::is_empty>::value, "");
456 |
457 | template
458 | inline ArrayView MakeArrayView(T *data, size_t size) {
459 | return ArrayView(data, size);
460 | }
461 |
462 |
463 | #endif // API_ARRAY_VIEW_H_
464 |
465 | #ifndef RTC_BASE_ZERO_MEMORY_H_
466 | #define RTC_BASE_ZERO_MEMORY_H_
467 |
468 |
469 | // Fill memory with zeros in a way that the compiler doesn't optimize it away
470 | // even if the pointer is not used afterwards.
471 | void ExplicitZeroMemory(void *ptr, size_t len);
472 |
473 | template::value &&
475 | std::is_trivial::value>::type * = nullptr>
476 | void ExplicitZeroMemory(ArrayView a) {
477 | ExplicitZeroMemory(a.data(), a.size());
478 | }
479 |
480 | #endif // RTC_BASE_ZERO_MEMORY_H_
481 |
482 | /*
483 | * Copyright 2004 The WebRTC Project Authors. All rights reserved.
484 | *
485 | * Use of this source code is governed by a BSD-style license
486 | * that can be found in the LICENSE file in the root of the source
487 | * tree. An additional intellectual property rights grant can be found
488 | * in the file PATENTS. All contributing project authors may
489 | * be found in the AUTHORS file in the root of the source tree.
490 | */
491 |
492 | #ifndef RTC_BASE_BUFFER_H_
493 | #define RTC_BASE_BUFFER_H_
494 |
495 | #include
496 | #include
497 | #include
498 | #include
499 | #include
500 |
501 |
502 | // (Internal; please don't use outside this file.) Determines if elements of
503 | // type U are compatible with a BufferT. For most types, we just ignore
504 | // top-level const and forbid top-level volatile and require T and U to be
505 | // otherwise equal, but all byte-sized integers (notably char, int8_t, and
506 | // uint8_t) are compatible with each other. (Note: We aim to get rid of this
507 | // behavior, and treat all types the same.)
508 | template
509 | struct BufferCompat {
510 | static constexpr bool value =
511 | !std::is_volatile::value &&
512 | ((std::is_integral::value && sizeof(T) == 1)
513 | ? (std::is_integral::value && sizeof(U) == 1)
514 | : (std::is_same::type>::value));
515 | };
516 |
517 |
518 | // Basic buffer class, can be grown and shrunk dynamically.
519 | // Unlike std::string/vector, does not initialize data when increasing size.
520 | // If "ZeroOnFree" is true, any memory is explicitly cleared before releasing.
521 | // The type alias "ZeroOnFreeBuffer" below should be used instead of setting
522 | // "ZeroOnFree" in the template manually to "true".
523 | template
524 | class BufferT {
525 | // We want T's destructor and default constructor to be trivial, i.e. perform
526 | // no action, so that we don't have to touch the memory we allocate and
527 | // deallocate. And we want T to be trivially copyable, so that we can copy T
528 | // instances with std::memcpy. This is precisely the definition of a trivial
529 | // type.
530 | static_assert(std::is_trivial::value, "T must be a trivial type.");
531 |
532 | // This class relies heavily on being able to mutate its data.
533 | static_assert(!std::is_const::value, "T may not be const");
534 |
535 | public:
536 | using value_type = T;
537 |
538 | // An empty BufferT.
539 | BufferT() : size_(0), capacity_(0), data_(nullptr) {
540 | RTC_DCHECK(IsConsistent());
541 | }
542 |
543 | // Disable copy construction and copy assignment, since copying a buffer is
544 | // expensive enough that we want to force the user to be explicit about it.
545 | BufferT(const BufferT &) = delete;
546 |
547 | BufferT &operator=(const BufferT &) = delete;
548 |
549 | BufferT(BufferT &&buf)
550 | : size_(buf.size()),
551 | capacity_(buf.capacity()),
552 | data_(std::move(buf.data_)) {
553 | RTC_DCHECK(IsConsistent());
554 | buf.OnMovedFrom();
555 | }
556 |
557 | // Construct a buffer with the specified number of uninitialized elements.
558 | explicit BufferT(size_t size) : BufferT(size, size) {}
559 |
560 | BufferT(size_t size, size_t capacity)
561 | : size_(size),
562 | capacity_(std::max(size, capacity)),
563 | data_(new T[capacity_]) {
564 | RTC_DCHECK(IsConsistent());
565 | }
566 |
567 | // Construct a buffer and copy the specified number of elements into it.
568 | template::value>::type * = nullptr>
571 | BufferT(const U *data, size_t size) : BufferT(data, size, size) {}
572 |
573 | template::value>::type * = nullptr>
576 | BufferT(U *data, size_t size, size_t capacity) : BufferT(size, capacity) {
577 | static_assert(sizeof(T) == sizeof(U), "");
578 | std::memcpy(data_.get(), data, size * sizeof(U));
579 | }
580 |
581 | // Construct a buffer from the contents of an array.
582 | template::value>::type * = nullptr>
586 | BufferT(U (&array)[N]) : BufferT(array, N) {}
587 |
588 | ~BufferT() { MaybeZeroCompleteBuffer(); }
589 |
590 | // Get a pointer to the data. Just .data() will give you a (const) T*, but if
591 | // T is a byte-sized integer, you may also use .data() for any other
592 | // byte-sized integer U.
593 | template::value>::type * = nullptr>
596 | const U *data() const {
597 | RTC_DCHECK(IsConsistent());
598 | return reinterpret_cast(data_.get());
599 | }
600 |
601 | template::value>::type * = nullptr>
604 | U *data() {
605 | RTC_DCHECK(IsConsistent());
606 | return reinterpret_cast(data_.get());
607 | }
608 |
609 | bool empty() const {
610 | RTC_DCHECK(IsConsistent());
611 | return size_ == 0;
612 | }
613 |
614 | size_t size() const {
615 | RTC_DCHECK(IsConsistent());
616 | return size_;
617 | }
618 |
619 | size_t capacity() const {
620 | RTC_DCHECK(IsConsistent());
621 | return capacity_;
622 | }
623 |
624 | BufferT &operator=(BufferT &&buf) {
625 | RTC_DCHECK(IsConsistent());
626 | RTC_DCHECK(buf.IsConsistent());
627 | size_ = buf.size_;
628 | capacity_ = buf.capacity_;
629 | data_ = std::move(buf.data_);
630 | buf.OnMovedFrom();
631 | return *this;
632 | }
633 |
634 | bool operator==(const BufferT &buf) const {
635 | RTC_DCHECK(IsConsistent());
636 | if (size_ != buf.size_) {
637 | return false;
638 | }
639 | if (std::is_integral::value) {
640 | // Optimization.
641 | return std::memcmp(data_.get(), buf.data_.get(), size_ * sizeof(T)) == 0;
642 | }
643 | for (size_t i = 0; i < size_; ++i) {
644 | if (data_[i] != buf.data_[i]) {
645 | return false;
646 | }
647 | }
648 | return true;
649 | }
650 |
651 | bool operator!=(const BufferT &buf) const { return !(*this == buf); }
652 |
653 | T &operator[](size_t index) {
654 | RTC_DCHECK_LT(index, size_);
655 | return data()[index];
656 | }
657 |
658 | T operator[](size_t index) const {
659 | RTC_DCHECK_LT(index, size_);
660 | return data()[index];
661 | }
662 |
663 | T *begin() { return data(); }
664 |
665 | T *end() { return data() + size(); }
666 |
667 | const T *begin() const { return data(); }
668 |
669 | const T *end() const { return data() + size(); }
670 |
671 | const T *cbegin() const { return data(); }
672 |
673 | const T *cend() const { return data() + size(); }
674 |
675 | // The SetData functions replace the contents of the buffer. They accept the
676 | // same input types as the constructors.
677 | template::value>::type * = nullptr>
680 | void SetData(const U *data, size_t size) {
681 | RTC_DCHECK(IsConsistent());
682 | const size_t old_size = size_;
683 | size_ = 0;
684 | AppendData(data, size);
685 | if (ZeroOnFree && size_ < old_size) {
686 | ZeroTrailingData(old_size - size_);
687 | }
688 | }
689 |
690 | template::value>::type * = nullptr>
694 | void SetData(const U (&array)[N]) {
695 | SetData(array, N);
696 | }
697 |
698 | template::value>::type * = nullptr>
701 | void SetData(const W &w) {
702 | SetData(w.data(), w.size());
703 | }
704 |
705 | // Replaces the data in the buffer with at most |max_elements| of data, using
706 | // the function |setter|, which should have the following signature:
707 | //
708 | // size_t setter(ArrayView view)
709 | //
710 | // |setter| is given an appropriately typed ArrayView of length exactly
711 | // |max_elements| that describes the area where it should write the data; it
712 | // should return the number of elements actually written. (If it doesn't fill
713 | // the whole ArrayView, it should leave the unused space at the end.)
714 | template::value>::type * = nullptr>
718 | size_t SetData(size_t max_elements, F &&setter) {
719 | RTC_DCHECK(IsConsistent());
720 | const size_t old_size = size_;
721 | size_ = 0;
722 | const size_t written = AppendData(max_elements, std::forward(setter));
723 | if (ZeroOnFree && size_ < old_size) {
724 | ZeroTrailingData(old_size - size_);
725 | }
726 | return written;
727 | }
728 |
729 | // The AppendData functions add data to the end of the buffer. They accept
730 | // the same input types as the constructors.
731 | template::value>::type * = nullptr>
734 | void AppendData(const U *data, size_t size) {
735 | RTC_DCHECK(IsConsistent());
736 | const size_t new_size = size_ + size;
737 | EnsureCapacityWithHeadroom(new_size, true);
738 | static_assert(sizeof(T) == sizeof(U), "");
739 | std::memcpy(data_.get() + size_, data, size * sizeof(U));
740 | size_ = new_size;
741 | RTC_DCHECK(IsConsistent());
742 | }
743 |
744 | template::value>::type * = nullptr>
748 | void AppendData(const U (&array)[N]) {
749 | AppendData(array, N);
750 | }
751 |
752 | template::value>::type * = nullptr>
755 | void AppendData(const W &w) {
756 | AppendData(w.data(), w.size());
757 | }
758 |
759 | template::value>::type * = nullptr>
762 | void AppendData(const U &item) {
763 | AppendData(&item, 1);
764 | }
765 |
766 | // Appends at most |max_elements| to the end of the buffer, using the function
767 | // |setter|, which should have the following signature:
768 | //
769 | // size_t setter(ArrayView view)
770 | //
771 | // |setter| is given an appropriately typed ArrayView of length exactly
772 | // |max_elements| that describes the area where it should write the data; it
773 | // should return the number of elements actually written. (If it doesn't fill
774 | // the whole ArrayView, it should leave the unused space at the end.)
775 | template::value>::type * = nullptr>
779 | size_t AppendData(size_t max_elements, F &&setter) {
780 | RTC_DCHECK(IsConsistent());
781 | const size_t old_size = size_;
782 | SetSize(old_size + max_elements);
783 | U *base_ptr = data() + old_size;
784 | size_t written_elements = setter(ArrayView(base_ptr, max_elements));
785 |
786 | RTC_CHECK_LE(written_elements, max_elements);
787 | size_ = old_size + written_elements;
788 | RTC_DCHECK(IsConsistent());
789 | return written_elements;
790 | }
791 |
792 | // Sets the size of the buffer. If the new size is smaller than the old, the
793 | // buffer contents will be kept but truncated; if the new size is greater,
794 | // the existing contents will be kept and the new space will be
795 | // uninitialized.
796 | void SetSize(size_t size) {
797 | const size_t old_size = size_;
798 | EnsureCapacityWithHeadroom(size, true);
799 | size_ = size;
800 | if (ZeroOnFree && size_ < old_size) {
801 | ZeroTrailingData(old_size - size_);
802 | }
803 | }
804 |
805 | // Ensure that the buffer size can be increased to at least capacity without
806 | // further reallocation. (Of course, this operation might need to reallocate
807 | // the buffer.)
808 | void EnsureCapacity(size_t capacity) {
809 | // Don't allocate extra headroom, since the user is asking for a specific
810 | // capacity.
811 | EnsureCapacityWithHeadroom(capacity, false);
812 | }
813 |
814 | // Resets the buffer to zero size without altering capacity. Works even if the
815 | // buffer has been moved from.
816 | void Clear() {
817 | MaybeZeroCompleteBuffer();
818 | size_ = 0;
819 | RTC_DCHECK(IsConsistent());
820 | }
821 |
822 | // Swaps two buffers. Also works for buffers that have been moved from.
823 | friend void swap(BufferT &a, BufferT &b) {
824 | using std::swap;
825 | swap(a.size_, b.size_);
826 | swap(a.capacity_, b.capacity_);
827 | swap(a.data_, b.data_);
828 | }
829 |
830 | private:
831 | void EnsureCapacityWithHeadroom(size_t capacity, bool extra_headroom) {
832 | RTC_DCHECK(IsConsistent());
833 | if (capacity <= capacity_)
834 | return;
835 |
836 | // If the caller asks for extra headroom, ensure that the new capacity is
837 | // >= 1.5 times the old capacity. Any constant > 1 is sufficient to prevent
838 | // quadratic behavior; as to why we pick 1.5 in particular, see
839 | // https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md and
840 | // http://www.gahcep.com/cpp-internals-stl-vector-part-1/.
841 | const size_t new_capacity =
842 | extra_headroom ? std::max(capacity, capacity_ + capacity_ / 2)
843 | : capacity;
844 |
845 | std::unique_ptr new_data(new T[new_capacity]);
846 | std::memcpy(new_data.get(), data_.get(), size_ * sizeof(T));
847 | MaybeZeroCompleteBuffer();
848 | data_ = std::move(new_data);
849 | capacity_ = new_capacity;
850 | RTC_DCHECK(IsConsistent());
851 | }
852 |
853 | // Zero the complete buffer if template argument "ZeroOnFree" is true.
854 | void MaybeZeroCompleteBuffer() {
855 | if (ZeroOnFree && capacity_) {
856 | // It would be sufficient to only zero "size_" elements, as all other
857 | // methods already ensure that the unused capacity contains no sensitive
858 | // data - but better safe than sorry.
859 | ExplicitZeroMemory(data_.get(), capacity_ * sizeof(T));
860 | }
861 | }
862 |
863 | // Zero the first "count" elements of unused capacity.
864 | void ZeroTrailingData(size_t count) {
865 | RTC_DCHECK(IsConsistent());
866 | RTC_DCHECK_LE(count, capacity_ - size_);
867 | ExplicitZeroMemory(data_.get() + size_, count * sizeof(T));
868 | }
869 |
870 | // Precondition for all methods except Clear and the destructor.
871 | // Postcondition for all methods except move construction and move
872 | // assignment, which leave the moved-from object in a possibly inconsistent
873 | // state.
874 | bool IsConsistent() const {
875 | return (data_ || capacity_ == 0) && capacity_ >= size_;
876 | }
877 |
878 | // Called when *this has been moved from. Conceptually it's a no-op, but we
879 | // can mutate the state slightly to help subsequent sanity checks catch bugs.
880 | void OnMovedFrom() {
881 | #if RTC_DCHECK_IS_ON
882 | // Make *this consistent and empty. Shouldn't be necessary, but better safe
883 | // than sorry.
884 | size_ = 0;
885 | capacity_ = 0;
886 | #else
887 | // Ensure that *this is always inconsistent, to provoke bugs.
888 | size_ = 1;
889 | capacity_ = 0;
890 | #endif
891 | }
892 |
893 | size_t size_;
894 | size_t capacity_;
895 | std::unique_ptr data_;
896 | };
897 |
898 | // By far the most common sort of buffer.
899 | using Buffer = BufferT;
900 |
901 | // A buffer that zeros memory before releasing it.
902 | template
903 | using ZeroOnFreeBuffer = BufferT;
904 |
905 |
906 | #endif // RTC_BASE_BUFFER_H_
907 |
908 |
909 | class ComfortNoiseDecoder {
910 | public:
911 | ComfortNoiseDecoder();
912 |
913 | ~ComfortNoiseDecoder() = default;
914 |
915 | ComfortNoiseDecoder(const ComfortNoiseDecoder &) = delete;
916 |
917 | ComfortNoiseDecoder &operator=(const ComfortNoiseDecoder &) = delete;
918 |
919 | void Reset();
920 |
921 | // Updates the CN state when a new SID packet arrives.
922 | // |sid| is a view of the SID packet without the headers.
923 | void UpdateSid(ArrayView sid);
924 |
925 | // Generates comfort noise.
926 | // |out_data| will be filled with samples - its size determines the number of
927 | // samples generated. When |new_period| is true, CNG history will be reset
928 | // before any audio is generated. Returns |false| if outData is too large -
929 | // currently 640 bytes (equalling 10ms at 64kHz).
930 | // TODO(ossu): Specify better limits for the size of out_data. Either let it
931 | // be unbounded or limit to 10ms in the current sample rate.
932 | bool Generate(ArrayView out_data, bool new_period);
933 |
934 | private:
935 | uint32_t dec_seed_;
936 | int32_t dec_target_energy_;
937 | int32_t dec_used_energy_;
938 | int16_t dec_target_reflCoefs_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
939 | int16_t dec_used_reflCoefs_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
940 | int16_t dec_filtstate_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
941 | int16_t dec_filtstateLow_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
942 | uint16_t dec_order_;
943 | int16_t dec_target_scale_factor_; /* Q29 */
944 | int16_t dec_used_scale_factor_; /* Q29 */
945 | };
946 |
947 | class ComfortNoiseEncoder {
948 | public:
949 | // Creates a comfort noise encoder.
950 | // |fs| selects sample rate: 8000 for narrowband or 16000 for wideband.
951 | // |interval| sets the interval at which to generate SID data (in ms).
952 | // |quality| selects the number of refl. coeffs. Maximum allowed is 12.
953 | ComfortNoiseEncoder(int fs, int interval, int quality);
954 |
955 | ~ComfortNoiseEncoder() = default;
956 |
957 | ComfortNoiseEncoder(const ComfortNoiseEncoder &) = delete;
958 |
959 | ComfortNoiseEncoder &operator=(const ComfortNoiseEncoder &) = delete;
960 |
961 | // Resets the comfort noise encoder to its initial state.
962 | // Parameters are set as during construction.
963 | void Reset(int fs, int interval, int quality);
964 |
965 | // Analyzes background noise from |speech| and appends coefficients to
966 | // |output|. Returns the number of coefficients generated. If |force_sid| is
967 | // true, a SID frame is forced and the internal sid interval counter is reset.
968 | // Will fail if the input size is too large (> 640 samples, see
969 | // ComfortNoiseDecoder::Generate).
970 | size_t Encode(ArrayView speech,
971 | bool force_sid,
972 | Buffer *output);
973 |
974 | private:
975 | size_t enc_nrOfCoefs_;
976 | int enc_sampfreq_;
977 | int16_t enc_interval_;
978 | int16_t enc_msSinceSid_;
979 | int32_t enc_Energy_;
980 | int16_t enc_reflCoefs_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
981 | int32_t enc_corrVector_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
982 | uint32_t enc_seed_;
983 | };
984 |
985 |
986 | #endif // MODULES_AUDIO_CODING_CODECS_CNG_WEBRTC_CNG_H_
987 |
--------------------------------------------------------------------------------
/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | //采用https://github.com/mackron/dr_libs/blob/master/dr_wav.h 解码
5 | #define DR_WAV_IMPLEMENTATION
6 |
7 | #include "dr_wav.h"
8 | #include "cng.h"
9 |
10 | #ifndef nullptr
11 | #define nullptr 0
12 | #endif
13 |
14 | #ifndef MIN
15 | #define MIN(A, B) ((A) < (B) ? (A) : (B))
16 | #endif
17 |
18 | //写wav文件
19 | void wavWrite_int16(char *filename, int16_t *buffer, size_t sampleRate, size_t totalSampleCount) {
20 | drwav_data_format format = {};
21 | format.container = drwav_container_riff; // <-- drwav_container_riff = normal WAV files, drwav_container_w64 = Sony Wave64.
22 | format.format = DR_WAVE_FORMAT_PCM; // <-- Any of the DR_WAVE_FORMAT_* codes.
23 | format.channels = 1;
24 | format.sampleRate = (drwav_uint32) sampleRate;
25 | format.bitsPerSample = 16;
26 | drwav *pWav = drwav_open_file_write(filename, &format);
27 | if (pWav) {
28 | drwav_uint64 samplesWritten = drwav_write(pWav, totalSampleCount, buffer);
29 | drwav_uninit(pWav);
30 | if (samplesWritten != totalSampleCount) {
31 | fprintf(stderr, "ERROR\n");
32 | exit(1);
33 | }
34 | }
35 | }
36 |
37 |
38 | //分割路径函数
39 | void splitpath(const char *path, char *drv, char *dir, char *name, char *ext) {
40 | const char *end;
41 | const char *p;
42 | const char *s;
43 | if (path[0] && path[1] == ':') {
44 | if (drv) {
45 | *drv++ = *path++;
46 | *drv++ = *path++;
47 | *drv = '\0';
48 | }
49 | } else if (drv)
50 | *drv = '\0';
51 | for (end = path; *end && *end != ':';)
52 | end++;
53 | for (p = end; p > path && *--p != '\\' && *p != '/';)
54 | if (*p == '.') {
55 | end = p;
56 | break;
57 | }
58 | if (ext)
59 | for (s = end; (*ext = *s++);)
60 | ext++;
61 | for (p = end; p > path;)
62 | if (*--p == '\\' || *p == '/') {
63 | p++;
64 | break;
65 | }
66 | if (name) {
67 | for (s = p; s < end;)
68 | *name++ = *s++;
69 | *name = '\0';
70 | }
71 | if (dir) {
72 | for (s = path; s < p;)
73 | *dir++ = *s++;
74 | *dir = '\0';
75 | }
76 | }
77 |
78 | enum {
79 | kSidShortIntervalUpdate = 1,
80 | kSidNormalIntervalUpdate = 100,
81 | kSidLongIntervalUpdate = 10000
82 | };
83 |
84 | enum : size_t {
85 | kCNGNumParamsLow = 0,
86 | kCNGNumParamsNormal = 8,
87 | kCNGNumParamsHigh = WEBRTC_CNG_MAX_LPC_ORDER,
88 | kCNGNumParamsTooHigh = WEBRTC_CNG_MAX_LPC_ORDER + 1
89 | };
90 |
91 | enum {
92 | kNoSid,
93 | kForceSid
94 | };
95 |
96 | int main(int argc, char *argv[]) {
97 | printf("WebRtc Comfort Noise Generator\n");
98 | printf("博客:http://cpuimage.cnblogs.com/\n");
99 | printf("舒适噪音生成器\n");
100 | int sample_rate_hz = 8000;// 8000, 16000, 32000, 48000, 64000
101 | int16_t speech_data_[640]; // Max size of CNG internal buffers.
102 | const size_t num_samples_10ms = (sample_rate_hz / 100);
103 | Buffer sid_data;
104 | int quality = kCNGNumParamsNormal;
105 | ComfortNoiseEncoder cng_encoder(sample_rate_hz, kSidNormalIntervalUpdate,
106 | quality);
107 | size_t ret = cng_encoder.Encode(ArrayView(
108 | speech_data_, num_samples_10ms),
109 | kNoSid, &sid_data);
110 | if (ret == 0) {
111 | size_t size = cng_encoder.Encode(ArrayView(speech_data_, num_samples_10ms),
112 | kForceSid, &sid_data);
113 | if (size == (quality + 1))
114 | printf("done \n");
115 | wavWrite_int16("cng.wav", speech_data_, sample_rate_hz, num_samples_10ms);
116 | }
117 | printf("按任意键退出程序 \n");
118 | getchar();
119 | return 0;
120 | }
121 |
--------------------------------------------------------------------------------