1 /*
2 ** Copyright 2003-2010, VisualOn, Inc.
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 ** http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16 /*******************************************************************************
17 File: tns.c
18
19 Content: Definition TNS tools functions
20
21 *******************************************************************************/
22
23 #include "basic_op.h"
24 #include "oper_32b.h"
25 #include "assert.h"
26 #include "aac_rom.h"
27 #include "psy_const.h"
28 #include "tns.h"
29 #include "tns_param.h"
30 #include "psy_configuration.h"
31 #include "tns_func.h"
32
33 #define UNUSED(x) (void)(x)
34
35 #define TNS_MODIFY_BEGIN 2600 /* Hz */
36 #define RATIO_PATCH_LOWER_BORDER 380 /* Hz */
37 #define TNS_GAIN_THRESH 141 /* 1.41*100 */
38 #define NORM_COEF 0x028f5c28
39
40 static const Word32 TNS_PARCOR_THRESH = 0x0ccccccd; /* 0.1*(1 << 31) */
41 /* Limit bands to > 2.0 kHz */
42 static unsigned short tnsMinBandNumberLong[12] =
43 { 11, 12, 15, 16, 17, 20, 25, 26, 24, 28, 30, 31 };
44 static unsigned short tnsMinBandNumberShort[12] =
45 { 2, 2, 2, 3, 3, 4, 6, 6, 8, 10, 10, 12 };
46
47 /**************************************/
48 /* Main/Low Profile TNS Parameters */
49 /**************************************/
50 static unsigned short tnsMaxBandsLongMainLow[12] =
51 { 31, 31, 34, 40, 42, 51, 46, 46, 42, 42, 42, 39 };
52
53 static unsigned short tnsMaxBandsShortMainLow[12] =
54 { 9, 9, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14 };
55
56
57 static void CalcWeightedSpectrum(const Word32 spectrum[],
58 Word16 weightedSpectrum[],
59 Word32* sfbEnergy,
60 const Word16* sfbOffset, Word16 lpcStartLine,
61 Word16 lpcStopLine, Word16 lpcStartBand,Word16 lpcStopBand,
62 Word32 *pWork32);
63
64
65
66 void AutoCorrelation(const Word16 input[], Word32 corr[],
67 Word16 samples, Word16 corrCoeff);
68 static Word16 AutoToParcor(Word32 workBuffer[], Word32 reflCoeff[], Word16 numOfCoeff);
69
70 static Word16 CalcTnsFilter(const Word16* signal, const Word32 window[], Word16 numOfLines,
71 Word16 tnsOrder, Word32 parcor[]);
72
73
74 static void Parcor2Index(const Word32 parcor[], Word16 index[], Word16 order,
75 Word16 bitsPerCoeff);
76
77 static void Index2Parcor(const Word16 index[], Word32 parcor[], Word16 order,
78 Word16 bitsPerCoeff);
79
80
81
82 static void AnalysisFilterLattice(const Word32 signal[], Word16 numOfLines,
83 const Word32 parCoeff[], Word16 order,
84 Word32 output[]);
85
86
87 /**
88 *
89 * function name: FreqToBandWithRounding
90 * description: Retrieve index of nearest band border
91 * returnt: index
92 *
93 */
FreqToBandWithRounding(Word32 freq,Word32 fs,Word16 numOfBands,const Word16 * bandStartOffset)94 static Word16 FreqToBandWithRounding(Word32 freq, /*!< frequency in Hertz */
95 Word32 fs, /*!< Sampling frequency in Hertz */
96 Word16 numOfBands, /*!< total number of bands */
97 const Word16 *bandStartOffset) /*!< table of band borders */
98 {
99 Word32 lineNumber, band;
100 Word32 temp, shift;
101
102 /* assert(freq >= 0); */
103 shift = norm_l(fs);
104 lineNumber = (extract_l(fixmul((bandStartOffset[numOfBands] << 2),Div_32(freq << shift,fs << shift))) + 1) >> 1;
105
106 /* freq > fs/2 */
107 temp = lineNumber - bandStartOffset[numOfBands] ;
108 if (temp >= 0)
109 return numOfBands;
110
111 /* find band the line number lies in */
112 for (band=0; band<numOfBands; band++) {
113 temp = bandStartOffset[band + 1] - lineNumber;
114 if (temp > 0) break;
115 }
116
117 temp = (lineNumber - bandStartOffset[band]);
118 temp = (temp - (bandStartOffset[band + 1] - lineNumber));
119 if ( temp > 0 )
120 {
121 band = band + 1;
122 }
123
124 return extract_l(band);
125 }
126
127
128 /**
129 *
130 * function name: InitTnsConfigurationLong
131 * description: Fill TNS_CONFIG structure with sensible content for long blocks
132 * returns: 0 if success
133 *
134 */
InitTnsConfigurationLong(Word32 bitRate,Word32 sampleRate,Word16 channels,TNS_CONFIG * tC,PSY_CONFIGURATION_LONG * pC,Word16 active)135 Word16 InitTnsConfigurationLong(Word32 bitRate, /*!< bitrate */
136 Word32 sampleRate, /*!< Sampling frequency */
137 Word16 channels, /*!< number of channels */
138 TNS_CONFIG *tC, /*!< TNS Config struct (modified) */
139 PSY_CONFIGURATION_LONG *pC, /*!< psy config struct */
140 Word16 active) /*!< tns active flag */
141 {
142
143 Word32 bitratePerChannel __unused;
144 tC->maxOrder = TNS_MAX_ORDER;
145 tC->tnsStartFreq = 1275;
146 tC->coefRes = 4;
147
148 /* to avoid integer division */
149 if ( sub(channels,2) == 0 ) {
150 bitratePerChannel = bitRate >> 1;
151 }
152 else {
153 bitratePerChannel = bitRate;
154 }
155
156 tC->tnsMaxSfb = tnsMaxBandsLongMainLow[pC->sampRateIdx];
157
158 tC->tnsActive = active;
159
160 /* now calc band and line borders */
161 tC->tnsStopBand = min(pC->sfbCnt, tC->tnsMaxSfb);
162 tC->tnsStopLine = pC->sfbOffset[tC->tnsStopBand];
163
164 tC->tnsStartBand = FreqToBandWithRounding(tC->tnsStartFreq, sampleRate,
165 pC->sfbCnt, (const Word16*)pC->sfbOffset);
166
167 tC->tnsModifyBeginCb = FreqToBandWithRounding(TNS_MODIFY_BEGIN,
168 sampleRate,
169 pC->sfbCnt,
170 (const Word16*)pC->sfbOffset);
171
172 tC->tnsRatioPatchLowestCb = FreqToBandWithRounding(RATIO_PATCH_LOWER_BORDER,
173 sampleRate,
174 pC->sfbCnt,
175 (const Word16*)pC->sfbOffset);
176
177
178 tC->tnsStartLine = pC->sfbOffset[tC->tnsStartBand];
179
180 tC->lpcStopBand = tnsMaxBandsLongMainLow[pC->sampRateIdx];
181 tC->lpcStopBand = min(tC->lpcStopBand, pC->sfbActive);
182
183 tC->lpcStopLine = pC->sfbOffset[tC->lpcStopBand];
184
185 tC->lpcStartBand = tnsMinBandNumberLong[pC->sampRateIdx];
186
187 tC->lpcStartLine = pC->sfbOffset[tC->lpcStartBand];
188
189 tC->threshold = TNS_GAIN_THRESH;
190
191
192 return(0);
193 }
194
195 /**
196 *
197 * function name: InitTnsConfigurationShort
198 * description: Fill TNS_CONFIG structure with sensible content for short blocks
199 * returns: 0 if success
200 *
201 */
InitTnsConfigurationShort(Word32 bitRate,Word32 sampleRate,Word16 channels,TNS_CONFIG * tC,PSY_CONFIGURATION_SHORT * pC,Word16 active)202 Word16 InitTnsConfigurationShort(Word32 bitRate, /*!< bitrate */
203 Word32 sampleRate, /*!< Sampling frequency */
204 Word16 channels, /*!< number of channels */
205 TNS_CONFIG *tC, /*!< TNS Config struct (modified) */
206 PSY_CONFIGURATION_SHORT *pC, /*!< psy config struct */
207 Word16 active) /*!< tns active flag */
208 {
209 Word32 bitratePerChannel __unused;
210 tC->maxOrder = TNS_MAX_ORDER_SHORT;
211 tC->tnsStartFreq = 2750;
212 tC->coefRes = 3;
213
214 /* to avoid integer division */
215 if ( sub(channels,2) == 0 ) {
216 bitratePerChannel = L_shr(bitRate,1);
217 }
218 else {
219 bitratePerChannel = bitRate;
220 }
221
222 tC->tnsMaxSfb = tnsMaxBandsShortMainLow[pC->sampRateIdx];
223
224 tC->tnsActive = active;
225
226 /* now calc band and line borders */
227 tC->tnsStopBand = min(pC->sfbCnt, tC->tnsMaxSfb);
228 tC->tnsStopLine = pC->sfbOffset[tC->tnsStopBand];
229
230 tC->tnsStartBand=FreqToBandWithRounding(tC->tnsStartFreq, sampleRate,
231 pC->sfbCnt, (const Word16*)pC->sfbOffset);
232
233 tC->tnsModifyBeginCb = FreqToBandWithRounding(TNS_MODIFY_BEGIN,
234 sampleRate,
235 pC->sfbCnt,
236 (const Word16*)pC->sfbOffset);
237
238 tC->tnsRatioPatchLowestCb = FreqToBandWithRounding(RATIO_PATCH_LOWER_BORDER,
239 sampleRate,
240 pC->sfbCnt,
241 (const Word16*)pC->sfbOffset);
242
243
244 tC->tnsStartLine = pC->sfbOffset[tC->tnsStartBand];
245
246 tC->lpcStopBand = tnsMaxBandsShortMainLow[pC->sampRateIdx];
247
248 tC->lpcStopBand = min(tC->lpcStopBand, pC->sfbActive);
249
250 tC->lpcStopLine = pC->sfbOffset[tC->lpcStopBand];
251
252 tC->lpcStartBand = tnsMinBandNumberShort[pC->sampRateIdx];
253
254 tC->lpcStartLine = pC->sfbOffset[tC->lpcStartBand];
255
256 tC->threshold = TNS_GAIN_THRESH;
257
258 return(0);
259 }
260
261 /**
262 *
263 * function name: TnsDetect
264 * description: Calculate TNS filter and decide on TNS usage
265 * returns: 0 if success
266 *
267 */
TnsDetect(TNS_DATA * tnsData,TNS_CONFIG tC,Word32 * pScratchTns,const Word16 sfbOffset[],Word32 * spectrum,Word16 subBlockNumber,Word16 blockType,Word32 * sfbEnergy)268 Word32 TnsDetect(TNS_DATA* tnsData, /*!< tns data structure (modified) */
269 TNS_CONFIG tC, /*!< tns config structure */
270 Word32* pScratchTns, /*!< pointer to scratch space */
271 const Word16 sfbOffset[], /*!< scalefactor size and table */
272 Word32* spectrum, /*!< spectral data */
273 Word16 subBlockNumber, /*!< subblock num */
274 Word16 blockType, /*!< blocktype (long or short) */
275 Word32 * sfbEnergy) /*!< sfb-wise energy */
276 {
277
278 Word32 predictionGain;
279 Word32 temp;
280 Word32* pWork32 = &pScratchTns[subBlockNumber >> 8];
281 Word16* pWeightedSpectrum = (Word16 *)&pScratchTns[subBlockNumber >> 8];
282
283
284 if (tC.tnsActive) {
285 CalcWeightedSpectrum(spectrum,
286 pWeightedSpectrum,
287 sfbEnergy,
288 sfbOffset,
289 tC.lpcStartLine,
290 tC.lpcStopLine,
291 tC.lpcStartBand,
292 tC.lpcStopBand,
293 pWork32);
294
295 temp = blockType - SHORT_WINDOW;
296 if ( temp != 0 ) {
297 predictionGain = CalcTnsFilter( &pWeightedSpectrum[tC.lpcStartLine],
298 tC.acfWindow,
299 tC.lpcStopLine - tC.lpcStartLine,
300 tC.maxOrder,
301 tnsData->dataRaw.tnsLong.subBlockInfo.parcor);
302
303
304 temp = predictionGain - tC.threshold;
305 if ( temp > 0 ) {
306 tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 1;
307 }
308 else {
309 tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 0;
310 }
311
312 tnsData->dataRaw.tnsLong.subBlockInfo.predictionGain = predictionGain;
313 }
314 else{
315
316 predictionGain = CalcTnsFilter( &pWeightedSpectrum[tC.lpcStartLine],
317 tC.acfWindow,
318 tC.lpcStopLine - tC.lpcStartLine,
319 tC.maxOrder,
320 tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].parcor);
321
322 temp = predictionGain - tC.threshold;
323 if ( temp > 0 ) {
324 tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 1;
325 }
326 else {
327 tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 0;
328 }
329
330 tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].predictionGain = predictionGain;
331 }
332
333 }
334 else{
335
336 temp = blockType - SHORT_WINDOW;
337 if ( temp != 0 ) {
338 tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 0;
339 tnsData->dataRaw.tnsLong.subBlockInfo.predictionGain = 0;
340 }
341 else {
342 tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 0;
343 tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].predictionGain = 0;
344 }
345 }
346
347 return(0);
348 }
349
350
351 /*****************************************************************************
352 *
353 * function name: TnsSync
354 * description: update tns parameter
355 *
356 *****************************************************************************/
TnsSync(TNS_DATA * tnsDataDest,const TNS_DATA * tnsDataSrc,const TNS_CONFIG tC,const Word16 subBlockNumber,const Word16 blockType)357 void TnsSync(TNS_DATA *tnsDataDest,
358 const TNS_DATA *tnsDataSrc,
359 const TNS_CONFIG tC,
360 const Word16 subBlockNumber,
361 const Word16 blockType)
362 {
363 TNS_SUBBLOCK_INFO *sbInfoDest;
364 const TNS_SUBBLOCK_INFO *sbInfoSrc;
365 Word32 i, temp;
366
367 temp = blockType - SHORT_WINDOW;
368 if ( temp != 0 ) {
369 sbInfoDest = &tnsDataDest->dataRaw.tnsLong.subBlockInfo;
370 sbInfoSrc = &tnsDataSrc->dataRaw.tnsLong.subBlockInfo;
371 }
372 else {
373 sbInfoDest = &tnsDataDest->dataRaw.tnsShort.subBlockInfo[subBlockNumber];
374 sbInfoSrc = &tnsDataSrc->dataRaw.tnsShort.subBlockInfo[subBlockNumber];
375 }
376
377 if (100*abs_s(sbInfoDest->predictionGain - sbInfoSrc->predictionGain) <
378 (3 * sbInfoDest->predictionGain)) {
379 sbInfoDest->tnsActive = sbInfoSrc->tnsActive;
380 for ( i=0; i< tC.maxOrder; i++) {
381 sbInfoDest->parcor[i] = sbInfoSrc->parcor[i];
382 }
383 }
384 }
385
386 /*****************************************************************************
387 *
388 * function name: TnsEncode
389 * description: do TNS filtering
390 * returns: 0 if success
391 *
392 *****************************************************************************/
TnsEncode(TNS_INFO * tnsInfo,TNS_DATA * tnsData,Word16 numOfSfb,TNS_CONFIG tC,Word16 lowPassLine,Word32 * spectrum,Word16 subBlockNumber,Word16 blockType)393 Word16 TnsEncode(TNS_INFO* tnsInfo, /*!< tns info structure (modified) */
394 TNS_DATA* tnsData, /*!< tns data structure (modified) */
395 Word16 numOfSfb, /*!< number of scale factor bands */
396 TNS_CONFIG tC, /*!< tns config structure */
397 Word16 lowPassLine, /*!< lowpass line */
398 Word32* spectrum, /*!< spectral data (modified) */
399 Word16 subBlockNumber, /*!< subblock num */
400 Word16 blockType) /*!< blocktype (long or short) */
401 {
402 Word32 i;
403 Word32 temp_s;
404 Word32 temp;
405 TNS_SUBBLOCK_INFO *psubBlockInfo;
406
407 temp_s = blockType - SHORT_WINDOW;
408 if ( temp_s != 0) {
409 psubBlockInfo = &tnsData->dataRaw.tnsLong.subBlockInfo;
410 if (psubBlockInfo->tnsActive == 0) {
411 tnsInfo->tnsActive[subBlockNumber] = 0;
412 return(0);
413 }
414 else {
415
416 Parcor2Index(psubBlockInfo->parcor,
417 tnsInfo->coef,
418 tC.maxOrder,
419 tC.coefRes);
420
421 Index2Parcor(tnsInfo->coef,
422 psubBlockInfo->parcor,
423 tC.maxOrder,
424 tC.coefRes);
425
426 for (i=tC.maxOrder - 1; i>=0; i--) {
427 temp = psubBlockInfo->parcor[i] - TNS_PARCOR_THRESH;
428 if ( temp > 0 )
429 break;
430 temp = psubBlockInfo->parcor[i] + TNS_PARCOR_THRESH;
431 if ( temp < 0 )
432 break;
433 }
434 tnsInfo->order[subBlockNumber] = i + 1;
435
436
437 tnsInfo->tnsActive[subBlockNumber] = 1;
438 for (i=subBlockNumber+1; i<TRANS_FAC; i++) {
439 tnsInfo->tnsActive[i] = 0;
440 }
441 tnsInfo->coefRes[subBlockNumber] = tC.coefRes;
442 tnsInfo->length[subBlockNumber] = numOfSfb - tC.tnsStartBand;
443
444
445 AnalysisFilterLattice(&(spectrum[tC.tnsStartLine]),
446 (min(tC.tnsStopLine,lowPassLine) - tC.tnsStartLine),
447 psubBlockInfo->parcor,
448 tnsInfo->order[subBlockNumber],
449 &(spectrum[tC.tnsStartLine]));
450
451 }
452 } /* if (blockType!=SHORT_WINDOW) */
453 else /*short block*/ {
454 psubBlockInfo = &tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber];
455 if (psubBlockInfo->tnsActive == 0) {
456 tnsInfo->tnsActive[subBlockNumber] = 0;
457 return(0);
458 }
459 else {
460
461 Parcor2Index(psubBlockInfo->parcor,
462 &tnsInfo->coef[subBlockNumber*TNS_MAX_ORDER_SHORT],
463 tC.maxOrder,
464 tC.coefRes);
465
466 Index2Parcor(&tnsInfo->coef[subBlockNumber*TNS_MAX_ORDER_SHORT],
467 psubBlockInfo->parcor,
468 tC.maxOrder,
469 tC.coefRes);
470 for (i=(tC.maxOrder - 1); i>=0; i--) {
471 temp = psubBlockInfo->parcor[i] - TNS_PARCOR_THRESH;
472 if ( temp > 0 )
473 break;
474
475 temp = psubBlockInfo->parcor[i] + TNS_PARCOR_THRESH;
476 if ( temp < 0 )
477 break;
478 }
479 tnsInfo->order[subBlockNumber] = i + 1;
480
481 tnsInfo->tnsActive[subBlockNumber] = 1;
482 tnsInfo->coefRes[subBlockNumber] = tC.coefRes;
483 tnsInfo->length[subBlockNumber] = numOfSfb - tC.tnsStartBand;
484
485
486 AnalysisFilterLattice(&(spectrum[tC.tnsStartLine]), (tC.tnsStopLine - tC.tnsStartLine),
487 psubBlockInfo->parcor,
488 tnsInfo->order[subBlockNumber],
489 &(spectrum[tC.tnsStartLine]));
490
491 }
492 }
493
494 return(0);
495 }
496
497
498 /*****************************************************************************
499 *
500 * function name: CalcWeightedSpectrum
501 * description: Calculate weighted spectrum for LPC calculation
502 *
503 *****************************************************************************/
CalcWeightedSpectrum(const Word32 spectrum[],Word16 weightedSpectrum[],Word32 * sfbEnergy,const Word16 * sfbOffset,Word16 lpcStartLine,Word16 lpcStopLine,Word16 lpcStartBand,Word16 lpcStopBand,Word32 * pWork32)504 static void CalcWeightedSpectrum(const Word32 spectrum[], /*!< input spectrum */
505 Word16 weightedSpectrum[],
506 Word32 *sfbEnergy, /*!< sfb energies */
507 const Word16 *sfbOffset,
508 Word16 lpcStartLine,
509 Word16 lpcStopLine,
510 Word16 lpcStartBand,
511 Word16 lpcStopBand,
512 Word32 *pWork32)
513 {
514 #define INT_BITS_SCAL 1<<(INT_BITS/2)
515
516 Word32 i, sfb, shift;
517 Word32 maxShift;
518 Word32 tmp_s, tmp2_s;
519 Word32 tmp, tmp2;
520 Word32 maxWS;
521 Word32 tnsSfbMean[MAX_SFB]; /* length [lpcStopBand-lpcStartBand] should be sufficient here */
522
523 maxWS = 0;
524
525 /* calc 1.0*2^-INT_BITS/2/sqrt(en) */
526 for( sfb = lpcStartBand; sfb < lpcStopBand; sfb++) {
527
528 tmp2 = sfbEnergy[sfb] - 2;
529 if( tmp2 > 0) {
530 tmp = rsqrt(sfbEnergy[sfb], INT_BITS);
531 if(tmp > INT_BITS_SCAL)
532 {
533 shift = norm_l(tmp);
534 tmp = Div_32( INT_BITS_SCAL << shift, tmp << shift );
535 }
536 else
537 {
538 tmp = 0x7fffffff;
539 }
540 }
541 else {
542 tmp = 0x7fffffff;
543 }
544 tnsSfbMean[sfb] = tmp;
545 }
546
547 /* spread normalized values from sfbs to lines */
548 sfb = lpcStartBand;
549 tmp = tnsSfbMean[sfb];
550 for ( i=lpcStartLine; i<lpcStopLine; i++){
551 tmp_s = sfbOffset[sfb + 1] - i;
552 if ( tmp_s == 0 ) {
553 sfb = sfb + 1;
554 tmp2_s = sfb + 1 - lpcStopBand;
555 if (tmp2_s <= 0) {
556 tmp = tnsSfbMean[sfb];
557 }
558 }
559 pWork32[i] = tmp;
560 }
561 /*filter down*/
562 for (i=(lpcStopLine - 2); i>=lpcStartLine; i--){
563 pWork32[i] = (pWork32[i] + pWork32[i + 1]) >> 1;
564 }
565 /* filter up */
566 for (i=(lpcStartLine + 1); i<lpcStopLine; i++){
567 pWork32[i] = (pWork32[i] + pWork32[i - 1]) >> 1;
568 }
569
570 /* weight and normalize */
571 for (i=lpcStartLine; i<lpcStopLine; i++){
572 pWork32[i] = MULHIGH(pWork32[i], spectrum[i]);
573 maxWS |= L_abs(pWork32[i]);
574 }
575 maxShift = norm_l(maxWS);
576
577 maxShift = 16 - maxShift;
578 if(maxShift >= 0)
579 {
580 for (i=lpcStartLine; i<lpcStopLine; i++){
581 weightedSpectrum[i] = pWork32[i] >> maxShift;
582 }
583 }
584 else
585 {
586 maxShift = -maxShift;
587 for (i=lpcStartLine; i<lpcStopLine; i++){
588 weightedSpectrum[i] = saturate(pWork32[i] << maxShift);
589 }
590 }
591 }
592
593
594
595
596 /*****************************************************************************
597 *
598 * function name: CalcTnsFilter
599 * description: LPC calculation for one TNS filter
600 * returns: prediction gain
601 * input: signal spectrum, acf window, no. of spectral lines,
602 * max. TNS order, ptr. to reflection ocefficients
603 * output: reflection coefficients
604 *(half) window size must be larger than tnsOrder !!*
605 ******************************************************************************/
606
CalcTnsFilter(const Word16 * signal,const Word32 window[],Word16 numOfLines,Word16 tnsOrder,Word32 parcor[])607 static Word16 CalcTnsFilter(const Word16 *signal,
608 const Word32 window[],
609 Word16 numOfLines,
610 Word16 tnsOrder,
611 Word32 parcor[])
612 {
613 Word32 parcorWorkBuffer[2*TNS_MAX_ORDER+1];
614 Word32 predictionGain;
615 Word32 i;
616 Word32 tnsOrderPlus1 = tnsOrder + 1;
617
618 UNUSED(window);
619
620 assert(tnsOrder <= TNS_MAX_ORDER); /* remove asserts later? (btg) */
621
622 for(i=0;i<tnsOrder;i++) {
623 parcor[i] = 0;
624 }
625
626 AutoCorrelation(signal, parcorWorkBuffer, numOfLines, tnsOrderPlus1);
627
628 /* early return if signal is very low: signal prediction off, with zero parcor coeffs */
629 if (parcorWorkBuffer[0] == 0)
630 return 0;
631
632 predictionGain = AutoToParcor(parcorWorkBuffer, parcor, tnsOrder);
633
634 return(predictionGain);
635 }
636
637 /*****************************************************************************
638 *
639 * function name: AutoCorrelation
640 * description: calc. autocorrelation (acf)
641 * returns: -
642 * input: input values, no. of input values, no. of acf values
643 * output: acf values
644 *
645 *****************************************************************************/
646 #ifndef ARMV5E
AutoCorrelation(const Word16 input[],Word32 corr[],Word16 samples,Word16 corrCoeff)647 void AutoCorrelation(const Word16 input[],
648 Word32 corr[],
649 Word16 samples,
650 Word16 corrCoeff) {
651 Word32 i, j, isamples;
652 Word32 accu;
653 Word32 scf;
654
655 scf = 10 - 1;
656
657 isamples = samples;
658 /* calc first corrCoef: R[0] = sum { t[i] * t[i] } ; i = 0..N-1 */
659 accu = 0;
660 for(j=0; j<isamples; j++) {
661 accu = L_add(accu, ((input[j] * input[j]) >> scf));
662 }
663 corr[0] = accu;
664
665 /* early termination if all corr coeffs are likely going to be zero */
666 if(corr[0] == 0) return ;
667
668 /* calc all other corrCoef: R[j] = sum { t[i] * t[i+j] } ; i = 0..(N-j-1), j=1..p */
669 for(i=1; i<corrCoeff; i++) {
670 isamples = isamples - 1;
671 accu = 0;
672 for(j=0; j<isamples; j++) {
673 accu = L_add(accu, ((input[j] * input[j+i]) >> scf));
674 }
675 corr[i] = accu;
676 }
677 }
678 #endif
679
680 /*****************************************************************************
681 *
682 * function name: AutoToParcor
683 * description: conversion autocorrelation to reflection coefficients
684 * returns: prediction gain
685 * input: <order+1> input values, no. of output values (=order),
686 * ptr. to workbuffer (required size: 2*order)
687 * output: <order> reflection coefficients
688 *
689 *****************************************************************************/
AutoToParcor(Word32 workBuffer[],Word32 reflCoeff[],Word16 numOfCoeff)690 static Word16 AutoToParcor(Word32 workBuffer[], Word32 reflCoeff[], Word16 numOfCoeff) {
691
692 Word32 i, j, shift;
693 Word32 *pWorkBuffer; /* temp pointer */
694 Word32 predictionGain = 0;
695 Word32 num, denom;
696 Word32 temp, workBuffer0;
697
698
699 num = workBuffer[0];
700 temp = workBuffer[numOfCoeff];
701
702 for(i=0; i<numOfCoeff-1; i++) {
703 workBuffer[i + numOfCoeff] = workBuffer[i + 1];
704 }
705 workBuffer[i + numOfCoeff] = temp;
706
707 for(i=0; i<numOfCoeff; i++) {
708 Word32 refc;
709
710
711 if (workBuffer[0] < L_abs(workBuffer[i + numOfCoeff])) {
712 return 0 ;
713 }
714 shift = norm_l(workBuffer[0]);
715 workBuffer0 = Div_32(1 << shift, workBuffer[0] << shift);
716 /* calculate refc = -workBuffer[numOfCoeff+i] / workBuffer[0]; -1 <= refc < 1 */
717 refc = L_negate(fixmul(workBuffer[numOfCoeff + i], workBuffer0));
718
719 reflCoeff[i] = refc;
720
721 pWorkBuffer = &(workBuffer[numOfCoeff]);
722
723 for(j=i; j<numOfCoeff; j++) {
724 Word32 accu1, accu2;
725 accu1 = L_add(pWorkBuffer[j], fixmul(refc, workBuffer[j - i]));
726 accu2 = L_add(workBuffer[j - i], fixmul(refc, pWorkBuffer[j]));
727 pWorkBuffer[j] = accu1;
728 workBuffer[j - i] = accu2;
729 }
730 }
731
732 denom = MULHIGH(workBuffer[0], NORM_COEF);
733
734 if (denom != 0) {
735 Word32 temp;
736 shift = norm_l(denom);
737 temp = Div_32(1 << shift, denom << shift);
738 predictionGain = fixmul(num, temp);
739 }
740
741 return extract_l(predictionGain);
742 }
743
744
745
Search3(Word32 parcor)746 static Word16 Search3(Word32 parcor)
747 {
748 Word32 index = 0;
749 Word32 i;
750 Word32 temp;
751
752 for (i=0;i<8;i++) {
753 temp = L_sub( parcor, tnsCoeff3Borders[i]);
754 if (temp > 0)
755 index=i;
756 }
757 return extract_l(index - 4);
758 }
759
Search4(Word32 parcor)760 static Word16 Search4(Word32 parcor)
761 {
762 Word32 index = 0;
763 Word32 i;
764 Word32 temp;
765
766
767 for (i=0;i<16;i++) {
768 temp = L_sub(parcor, tnsCoeff4Borders[i]);
769 if (temp > 0)
770 index=i;
771 }
772 return extract_l(index - 8);
773 }
774
775
776
777 /*****************************************************************************
778 *
779 * functionname: Parcor2Index
780 * description: quantization index for reflection coefficients
781 *
782 *****************************************************************************/
Parcor2Index(const Word32 parcor[],Word16 index[],Word16 order,Word16 bitsPerCoeff)783 static void Parcor2Index(const Word32 parcor[], /*!< parcor coefficients */
784 Word16 index[], /*!< quantized coeff indices */
785 Word16 order, /*!< filter order */
786 Word16 bitsPerCoeff) { /*!< quantizer resolution */
787 Word32 i;
788 Word32 temp;
789
790 for(i=0; i<order; i++) {
791 temp = bitsPerCoeff - 3;
792 if (temp == 0) {
793 index[i] = Search3(parcor[i]);
794 }
795 else {
796 index[i] = Search4(parcor[i]);
797 }
798 }
799 }
800
801 /*****************************************************************************
802 *
803 * functionname: Index2Parcor
804 * description: Inverse quantization for reflection coefficients
805 *
806 *****************************************************************************/
Index2Parcor(const Word16 index[],Word32 parcor[],Word16 order,Word16 bitsPerCoeff)807 static void Index2Parcor(const Word16 index[], /*!< quantized values */
808 Word32 parcor[], /*!< ptr. to reflection coefficients (output) */
809 Word16 order, /*!< no. of coefficients */
810 Word16 bitsPerCoeff) /*!< quantizer resolution */
811 {
812 Word32 i;
813 Word32 temp;
814
815 for (i=0; i<order; i++) {
816 temp = bitsPerCoeff - 4;
817 if ( temp == 0 ) {
818 parcor[i] = tnsCoeff4[index[i] + 8];
819 }
820 else {
821 parcor[i] = tnsCoeff3[index[i] + 4];
822 }
823 }
824 }
825
826 /*****************************************************************************
827 *
828 * functionname: FIRLattice
829 * description: in place lattice filtering of spectral data
830 * returns: pointer to modified data
831 *
832 *****************************************************************************/
FIRLattice(Word16 order,Word32 x,Word32 * state_par,const Word32 * coef_par)833 static Word32 FIRLattice(Word16 order, /*!< filter order */
834 Word32 x, /*!< spectral data */
835 Word32 *state_par, /*!< filter states */
836 const Word32 *coef_par) /*!< filter coefficients */
837 {
838 Word32 i;
839 Word32 accu,tmp,tmpSave;
840
841 x = x >> 1;
842 tmpSave = x;
843
844 for (i=0; i<(order - 1); i++) {
845
846 tmp = L_add(fixmul(coef_par[i], x), state_par[i]);
847 x = L_add(fixmul(coef_par[i], state_par[i]), x);
848
849 state_par[i] = tmpSave;
850 tmpSave = tmp;
851 }
852
853 /* last stage: only need half operations */
854 accu = fixmul(state_par[order - 1], coef_par[(order - 1)]);
855 state_par[(order - 1)] = tmpSave;
856
857 x = L_add(accu, x);
858 x = L_add(x, x);
859
860 return x;
861 }
862
863 /*****************************************************************************
864 *
865 * functionname: AnalysisFilterLattice
866 * description: filters spectral lines with TNS filter
867 *
868 *****************************************************************************/
AnalysisFilterLattice(const Word32 signal[],Word16 numOfLines,const Word32 parCoeff[],Word16 order,Word32 output[])869 static void AnalysisFilterLattice(const Word32 signal[], /*!< input spectrum */
870 Word16 numOfLines, /*!< no. of lines */
871 const Word32 parCoeff[],/*!< PARC coefficients */
872 Word16 order, /*!< filter order */
873 Word32 output[]) /*!< filtered signal values */
874 {
875
876 Word32 state_par[TNS_MAX_ORDER];
877 Word32 j;
878
879 for ( j=0; j<TNS_MAX_ORDER; j++ ) {
880 state_par[j] = 0;
881 }
882
883 for(j=0; j<numOfLines; j++) {
884 output[j] = FIRLattice(order,signal[j],state_par,parCoeff);
885 }
886 }
887
888 /*****************************************************************************
889 *
890 * functionname: ApplyTnsMultTableToRatios
891 * description: Change thresholds according to tns
892 *
893 *****************************************************************************/
ApplyTnsMultTableToRatios(Word16 startCb,Word16 stopCb,TNS_SUBBLOCK_INFO subInfo,Word32 * thresholds)894 void ApplyTnsMultTableToRatios(Word16 startCb,
895 Word16 stopCb,
896 TNS_SUBBLOCK_INFO subInfo, /*!< TNS subblock info */
897 Word32 *thresholds) /*!< thresholds (modified) */
898 {
899 Word32 i;
900 if (subInfo.tnsActive) {
901 for(i=startCb; i<stopCb; i++) {
902 /* thresholds[i] * 0.25 */
903 thresholds[i] = (thresholds[i] >> 2);
904 }
905 }
906 }
907