OLD | NEW |
| (Empty) |
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 "webrtc_cng.h" | |
12 | |
13 #include <string.h> | |
14 #include <stdlib.h> | |
15 | |
16 #include "cng_helpfuns.h" | |
17 #include "signal_processing_library.h" | |
18 | |
19 typedef struct WebRtcCngDecoder_ { | |
20 uint32_t dec_seed; | |
21 int32_t dec_target_energy; | |
22 int32_t dec_used_energy; | |
23 int16_t dec_target_reflCoefs[WEBRTC_CNG_MAX_LPC_ORDER + 1]; | |
24 int16_t dec_used_reflCoefs[WEBRTC_CNG_MAX_LPC_ORDER + 1]; | |
25 int16_t dec_filtstate[WEBRTC_CNG_MAX_LPC_ORDER + 1]; | |
26 int16_t dec_filtstateLow[WEBRTC_CNG_MAX_LPC_ORDER + 1]; | |
27 int16_t dec_Efiltstate[WEBRTC_CNG_MAX_LPC_ORDER + 1]; | |
28 int16_t dec_EfiltstateLow[WEBRTC_CNG_MAX_LPC_ORDER + 1]; | |
29 int16_t dec_order; | |
30 int16_t dec_target_scale_factor; /* Q29 */ | |
31 int16_t dec_used_scale_factor; /* Q29 */ | |
32 int16_t target_scale_factor; /* Q13 */ | |
33 int16_t errorcode; | |
34 int16_t initflag; | |
35 } WebRtcCngDecoder; | |
36 | |
37 typedef struct WebRtcCngEncoder_ { | |
38 size_t enc_nrOfCoefs; | |
39 int enc_sampfreq; | |
40 int16_t enc_interval; | |
41 int16_t enc_msSinceSID; | |
42 int32_t enc_Energy; | |
43 int16_t enc_reflCoefs[WEBRTC_CNG_MAX_LPC_ORDER + 1]; | |
44 int32_t enc_corrVector[WEBRTC_CNG_MAX_LPC_ORDER + 1]; | |
45 uint32_t enc_seed; | |
46 int16_t errorcode; | |
47 int16_t initflag; | |
48 } WebRtcCngEncoder; | |
49 | |
50 const int32_t WebRtcCng_kDbov[94] = { | |
51 1081109975, 858756178, 682134279, 541838517, 430397633, 341876992, | |
52 271562548, 215709799, 171344384, 136103682, 108110997, 85875618, | |
53 68213428, 54183852, 43039763, 34187699, 27156255, 21570980, | |
54 17134438, 13610368, 10811100, 8587562, 6821343, 5418385, | |
55 4303976, 3418770, 2715625, 2157098, 1713444, 1361037, | |
56 1081110, 858756, 682134, 541839, 430398, 341877, | |
57 271563, 215710, 171344, 136104, 108111, 85876, | |
58 68213, 54184, 43040, 34188, 27156, 21571, | |
59 17134, 13610, 10811, 8588, 6821, 5418, | |
60 4304, 3419, 2716, 2157, 1713, 1361, | |
61 1081, 859, 682, 542, 430, 342, | |
62 272, 216, 171, 136, 108, 86, | |
63 68, 54, 43, 34, 27, 22, | |
64 17, 14, 11, 9, 7, 5, | |
65 4, 3, 3, 2, 2, 1, | |
66 1, 1, 1, 1 | |
67 }; | |
68 | |
69 const int16_t WebRtcCng_kCorrWindow[WEBRTC_CNG_MAX_LPC_ORDER] = { | |
70 32702, 32636, 32570, 32505, 32439, 32374, | |
71 32309, 32244, 32179, 32114, 32049, 31985 | |
72 }; | |
73 | |
74 /**************************************************************************** | |
75 * WebRtcCng_CreateEnc/Dec(...) | |
76 * | |
77 * These functions create an instance to the specified structure | |
78 * | |
79 * Input: | |
80 * - XXX_inst : Pointer to created instance that should be created | |
81 * | |
82 * Return value : 0 - Ok | |
83 * -1 - Error | |
84 */ | |
85 int16_t WebRtcCng_CreateEnc(CNG_enc_inst** cng_inst) { | |
86 if (cng_inst != NULL) { | |
87 *cng_inst = (CNG_enc_inst*) malloc(sizeof(WebRtcCngEncoder)); | |
88 if (*cng_inst != NULL) { | |
89 (*(WebRtcCngEncoder**) cng_inst)->errorcode = 0; | |
90 (*(WebRtcCngEncoder**) cng_inst)->initflag = 0; | |
91 | |
92 /* Needed to get the right function pointers in SPLIB. */ | |
93 WebRtcSpl_Init(); | |
94 | |
95 return 0; | |
96 } else { | |
97 /* The memory could not be allocated. */ | |
98 return -1; | |
99 } | |
100 } else { | |
101 /* The input pointer is invalid (NULL). */ | |
102 return -1; | |
103 } | |
104 } | |
105 | |
106 int16_t WebRtcCng_CreateDec(CNG_dec_inst** cng_inst) { | |
107 if (cng_inst != NULL ) { | |
108 *cng_inst = (CNG_dec_inst*) malloc(sizeof(WebRtcCngDecoder)); | |
109 if (*cng_inst != NULL ) { | |
110 (*(WebRtcCngDecoder**) cng_inst)->errorcode = 0; | |
111 (*(WebRtcCngDecoder**) cng_inst)->initflag = 0; | |
112 | |
113 /* Needed to get the right function pointers in SPLIB. */ | |
114 WebRtcSpl_Init(); | |
115 | |
116 return 0; | |
117 } else { | |
118 /* The memory could not be allocated */ | |
119 return -1; | |
120 } | |
121 } else { | |
122 /* The input pointer is invalid (NULL). */ | |
123 return -1; | |
124 } | |
125 } | |
126 | |
127 /**************************************************************************** | |
128 * WebRtcCng_InitEnc/Dec(...) | |
129 * | |
130 * This function initializes a instance | |
131 * | |
132 * Input: | |
133 * - cng_inst : Instance that should be initialized | |
134 * | |
135 * - fs : 8000 for narrowband and 16000 for wideband | |
136 * - interval : generate SID data every interval ms | |
137 * - quality : TBD | |
138 * | |
139 * Output: | |
140 * - cng_inst : Initialized instance | |
141 * | |
142 * Return value : 0 - Ok | |
143 * -1 - Error | |
144 */ | |
145 int WebRtcCng_InitEnc(CNG_enc_inst* cng_inst, int fs, int16_t interval, | |
146 int16_t quality) { | |
147 int i; | |
148 WebRtcCngEncoder* inst = (WebRtcCngEncoder*) cng_inst; | |
149 memset(inst, 0, sizeof(WebRtcCngEncoder)); | |
150 | |
151 /* Check LPC order */ | |
152 if (quality > WEBRTC_CNG_MAX_LPC_ORDER || quality <= 0) { | |
153 inst->errorcode = CNG_DISALLOWED_LPC_ORDER; | |
154 return -1; | |
155 } | |
156 | |
157 inst->enc_sampfreq = fs; | |
158 inst->enc_interval = interval; | |
159 inst->enc_nrOfCoefs = quality; | |
160 inst->enc_msSinceSID = 0; | |
161 inst->enc_seed = 7777; /* For debugging only. */ | |
162 inst->enc_Energy = 0; | |
163 for (i = 0; i < (WEBRTC_CNG_MAX_LPC_ORDER + 1); i++) { | |
164 inst->enc_reflCoefs[i] = 0; | |
165 inst->enc_corrVector[i] = 0; | |
166 } | |
167 inst->initflag = 1; | |
168 | |
169 return 0; | |
170 } | |
171 | |
172 void WebRtcCng_InitDec(CNG_dec_inst* cng_inst) { | |
173 int i; | |
174 | |
175 WebRtcCngDecoder* inst = (WebRtcCngDecoder*) cng_inst; | |
176 | |
177 memset(inst, 0, sizeof(WebRtcCngDecoder)); | |
178 inst->dec_seed = 7777; /* For debugging only. */ | |
179 inst->dec_order = 5; | |
180 inst->dec_target_scale_factor = 0; | |
181 inst->dec_used_scale_factor = 0; | |
182 for (i = 0; i < (WEBRTC_CNG_MAX_LPC_ORDER + 1); i++) { | |
183 inst->dec_filtstate[i] = 0; | |
184 inst->dec_target_reflCoefs[i] = 0; | |
185 inst->dec_used_reflCoefs[i] = 0; | |
186 } | |
187 inst->dec_target_reflCoefs[0] = 0; | |
188 inst->dec_used_reflCoefs[0] = 0; | |
189 inst->dec_used_energy = 0; | |
190 inst->initflag = 1; | |
191 } | |
192 | |
193 /**************************************************************************** | |
194 * WebRtcCng_FreeEnc/Dec(...) | |
195 * | |
196 * These functions frees the dynamic memory of a specified instance | |
197 * | |
198 * Input: | |
199 * - cng_inst : Pointer to created instance that should be freed | |
200 * | |
201 * Return value : 0 - Ok | |
202 * -1 - Error | |
203 */ | |
204 int16_t WebRtcCng_FreeEnc(CNG_enc_inst* cng_inst) { | |
205 free(cng_inst); | |
206 return 0; | |
207 } | |
208 | |
209 int16_t WebRtcCng_FreeDec(CNG_dec_inst* cng_inst) { | |
210 free(cng_inst); | |
211 return 0; | |
212 } | |
213 | |
214 /**************************************************************************** | |
215 * WebRtcCng_Encode(...) | |
216 * | |
217 * These functions analyzes background noise | |
218 * | |
219 * Input: | |
220 * - cng_inst : Pointer to created instance | |
221 * - speech : Signal (noise) to be analyzed | |
222 * - nrOfSamples : Size of speech vector | |
223 * - bytesOut : Nr of bytes to transmit, might be 0 | |
224 * | |
225 * Return value : 0 - Ok | |
226 * -1 - Error | |
227 */ | |
228 int WebRtcCng_Encode(CNG_enc_inst* cng_inst, int16_t* speech, | |
229 size_t nrOfSamples, uint8_t* SIDdata, | |
230 size_t* bytesOut, int16_t forceSID) { | |
231 WebRtcCngEncoder* inst = (WebRtcCngEncoder*) cng_inst; | |
232 | |
233 int16_t arCoefs[WEBRTC_CNG_MAX_LPC_ORDER + 1]; | |
234 int32_t corrVector[WEBRTC_CNG_MAX_LPC_ORDER + 1]; | |
235 int16_t refCs[WEBRTC_CNG_MAX_LPC_ORDER + 1]; | |
236 int16_t hanningW[WEBRTC_CNG_MAX_OUTSIZE_ORDER]; | |
237 int16_t ReflBeta = 19661; /* 0.6 in q15. */ | |
238 int16_t ReflBetaComp = 13107; /* 0.4 in q15. */ | |
239 int32_t outEnergy; | |
240 int outShifts; | |
241 size_t i; | |
242 int stab; | |
243 int acorrScale; | |
244 size_t index; | |
245 size_t ind, factor; | |
246 int32_t* bptr; | |
247 int32_t blo, bhi; | |
248 int16_t negate; | |
249 const int16_t* aptr; | |
250 int16_t speechBuf[WEBRTC_CNG_MAX_OUTSIZE_ORDER]; | |
251 | |
252 /* Check if encoder initiated. */ | |
253 if (inst->initflag != 1) { | |
254 inst->errorcode = CNG_ENCODER_NOT_INITIATED; | |
255 return -1; | |
256 } | |
257 | |
258 /* Check framesize. */ | |
259 if (nrOfSamples > WEBRTC_CNG_MAX_OUTSIZE_ORDER) { | |
260 inst->errorcode = CNG_DISALLOWED_FRAME_SIZE; | |
261 return -1; | |
262 } | |
263 | |
264 for (i = 0; i < nrOfSamples; i++) { | |
265 speechBuf[i] = speech[i]; | |
266 } | |
267 | |
268 factor = nrOfSamples; | |
269 | |
270 /* Calculate energy and a coefficients. */ | |
271 outEnergy = WebRtcSpl_Energy(speechBuf, nrOfSamples, &outShifts); | |
272 while (outShifts > 0) { | |
273 /* We can only do 5 shifts without destroying accuracy in | |
274 * division factor. */ | |
275 if (outShifts > 5) { | |
276 outEnergy <<= (outShifts - 5); | |
277 outShifts = 5; | |
278 } else { | |
279 factor /= 2; | |
280 outShifts--; | |
281 } | |
282 } | |
283 outEnergy = WebRtcSpl_DivW32W16(outEnergy, (int16_t)factor); | |
284 | |
285 if (outEnergy > 1) { | |
286 /* Create Hanning Window. */ | |
287 WebRtcSpl_GetHanningWindow(hanningW, nrOfSamples / 2); | |
288 for (i = 0; i < (nrOfSamples / 2); i++) | |
289 hanningW[nrOfSamples - i - 1] = hanningW[i]; | |
290 | |
291 WebRtcSpl_ElementwiseVectorMult(speechBuf, hanningW, speechBuf, nrOfSamples, | |
292 14); | |
293 | |
294 WebRtcSpl_AutoCorrelation(speechBuf, nrOfSamples, inst->enc_nrOfCoefs, | |
295 corrVector, &acorrScale); | |
296 | |
297 if (*corrVector == 0) | |
298 *corrVector = WEBRTC_SPL_WORD16_MAX; | |
299 | |
300 /* Adds the bandwidth expansion. */ | |
301 aptr = WebRtcCng_kCorrWindow; | |
302 bptr = corrVector; | |
303 | |
304 /* (zzz) lpc16_1 = 17+1+820+2+2 = 842 (ordo2=700). */ | |
305 for (ind = 0; ind < inst->enc_nrOfCoefs; ind++) { | |
306 /* The below code multiplies the 16 b corrWindow values (Q15) with | |
307 * the 32 b corrvector (Q0) and shifts the result down 15 steps. */ | |
308 negate = *bptr < 0; | |
309 if (negate) | |
310 *bptr = -*bptr; | |
311 | |
312 blo = (int32_t) * aptr * (*bptr & 0xffff); | |
313 bhi = ((blo >> 16) & 0xffff) | |
314 + ((int32_t)(*aptr++) * ((*bptr >> 16) & 0xffff)); | |
315 blo = (blo & 0xffff) | ((bhi & 0xffff) << 16); | |
316 | |
317 *bptr = (((bhi >> 16) & 0x7fff) << 17) | ((uint32_t) blo >> 15); | |
318 if (negate) | |
319 *bptr = -*bptr; | |
320 bptr++; | |
321 } | |
322 /* End of bandwidth expansion. */ | |
323 | |
324 stab = WebRtcSpl_LevinsonDurbin(corrVector, arCoefs, refCs, | |
325 inst->enc_nrOfCoefs); | |
326 | |
327 if (!stab) { | |
328 /* Disregard from this frame */ | |
329 *bytesOut = 0; | |
330 return 0; | |
331 } | |
332 | |
333 } else { | |
334 for (i = 0; i < inst->enc_nrOfCoefs; i++) | |
335 refCs[i] = 0; | |
336 } | |
337 | |
338 if (forceSID) { | |
339 /* Read instantaneous values instead of averaged. */ | |
340 for (i = 0; i < inst->enc_nrOfCoefs; i++) | |
341 inst->enc_reflCoefs[i] = refCs[i]; | |
342 inst->enc_Energy = outEnergy; | |
343 } else { | |
344 /* Average history with new values. */ | |
345 for (i = 0; i < (inst->enc_nrOfCoefs); i++) { | |
346 inst->enc_reflCoefs[i] = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT( | |
347 inst->enc_reflCoefs[i], ReflBeta, 15); | |
348 inst->enc_reflCoefs[i] += (int16_t) WEBRTC_SPL_MUL_16_16_RSFT( | |
349 refCs[i], ReflBetaComp, 15); | |
350 } | |
351 inst->enc_Energy = (outEnergy >> 2) + (inst->enc_Energy >> 1) | |
352 + (inst->enc_Energy >> 2); | |
353 } | |
354 | |
355 if (inst->enc_Energy < 1) { | |
356 inst->enc_Energy = 1; | |
357 } | |
358 | |
359 if ((inst->enc_msSinceSID > (inst->enc_interval - 1)) || forceSID) { | |
360 | |
361 /* Search for best dbov value. */ | |
362 index = 0; | |
363 for (i = 1; i < 93; i++) { | |
364 /* Always round downwards. */ | |
365 if ((inst->enc_Energy - WebRtcCng_kDbov[i]) > 0) { | |
366 index = i; | |
367 break; | |
368 } | |
369 } | |
370 if ((i == 93) && (index == 0)) | |
371 index = 94; | |
372 SIDdata[0] = (uint8_t)index; | |
373 | |
374 /* Quantize coefficients with tweak for WebRtc implementation of RFC3389. */ | |
375 if (inst->enc_nrOfCoefs == WEBRTC_CNG_MAX_LPC_ORDER) { | |
376 for (i = 0; i < inst->enc_nrOfCoefs; i++) { | |
377 /* Q15 to Q7 with rounding. */ | |
378 SIDdata[i + 1] = ((inst->enc_reflCoefs[i] + 128) >> 8); | |
379 } | |
380 } else { | |
381 for (i = 0; i < inst->enc_nrOfCoefs; i++) { | |
382 /* Q15 to Q7 with rounding. */ | |
383 SIDdata[i + 1] = (127 + ((inst->enc_reflCoefs[i] + 128) >> 8)); | |
384 } | |
385 } | |
386 | |
387 inst->enc_msSinceSID = 0; | |
388 *bytesOut = inst->enc_nrOfCoefs + 1; | |
389 | |
390 inst->enc_msSinceSID += | |
391 (int16_t)((1000 * nrOfSamples) / inst->enc_sampfreq); | |
392 return (int)(inst->enc_nrOfCoefs + 1); | |
393 } else { | |
394 inst->enc_msSinceSID += | |
395 (int16_t)((1000 * nrOfSamples) / inst->enc_sampfreq); | |
396 *bytesOut = 0; | |
397 return 0; | |
398 } | |
399 } | |
400 | |
401 /**************************************************************************** | |
402 * WebRtcCng_UpdateSid(...) | |
403 * | |
404 * These functions updates the CN state, when a new SID packet arrives | |
405 * | |
406 * Input: | |
407 * - cng_inst : Pointer to created instance that should be freed | |
408 * - SID : SID packet, all headers removed | |
409 * - length : Length in bytes of SID packet | |
410 * | |
411 * Return value : 0 - Ok | |
412 * -1 - Error | |
413 */ | |
414 int16_t WebRtcCng_UpdateSid(CNG_dec_inst* cng_inst, uint8_t* SID, | |
415 size_t length) { | |
416 | |
417 WebRtcCngDecoder* inst = (WebRtcCngDecoder*) cng_inst; | |
418 int16_t refCs[WEBRTC_CNG_MAX_LPC_ORDER]; | |
419 int32_t targetEnergy; | |
420 int i; | |
421 | |
422 if (inst->initflag != 1) { | |
423 inst->errorcode = CNG_DECODER_NOT_INITIATED; | |
424 return -1; | |
425 } | |
426 | |
427 /* Throw away reflection coefficients of higher order than we can handle. */ | |
428 if (length > (WEBRTC_CNG_MAX_LPC_ORDER + 1)) | |
429 length = WEBRTC_CNG_MAX_LPC_ORDER + 1; | |
430 | |
431 inst->dec_order = (int16_t)length - 1; | |
432 | |
433 if (SID[0] > 93) | |
434 SID[0] = 93; | |
435 targetEnergy = WebRtcCng_kDbov[SID[0]]; | |
436 /* Take down target energy to 75%. */ | |
437 targetEnergy = targetEnergy >> 1; | |
438 targetEnergy += targetEnergy >> 2; | |
439 | |
440 inst->dec_target_energy = targetEnergy; | |
441 | |
442 /* Reconstruct coeffs with tweak for WebRtc implementation of RFC3389. */ | |
443 if (inst->dec_order == WEBRTC_CNG_MAX_LPC_ORDER) { | |
444 for (i = 0; i < (inst->dec_order); i++) { | |
445 refCs[i] = SID[i + 1] << 8; /* Q7 to Q15*/ | |
446 inst->dec_target_reflCoefs[i] = refCs[i]; | |
447 } | |
448 } else { | |
449 for (i = 0; i < (inst->dec_order); i++) { | |
450 refCs[i] = (SID[i + 1] - 127) << 8; /* Q7 to Q15. */ | |
451 inst->dec_target_reflCoefs[i] = refCs[i]; | |
452 } | |
453 } | |
454 | |
455 for (i = (inst->dec_order); i < WEBRTC_CNG_MAX_LPC_ORDER; i++) { | |
456 refCs[i] = 0; | |
457 inst->dec_target_reflCoefs[i] = refCs[i]; | |
458 } | |
459 | |
460 return 0; | |
461 } | |
462 | |
463 /**************************************************************************** | |
464 * WebRtcCng_Generate(...) | |
465 * | |
466 * These functions generates CN data when needed | |
467 * | |
468 * Input: | |
469 * - cng_inst : Pointer to created instance that should be freed | |
470 * - outData : pointer to area to write CN data | |
471 * - nrOfSamples : How much data to generate | |
472 * | |
473 * Return value : 0 - Ok | |
474 * -1 - Error | |
475 */ | |
476 int16_t WebRtcCng_Generate(CNG_dec_inst* cng_inst, int16_t* outData, | |
477 size_t nrOfSamples, int16_t new_period) { | |
478 WebRtcCngDecoder* inst = (WebRtcCngDecoder*) cng_inst; | |
479 | |
480 size_t i; | |
481 int16_t excitation[WEBRTC_CNG_MAX_OUTSIZE_ORDER]; | |
482 int16_t low[WEBRTC_CNG_MAX_OUTSIZE_ORDER]; | |
483 int16_t lpPoly[WEBRTC_CNG_MAX_LPC_ORDER + 1]; | |
484 int16_t ReflBetaStd = 26214; /* 0.8 in q15. */ | |
485 int16_t ReflBetaCompStd = 6553; /* 0.2 in q15. */ | |
486 int16_t ReflBetaNewP = 19661; /* 0.6 in q15. */ | |
487 int16_t ReflBetaCompNewP = 13107; /* 0.4 in q15. */ | |
488 int16_t Beta, BetaC, tmp1, tmp2, tmp3; | |
489 int32_t targetEnergy; | |
490 int16_t En; | |
491 int16_t temp16; | |
492 | |
493 if (nrOfSamples > WEBRTC_CNG_MAX_OUTSIZE_ORDER) { | |
494 inst->errorcode = CNG_DISALLOWED_FRAME_SIZE; | |
495 return -1; | |
496 } | |
497 | |
498 if (new_period) { | |
499 inst->dec_used_scale_factor = inst->dec_target_scale_factor; | |
500 Beta = ReflBetaNewP; | |
501 BetaC = ReflBetaCompNewP; | |
502 } else { | |
503 Beta = ReflBetaStd; | |
504 BetaC = ReflBetaCompStd; | |
505 } | |
506 | |
507 /* Here we use a 0.5 weighting, should possibly be modified to 0.6. */ | |
508 tmp1 = inst->dec_used_scale_factor << 2; /* Q13->Q15 */ | |
509 tmp2 = inst->dec_target_scale_factor << 2; /* Q13->Q15 */ | |
510 tmp3 = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(tmp1, Beta, 15); | |
511 tmp3 += (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(tmp2, BetaC, 15); | |
512 inst->dec_used_scale_factor = tmp3 >> 2; /* Q15->Q13 */ | |
513 | |
514 inst->dec_used_energy = inst->dec_used_energy >> 1; | |
515 inst->dec_used_energy += inst->dec_target_energy >> 1; | |
516 | |
517 /* Do the same for the reflection coeffs. */ | |
518 for (i = 0; i < WEBRTC_CNG_MAX_LPC_ORDER; i++) { | |
519 inst->dec_used_reflCoefs[i] = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT( | |
520 inst->dec_used_reflCoefs[i], Beta, 15); | |
521 inst->dec_used_reflCoefs[i] += (int16_t) WEBRTC_SPL_MUL_16_16_RSFT( | |
522 inst->dec_target_reflCoefs[i], BetaC, 15); | |
523 } | |
524 | |
525 /* Compute the polynomial coefficients. */ | |
526 WebRtcCng_K2a16(inst->dec_used_reflCoefs, WEBRTC_CNG_MAX_LPC_ORDER, lpPoly); | |
527 | |
528 | |
529 targetEnergy = inst->dec_used_energy; | |
530 | |
531 /* Calculate scaling factor based on filter energy. */ | |
532 En = 8192; /* 1.0 in Q13. */ | |
533 for (i = 0; i < (WEBRTC_CNG_MAX_LPC_ORDER); i++) { | |
534 | |
535 /* Floating point value for reference. | |
536 E *= 1.0 - (inst->dec_used_reflCoefs[i] / 32768.0) * | |
537 (inst->dec_used_reflCoefs[i] / 32768.0); | |
538 */ | |
539 | |
540 /* Same in fixed point. */ | |
541 /* K(i).^2 in Q15. */ | |
542 temp16 = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT( | |
543 inst->dec_used_reflCoefs[i], inst->dec_used_reflCoefs[i], 15); | |
544 /* 1 - K(i).^2 in Q15. */ | |
545 temp16 = 0x7fff - temp16; | |
546 En = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(En, temp16, 15); | |
547 } | |
548 | |
549 /* float scaling= sqrt(E * inst->dec_target_energy / (1 << 24)); */ | |
550 | |
551 /* Calculate sqrt(En * target_energy / excitation energy) */ | |
552 targetEnergy = WebRtcSpl_Sqrt(inst->dec_used_energy); | |
553 | |
554 En = (int16_t) WebRtcSpl_Sqrt(En) << 6; | |
555 En = (En * 3) >> 1; /* 1.5 estimates sqrt(2). */ | |
556 inst->dec_used_scale_factor = (int16_t)((En * targetEnergy) >> 12); | |
557 | |
558 /* Generate excitation. */ | |
559 /* Excitation energy per sample is 2.^24 - Q13 N(0,1). */ | |
560 for (i = 0; i < nrOfSamples; i++) { | |
561 excitation[i] = WebRtcSpl_RandN(&inst->dec_seed) >> 1; | |
562 } | |
563 | |
564 /* Scale to correct energy. */ | |
565 WebRtcSpl_ScaleVector(excitation, excitation, inst->dec_used_scale_factor, | |
566 nrOfSamples, 13); | |
567 | |
568 /* |lpPoly| - Coefficients in Q12. | |
569 * |excitation| - Speech samples. | |
570 * |nst->dec_filtstate| - State preservation. | |
571 * |outData| - Filtered speech samples. */ | |
572 WebRtcSpl_FilterAR(lpPoly, WEBRTC_CNG_MAX_LPC_ORDER + 1, excitation, | |
573 nrOfSamples, inst->dec_filtstate, WEBRTC_CNG_MAX_LPC_ORDER, | |
574 inst->dec_filtstateLow, WEBRTC_CNG_MAX_LPC_ORDER, outData, | |
575 low, nrOfSamples); | |
576 | |
577 return 0; | |
578 } | |
579 | |
580 /**************************************************************************** | |
581 * WebRtcCng_GetErrorCodeEnc/Dec(...) | |
582 * | |
583 * This functions can be used to check the error code of a CNG instance. When | |
584 * a function returns -1 a error code will be set for that instance. The | |
585 * function below extract the code of the last error that occured in the | |
586 * specified instance. | |
587 * | |
588 * Input: | |
589 * - CNG_inst : CNG enc/dec instance | |
590 * | |
591 * Return value : Error code | |
592 */ | |
593 int16_t WebRtcCng_GetErrorCodeEnc(CNG_enc_inst* cng_inst) { | |
594 /* Typecast pointer to real structure. */ | |
595 WebRtcCngEncoder* inst = (WebRtcCngEncoder*) cng_inst; | |
596 return inst->errorcode; | |
597 } | |
598 | |
599 int16_t WebRtcCng_GetErrorCodeDec(CNG_dec_inst* cng_inst) { | |
600 /* Typecast pointer to real structure. */ | |
601 WebRtcCngDecoder* inst = (WebRtcCngDecoder*) cng_inst; | |
602 return inst->errorcode; | |
603 } | |
OLD | NEW |