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: psy_main.c
18
19 Content: Psychoacoustic major functions
20
21 *******************************************************************************/
22
23 #include "typedef.h"
24 #include "basic_op.h"
25 #include "oper_32b.h"
26 #include "psy_const.h"
27 #include "block_switch.h"
28 #include "transform.h"
29 #include "spreading.h"
30 #include "pre_echo_control.h"
31 #include "band_nrg.h"
32 #include "psy_configuration.h"
33 #include "psy_data.h"
34 #include "ms_stereo.h"
35 #include "interface.h"
36 #include "psy_main.h"
37 #include "grp_data.h"
38 #include "tns_func.h"
39 #include "memalign.h"
40
41 #define UNUSED(x) (void)(x)
42
43 /* long start short stop */
44 static Word16 blockType2windowShape[] = {KBD_WINDOW,SINE_WINDOW,SINE_WINDOW,KBD_WINDOW};
45
46 /*
47 forward definitions
48 */
49 static Word16 advancePsychLong(PSY_DATA* psyData,
50 TNS_DATA* tnsData,
51 PSY_CONFIGURATION_LONG *hPsyConfLong,
52 PSY_OUT_CHANNEL* psyOutChannel,
53 Word32 *pScratchTns,
54 const TNS_DATA *tnsData2,
55 const Word16 ch);
56
57 static Word16 advancePsychLongMS (PSY_DATA psyData[MAX_CHANNELS],
58 const PSY_CONFIGURATION_LONG *hPsyConfLong);
59
60 static Word16 advancePsychShort(PSY_DATA* psyData,
61 TNS_DATA* tnsData,
62 const PSY_CONFIGURATION_SHORT *hPsyConfShort,
63 PSY_OUT_CHANNEL* psyOutChannel,
64 Word32 *pScratchTns,
65 const TNS_DATA *tnsData2,
66 const Word16 ch);
67
68 static Word16 advancePsychShortMS (PSY_DATA psyData[MAX_CHANNELS],
69 const PSY_CONFIGURATION_SHORT *hPsyConfShort);
70
71
72 /*****************************************************************************
73 *
74 * function name: PsyNew
75 * description: allocates memory for psychoacoustic
76 * returns: an error code
77 * input: pointer to a psych handle
78 *
79 *****************************************************************************/
PsyNew(PSY_KERNEL * hPsy,Word32 nChan,VO_MEM_OPERATOR * pMemOP)80 Word16 PsyNew(PSY_KERNEL *hPsy, Word32 nChan, VO_MEM_OPERATOR *pMemOP)
81 {
82 Word16 i;
83 Word32 *mdctSpectrum;
84 Word32 *scratchTNS;
85 Word16 *mdctDelayBuffer;
86
87 mdctSpectrum = (Word32 *)mem_malloc(pMemOP, nChan * FRAME_LEN_LONG * sizeof(Word32), 32, VO_INDEX_ENC_AAC);
88 if(NULL == mdctSpectrum)
89 return 1;
90
91 scratchTNS = (Word32 *)mem_malloc(pMemOP, nChan * FRAME_LEN_LONG * sizeof(Word32), 32, VO_INDEX_ENC_AAC);
92 if(NULL == scratchTNS)
93 {
94 return 1;
95 }
96
97 mdctDelayBuffer = (Word16 *)mem_malloc(pMemOP, nChan * BLOCK_SWITCHING_OFFSET * sizeof(Word16), 32, VO_INDEX_ENC_AAC);
98 if(NULL == mdctDelayBuffer)
99 {
100 return 1;
101 }
102
103 for (i=0; i<nChan; i++){
104 hPsy->psyData[i].mdctDelayBuffer = mdctDelayBuffer + i*BLOCK_SWITCHING_OFFSET;
105 hPsy->psyData[i].mdctSpectrum = mdctSpectrum + i*FRAME_LEN_LONG;
106 }
107
108 hPsy->pScratchTns = scratchTNS;
109
110 return 0;
111 }
112
113
114 /*****************************************************************************
115 *
116 * function name: PsyDelete
117 * description: allocates memory for psychoacoustic
118 * returns: an error code
119 *
120 *****************************************************************************/
PsyDelete(PSY_KERNEL * hPsy,VO_MEM_OPERATOR * pMemOP)121 Word16 PsyDelete(PSY_KERNEL *hPsy, VO_MEM_OPERATOR *pMemOP)
122 {
123 Word32 nch;
124
125 if(hPsy)
126 {
127 if(hPsy->psyData[0].mdctDelayBuffer)
128 mem_free(pMemOP, hPsy->psyData[0].mdctDelayBuffer, VO_INDEX_ENC_AAC);
129
130 if(hPsy->psyData[0].mdctSpectrum)
131 mem_free(pMemOP, hPsy->psyData[0].mdctSpectrum, VO_INDEX_ENC_AAC);
132
133 for (nch=0; nch<MAX_CHANNELS; nch++){
134 hPsy->psyData[nch].mdctDelayBuffer = NULL;
135 hPsy->psyData[nch].mdctSpectrum = NULL;
136 }
137
138 if(hPsy->pScratchTns)
139 {
140 mem_free(pMemOP, hPsy->pScratchTns, VO_INDEX_ENC_AAC);
141 hPsy->pScratchTns = NULL;
142 }
143 }
144
145 return 0;
146 }
147
148
149 /*****************************************************************************
150 *
151 * function name: PsyOutNew
152 * description: allocates memory for psyOut struc
153 * returns: an error code
154 * input: pointer to a psych handle
155 *
156 *****************************************************************************/
PsyOutNew(PSY_OUT * hPsyOut,VO_MEM_OPERATOR * pMemOP)157 Word16 PsyOutNew(PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP)
158 {
159 pMemOP->Set(VO_INDEX_ENC_AAC, hPsyOut, 0, sizeof(PSY_OUT));
160 /*
161 alloc some more stuff, tbd
162 */
163 return 0;
164 }
165
166 /*****************************************************************************
167 *
168 * function name: PsyOutDelete
169 * description: allocates memory for psychoacoustic
170 * returns: an error code
171 *
172 *****************************************************************************/
PsyOutDelete(PSY_OUT * hPsyOut,VO_MEM_OPERATOR * pMemOP)173 Word16 PsyOutDelete(PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP)
174 {
175 UNUSED(hPsyOut);
176 UNUSED(pMemOP);
177
178 return 0;
179 }
180
181
182 /*****************************************************************************
183 *
184 * function name: psyMainInit
185 * description: initializes psychoacoustic
186 * returns: an error code
187 *
188 *****************************************************************************/
189
psyMainInit(PSY_KERNEL * hPsy,Word32 sampleRate,Word32 bitRate,Word16 channels,Word16 tnsMask,Word16 bandwidth)190 Word16 psyMainInit(PSY_KERNEL *hPsy,
191 Word32 sampleRate,
192 Word32 bitRate,
193 Word16 channels,
194 Word16 tnsMask,
195 Word16 bandwidth)
196 {
197 Word16 ch, err;
198 Word32 channelBitRate = bitRate/channels;
199
200 err = InitPsyConfigurationLong(channelBitRate,
201 sampleRate,
202 bandwidth,
203 &(hPsy->psyConfLong));
204
205 if (!err) {
206 hPsy->sampleRateIdx = hPsy->psyConfLong.sampRateIdx;
207 err = InitTnsConfigurationLong(bitRate, sampleRate, channels,
208 &hPsy->psyConfLong.tnsConf, &hPsy->psyConfLong, tnsMask&2);
209 }
210
211 if (!err)
212 err = InitPsyConfigurationShort(channelBitRate,
213 sampleRate,
214 bandwidth,
215 &hPsy->psyConfShort);
216 if (!err) {
217 err = InitTnsConfigurationShort(bitRate, sampleRate, channels,
218 &hPsy->psyConfShort.tnsConf, &hPsy->psyConfShort, tnsMask&1);
219 }
220
221 if (!err)
222 for(ch=0;ch < channels;ch++){
223
224 InitBlockSwitching(&hPsy->psyData[ch].blockSwitchingControl,
225 bitRate, channels);
226
227 InitPreEchoControl(hPsy->psyData[ch].sfbThresholdnm1,
228 hPsy->psyConfLong.sfbCnt,
229 hPsy->psyConfLong.sfbThresholdQuiet);
230 hPsy->psyData[ch].mdctScalenm1 = 0;
231 }
232
233 return(err);
234 }
235
236 /*****************************************************************************
237 *
238 * function name: psyMain
239 * description: psychoacoustic main function
240 * returns: an error code
241 *
242 * This function assumes that enough input data is in the modulo buffer.
243 *
244 *****************************************************************************/
245
psyMain(Word16 nChannels,ELEMENT_INFO * elemInfo,Word16 * timeSignal,PSY_DATA psyData[MAX_CHANNELS],TNS_DATA tnsData[MAX_CHANNELS],PSY_CONFIGURATION_LONG * hPsyConfLong,PSY_CONFIGURATION_SHORT * hPsyConfShort,PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],PSY_OUT_ELEMENT * psyOutElement,Word32 * pScratchTns,Word32 sampleRate)246 Word16 psyMain(Word16 nChannels,
247 ELEMENT_INFO *elemInfo,
248 Word16 *timeSignal,
249 PSY_DATA psyData[MAX_CHANNELS],
250 TNS_DATA tnsData[MAX_CHANNELS],
251 PSY_CONFIGURATION_LONG *hPsyConfLong,
252 PSY_CONFIGURATION_SHORT *hPsyConfShort,
253 PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
254 PSY_OUT_ELEMENT *psyOutElement,
255 Word32 *pScratchTns,
256 Word32 sampleRate)
257 {
258 Word16 maxSfbPerGroup[MAX_CHANNELS];
259 Word16 mdctScalingArray[MAX_CHANNELS];
260
261 Word16 ch; /* counts through channels */
262 Word16 sfb; /* counts through scalefactor bands */
263 Word16 line; /* counts through lines */
264 Word16 channels;
265 Word16 maxScale;
266
267 channels = elemInfo->nChannelsInEl;
268 maxScale = 0;
269
270 /* block switching */
271 for(ch = 0; ch < channels; ch++) {
272 BlockSwitching(&psyData[ch].blockSwitchingControl,
273 timeSignal+elemInfo->ChannelIndex[ch],
274 sampleRate,
275 nChannels);
276 }
277
278 /* synch left and right block type */
279 SyncBlockSwitching(&psyData[0].blockSwitchingControl,
280 &psyData[1].blockSwitchingControl,
281 channels);
282
283 /* transform
284 and get maxScale (max mdctScaling) for all channels */
285 for(ch=0; ch<channels; ch++) {
286 Transform_Real(psyData[ch].mdctDelayBuffer,
287 timeSignal+elemInfo->ChannelIndex[ch],
288 nChannels,
289 psyData[ch].mdctSpectrum,
290 &(mdctScalingArray[ch]),
291 psyData[ch].blockSwitchingControl.windowSequence);
292 maxScale = max(maxScale, mdctScalingArray[ch]);
293 }
294
295 /* common scaling for all channels */
296 for (ch=0; ch<channels; ch++) {
297 Word16 scaleDiff = maxScale - mdctScalingArray[ch];
298
299 if (scaleDiff > 0) {
300 Word32 *Spectrum = psyData[ch].mdctSpectrum;
301 for(line=0; line<FRAME_LEN_LONG; line++) {
302 *Spectrum = (*Spectrum) >> scaleDiff;
303 Spectrum++;
304 }
305 }
306 psyData[ch].mdctScale = maxScale;
307 }
308
309 for (ch=0; ch<channels; ch++) {
310
311 if(psyData[ch].blockSwitchingControl.windowSequence != SHORT_WINDOW) {
312 /* update long block parameter */
313 advancePsychLong(&psyData[ch],
314 &tnsData[ch],
315 hPsyConfLong,
316 &psyOutChannel[ch],
317 pScratchTns,
318 &tnsData[1 - ch],
319 ch);
320
321 /* determine maxSfb */
322 for (sfb=hPsyConfLong->sfbCnt-1; sfb>=0; sfb--) {
323 for (line=hPsyConfLong->sfbOffset[sfb+1] - 1; line>=hPsyConfLong->sfbOffset[sfb]; line--) {
324
325 if (psyData[ch].mdctSpectrum[line] != 0) break;
326 }
327 if (line >= hPsyConfLong->sfbOffset[sfb]) break;
328 }
329 maxSfbPerGroup[ch] = sfb + 1;
330
331 /* Calc bandwise energies for mid and side channel
332 Do it only if 2 channels exist */
333
334 if (ch == 1)
335 advancePsychLongMS(psyData, hPsyConfLong);
336 }
337 else {
338 advancePsychShort(&psyData[ch],
339 &tnsData[ch],
340 hPsyConfShort,
341 &psyOutChannel[ch],
342 pScratchTns,
343 &tnsData[1 - ch],
344 ch);
345
346 /* Calc bandwise energies for mid and side channel
347 Do it only if 2 channels exist */
348
349 if (ch == 1)
350 advancePsychShortMS (psyData, hPsyConfShort);
351 }
352 }
353
354 /* group short data */
355 for(ch=0; ch<channels; ch++) {
356
357 if (psyData[ch].blockSwitchingControl.windowSequence == SHORT_WINDOW) {
358 groupShortData(psyData[ch].mdctSpectrum,
359 pScratchTns,
360 &psyData[ch].sfbThreshold,
361 &psyData[ch].sfbEnergy,
362 &psyData[ch].sfbEnergyMS,
363 &psyData[ch].sfbSpreadedEnergy,
364 hPsyConfShort->sfbCnt,
365 hPsyConfShort->sfbOffset,
366 hPsyConfShort->sfbMinSnr,
367 psyOutElement->groupedSfbOffset[ch],
368 &maxSfbPerGroup[ch],
369 psyOutElement->groupedSfbMinSnr[ch],
370 psyData[ch].blockSwitchingControl.noOfGroups,
371 psyData[ch].blockSwitchingControl.groupLen);
372 }
373 }
374
375
376 #if (MAX_CHANNELS>1)
377 /*
378 stereo Processing
379 */
380 if (channels == 2) {
381 psyOutElement->toolsInfo.msDigest = MS_NONE;
382 maxSfbPerGroup[0] = maxSfbPerGroup[1] = max(maxSfbPerGroup[0], maxSfbPerGroup[1]);
383
384
385 if (psyData[0].blockSwitchingControl.windowSequence != SHORT_WINDOW)
386 MsStereoProcessing(psyData[0].sfbEnergy.sfbLong,
387 psyData[1].sfbEnergy.sfbLong,
388 psyData[0].sfbEnergyMS.sfbLong,
389 psyData[1].sfbEnergyMS.sfbLong,
390 psyData[0].mdctSpectrum,
391 psyData[1].mdctSpectrum,
392 psyData[0].sfbThreshold.sfbLong,
393 psyData[1].sfbThreshold.sfbLong,
394 psyData[0].sfbSpreadedEnergy.sfbLong,
395 psyData[1].sfbSpreadedEnergy.sfbLong,
396 (Word16*)&psyOutElement->toolsInfo.msDigest,
397 (Word16*)psyOutElement->toolsInfo.msMask,
398 hPsyConfLong->sfbCnt,
399 hPsyConfLong->sfbCnt,
400 maxSfbPerGroup[0],
401 (const Word16*)hPsyConfLong->sfbOffset);
402 else
403 MsStereoProcessing(psyData[0].sfbEnergy.sfbLong,
404 psyData[1].sfbEnergy.sfbLong,
405 psyData[0].sfbEnergyMS.sfbLong,
406 psyData[1].sfbEnergyMS.sfbLong,
407 psyData[0].mdctSpectrum,
408 psyData[1].mdctSpectrum,
409 psyData[0].sfbThreshold.sfbLong,
410 psyData[1].sfbThreshold.sfbLong,
411 psyData[0].sfbSpreadedEnergy.sfbLong,
412 psyData[1].sfbSpreadedEnergy.sfbLong,
413 (Word16*)&psyOutElement->toolsInfo.msDigest,
414 (Word16*)psyOutElement->toolsInfo.msMask,
415 psyData[0].blockSwitchingControl.noOfGroups*hPsyConfShort->sfbCnt,
416 hPsyConfShort->sfbCnt,
417 maxSfbPerGroup[0],
418 (const Word16*)psyOutElement->groupedSfbOffset[0]);
419 }
420
421 #endif /* (MAX_CHANNELS>1) */
422
423 /*
424 build output
425 */
426 for(ch=0;ch<channels;ch++) {
427
428 if (psyData[ch].blockSwitchingControl.windowSequence != SHORT_WINDOW)
429 BuildInterface(psyData[ch].mdctSpectrum,
430 psyData[ch].mdctScale,
431 &psyData[ch].sfbThreshold,
432 &psyData[ch].sfbEnergy,
433 &psyData[ch].sfbSpreadedEnergy,
434 psyData[ch].sfbEnergySum,
435 psyData[ch].sfbEnergySumMS,
436 psyData[ch].blockSwitchingControl.windowSequence,
437 blockType2windowShape[psyData[ch].blockSwitchingControl.windowSequence],
438 hPsyConfLong->sfbCnt,
439 hPsyConfLong->sfbOffset,
440 maxSfbPerGroup[ch],
441 hPsyConfLong->sfbMinSnr,
442 psyData[ch].blockSwitchingControl.noOfGroups,
443 psyData[ch].blockSwitchingControl.groupLen,
444 &psyOutChannel[ch]);
445 else
446 BuildInterface(psyData[ch].mdctSpectrum,
447 psyData[ch].mdctScale,
448 &psyData[ch].sfbThreshold,
449 &psyData[ch].sfbEnergy,
450 &psyData[ch].sfbSpreadedEnergy,
451 psyData[ch].sfbEnergySum,
452 psyData[ch].sfbEnergySumMS,
453 SHORT_WINDOW,
454 SINE_WINDOW,
455 psyData[0].blockSwitchingControl.noOfGroups*hPsyConfShort->sfbCnt,
456 psyOutElement->groupedSfbOffset[ch],
457 maxSfbPerGroup[ch],
458 psyOutElement->groupedSfbMinSnr[ch],
459 psyData[ch].blockSwitchingControl.noOfGroups,
460 psyData[ch].blockSwitchingControl.groupLen,
461 &psyOutChannel[ch]);
462 }
463
464 return(0); /* no error */
465 }
466
467 /*****************************************************************************
468 *
469 * function name: advancePsychLong
470 * description: psychoacoustic for long blocks
471 *
472 *****************************************************************************/
473
advancePsychLong(PSY_DATA * psyData,TNS_DATA * tnsData,PSY_CONFIGURATION_LONG * hPsyConfLong,PSY_OUT_CHANNEL * psyOutChannel,Word32 * pScratchTns,const TNS_DATA * tnsData2,const Word16 ch)474 static Word16 advancePsychLong(PSY_DATA* psyData,
475 TNS_DATA* tnsData,
476 PSY_CONFIGURATION_LONG *hPsyConfLong,
477 PSY_OUT_CHANNEL* psyOutChannel,
478 Word32 *pScratchTns,
479 const TNS_DATA* tnsData2,
480 const Word16 ch)
481 {
482 Word32 i;
483 Word32 normEnergyShift = (psyData->mdctScale + 1) << 1; /* in reference code, mdct spectrum must be multipied with 2, so +1 */
484 Word32 clipEnergy = hPsyConfLong->clipEnergy >> normEnergyShift;
485 Word32 *data0, *data1, tdata;
486
487 /* low pass */
488 data0 = psyData->mdctSpectrum + hPsyConfLong->lowpassLine;
489 for(i=hPsyConfLong->lowpassLine; i<FRAME_LEN_LONG; i++) {
490 *data0++ = 0;
491 }
492
493 /* Calc sfb-bandwise mdct-energies for left and right channel */
494 CalcBandEnergy( psyData->mdctSpectrum,
495 hPsyConfLong->sfbOffset,
496 hPsyConfLong->sfbActive,
497 psyData->sfbEnergy.sfbLong,
498 &psyData->sfbEnergySum.sfbLong);
499
500 /*
501 TNS detect
502 */
503 TnsDetect(tnsData,
504 hPsyConfLong->tnsConf,
505 pScratchTns,
506 (const Word16*)hPsyConfLong->sfbOffset,
507 psyData->mdctSpectrum,
508 0,
509 psyData->blockSwitchingControl.windowSequence,
510 psyData->sfbEnergy.sfbLong);
511
512 /* TnsSync */
513 if (ch == 1) {
514 TnsSync(tnsData,
515 tnsData2,
516 hPsyConfLong->tnsConf,
517 0,
518 psyData->blockSwitchingControl.windowSequence);
519 }
520
521 /* Tns Encoder */
522 TnsEncode(&psyOutChannel->tnsInfo,
523 tnsData,
524 hPsyConfLong->sfbCnt,
525 hPsyConfLong->tnsConf,
526 hPsyConfLong->lowpassLine,
527 psyData->mdctSpectrum,
528 0,
529 psyData->blockSwitchingControl.windowSequence);
530
531 /* first part of threshold calculation */
532 data0 = psyData->sfbEnergy.sfbLong;
533 data1 = psyData->sfbThreshold.sfbLong;
534 for (i=hPsyConfLong->sfbCnt; i; i--) {
535 tdata = L_mpy_ls(*data0++, hPsyConfLong->ratio);
536 *data1++ = min(tdata, clipEnergy);
537 }
538
539 /* Calc sfb-bandwise mdct-energies for left and right channel again */
540 if (tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive!=0) {
541 Word16 tnsStartBand = hPsyConfLong->tnsConf.tnsStartBand;
542 CalcBandEnergy( psyData->mdctSpectrum,
543 hPsyConfLong->sfbOffset+tnsStartBand,
544 hPsyConfLong->sfbActive - tnsStartBand,
545 psyData->sfbEnergy.sfbLong+tnsStartBand,
546 &psyData->sfbEnergySum.sfbLong);
547
548 data0 = psyData->sfbEnergy.sfbLong;
549 tdata = psyData->sfbEnergySum.sfbLong;
550 for (i=0; i<tnsStartBand; i++)
551 tdata += *data0++;
552
553 psyData->sfbEnergySum.sfbLong = tdata;
554 }
555
556
557 /* spreading energy */
558 SpreadingMax(hPsyConfLong->sfbCnt,
559 hPsyConfLong->sfbMaskLowFactor,
560 hPsyConfLong->sfbMaskHighFactor,
561 psyData->sfbThreshold.sfbLong);
562
563 /* threshold in quiet */
564 data0 = psyData->sfbThreshold.sfbLong;
565 data1 = hPsyConfLong->sfbThresholdQuiet;
566 for (i=hPsyConfLong->sfbCnt; i; i--)
567 {
568 *data0 = max(*data0, (*data1 >> normEnergyShift));
569 data0++; data1++;
570 }
571
572 /* preecho control */
573 if (psyData->blockSwitchingControl.windowSequence == STOP_WINDOW) {
574 data0 = psyData->sfbThresholdnm1;
575 for (i=hPsyConfLong->sfbCnt; i; i--) {
576 *data0++ = MAX_32;
577 }
578 psyData->mdctScalenm1 = 0;
579 }
580
581 PreEchoControl( psyData->sfbThresholdnm1,
582 hPsyConfLong->sfbCnt,
583 hPsyConfLong->maxAllowedIncreaseFactor,
584 hPsyConfLong->minRemainingThresholdFactor,
585 psyData->sfbThreshold.sfbLong,
586 psyData->mdctScale,
587 psyData->mdctScalenm1);
588 psyData->mdctScalenm1 = psyData->mdctScale;
589
590
591 if (psyData->blockSwitchingControl.windowSequence== START_WINDOW) {
592 data0 = psyData->sfbThresholdnm1;
593 for (i=hPsyConfLong->sfbCnt; i; i--) {
594 *data0++ = MAX_32;
595 }
596 psyData->mdctScalenm1 = 0;
597 }
598
599 /* apply tns mult table on cb thresholds */
600 ApplyTnsMultTableToRatios(hPsyConfLong->tnsConf.tnsRatioPatchLowestCb,
601 hPsyConfLong->tnsConf.tnsStartBand,
602 tnsData->dataRaw.tnsLong.subBlockInfo,
603 psyData->sfbThreshold.sfbLong);
604
605
606 /* spreaded energy */
607 data0 = psyData->sfbSpreadedEnergy.sfbLong;
608 data1 = psyData->sfbEnergy.sfbLong;
609 for (i=hPsyConfLong->sfbCnt; i; i--) {
610 //psyData->sfbSpreadedEnergy.sfbLong[i] = psyData->sfbEnergy.sfbLong[i];
611 *data0++ = *data1++;
612 }
613
614 /* spreading energy */
615 SpreadingMax(hPsyConfLong->sfbCnt,
616 hPsyConfLong->sfbMaskLowFactorSprEn,
617 hPsyConfLong->sfbMaskHighFactorSprEn,
618 psyData->sfbSpreadedEnergy.sfbLong);
619
620 return 0;
621 }
622
623 /*****************************************************************************
624 *
625 * function name: advancePsychLongMS
626 * description: update mdct-energies for left add or minus right channel
627 * for long block
628 *
629 *****************************************************************************/
advancePsychLongMS(PSY_DATA psyData[MAX_CHANNELS],const PSY_CONFIGURATION_LONG * hPsyConfLong)630 static Word16 advancePsychLongMS (PSY_DATA psyData[MAX_CHANNELS],
631 const PSY_CONFIGURATION_LONG *hPsyConfLong)
632 {
633 CalcBandEnergyMS(psyData[0].mdctSpectrum,
634 psyData[1].mdctSpectrum,
635 hPsyConfLong->sfbOffset,
636 hPsyConfLong->sfbActive,
637 psyData[0].sfbEnergyMS.sfbLong,
638 &psyData[0].sfbEnergySumMS.sfbLong,
639 psyData[1].sfbEnergyMS.sfbLong,
640 &psyData[1].sfbEnergySumMS.sfbLong);
641
642 return 0;
643 }
644
645
646 /*****************************************************************************
647 *
648 * function name: advancePsychShort
649 * description: psychoacoustic for short blocks
650 *
651 *****************************************************************************/
652
advancePsychShort(PSY_DATA * psyData,TNS_DATA * tnsData,const PSY_CONFIGURATION_SHORT * hPsyConfShort,PSY_OUT_CHANNEL * psyOutChannel,Word32 * pScratchTns,const TNS_DATA * tnsData2,const Word16 ch)653 static Word16 advancePsychShort(PSY_DATA* psyData,
654 TNS_DATA* tnsData,
655 const PSY_CONFIGURATION_SHORT *hPsyConfShort,
656 PSY_OUT_CHANNEL* psyOutChannel,
657 Word32 *pScratchTns,
658 const TNS_DATA *tnsData2,
659 const Word16 ch)
660 {
661 Word32 w;
662 Word32 normEnergyShift = (psyData->mdctScale + 1) << 1; /* in reference code, mdct spectrum must be multipied with 2, so +1 */
663 Word32 clipEnergy = hPsyConfShort->clipEnergy >> normEnergyShift;
664 Word32 wOffset = 0;
665 Word32 *data0;
666 const Word32 *data1;
667
668 for(w = 0; w < TRANS_FAC; w++) {
669 Word32 i, tdata;
670
671 /* low pass */
672 data0 = psyData->mdctSpectrum + wOffset + hPsyConfShort->lowpassLine;
673 for(i=hPsyConfShort->lowpassLine; i<FRAME_LEN_SHORT; i++){
674 *data0++ = 0;
675 }
676
677 /* Calc sfb-bandwise mdct-energies for left and right channel */
678 CalcBandEnergy( psyData->mdctSpectrum+wOffset,
679 hPsyConfShort->sfbOffset,
680 hPsyConfShort->sfbActive,
681 psyData->sfbEnergy.sfbShort[w],
682 &psyData->sfbEnergySum.sfbShort[w]);
683 /*
684 TNS
685 */
686 TnsDetect(tnsData,
687 hPsyConfShort->tnsConf,
688 pScratchTns,
689 (const Word16*)hPsyConfShort->sfbOffset,
690 psyData->mdctSpectrum+wOffset,
691 w,
692 psyData->blockSwitchingControl.windowSequence,
693 psyData->sfbEnergy.sfbShort[w]);
694
695 /* TnsSync */
696 if (ch == 1) {
697 TnsSync(tnsData,
698 tnsData2,
699 hPsyConfShort->tnsConf,
700 w,
701 psyData->blockSwitchingControl.windowSequence);
702 }
703
704 TnsEncode(&psyOutChannel->tnsInfo,
705 tnsData,
706 hPsyConfShort->sfbCnt,
707 hPsyConfShort->tnsConf,
708 hPsyConfShort->lowpassLine,
709 psyData->mdctSpectrum+wOffset,
710 w,
711 psyData->blockSwitchingControl.windowSequence);
712
713 /* first part of threshold calculation */
714 data0 = psyData->sfbThreshold.sfbShort[w];
715 data1 = psyData->sfbEnergy.sfbShort[w];
716 for (i=hPsyConfShort->sfbCnt; i; i--) {
717 tdata = L_mpy_ls(*data1++, hPsyConfShort->ratio);
718 *data0++ = min(tdata, clipEnergy);
719 }
720
721 /* Calc sfb-bandwise mdct-energies for left and right channel again */
722 if (tnsData->dataRaw.tnsShort.subBlockInfo[w].tnsActive != 0) {
723 Word16 tnsStartBand = hPsyConfShort->tnsConf.tnsStartBand;
724 CalcBandEnergy( psyData->mdctSpectrum+wOffset,
725 hPsyConfShort->sfbOffset+tnsStartBand,
726 (hPsyConfShort->sfbActive - tnsStartBand),
727 psyData->sfbEnergy.sfbShort[w]+tnsStartBand,
728 &psyData->sfbEnergySum.sfbShort[w]);
729
730 tdata = psyData->sfbEnergySum.sfbShort[w];
731 data0 = psyData->sfbEnergy.sfbShort[w];
732 for (i=tnsStartBand; i; i--)
733 tdata += *data0++;
734
735 psyData->sfbEnergySum.sfbShort[w] = tdata;
736 }
737
738 /* spreading */
739 SpreadingMax(hPsyConfShort->sfbCnt,
740 hPsyConfShort->sfbMaskLowFactor,
741 hPsyConfShort->sfbMaskHighFactor,
742 psyData->sfbThreshold.sfbShort[w]);
743
744
745 /* threshold in quiet */
746 data0 = psyData->sfbThreshold.sfbShort[w];
747 data1 = hPsyConfShort->sfbThresholdQuiet;
748 for (i=hPsyConfShort->sfbCnt; i; i--)
749 {
750 *data0 = max(*data0, (*data1 >> normEnergyShift));
751
752 data0++; data1++;
753 }
754
755
756 /* preecho */
757 PreEchoControl( psyData->sfbThresholdnm1,
758 hPsyConfShort->sfbCnt,
759 hPsyConfShort->maxAllowedIncreaseFactor,
760 hPsyConfShort->minRemainingThresholdFactor,
761 psyData->sfbThreshold.sfbShort[w],
762 psyData->mdctScale,
763 w==0 ? psyData->mdctScalenm1 : psyData->mdctScale);
764
765 /* apply tns mult table on cb thresholds */
766 ApplyTnsMultTableToRatios( hPsyConfShort->tnsConf.tnsRatioPatchLowestCb,
767 hPsyConfShort->tnsConf.tnsStartBand,
768 tnsData->dataRaw.tnsShort.subBlockInfo[w],
769 psyData->sfbThreshold.sfbShort[w]);
770
771 /* spreaded energy */
772 data0 = psyData->sfbSpreadedEnergy.sfbShort[w];
773 data1 = psyData->sfbEnergy.sfbShort[w];
774 for (i=hPsyConfShort->sfbCnt; i; i--) {
775 *data0++ = *data1++;
776 }
777 SpreadingMax(hPsyConfShort->sfbCnt,
778 hPsyConfShort->sfbMaskLowFactorSprEn,
779 hPsyConfShort->sfbMaskHighFactorSprEn,
780 psyData->sfbSpreadedEnergy.sfbShort[w]);
781
782 wOffset += FRAME_LEN_SHORT;
783 } /* for TRANS_FAC */
784
785 psyData->mdctScalenm1 = psyData->mdctScale;
786
787 return 0;
788 }
789
790 /*****************************************************************************
791 *
792 * function name: advancePsychShortMS
793 * description: update mdct-energies for left add or minus right channel
794 * for short block
795 *
796 *****************************************************************************/
advancePsychShortMS(PSY_DATA psyData[MAX_CHANNELS],const PSY_CONFIGURATION_SHORT * hPsyConfShort)797 static Word16 advancePsychShortMS (PSY_DATA psyData[MAX_CHANNELS],
798 const PSY_CONFIGURATION_SHORT *hPsyConfShort)
799 {
800 Word32 w, wOffset;
801 wOffset = 0;
802 for(w=0; w<TRANS_FAC; w++) {
803 CalcBandEnergyMS(psyData[0].mdctSpectrum+wOffset,
804 psyData[1].mdctSpectrum+wOffset,
805 hPsyConfShort->sfbOffset,
806 hPsyConfShort->sfbActive,
807 psyData[0].sfbEnergyMS.sfbShort[w],
808 &psyData[0].sfbEnergySumMS.sfbShort[w],
809 psyData[1].sfbEnergyMS.sfbShort[w],
810 &psyData[1].sfbEnergySumMS.sfbShort[w]);
811 wOffset += FRAME_LEN_SHORT;
812 }
813
814 return 0;
815 }
816