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
4184333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#define UNUSED(x) (void)(x)
4284333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber
43956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*                                    long       start       short       stop */
44956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 blockType2windowShape[] = {KBD_WINDOW,SINE_WINDOW,SINE_WINDOW,KBD_WINDOW};
45956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
46956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*
47956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  forward definitions
48956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*/
49956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 advancePsychLong(PSY_DATA* psyData,
50956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               TNS_DATA* tnsData,
51956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               PSY_CONFIGURATION_LONG *hPsyConfLong,
52956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               PSY_OUT_CHANNEL* psyOutChannel,
53956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               Word32 *pScratchTns,
54956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               const TNS_DATA *tnsData2,
55956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               const Word16 ch);
56956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
57956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 advancePsychLongMS (PSY_DATA  psyData[MAX_CHANNELS],
58956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                  const PSY_CONFIGURATION_LONG *hPsyConfLong);
59956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
60956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 advancePsychShort(PSY_DATA* psyData,
61956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                TNS_DATA* tnsData,
62956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                const PSY_CONFIGURATION_SHORT *hPsyConfShort,
63956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                PSY_OUT_CHANNEL* psyOutChannel,
64956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                Word32 *pScratchTns,
65956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                const TNS_DATA *tnsData2,
66956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                const Word16 ch);
67956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
68956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 advancePsychShortMS (PSY_DATA  psyData[MAX_CHANNELS],
69956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                   const PSY_CONFIGURATION_SHORT *hPsyConfShort);
70956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
71956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
72956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
73956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
74956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: PsyNew
75956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  allocates memory for psychoacoustic
76956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:      an error code
77956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* input:        pointer to a psych handle
78956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
79956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
80956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 PsyNew(PSY_KERNEL *hPsy, Word32 nChan, VO_MEM_OPERATOR *pMemOP)
81956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
82e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  Word16 i;
83e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  Word32 *mdctSpectrum;
84e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  Word32 *scratchTNS;
85e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  Word16 *mdctDelayBuffer;
86b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
87e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  mdctSpectrum = (Word32 *)mem_malloc(pMemOP, nChan * FRAME_LEN_LONG * sizeof(Word32), 32, VO_INDEX_ENC_AAC);
88e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  if(NULL == mdctSpectrum)
89e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  return 1;
90e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
91e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  scratchTNS = (Word32 *)mem_malloc(pMemOP, nChan * FRAME_LEN_LONG * sizeof(Word32), 32, VO_INDEX_ENC_AAC);
92e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  if(NULL == scratchTNS)
93e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  {
94956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  return 1;
95e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  }
96e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
97e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  mdctDelayBuffer = (Word16 *)mem_malloc(pMemOP, nChan * BLOCK_SWITCHING_OFFSET * sizeof(Word16), 32, VO_INDEX_ENC_AAC);
98e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  if(NULL == mdctDelayBuffer)
99e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  {
100e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  return 1;
101e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  }
102e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
103956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for (i=0; i<nChan; i++){
104b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    hPsy->psyData[i].mdctDelayBuffer = mdctDelayBuffer + i*BLOCK_SWITCHING_OFFSET;
105956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    hPsy->psyData[i].mdctSpectrum = mdctSpectrum + i*FRAME_LEN_LONG;
106956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
107956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
108956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  hPsy->pScratchTns = scratchTNS;
109956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
110956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return 0;
111956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
112956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
113956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
114956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
115956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
116956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: PsyDelete
117956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  allocates memory for psychoacoustic
118956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:      an error code
119956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
120956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
121956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 PsyDelete(PSY_KERNEL  *hPsy, VO_MEM_OPERATOR *pMemOP)
122956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
123e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  Word32 nch;
124e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
125e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  if(hPsy)
126e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  {
127e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	if(hPsy->psyData[0].mdctDelayBuffer)
128e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		mem_free(pMemOP, hPsy->psyData[0].mdctDelayBuffer, VO_INDEX_ENC_AAC);
129b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
130e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    if(hPsy->psyData[0].mdctSpectrum)
131e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		mem_free(pMemOP, hPsy->psyData[0].mdctSpectrum, VO_INDEX_ENC_AAC);
132e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
133e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    for (nch=0; nch<MAX_CHANNELS; nch++){
134b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard	  hPsy->psyData[nch].mdctDelayBuffer = NULL;
135e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  hPsy->psyData[nch].mdctSpectrum = NULL;
136e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	}
137e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
138e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	if(hPsy->pScratchTns)
139e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	{
140e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		mem_free(pMemOP, hPsy->pScratchTns, VO_INDEX_ENC_AAC);
141e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		hPsy->pScratchTns = NULL;
142e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	}
143e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  }
144956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
145956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return 0;
146956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
147956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
148956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
149956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
150956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
151956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: PsyOutNew
152956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  allocates memory for psyOut struc
153956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:      an error code
154956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* input:        pointer to a psych handle
155956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
156956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
157956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 PsyOutNew(PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP)
158956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
159956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  pMemOP->Set(VO_INDEX_ENC_AAC, hPsyOut, 0, sizeof(PSY_OUT));
160956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /*
161956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    alloc some more stuff, tbd
162956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  */
163956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return 0;
164956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
165956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
166956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
167956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
168956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: PsyOutDelete
169956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  allocates memory for psychoacoustic
170956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:      an error code
171956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
172956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
173956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 PsyOutDelete(PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP)
174956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
17584333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber  UNUSED(hPsyOut);
17684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber  UNUSED(pMemOP);
17784333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber
178956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return 0;
179956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
180956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
181956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
182956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
183956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
184956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: psyMainInit
185956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  initializes psychoacoustic
186956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:      an error code
187956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
188956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
189956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
190956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 psyMainInit(PSY_KERNEL *hPsy,
191956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   Word32 sampleRate,
192956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   Word32 bitRate,
193956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   Word16 channels,
194956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   Word16 tnsMask,
195956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   Word16 bandwidth)
196956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
197956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word16 ch, err;
198956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 channelBitRate = bitRate/channels;
199956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
200956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  err = InitPsyConfigurationLong(channelBitRate,
201956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                 sampleRate,
202956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                 bandwidth,
203e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard                                 &(hPsy->psyConfLong));
204e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
205956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (!err) {
206e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard      hPsy->sampleRateIdx = hPsy->psyConfLong.sampRateIdx;
207956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  err = InitTnsConfigurationLong(bitRate, sampleRate, channels,
208956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                   &hPsy->psyConfLong.tnsConf, &hPsy->psyConfLong, tnsMask&2);
209956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
210956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
211956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (!err)
212956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    err = InitPsyConfigurationShort(channelBitRate,
213956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                    sampleRate,
214956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                    bandwidth,
215956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                    &hPsy->psyConfShort);
216956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (!err) {
217956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    err = InitTnsConfigurationShort(bitRate, sampleRate, channels,
218956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                    &hPsy->psyConfShort.tnsConf, &hPsy->psyConfShort, tnsMask&1);
219956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
220956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
221956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (!err)
222956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    for(ch=0;ch < channels;ch++){
223b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
224956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      InitBlockSwitching(&hPsy->psyData[ch].blockSwitchingControl,
225956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         bitRate, channels);
226956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
227956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      InitPreEchoControl(hPsy->psyData[ch].sfbThresholdnm1,
228956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         hPsy->psyConfLong.sfbCnt,
229956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         hPsy->psyConfLong.sfbThresholdQuiet);
230b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      hPsy->psyData[ch].mdctScalenm1 = 0;
231956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
232956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
233956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	return(err);
234956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
235956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
236956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
237956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
238956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: psyMain
239956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  psychoacoustic main function
240956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:      an error code
241956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
242956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*    This function assumes that enough input data is in the modulo buffer.
243956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
244956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
245956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
246956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 psyMain(Word16                   nChannels,
247956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               ELEMENT_INFO            *elemInfo,
248b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard               Word16                  *timeSignal,
249956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               PSY_DATA                 psyData[MAX_CHANNELS],
250956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               TNS_DATA                 tnsData[MAX_CHANNELS],
251956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               PSY_CONFIGURATION_LONG  *hPsyConfLong,
252956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               PSY_CONFIGURATION_SHORT *hPsyConfShort,
253956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               PSY_OUT_CHANNEL          psyOutChannel[MAX_CHANNELS],
254956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               PSY_OUT_ELEMENT         *psyOutElement,
255956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               Word32                  *pScratchTns,
256956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong			   Word32				   sampleRate)
257956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
258956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word16 maxSfbPerGroup[MAX_CHANNELS];
259956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word16 mdctScalingArray[MAX_CHANNELS];
260956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
261956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word16 ch;   /* counts through channels          */
262956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word16 sfb;  /* counts through scalefactor bands */
263956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word16 line; /* counts through lines             */
264956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word16 channels;
265956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word16 maxScale;
266956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
267b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  channels = elemInfo->nChannelsInEl;
268b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  maxScale = 0;
269956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
270e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  /* block switching */
271956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for(ch = 0; ch < channels; ch++) {
272956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    BlockSwitching(&psyData[ch].blockSwitchingControl,
273956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   timeSignal+elemInfo->ChannelIndex[ch],
274956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong				   sampleRate,
275956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   nChannels);
276956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
277956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
278956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* synch left and right block type */
279956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  SyncBlockSwitching(&psyData[0].blockSwitchingControl,
280956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[1].blockSwitchingControl,
281956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     channels);
282956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
283956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* transform
284956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong     and get maxScale (max mdctScaling) for all channels */
285956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for(ch=0; ch<channels; ch++) {
286956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    Transform_Real(psyData[ch].mdctDelayBuffer,
287956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   timeSignal+elemInfo->ChannelIndex[ch],
288956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   nChannels,
289956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   psyData[ch].mdctSpectrum,
290956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   &(mdctScalingArray[ch]),
291956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   psyData[ch].blockSwitchingControl.windowSequence);
292956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    maxScale = max(maxScale, mdctScalingArray[ch]);
293956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
294956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
295956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* common scaling for all channels */
296956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for (ch=0; ch<channels; ch++) {
297956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    Word16 scaleDiff = maxScale - mdctScalingArray[ch];
298b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
299956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (scaleDiff > 0) {
300956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      Word32 *Spectrum = psyData[ch].mdctSpectrum;
301956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  for(line=0; line<FRAME_LEN_LONG; line++) {
302956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        *Spectrum = (*Spectrum) >> scaleDiff;
303956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		Spectrum++;
304956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      }
305956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
306b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    psyData[ch].mdctScale = maxScale;
307956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
308956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
309956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for (ch=0; ch<channels; ch++) {
310b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
311956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if(psyData[ch].blockSwitchingControl.windowSequence != SHORT_WINDOW) {
312956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      /* update long block parameter */
313956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  advancePsychLong(&psyData[ch],
314956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                       &tnsData[ch],
315956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                       hPsyConfLong,
316956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                       &psyOutChannel[ch],
317956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                       pScratchTns,
318956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                       &tnsData[1 - ch],
319956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                       ch);
320956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
321956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      /* determine maxSfb */
322956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      for (sfb=hPsyConfLong->sfbCnt-1; sfb>=0; sfb--) {
323956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        for (line=hPsyConfLong->sfbOffset[sfb+1] - 1; line>=hPsyConfLong->sfbOffset[sfb]; line--) {
324b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
325956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong          if (psyData[ch].mdctSpectrum[line] != 0) break;
326956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        }
327956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        if (line >= hPsyConfLong->sfbOffset[sfb]) break;
328956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      }
329956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      maxSfbPerGroup[ch] = sfb + 1;
330956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
331956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      /* Calc bandwise energies for mid and side channel
332956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong         Do it only if 2 channels exist */
333b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
334956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      if (ch == 1)
335956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        advancePsychLongMS(psyData, hPsyConfLong);
336956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
337956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    else {
338956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      advancePsychShort(&psyData[ch],
339956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                        &tnsData[ch],
340956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                        hPsyConfShort,
341956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                        &psyOutChannel[ch],
342956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                        pScratchTns,
343956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                        &tnsData[1 - ch],
344956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                        ch);
345956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
346956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      /* Calc bandwise energies for mid and side channel
347956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong         Do it only if 2 channels exist */
348b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
349956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      if (ch == 1)
350956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        advancePsychShortMS (psyData, hPsyConfShort);
351956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
352956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
353956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
354956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* group short data */
355956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for(ch=0; ch<channels; ch++) {
356b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
357956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (psyData[ch].blockSwitchingControl.windowSequence == SHORT_WINDOW) {
358956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      groupShortData(psyData[ch].mdctSpectrum,
359956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     pScratchTns,
360956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[ch].sfbThreshold,
361956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[ch].sfbEnergy,
362956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[ch].sfbEnergyMS,
363956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[ch].sfbSpreadedEnergy,
364956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     hPsyConfShort->sfbCnt,
365956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     hPsyConfShort->sfbOffset,
366956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     hPsyConfShort->sfbMinSnr,
367956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyOutElement->groupedSfbOffset[ch],
368956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &maxSfbPerGroup[ch],
369956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyOutElement->groupedSfbMinSnr[ch],
370956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].blockSwitchingControl.noOfGroups,
371956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].blockSwitchingControl.groupLen);
372956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
373956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
374956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
375956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
376956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#if (MAX_CHANNELS>1)
377956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /*
378956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    stereo Processing
379956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  */
380956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (channels == 2) {
381b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    psyOutElement->toolsInfo.msDigest = MS_NONE;
382956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    maxSfbPerGroup[0] = maxSfbPerGroup[1] = max(maxSfbPerGroup[0], maxSfbPerGroup[1]);
383956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
384b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
385956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (psyData[0].blockSwitchingControl.windowSequence != SHORT_WINDOW)
386956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      MsStereoProcessing(psyData[0].sfbEnergy.sfbLong,
387956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         psyData[1].sfbEnergy.sfbLong,
388956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         psyData[0].sfbEnergyMS.sfbLong,
389956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         psyData[1].sfbEnergyMS.sfbLong,
390956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         psyData[0].mdctSpectrum,
391956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         psyData[1].mdctSpectrum,
392956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         psyData[0].sfbThreshold.sfbLong,
393956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         psyData[1].sfbThreshold.sfbLong,
394956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         psyData[0].sfbSpreadedEnergy.sfbLong,
395956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         psyData[1].sfbSpreadedEnergy.sfbLong,
396956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         (Word16*)&psyOutElement->toolsInfo.msDigest,
397956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         (Word16*)psyOutElement->toolsInfo.msMask,
398956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         hPsyConfLong->sfbCnt,
399956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         hPsyConfLong->sfbCnt,
400956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         maxSfbPerGroup[0],
401956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         (const Word16*)hPsyConfLong->sfbOffset);
402956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      else
403956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        MsStereoProcessing(psyData[0].sfbEnergy.sfbLong,
404956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           psyData[1].sfbEnergy.sfbLong,
405956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           psyData[0].sfbEnergyMS.sfbLong,
406956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           psyData[1].sfbEnergyMS.sfbLong,
407956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           psyData[0].mdctSpectrum,
408956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           psyData[1].mdctSpectrum,
409956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           psyData[0].sfbThreshold.sfbLong,
410956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           psyData[1].sfbThreshold.sfbLong,
411956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           psyData[0].sfbSpreadedEnergy.sfbLong,
412956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           psyData[1].sfbSpreadedEnergy.sfbLong,
413956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           (Word16*)&psyOutElement->toolsInfo.msDigest,
414956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           (Word16*)psyOutElement->toolsInfo.msMask,
415956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           psyData[0].blockSwitchingControl.noOfGroups*hPsyConfShort->sfbCnt,
416956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           hPsyConfShort->sfbCnt,
417956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           maxSfbPerGroup[0],
418956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           (const Word16*)psyOutElement->groupedSfbOffset[0]);
419956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
420956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
421956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#endif /* (MAX_CHANNELS>1) */
422956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
423956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /*
424956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    build output
425956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  */
426956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for(ch=0;ch<channels;ch++) {
427b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
428956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (psyData[ch].blockSwitchingControl.windowSequence != SHORT_WINDOW)
429956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      BuildInterface(psyData[ch].mdctSpectrum,
430956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].mdctScale,
431956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[ch].sfbThreshold,
432956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[ch].sfbEnergy,
433956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[ch].sfbSpreadedEnergy,
434956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].sfbEnergySum,
435956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].sfbEnergySumMS,
436956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].blockSwitchingControl.windowSequence,
437956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     blockType2windowShape[psyData[ch].blockSwitchingControl.windowSequence],
438956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     hPsyConfLong->sfbCnt,
439956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     hPsyConfLong->sfbOffset,
440956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     maxSfbPerGroup[ch],
441956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     hPsyConfLong->sfbMinSnr,
442956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].blockSwitchingControl.noOfGroups,
443956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].blockSwitchingControl.groupLen,
444956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyOutChannel[ch]);
445956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    else
446956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      BuildInterface(psyData[ch].mdctSpectrum,
447956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].mdctScale,
448956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[ch].sfbThreshold,
449956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[ch].sfbEnergy,
450956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[ch].sfbSpreadedEnergy,
451956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].sfbEnergySum,
452956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].sfbEnergySumMS,
453956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     SHORT_WINDOW,
454956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     SINE_WINDOW,
455956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[0].blockSwitchingControl.noOfGroups*hPsyConfShort->sfbCnt,
456956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyOutElement->groupedSfbOffset[ch],
457956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     maxSfbPerGroup[ch],
458956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyOutElement->groupedSfbMinSnr[ch],
459956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].blockSwitchingControl.noOfGroups,
460956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[ch].blockSwitchingControl.groupLen,
461956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyOutChannel[ch]);
462956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
463956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
464956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return(0); /* no error */
465956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
466956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
467956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
468956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
469956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: advancePsychLong
470956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  psychoacoustic for long blocks
471956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
472956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
473956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
474956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 advancePsychLong(PSY_DATA* psyData,
475956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               TNS_DATA* tnsData,
476956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               PSY_CONFIGURATION_LONG *hPsyConfLong,
477956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               PSY_OUT_CHANNEL* psyOutChannel,
478956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               Word32 *pScratchTns,
479956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               const TNS_DATA* tnsData2,
480956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               const Word16 ch)
481956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
482956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 i;
483956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 normEnergyShift = (psyData->mdctScale + 1) << 1; /* in reference code, mdct spectrum must be multipied with 2, so +1 */
484e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  Word32 clipEnergy = hPsyConfLong->clipEnergy >> normEnergyShift;
485956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 *data0, *data1, tdata;
486956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
487956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* low pass */
488e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  data0 = psyData->mdctSpectrum + hPsyConfLong->lowpassLine;
489956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for(i=hPsyConfLong->lowpassLine; i<FRAME_LEN_LONG; i++) {
490b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    *data0++ = 0;
491956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
492956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
493956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* Calc sfb-bandwise mdct-energies for left and right channel */
494956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  CalcBandEnergy( psyData->mdctSpectrum,
495956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                  hPsyConfLong->sfbOffset,
496956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                  hPsyConfLong->sfbActive,
497956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                  psyData->sfbEnergy.sfbLong,
498956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                  &psyData->sfbEnergySum.sfbLong);
499956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
500956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /*
501956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    TNS detect
502956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  */
503956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  TnsDetect(tnsData,
504956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            hPsyConfLong->tnsConf,
505956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            pScratchTns,
506956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            (const Word16*)hPsyConfLong->sfbOffset,
507956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            psyData->mdctSpectrum,
508956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            0,
509956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            psyData->blockSwitchingControl.windowSequence,
510956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            psyData->sfbEnergy.sfbLong);
511956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
512b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  /*  TnsSync */
513956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (ch == 1) {
514956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    TnsSync(tnsData,
515956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            tnsData2,
516956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            hPsyConfLong->tnsConf,
517956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            0,
518956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            psyData->blockSwitchingControl.windowSequence);
519956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
520956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
521b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  /*  Tns Encoder */
522956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  TnsEncode(&psyOutChannel->tnsInfo,
523956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            tnsData,
524956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            hPsyConfLong->sfbCnt,
525956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            hPsyConfLong->tnsConf,
526956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            hPsyConfLong->lowpassLine,
527956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            psyData->mdctSpectrum,
528956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            0,
529956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            psyData->blockSwitchingControl.windowSequence);
530956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
531956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* first part of threshold calculation */
532e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  data0 = psyData->sfbEnergy.sfbLong;
533e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  data1 = psyData->sfbThreshold.sfbLong;
534956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for (i=hPsyConfLong->sfbCnt; i; i--) {
535956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    tdata = L_mpy_ls(*data0++, hPsyConfLong->ratio);
536e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    *data1++ = min(tdata, clipEnergy);
537956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
538956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
539b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  /* Calc sfb-bandwise mdct-energies for left and right channel again */
540956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive!=0) {
541b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    Word16 tnsStartBand = hPsyConfLong->tnsConf.tnsStartBand;
542956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    CalcBandEnergy( psyData->mdctSpectrum,
543956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    hPsyConfLong->sfbOffset+tnsStartBand,
544956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    hPsyConfLong->sfbActive - tnsStartBand,
545956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    psyData->sfbEnergy.sfbLong+tnsStartBand,
546956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    &psyData->sfbEnergySum.sfbLong);
547b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
548e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	data0 = psyData->sfbEnergy.sfbLong;
549e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	tdata = psyData->sfbEnergySum.sfbLong;
550956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	for (i=0; i<tnsStartBand; i++)
551e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard      tdata += *data0++;
552e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
553956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	psyData->sfbEnergySum.sfbLong = tdata;
554956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
555956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
556956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
557956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* spreading energy */
558956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  SpreadingMax(hPsyConfLong->sfbCnt,
559956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               hPsyConfLong->sfbMaskLowFactor,
560956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               hPsyConfLong->sfbMaskHighFactor,
561956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               psyData->sfbThreshold.sfbLong);
562956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
563956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* threshold in quiet */
564e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  data0 = psyData->sfbThreshold.sfbLong;
565e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  data1 = hPsyConfLong->sfbThresholdQuiet;
566956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for (i=hPsyConfLong->sfbCnt; i; i--)
567e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  {
568e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  *data0 = max(*data0, (*data1 >> normEnergyShift));
569e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  data0++; data1++;
570956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
571956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
572b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  /* preecho control */
573956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (psyData->blockSwitchingControl.windowSequence == STOP_WINDOW) {
574e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    data0 = psyData->sfbThresholdnm1;
575e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	for (i=hPsyConfLong->sfbCnt; i; i--) {
576b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      *data0++ = MAX_32;
577e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    }
578b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    psyData->mdctScalenm1 = 0;
579956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
580956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
581956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  PreEchoControl( psyData->sfbThresholdnm1,
582956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                  hPsyConfLong->sfbCnt,
583956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                  hPsyConfLong->maxAllowedIncreaseFactor,
584956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                  hPsyConfLong->minRemainingThresholdFactor,
585956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                  psyData->sfbThreshold.sfbLong,
586956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                  psyData->mdctScale,
587956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                  psyData->mdctScalenm1);
588b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  psyData->mdctScalenm1 = psyData->mdctScale;
589b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
590956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
591956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (psyData->blockSwitchingControl.windowSequence== START_WINDOW) {
592e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    data0 = psyData->sfbThresholdnm1;
593956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	for (i=hPsyConfLong->sfbCnt; i; i--) {
594b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      *data0++ = MAX_32;
595956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
596b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    psyData->mdctScalenm1 = 0;
597956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
598956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
599956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* apply tns mult table on cb thresholds */
600956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  ApplyTnsMultTableToRatios(hPsyConfLong->tnsConf.tnsRatioPatchLowestCb,
601956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                            hPsyConfLong->tnsConf.tnsStartBand,
602956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                            tnsData->dataRaw.tnsLong.subBlockInfo,
603956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                            psyData->sfbThreshold.sfbLong);
604956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
605956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
606956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* spreaded energy */
607e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  data0 = psyData->sfbSpreadedEnergy.sfbLong;
608e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  data1 = psyData->sfbEnergy.sfbLong;
609956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for (i=hPsyConfLong->sfbCnt; i; i--) {
610b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    //psyData->sfbSpreadedEnergy.sfbLong[i] = psyData->sfbEnergy.sfbLong[i];
611956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  *data0++ = *data1++;
612956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
613956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
614956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* spreading energy */
615956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  SpreadingMax(hPsyConfLong->sfbCnt,
616b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard               hPsyConfLong->sfbMaskLowFactorSprEn,
617956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               hPsyConfLong->sfbMaskHighFactorSprEn,
618956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong               psyData->sfbSpreadedEnergy.sfbLong);
619956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
620956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return 0;
621956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
622956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
623956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
624956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
625956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: advancePsychLongMS
626b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard* description:   update mdct-energies for left add or minus right channel
627956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*				for long block
628956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
629956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
630956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 advancePsychLongMS (PSY_DATA psyData[MAX_CHANNELS],
631956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                  const PSY_CONFIGURATION_LONG *hPsyConfLong)
632956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
633956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  CalcBandEnergyMS(psyData[0].mdctSpectrum,
634956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   psyData[1].mdctSpectrum,
635956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   hPsyConfLong->sfbOffset,
636956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   hPsyConfLong->sfbActive,
637956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   psyData[0].sfbEnergyMS.sfbLong,
638956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   &psyData[0].sfbEnergySumMS.sfbLong,
639956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   psyData[1].sfbEnergyMS.sfbLong,
640956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   &psyData[1].sfbEnergySumMS.sfbLong);
641956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
642956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return 0;
643956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
644956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
645956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
646956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
647956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
648956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: advancePsychShort
649956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  psychoacoustic for short blocks
650956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
651956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
652956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
653956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 advancePsychShort(PSY_DATA* psyData,
654956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                TNS_DATA* tnsData,
655956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                const PSY_CONFIGURATION_SHORT *hPsyConfShort,
656956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                PSY_OUT_CHANNEL* psyOutChannel,
657956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                Word32 *pScratchTns,
658956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                const TNS_DATA *tnsData2,
659956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                const Word16 ch)
660956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
661956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 w;
662956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 normEnergyShift = (psyData->mdctScale + 1) << 1; /* in reference code, mdct spectrum must be multipied with 2, so +1 */
663956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 clipEnergy = hPsyConfShort->clipEnergy >> normEnergyShift;
664b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  Word32 wOffset = 0;
6659fc4dfb69df0b5a13b7a1904272eb1dcf8113d0cMartin Storsjo  Word32 *data0;
6669fc4dfb69df0b5a13b7a1904272eb1dcf8113d0cMartin Storsjo  const Word32 *data1;
667956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
668956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for(w = 0; w < TRANS_FAC; w++) {
669956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    Word32 i, tdata;
670956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
671956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /* low pass */
672e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    data0 = psyData->mdctSpectrum + wOffset + hPsyConfShort->lowpassLine;
673956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	for(i=hPsyConfShort->lowpassLine; i<FRAME_LEN_SHORT; i++){
674b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      *data0++ = 0;
675956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
676956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
677956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /* Calc sfb-bandwise mdct-energies for left and right channel */
678956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    CalcBandEnergy( psyData->mdctSpectrum+wOffset,
679956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    hPsyConfShort->sfbOffset,
680956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    hPsyConfShort->sfbActive,
681956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    psyData->sfbEnergy.sfbShort[w],
682956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    &psyData->sfbEnergySum.sfbShort[w]);
683956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /*
684956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong       TNS
685956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    */
686956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    TnsDetect(tnsData,
687956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              hPsyConfShort->tnsConf,
688956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              pScratchTns,
689956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              (const Word16*)hPsyConfShort->sfbOffset,
690956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              psyData->mdctSpectrum+wOffset,
691956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              w,
692956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              psyData->blockSwitchingControl.windowSequence,
693956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              psyData->sfbEnergy.sfbShort[w]);
694956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
695956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /*  TnsSync */
696956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (ch == 1) {
697956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      TnsSync(tnsData,
698956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              tnsData2,
699956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              hPsyConfShort->tnsConf,
700956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              w,
701956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              psyData->blockSwitchingControl.windowSequence);
702956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
703956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
704956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    TnsEncode(&psyOutChannel->tnsInfo,
705956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              tnsData,
706956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              hPsyConfShort->sfbCnt,
707956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              hPsyConfShort->tnsConf,
708956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              hPsyConfShort->lowpassLine,
709956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              psyData->mdctSpectrum+wOffset,
710956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              w,
711956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              psyData->blockSwitchingControl.windowSequence);
712956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
713956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /* first part of threshold calculation */
714e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    data0 = psyData->sfbThreshold.sfbShort[w];
715e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	data1 = psyData->sfbEnergy.sfbShort[w];
716956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	for (i=hPsyConfShort->sfbCnt; i; i--) {
717956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      tdata = L_mpy_ls(*data1++, hPsyConfShort->ratio);
718e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard      *data0++ = min(tdata, clipEnergy);
719956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
720956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
721b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    /* Calc sfb-bandwise mdct-energies for left and right channel again */
722956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (tnsData->dataRaw.tnsShort.subBlockInfo[w].tnsActive != 0) {
723b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      Word16 tnsStartBand = hPsyConfShort->tnsConf.tnsStartBand;
724956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      CalcBandEnergy( psyData->mdctSpectrum+wOffset,
725956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                      hPsyConfShort->sfbOffset+tnsStartBand,
726956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                      (hPsyConfShort->sfbActive - tnsStartBand),
727956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                      psyData->sfbEnergy.sfbShort[w]+tnsStartBand,
728e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard                      &psyData->sfbEnergySum.sfbShort[w]);
729956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
730e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard      tdata = psyData->sfbEnergySum.sfbShort[w];
731e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  data0 = psyData->sfbEnergy.sfbShort[w];
732956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  for (i=tnsStartBand; i; i--)
733e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        tdata += *data0++;
734e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
735956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  psyData->sfbEnergySum.sfbShort[w] = tdata;
736956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
737956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
738956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /* spreading */
739956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    SpreadingMax(hPsyConfShort->sfbCnt,
740956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 hPsyConfShort->sfbMaskLowFactor,
741956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 hPsyConfShort->sfbMaskHighFactor,
742956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 psyData->sfbThreshold.sfbShort[w]);
743956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
744956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
745956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /* threshold in quiet */
746e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    data0 = psyData->sfbThreshold.sfbShort[w];
747e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	data1 = hPsyConfShort->sfbThresholdQuiet;
748956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	for (i=hPsyConfShort->sfbCnt; i; i--)
749e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    {
750e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		*data0 = max(*data0, (*data1 >> normEnergyShift));
751e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
752e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		data0++; data1++;
753e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	}
754956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
755956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
756b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    /* preecho */
757956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    PreEchoControl( psyData->sfbThresholdnm1,
758956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    hPsyConfShort->sfbCnt,
759956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    hPsyConfShort->maxAllowedIncreaseFactor,
760956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    hPsyConfShort->minRemainingThresholdFactor,
761956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    psyData->sfbThreshold.sfbShort[w],
762956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    psyData->mdctScale,
763956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    w==0 ? psyData->mdctScalenm1 : psyData->mdctScale);
764956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
765956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /* apply tns mult table on cb thresholds */
766956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    ApplyTnsMultTableToRatios( hPsyConfShort->tnsConf.tnsRatioPatchLowestCb,
767956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               hPsyConfShort->tnsConf.tnsStartBand,
768956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               tnsData->dataRaw.tnsShort.subBlockInfo[w],
769956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               psyData->sfbThreshold.sfbShort[w]);
770956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
771956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /* spreaded energy */
772e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    data0 = psyData->sfbSpreadedEnergy.sfbShort[w];
773e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	data1 = psyData->sfbEnergy.sfbShort[w];
774956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	for (i=hPsyConfShort->sfbCnt; i; i--) {
775956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  *data0++ = *data1++;
776956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
777956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    SpreadingMax(hPsyConfShort->sfbCnt,
778b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard                 hPsyConfShort->sfbMaskLowFactorSprEn,
779956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 hPsyConfShort->sfbMaskHighFactorSprEn,
780956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 psyData->sfbSpreadedEnergy.sfbShort[w]);
781956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
782956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    wOffset += FRAME_LEN_SHORT;
783956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  } /* for TRANS_FAC */
784956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
785b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  psyData->mdctScalenm1 = psyData->mdctScale;
786956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
787956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return 0;
788956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
789956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
790956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
791956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
792956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: advancePsychShortMS
793b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard* description:   update mdct-energies for left add or minus right channel
794956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*				for short block
795956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
796956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
797956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 advancePsychShortMS (PSY_DATA psyData[MAX_CHANNELS],
798956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                   const PSY_CONFIGURATION_SHORT *hPsyConfShort)
799956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
800956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 w, wOffset;
801b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  wOffset = 0;
802956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for(w=0; w<TRANS_FAC; w++) {
803956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    CalcBandEnergyMS(psyData[0].mdctSpectrum+wOffset,
804956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[1].mdctSpectrum+wOffset,
805956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     hPsyConfShort->sfbOffset,
806956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     hPsyConfShort->sfbActive,
807956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[0].sfbEnergyMS.sfbShort[w],
808956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[0].sfbEnergySumMS.sfbShort[w],
809956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     psyData[1].sfbEnergyMS.sfbShort[w],
810956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                     &psyData[1].sfbEnergySumMS.sfbShort[w]);
811956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    wOffset += FRAME_LEN_SHORT;
812956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
813956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
814956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return 0;
815956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
816