psy_main.c revision b676a05348e4c516fa8b57e33b10548e6142c3f8
1e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/*
2e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Copyright 2003-2010, VisualOn, Inc.
3e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
4e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Licensed under the Apache License, Version 2.0 (the "License");
5e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** you may not use this file except in compliance with the License.
6e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** You may obtain a copy of the License at
7e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
8e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **     http://www.apache.org/licenses/LICENSE-2.0
9e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
10e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Unless required by applicable law or agreed to in writing, software
11e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** distributed under the License is distributed on an "AS IS" BASIS,
12e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** See the License for the specific language governing permissions and
14e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** limitations under the License.
15e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard */
16e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/*******************************************************************************
17e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	File:		psy_main.c
18e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
19e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	Content:	Psychoacoustic major functions
20e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
21956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*******************************************************************************/
22956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
23e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "typedef.h"
24e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "basic_op.h"
25956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "oper_32b.h"
26956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "psy_const.h"
27956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "block_switch.h"
28956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "transform.h"
29956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "spreading.h"
30956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "pre_echo_control.h"
31956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "band_nrg.h"
32956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "psy_configuration.h"
33956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "psy_data.h"
34956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "ms_stereo.h"
35956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "interface.h"
36956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "psy_main.h"
37956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "grp_data.h"
38956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "tns_func.h"
39956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "memalign.h"
40956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
41956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*                                    long       start       short       stop */
42956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 blockType2windowShape[] = {KBD_WINDOW,SINE_WINDOW,SINE_WINDOW,KBD_WINDOW};
43956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
44956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*
45956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  forward definitions
46956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*/
47956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 advancePsychLong(PSY_DATA* psyData,
48956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               TNS_DATA* tnsData,
49956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               PSY_CONFIGURATION_LONG *hPsyConfLong,
50956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               PSY_OUT_CHANNEL* psyOutChannel,
51956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               Word32 *pScratchTns,
52956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               const TNS_DATA *tnsData2,
53956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               const Word16 ch);
54956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
55956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 advancePsychLongMS (PSY_DATA  psyData[MAX_CHANNELS],
56956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                  const PSY_CONFIGURATION_LONG *hPsyConfLong);
57956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
58956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 advancePsychShort(PSY_DATA* psyData,
59956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                TNS_DATA* tnsData,
60956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                const PSY_CONFIGURATION_SHORT *hPsyConfShort,
61956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                PSY_OUT_CHANNEL* psyOutChannel,
62956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                Word32 *pScratchTns,
63956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                const TNS_DATA *tnsData2,
64956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                const Word16 ch);
65956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
66956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 advancePsychShortMS (PSY_DATA  psyData[MAX_CHANNELS],
67956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                   const PSY_CONFIGURATION_SHORT *hPsyConfShort);
68956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
69956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
70956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
71956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
72956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: PsyNew
73956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  allocates memory for psychoacoustic
74956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:      an error code
75956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* input:        pointer to a psych handle
76956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
77956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
78956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 PsyNew(PSY_KERNEL *hPsy, Word32 nChan, VO_MEM_OPERATOR *pMemOP)
79956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
80e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  Word16 i;
81e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  Word32 *mdctSpectrum;
82e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  Word32 *scratchTNS;
83e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  Word16 *mdctDelayBuffer;
84b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
85e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  mdctSpectrum = (Word32 *)mem_malloc(pMemOP, nChan * FRAME_LEN_LONG * sizeof(Word32), 32, VO_INDEX_ENC_AAC);
86e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  if(NULL == mdctSpectrum)
87e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  return 1;
88e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
89e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  scratchTNS = (Word32 *)mem_malloc(pMemOP, nChan * FRAME_LEN_LONG * sizeof(Word32), 32, VO_INDEX_ENC_AAC);
90e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  if(NULL == scratchTNS)
91e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  {
92956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  return 1;
93e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  }
94e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
95e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  mdctDelayBuffer = (Word16 *)mem_malloc(pMemOP, nChan * BLOCK_SWITCHING_OFFSET * sizeof(Word16), 32, VO_INDEX_ENC_AAC);
96e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  if(NULL == mdctDelayBuffer)
97e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  {
98e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  return 1;
99e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  }
100e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
101956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for (i=0; i<nChan; i++){
102b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    hPsy->psyData[i].mdctDelayBuffer = mdctDelayBuffer + i*BLOCK_SWITCHING_OFFSET;
103956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    hPsy->psyData[i].mdctSpectrum = mdctSpectrum + i*FRAME_LEN_LONG;
104956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
105956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
106956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  hPsy->pScratchTns = scratchTNS;
107956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
108956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return 0;
109956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
110956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
111956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
112956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
113956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
114956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: PsyDelete
115956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  allocates memory for psychoacoustic
116956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:      an error code
117956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
118956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
119956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 PsyDelete(PSY_KERNEL  *hPsy, VO_MEM_OPERATOR *pMemOP)
120956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
121e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  Word32 nch;
122e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
123e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  if(hPsy)
124e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  {
125e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	if(hPsy->psyData[0].mdctDelayBuffer)
126e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		mem_free(pMemOP, hPsy->psyData[0].mdctDelayBuffer, VO_INDEX_ENC_AAC);
127b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
128e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    if(hPsy->psyData[0].mdctSpectrum)
129e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		mem_free(pMemOP, hPsy->psyData[0].mdctSpectrum, VO_INDEX_ENC_AAC);
130e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
131e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    for (nch=0; nch<MAX_CHANNELS; nch++){
132b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard	  hPsy->psyData[nch].mdctDelayBuffer = NULL;
133e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  hPsy->psyData[nch].mdctSpectrum = NULL;
134e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	}
135e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
136e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	if(hPsy->pScratchTns)
137e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	{
138e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		mem_free(pMemOP, hPsy->pScratchTns, VO_INDEX_ENC_AAC);
139e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		hPsy->pScratchTns = NULL;
140e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	}
141e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  }
142956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
143956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return 0;
144956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
145956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
146956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
147956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
148956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
149956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: PsyOutNew
150956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  allocates memory for psyOut struc
151956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:      an error code
152956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* input:        pointer to a psych handle
153956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
154956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
155956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 PsyOutNew(PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP)
156956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
157956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  pMemOP->Set(VO_INDEX_ENC_AAC, hPsyOut, 0, sizeof(PSY_OUT));
158956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /*
159956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    alloc some more stuff, tbd
160956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  */
161956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return 0;
162956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
163956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
164956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
165956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
166956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: PsyOutDelete
167956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  allocates memory for psychoacoustic
168956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:      an error code
169956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
170956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
171956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 PsyOutDelete(PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP)
172956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
173956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  hPsyOut=NULL;
174956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return 0;
175956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
176956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
177956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
178956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
179956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
180956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: psyMainInit
181956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  initializes psychoacoustic
182956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:      an error code
183956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
184956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
185956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
186956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 psyMainInit(PSY_KERNEL *hPsy,
187956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   Word32 sampleRate,
188956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   Word32 bitRate,
189956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   Word16 channels,
190956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   Word16 tnsMask,
191956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   Word16 bandwidth)
192956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
193956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word16 ch, err;
194956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 channelBitRate = bitRate/channels;
195956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
196956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  err = InitPsyConfigurationLong(channelBitRate,
197956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                 sampleRate,
198956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                 bandwidth,
199e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard                                 &(hPsy->psyConfLong));
200e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
201956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (!err) {
202e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard      hPsy->sampleRateIdx = hPsy->psyConfLong.sampRateIdx;
203956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  err = InitTnsConfigurationLong(bitRate, sampleRate, channels,
204956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                   &hPsy->psyConfLong.tnsConf, &hPsy->psyConfLong, tnsMask&2);
205956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
206956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
207956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (!err)
208956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    err = InitPsyConfigurationShort(channelBitRate,
209956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                    sampleRate,
210956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                    bandwidth,
211956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                    &hPsy->psyConfShort);
212956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (!err) {
213956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    err = InitTnsConfigurationShort(bitRate, sampleRate, channels,
214956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                    &hPsy->psyConfShort.tnsConf, &hPsy->psyConfShort, tnsMask&1);
215956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
216956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
217956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (!err)
218956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    for(ch=0;ch < channels;ch++){
219b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
220956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      InitBlockSwitching(&hPsy->psyData[ch].blockSwitchingControl,
221956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         bitRate, channels);
222956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
223956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      InitPreEchoControl(hPsy->psyData[ch].sfbThresholdnm1,
224956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         hPsy->psyConfLong.sfbCnt,
225956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         hPsy->psyConfLong.sfbThresholdQuiet);
226b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      hPsy->psyData[ch].mdctScalenm1 = 0;
227956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
228956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
229956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	return(err);
230956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
231956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
232956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
233956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
234956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: psyMain
235956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  psychoacoustic main function
236956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:      an error code
237956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
238956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*    This function assumes that enough input data is in the modulo buffer.
239956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
240956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
241956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
242956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 psyMain(Word16                   nChannels,
243956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               ELEMENT_INFO            *elemInfo,
244b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard               Word16                  *timeSignal,
245956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               PSY_DATA                 psyData[MAX_CHANNELS],
246956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               TNS_DATA                 tnsData[MAX_CHANNELS],
247956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               PSY_CONFIGURATION_LONG  *hPsyConfLong,
248956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               PSY_CONFIGURATION_SHORT *hPsyConfShort,
249956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               PSY_OUT_CHANNEL          psyOutChannel[MAX_CHANNELS],
250956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               PSY_OUT_ELEMENT         *psyOutElement,
251956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               Word32                  *pScratchTns,
252956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong			   Word32				   sampleRate)
253956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
254956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word16 maxSfbPerGroup[MAX_CHANNELS];
255956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word16 mdctScalingArray[MAX_CHANNELS];
256956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
257956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word16 ch;   /* counts through channels          */
258956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word16 sfb;  /* counts through scalefactor bands */
259956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word16 line; /* counts through lines             */
260956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word16 channels;
261956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word16 maxScale;
262956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
263b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  channels = elemInfo->nChannelsInEl;
264b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  maxScale = 0;
265956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
266e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  /* block switching */
267956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for(ch = 0; ch < channels; ch++) {
268956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    BlockSwitching(&psyData[ch].blockSwitchingControl,
269956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   timeSignal+elemInfo->ChannelIndex[ch],
270956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong				   sampleRate,
271956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   nChannels);
272956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
273956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
274956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* synch left and right block type */
275956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  SyncBlockSwitching(&psyData[0].blockSwitchingControl,
276956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[1].blockSwitchingControl,
277956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     channels);
278956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
279956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* transform
280956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong     and get maxScale (max mdctScaling) for all channels */
281956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for(ch=0; ch<channels; ch++) {
282956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    Transform_Real(psyData[ch].mdctDelayBuffer,
283956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   timeSignal+elemInfo->ChannelIndex[ch],
284956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   nChannels,
285956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   psyData[ch].mdctSpectrum,
286956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   &(mdctScalingArray[ch]),
287956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   psyData[ch].blockSwitchingControl.windowSequence);
288956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    maxScale = max(maxScale, mdctScalingArray[ch]);
289956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
290956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
291956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* common scaling for all channels */
292956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for (ch=0; ch<channels; ch++) {
293956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    Word16 scaleDiff = maxScale - mdctScalingArray[ch];
294b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
295956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (scaleDiff > 0) {
296956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      Word32 *Spectrum = psyData[ch].mdctSpectrum;
297956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  for(line=0; line<FRAME_LEN_LONG; line++) {
298956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        *Spectrum = (*Spectrum) >> scaleDiff;
299956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		Spectrum++;
300956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      }
301956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
302b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    psyData[ch].mdctScale = maxScale;
303956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
304956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
305956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for (ch=0; ch<channels; ch++) {
306b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
307956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if(psyData[ch].blockSwitchingControl.windowSequence != SHORT_WINDOW) {
308956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      /* update long block parameter */
309956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  advancePsychLong(&psyData[ch],
310956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                       &tnsData[ch],
311956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                       hPsyConfLong,
312956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                       &psyOutChannel[ch],
313956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                       pScratchTns,
314956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                       &tnsData[1 - ch],
315956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                       ch);
316956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
317956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      /* determine maxSfb */
318956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      for (sfb=hPsyConfLong->sfbCnt-1; sfb>=0; sfb--) {
319956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        for (line=hPsyConfLong->sfbOffset[sfb+1] - 1; line>=hPsyConfLong->sfbOffset[sfb]; line--) {
320b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
321956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong          if (psyData[ch].mdctSpectrum[line] != 0) break;
322956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        }
323956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        if (line >= hPsyConfLong->sfbOffset[sfb]) break;
324956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      }
325956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      maxSfbPerGroup[ch] = sfb + 1;
326956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
327956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      /* Calc bandwise energies for mid and side channel
328956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong         Do it only if 2 channels exist */
329b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
330956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      if (ch == 1)
331956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        advancePsychLongMS(psyData, hPsyConfLong);
332956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
333956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    else {
334956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      advancePsychShort(&psyData[ch],
335956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                        &tnsData[ch],
336956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                        hPsyConfShort,
337956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                        &psyOutChannel[ch],
338956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                        pScratchTns,
339956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                        &tnsData[1 - ch],
340956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                        ch);
341956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
342956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      /* Calc bandwise energies for mid and side channel
343956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong         Do it only if 2 channels exist */
344b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
345956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      if (ch == 1)
346956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        advancePsychShortMS (psyData, hPsyConfShort);
347956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
348956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
349956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
350956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* group short data */
351956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for(ch=0; ch<channels; ch++) {
352b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
353956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (psyData[ch].blockSwitchingControl.windowSequence == SHORT_WINDOW) {
354956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      groupShortData(psyData[ch].mdctSpectrum,
355956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     pScratchTns,
356956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[ch].sfbThreshold,
357956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[ch].sfbEnergy,
358956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[ch].sfbEnergyMS,
359956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[ch].sfbSpreadedEnergy,
360956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     hPsyConfShort->sfbCnt,
361956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     hPsyConfShort->sfbOffset,
362956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     hPsyConfShort->sfbMinSnr,
363956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyOutElement->groupedSfbOffset[ch],
364956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &maxSfbPerGroup[ch],
365956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyOutElement->groupedSfbMinSnr[ch],
366956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].blockSwitchingControl.noOfGroups,
367956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].blockSwitchingControl.groupLen);
368956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
369956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
370956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
371956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
372956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#if (MAX_CHANNELS>1)
373956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /*
374956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    stereo Processing
375956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  */
376956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (channels == 2) {
377b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    psyOutElement->toolsInfo.msDigest = MS_NONE;
378956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    maxSfbPerGroup[0] = maxSfbPerGroup[1] = max(maxSfbPerGroup[0], maxSfbPerGroup[1]);
379956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
380b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
381956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (psyData[0].blockSwitchingControl.windowSequence != SHORT_WINDOW)
382956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      MsStereoProcessing(psyData[0].sfbEnergy.sfbLong,
383956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         psyData[1].sfbEnergy.sfbLong,
384956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         psyData[0].sfbEnergyMS.sfbLong,
385956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         psyData[1].sfbEnergyMS.sfbLong,
386956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         psyData[0].mdctSpectrum,
387956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         psyData[1].mdctSpectrum,
388956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         psyData[0].sfbThreshold.sfbLong,
389956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         psyData[1].sfbThreshold.sfbLong,
390956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         psyData[0].sfbSpreadedEnergy.sfbLong,
391956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         psyData[1].sfbSpreadedEnergy.sfbLong,
392956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         (Word16*)&psyOutElement->toolsInfo.msDigest,
393956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         (Word16*)psyOutElement->toolsInfo.msMask,
394956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         hPsyConfLong->sfbCnt,
395956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         hPsyConfLong->sfbCnt,
396956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         maxSfbPerGroup[0],
397956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         (const Word16*)hPsyConfLong->sfbOffset);
398956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      else
399956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        MsStereoProcessing(psyData[0].sfbEnergy.sfbLong,
400956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           psyData[1].sfbEnergy.sfbLong,
401956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           psyData[0].sfbEnergyMS.sfbLong,
402956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           psyData[1].sfbEnergyMS.sfbLong,
403956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           psyData[0].mdctSpectrum,
404956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           psyData[1].mdctSpectrum,
405956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           psyData[0].sfbThreshold.sfbLong,
406956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           psyData[1].sfbThreshold.sfbLong,
407956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           psyData[0].sfbSpreadedEnergy.sfbLong,
408956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           psyData[1].sfbSpreadedEnergy.sfbLong,
409956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           (Word16*)&psyOutElement->toolsInfo.msDigest,
410956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           (Word16*)psyOutElement->toolsInfo.msMask,
411956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           psyData[0].blockSwitchingControl.noOfGroups*hPsyConfShort->sfbCnt,
412956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           hPsyConfShort->sfbCnt,
413956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           maxSfbPerGroup[0],
414956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           (const Word16*)psyOutElement->groupedSfbOffset[0]);
415956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
416956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
417956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#endif /* (MAX_CHANNELS>1) */
418956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
419956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /*
420956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    build output
421956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  */
422956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for(ch=0;ch<channels;ch++) {
423b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
424956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (psyData[ch].blockSwitchingControl.windowSequence != SHORT_WINDOW)
425956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      BuildInterface(psyData[ch].mdctSpectrum,
426956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].mdctScale,
427956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[ch].sfbThreshold,
428956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[ch].sfbEnergy,
429956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[ch].sfbSpreadedEnergy,
430956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].sfbEnergySum,
431956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].sfbEnergySumMS,
432956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].blockSwitchingControl.windowSequence,
433956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     blockType2windowShape[psyData[ch].blockSwitchingControl.windowSequence],
434956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     hPsyConfLong->sfbCnt,
435956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     hPsyConfLong->sfbOffset,
436956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     maxSfbPerGroup[ch],
437956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     hPsyConfLong->sfbMinSnr,
438956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].blockSwitchingControl.noOfGroups,
439956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].blockSwitchingControl.groupLen,
440956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyOutChannel[ch]);
441956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    else
442956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      BuildInterface(psyData[ch].mdctSpectrum,
443956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].mdctScale,
444956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[ch].sfbThreshold,
445956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[ch].sfbEnergy,
446956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[ch].sfbSpreadedEnergy,
447956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].sfbEnergySum,
448956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].sfbEnergySumMS,
449956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     SHORT_WINDOW,
450956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     SINE_WINDOW,
451956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[0].blockSwitchingControl.noOfGroups*hPsyConfShort->sfbCnt,
452956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyOutElement->groupedSfbOffset[ch],
453956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     maxSfbPerGroup[ch],
454956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyOutElement->groupedSfbMinSnr[ch],
455956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].blockSwitchingControl.noOfGroups,
456956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].blockSwitchingControl.groupLen,
457956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyOutChannel[ch]);
458956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
459956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
460956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return(0); /* no error */
461956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
462956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
463956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
464956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
465956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: advancePsychLong
466956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  psychoacoustic for long blocks
467956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
468956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
469956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
470956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 advancePsychLong(PSY_DATA* psyData,
471956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               TNS_DATA* tnsData,
472956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               PSY_CONFIGURATION_LONG *hPsyConfLong,
473956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               PSY_OUT_CHANNEL* psyOutChannel,
474956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               Word32 *pScratchTns,
475956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               const TNS_DATA* tnsData2,
476956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               const Word16 ch)
477956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
478956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 i;
479956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 normEnergyShift = (psyData->mdctScale + 1) << 1; /* in reference code, mdct spectrum must be multipied with 2, so +1 */
480e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  Word32 clipEnergy = hPsyConfLong->clipEnergy >> normEnergyShift;
481956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 *data0, *data1, tdata;
482956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
483956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* low pass */
484e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  data0 = psyData->mdctSpectrum + hPsyConfLong->lowpassLine;
485956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for(i=hPsyConfLong->lowpassLine; i<FRAME_LEN_LONG; i++) {
486b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    *data0++ = 0;
487956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
488956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
489956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* Calc sfb-bandwise mdct-energies for left and right channel */
490956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  CalcBandEnergy( psyData->mdctSpectrum,
491956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                  hPsyConfLong->sfbOffset,
492956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                  hPsyConfLong->sfbActive,
493956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                  psyData->sfbEnergy.sfbLong,
494956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                  &psyData->sfbEnergySum.sfbLong);
495956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
496956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /*
497956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    TNS detect
498956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  */
499956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  TnsDetect(tnsData,
500956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            hPsyConfLong->tnsConf,
501956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            pScratchTns,
502956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            (const Word16*)hPsyConfLong->sfbOffset,
503956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            psyData->mdctSpectrum,
504956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            0,
505956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            psyData->blockSwitchingControl.windowSequence,
506956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            psyData->sfbEnergy.sfbLong);
507956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
508b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  /*  TnsSync */
509956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (ch == 1) {
510956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    TnsSync(tnsData,
511956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            tnsData2,
512956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            hPsyConfLong->tnsConf,
513956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            0,
514956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            psyData->blockSwitchingControl.windowSequence);
515956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
516956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
517b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  /*  Tns Encoder */
518956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  TnsEncode(&psyOutChannel->tnsInfo,
519956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            tnsData,
520956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            hPsyConfLong->sfbCnt,
521956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            hPsyConfLong->tnsConf,
522956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            hPsyConfLong->lowpassLine,
523956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            psyData->mdctSpectrum,
524956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            0,
525956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            psyData->blockSwitchingControl.windowSequence);
526956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
527956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* first part of threshold calculation */
528e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  data0 = psyData->sfbEnergy.sfbLong;
529e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  data1 = psyData->sfbThreshold.sfbLong;
530956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for (i=hPsyConfLong->sfbCnt; i; i--) {
531956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    tdata = L_mpy_ls(*data0++, hPsyConfLong->ratio);
532e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    *data1++ = min(tdata, clipEnergy);
533956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
534956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
535b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  /* Calc sfb-bandwise mdct-energies for left and right channel again */
536956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive!=0) {
537b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    Word16 tnsStartBand = hPsyConfLong->tnsConf.tnsStartBand;
538956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    CalcBandEnergy( psyData->mdctSpectrum,
539956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    hPsyConfLong->sfbOffset+tnsStartBand,
540956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    hPsyConfLong->sfbActive - tnsStartBand,
541956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    psyData->sfbEnergy.sfbLong+tnsStartBand,
542956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    &psyData->sfbEnergySum.sfbLong);
543b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
544e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	data0 = psyData->sfbEnergy.sfbLong;
545e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	tdata = psyData->sfbEnergySum.sfbLong;
546956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	for (i=0; i<tnsStartBand; i++)
547e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard      tdata += *data0++;
548e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
549956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	psyData->sfbEnergySum.sfbLong = tdata;
550956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
551956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
552956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
553956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* spreading energy */
554956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  SpreadingMax(hPsyConfLong->sfbCnt,
555956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               hPsyConfLong->sfbMaskLowFactor,
556956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               hPsyConfLong->sfbMaskHighFactor,
557956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               psyData->sfbThreshold.sfbLong);
558956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
559956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* threshold in quiet */
560e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  data0 = psyData->sfbThreshold.sfbLong;
561e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  data1 = hPsyConfLong->sfbThresholdQuiet;
562956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for (i=hPsyConfLong->sfbCnt; i; i--)
563e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  {
564e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  *data0 = max(*data0, (*data1 >> normEnergyShift));
565e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  data0++; data1++;
566956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
567956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
568b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  /* preecho control */
569956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (psyData->blockSwitchingControl.windowSequence == STOP_WINDOW) {
570e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    data0 = psyData->sfbThresholdnm1;
571e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	for (i=hPsyConfLong->sfbCnt; i; i--) {
572b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      *data0++ = MAX_32;
573e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    }
574b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    psyData->mdctScalenm1 = 0;
575956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
576956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
577956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  PreEchoControl( psyData->sfbThresholdnm1,
578956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                  hPsyConfLong->sfbCnt,
579956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                  hPsyConfLong->maxAllowedIncreaseFactor,
580956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                  hPsyConfLong->minRemainingThresholdFactor,
581956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                  psyData->sfbThreshold.sfbLong,
582956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                  psyData->mdctScale,
583956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                  psyData->mdctScalenm1);
584b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  psyData->mdctScalenm1 = psyData->mdctScale;
585b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
586956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
587956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (psyData->blockSwitchingControl.windowSequence== START_WINDOW) {
588e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    data0 = psyData->sfbThresholdnm1;
589956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	for (i=hPsyConfLong->sfbCnt; i; i--) {
590b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      *data0++ = MAX_32;
591956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
592b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    psyData->mdctScalenm1 = 0;
593956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
594956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
595956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* apply tns mult table on cb thresholds */
596956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  ApplyTnsMultTableToRatios(hPsyConfLong->tnsConf.tnsRatioPatchLowestCb,
597956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                            hPsyConfLong->tnsConf.tnsStartBand,
598956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                            tnsData->dataRaw.tnsLong.subBlockInfo,
599956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                            psyData->sfbThreshold.sfbLong);
600956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
601956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
602956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* spreaded energy */
603e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  data0 = psyData->sfbSpreadedEnergy.sfbLong;
604e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  data1 = psyData->sfbEnergy.sfbLong;
605956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for (i=hPsyConfLong->sfbCnt; i; i--) {
606b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    //psyData->sfbSpreadedEnergy.sfbLong[i] = psyData->sfbEnergy.sfbLong[i];
607956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  *data0++ = *data1++;
608956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
609956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
610956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* spreading energy */
611956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  SpreadingMax(hPsyConfLong->sfbCnt,
612b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard               hPsyConfLong->sfbMaskLowFactorSprEn,
613956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               hPsyConfLong->sfbMaskHighFactorSprEn,
614956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               psyData->sfbSpreadedEnergy.sfbLong);
615956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
616956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return 0;
617956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
618956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
619956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
620956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
621956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: advancePsychLongMS
622b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard* description:   update mdct-energies for left add or minus right channel
623956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*				for long block
624956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
625956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
626956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 advancePsychLongMS (PSY_DATA psyData[MAX_CHANNELS],
627956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                  const PSY_CONFIGURATION_LONG *hPsyConfLong)
628956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
629956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  CalcBandEnergyMS(psyData[0].mdctSpectrum,
630956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   psyData[1].mdctSpectrum,
631956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   hPsyConfLong->sfbOffset,
632956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   hPsyConfLong->sfbActive,
633956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   psyData[0].sfbEnergyMS.sfbLong,
634956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   &psyData[0].sfbEnergySumMS.sfbLong,
635956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   psyData[1].sfbEnergyMS.sfbLong,
636956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   &psyData[1].sfbEnergySumMS.sfbLong);
637956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
638956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return 0;
639956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
640956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
641956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
642956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
643956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
644956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: advancePsychShort
645956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  psychoacoustic for short blocks
646956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
647956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
648956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
649956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 advancePsychShort(PSY_DATA* psyData,
650956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                TNS_DATA* tnsData,
651956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                const PSY_CONFIGURATION_SHORT *hPsyConfShort,
652956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                PSY_OUT_CHANNEL* psyOutChannel,
653956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                Word32 *pScratchTns,
654956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                const TNS_DATA *tnsData2,
655956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                const Word16 ch)
656956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
657956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 w;
658956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 normEnergyShift = (psyData->mdctScale + 1) << 1; /* in reference code, mdct spectrum must be multipied with 2, so +1 */
659956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 clipEnergy = hPsyConfShort->clipEnergy >> normEnergyShift;
660b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  Word32 wOffset = 0;
661956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 *data0, *data1;
662956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
663956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for(w = 0; w < TRANS_FAC; w++) {
664956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    Word32 i, tdata;
665956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
666956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /* low pass */
667e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    data0 = psyData->mdctSpectrum + wOffset + hPsyConfShort->lowpassLine;
668956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	for(i=hPsyConfShort->lowpassLine; i<FRAME_LEN_SHORT; i++){
669b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      *data0++ = 0;
670956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
671956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
672956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /* Calc sfb-bandwise mdct-energies for left and right channel */
673956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    CalcBandEnergy( psyData->mdctSpectrum+wOffset,
674956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    hPsyConfShort->sfbOffset,
675956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    hPsyConfShort->sfbActive,
676956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    psyData->sfbEnergy.sfbShort[w],
677956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    &psyData->sfbEnergySum.sfbShort[w]);
678956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /*
679956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong       TNS
680956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    */
681956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    TnsDetect(tnsData,
682956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              hPsyConfShort->tnsConf,
683956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              pScratchTns,
684956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              (const Word16*)hPsyConfShort->sfbOffset,
685956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              psyData->mdctSpectrum+wOffset,
686956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              w,
687956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              psyData->blockSwitchingControl.windowSequence,
688956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              psyData->sfbEnergy.sfbShort[w]);
689956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
690956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /*  TnsSync */
691956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (ch == 1) {
692956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      TnsSync(tnsData,
693956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              tnsData2,
694956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              hPsyConfShort->tnsConf,
695956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              w,
696956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              psyData->blockSwitchingControl.windowSequence);
697956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
698956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
699956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    TnsEncode(&psyOutChannel->tnsInfo,
700956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              tnsData,
701956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              hPsyConfShort->sfbCnt,
702956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              hPsyConfShort->tnsConf,
703956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              hPsyConfShort->lowpassLine,
704956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              psyData->mdctSpectrum+wOffset,
705956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              w,
706956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              psyData->blockSwitchingControl.windowSequence);
707956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
708956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /* first part of threshold calculation */
709e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    data0 = psyData->sfbThreshold.sfbShort[w];
710e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	data1 = psyData->sfbEnergy.sfbShort[w];
711956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	for (i=hPsyConfShort->sfbCnt; i; i--) {
712956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      tdata = L_mpy_ls(*data1++, hPsyConfShort->ratio);
713e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard      *data0++ = min(tdata, clipEnergy);
714956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
715956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
716b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    /* Calc sfb-bandwise mdct-energies for left and right channel again */
717956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (tnsData->dataRaw.tnsShort.subBlockInfo[w].tnsActive != 0) {
718b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      Word16 tnsStartBand = hPsyConfShort->tnsConf.tnsStartBand;
719956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      CalcBandEnergy( psyData->mdctSpectrum+wOffset,
720956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                      hPsyConfShort->sfbOffset+tnsStartBand,
721956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                      (hPsyConfShort->sfbActive - tnsStartBand),
722956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                      psyData->sfbEnergy.sfbShort[w]+tnsStartBand,
723e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard                      &psyData->sfbEnergySum.sfbShort[w]);
724956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
725e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard      tdata = psyData->sfbEnergySum.sfbShort[w];
726e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  data0 = psyData->sfbEnergy.sfbShort[w];
727956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  for (i=tnsStartBand; i; i--)
728e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        tdata += *data0++;
729e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
730956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  psyData->sfbEnergySum.sfbShort[w] = tdata;
731956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
732956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
733956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /* spreading */
734956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    SpreadingMax(hPsyConfShort->sfbCnt,
735956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 hPsyConfShort->sfbMaskLowFactor,
736956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 hPsyConfShort->sfbMaskHighFactor,
737956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 psyData->sfbThreshold.sfbShort[w]);
738956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
739956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
740956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /* threshold in quiet */
741e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    data0 = psyData->sfbThreshold.sfbShort[w];
742e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	data1 = hPsyConfShort->sfbThresholdQuiet;
743956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	for (i=hPsyConfShort->sfbCnt; i; i--)
744e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    {
745e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		*data0 = max(*data0, (*data1 >> normEnergyShift));
746e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
747e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		data0++; data1++;
748e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	}
749956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
750956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
751b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    /* preecho */
752956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    PreEchoControl( psyData->sfbThresholdnm1,
753956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    hPsyConfShort->sfbCnt,
754956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    hPsyConfShort->maxAllowedIncreaseFactor,
755956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    hPsyConfShort->minRemainingThresholdFactor,
756956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    psyData->sfbThreshold.sfbShort[w],
757956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    psyData->mdctScale,
758956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    w==0 ? psyData->mdctScalenm1 : psyData->mdctScale);
759956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
760956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /* apply tns mult table on cb thresholds */
761956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    ApplyTnsMultTableToRatios( hPsyConfShort->tnsConf.tnsRatioPatchLowestCb,
762956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               hPsyConfShort->tnsConf.tnsStartBand,
763956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               tnsData->dataRaw.tnsShort.subBlockInfo[w],
764956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               psyData->sfbThreshold.sfbShort[w]);
765956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
766956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /* spreaded energy */
767e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    data0 = psyData->sfbSpreadedEnergy.sfbShort[w];
768e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	data1 = psyData->sfbEnergy.sfbShort[w];
769956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	for (i=hPsyConfShort->sfbCnt; i; i--) {
770956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  *data0++ = *data1++;
771956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
772956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    SpreadingMax(hPsyConfShort->sfbCnt,
773b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard                 hPsyConfShort->sfbMaskLowFactorSprEn,
774956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 hPsyConfShort->sfbMaskHighFactorSprEn,
775956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 psyData->sfbSpreadedEnergy.sfbShort[w]);
776956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
777956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    wOffset += FRAME_LEN_SHORT;
778956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  } /* for TRANS_FAC */
779956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
780b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  psyData->mdctScalenm1 = psyData->mdctScale;
781956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
782956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return 0;
783956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
784956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
785956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
786956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
787956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: advancePsychShortMS
788b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard* description:   update mdct-energies for left add or minus right channel
789956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*				for short block
790956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
791956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
792956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 advancePsychShortMS (PSY_DATA psyData[MAX_CHANNELS],
793956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                   const PSY_CONFIGURATION_SHORT *hPsyConfShort)
794956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
795956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 w, wOffset;
796b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  wOffset = 0;
797956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for(w=0; w<TRANS_FAC; w++) {
798956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    CalcBandEnergyMS(psyData[0].mdctSpectrum+wOffset,
799956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[1].mdctSpectrum+wOffset,
800956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     hPsyConfShort->sfbOffset,
801956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     hPsyConfShort->sfbActive,
802956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[0].sfbEnergyMS.sfbShort[w],
803956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[0].sfbEnergySumMS.sfbShort[w],
804956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[1].sfbEnergyMS.sfbShort[w],
805956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[1].sfbEnergySumMS.sfbShort[w]);
806956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    wOffset += FRAME_LEN_SHORT;
807956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
808956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
809956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return 0;
810956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
811