• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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