Coverage Report

Created: 2024-06-17 06:33

/src/aac/libAACenc/src/psy_main.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -----------------------------------------------------------------------------
2
Software License for The Fraunhofer FDK AAC Codec Library for Android
3
4
© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
5
Forschung e.V. All rights reserved.
6
7
 1.    INTRODUCTION
8
The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9
that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10
scheme for digital audio. This FDK AAC Codec software is intended to be used on
11
a wide variety of Android devices.
12
13
AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14
general perceptual audio codecs. AAC-ELD is considered the best-performing
15
full-bandwidth communications codec by independent studies and is widely
16
deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17
specifications.
18
19
Patent licenses for necessary patent claims for the FDK AAC Codec (including
20
those of Fraunhofer) may be obtained through Via Licensing
21
(www.vialicensing.com) or through the respective patent owners individually for
22
the purpose of encoding or decoding bit streams in products that are compliant
23
with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24
Android devices already license these patent claims through Via Licensing or
25
directly from the patent owners, and therefore FDK AAC Codec software may
26
already be covered under those patent licenses when it is used for those
27
licensed purposes only.
28
29
Commercially-licensed AAC software libraries, including floating-point versions
30
with enhanced sound quality, are also available from Fraunhofer. Users are
31
encouraged to check the Fraunhofer website for additional applications
32
information and documentation.
33
34
2.    COPYRIGHT LICENSE
35
36
Redistribution and use in source and binary forms, with or without modification,
37
are permitted without payment of copyright license fees provided that you
38
satisfy the following conditions:
39
40
You must retain the complete text of this software license in redistributions of
41
the FDK AAC Codec or your modifications thereto in source code form.
42
43
You must retain the complete text of this software license in the documentation
44
and/or other materials provided with redistributions of the FDK AAC Codec or
45
your modifications thereto in binary form. You must make available free of
46
charge copies of the complete source code of the FDK AAC Codec and your
47
modifications thereto to recipients of copies in binary form.
48
49
The name of Fraunhofer may not be used to endorse or promote products derived
50
from this library without prior written permission.
51
52
You may not charge copyright license fees for anyone to use, copy or distribute
53
the FDK AAC Codec software or your modifications thereto.
54
55
Your modified versions of the FDK AAC Codec must carry prominent notices stating
56
that you changed the software and the date of any change. For modified versions
57
of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58
must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59
AAC Codec Library for Android."
60
61
3.    NO PATENT LICENSE
62
63
NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64
limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65
Fraunhofer provides no warranty of patent non-infringement with respect to this
66
software.
67
68
You may use this FDK AAC Codec software or modifications thereto only for
69
purposes that are authorized by appropriate patent licenses.
70
71
4.    DISCLAIMER
72
73
This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74
holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75
including but not limited to the implied warranties of merchantability and
76
fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77
CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78
or consequential damages, including but not limited to procurement of substitute
79
goods or services; loss of use, data, or profits, or business interruption,
80
however caused and on any theory of liability, whether in contract, strict
81
liability, or tort (including negligence), arising in any way out of the use of
82
this software, even if advised of the possibility of such damage.
83
84
5.    CONTACT INFORMATION
85
86
Fraunhofer Institute for Integrated Circuits IIS
87
Attention: Audio and Multimedia Departments - FDK AAC LL
88
Am Wolfsmantel 33
89
91058 Erlangen, Germany
90
91
www.iis.fraunhofer.de/amm
92
amm-info@iis.fraunhofer.de
93
----------------------------------------------------------------------------- */
94
95
/**************************** AAC encoder library ******************************
96
97
   Author(s):   M.Werner
98
99
   Description: Psychoaccoustic major function block
100
101
*******************************************************************************/
102
103
#include "psy_const.h"
104
105
#include "block_switch.h"
106
#include "transform.h"
107
#include "spreading.h"
108
#include "pre_echo_control.h"
109
#include "band_nrg.h"
110
#include "psy_configuration.h"
111
#include "psy_data.h"
112
#include "ms_stereo.h"
113
#include "interface.h"
114
#include "psy_main.h"
115
#include "grp_data.h"
116
#include "tns_func.h"
117
#include "pns_func.h"
118
#include "tonality.h"
119
#include "aacEnc_ram.h"
120
#include "intensity.h"
121
122
/* blending to reduce gibbs artifacts */
123
0
#define FADE_OUT_LEN 6
124
static const FIXP_DBL fadeOutFactor[FADE_OUT_LEN] = {
125
    1840644096, 1533870080, 1227096064, 920322048, 613548032, 306774016};
126
127
/* forward definitions */
128
129
/*****************************************************************************
130
131
    functionname: FDKaacEnc_PsyNew
132
    description:  allocates memory for psychoacoustic
133
    returns:      an error code
134
    input:        pointer to a psych handle
135
136
*****************************************************************************/
137
AAC_ENCODER_ERROR FDKaacEnc_PsyNew(PSY_INTERNAL **phpsy, const INT nElements,
138
0
                                   const INT nChannels, UCHAR *dynamic_RAM) {
139
0
  AAC_ENCODER_ERROR ErrorStatus;
140
0
  PSY_INTERNAL *hPsy;
141
0
  INT i;
142
143
0
  hPsy = GetRam_aacEnc_PsyInternal();
144
0
  *phpsy = hPsy;
145
0
  if (hPsy == NULL) {
146
0
    ErrorStatus = AAC_ENC_NO_MEMORY;
147
0
    goto bail;
148
0
  }
149
150
0
  for (i = 0; i < nElements; i++) {
151
    /* PSY_ELEMENT */
152
0
    hPsy->psyElement[i] = GetRam_aacEnc_PsyElement(i);
153
0
    if (hPsy->psyElement[i] == NULL) {
154
0
      ErrorStatus = AAC_ENC_NO_MEMORY;
155
0
      goto bail;
156
0
    }
157
0
  }
158
159
0
  for (i = 0; i < nChannels; i++) {
160
    /* PSY_STATIC */
161
0
    hPsy->pStaticChannels[i] = GetRam_aacEnc_PsyStatic(i);
162
0
    if (hPsy->pStaticChannels[i] == NULL) {
163
0
      ErrorStatus = AAC_ENC_NO_MEMORY;
164
0
      goto bail;
165
0
    }
166
    /* AUDIO INPUT BUFFER */
167
0
    hPsy->pStaticChannels[i]->psyInputBuffer = GetRam_aacEnc_PsyInputBuffer(i);
168
0
    if (hPsy->pStaticChannels[i]->psyInputBuffer == NULL) {
169
0
      ErrorStatus = AAC_ENC_NO_MEMORY;
170
0
      goto bail;
171
0
    }
172
0
  }
173
174
  /* reusable psych memory */
175
0
  hPsy->psyDynamic = GetRam_aacEnc_PsyDynamic(0, dynamic_RAM);
176
177
0
  return AAC_ENC_OK;
178
179
0
bail:
180
0
  FDKaacEnc_PsyClose(phpsy, NULL);
181
182
0
  return ErrorStatus;
183
0
}
184
185
/*****************************************************************************
186
187
    functionname: FDKaacEnc_PsyOutNew
188
    description:  allocates memory for psyOut struc
189
    returns:      an error code
190
    input:        pointer to a psych handle
191
192
*****************************************************************************/
193
AAC_ENCODER_ERROR FDKaacEnc_PsyOutNew(PSY_OUT **phpsyOut, const INT nElements,
194
                                      const INT nChannels, const INT nSubFrames,
195
0
                                      UCHAR *dynamic_RAM) {
196
0
  AAC_ENCODER_ERROR ErrorStatus;
197
0
  int n, i;
198
0
  int elInc = 0, chInc = 0;
199
200
0
  for (n = 0; n < nSubFrames; n++) {
201
0
    phpsyOut[n] = GetRam_aacEnc_PsyOut(n);
202
203
0
    if (phpsyOut[n] == NULL) {
204
0
      ErrorStatus = AAC_ENC_NO_MEMORY;
205
0
      goto bail;
206
0
    }
207
208
0
    for (i = 0; i < nChannels; i++) {
209
0
      phpsyOut[n]->pPsyOutChannels[i] = GetRam_aacEnc_PsyOutChannel(chInc++);
210
0
      if (NULL == phpsyOut[n]->pPsyOutChannels[i]) {
211
0
        ErrorStatus = AAC_ENC_NO_MEMORY;
212
0
        goto bail;
213
0
      }
214
0
    }
215
216
0
    for (i = 0; i < nElements; i++) {
217
0
      phpsyOut[n]->psyOutElement[i] = GetRam_aacEnc_PsyOutElements(elInc++);
218
0
      if (phpsyOut[n]->psyOutElement[i] == NULL) {
219
0
        ErrorStatus = AAC_ENC_NO_MEMORY;
220
0
        goto bail;
221
0
      }
222
0
    }
223
0
  } /* nSubFrames */
224
225
0
  return AAC_ENC_OK;
226
227
0
bail:
228
0
  FDKaacEnc_PsyClose(NULL, phpsyOut);
229
0
  return ErrorStatus;
230
0
}
231
232
AAC_ENCODER_ERROR FDKaacEnc_psyInitStates(PSY_INTERNAL *hPsy,
233
                                          PSY_STATIC *psyStatic,
234
0
                                          AUDIO_OBJECT_TYPE audioObjectType) {
235
  /* init input buffer */
236
0
  FDKmemclear(psyStatic->psyInputBuffer,
237
0
              MAX_INPUT_BUFFER_SIZE * sizeof(INT_PCM));
238
239
0
  FDKaacEnc_InitBlockSwitching(&psyStatic->blockSwitchingControl,
240
0
                               isLowDelay(audioObjectType));
241
242
0
  return AAC_ENC_OK;
243
0
}
244
245
AAC_ENCODER_ERROR FDKaacEnc_psyInit(PSY_INTERNAL *hPsy, PSY_OUT **phpsyOut,
246
                                    const INT nSubFrames,
247
                                    const INT nMaxChannels,
248
                                    const AUDIO_OBJECT_TYPE audioObjectType,
249
0
                                    CHANNEL_MAPPING *cm) {
250
0
  AAC_ENCODER_ERROR ErrorStatus = AAC_ENC_OK;
251
0
  int i, ch, n, chInc = 0, resetChannels = 3;
252
253
0
  if ((nMaxChannels > 2) && (cm->nChannels == 2)) {
254
0
    chInc = 1;
255
0
    FDKaacEnc_psyInitStates(hPsy, hPsy->pStaticChannels[0], audioObjectType);
256
0
  }
257
258
0
  if ((nMaxChannels == 2)) {
259
0
    resetChannels = 0;
260
0
  }
261
262
0
  for (i = 0; i < cm->nElements; i++) {
263
0
    for (ch = 0; ch < cm->elInfo[i].nChannelsInEl; ch++) {
264
0
      hPsy->psyElement[i]->psyStatic[ch] = hPsy->pStaticChannels[chInc];
265
0
      if (cm->elInfo[i].elType != ID_LFE) {
266
0
        if (chInc >= resetChannels) {
267
0
          FDKaacEnc_psyInitStates(hPsy, hPsy->psyElement[i]->psyStatic[ch],
268
0
                                  audioObjectType);
269
0
        }
270
0
        mdct_init(&(hPsy->psyElement[i]->psyStatic[ch]->mdctPers), NULL, 0);
271
0
        hPsy->psyElement[i]->psyStatic[ch]->isLFE = 0;
272
0
      } else {
273
0
        hPsy->psyElement[i]->psyStatic[ch]->isLFE = 1;
274
0
      }
275
0
      chInc++;
276
0
    }
277
0
  }
278
279
0
  for (n = 0; n < nSubFrames; n++) {
280
0
    chInc = 0;
281
0
    for (i = 0; i < cm->nElements; i++) {
282
0
      for (ch = 0; ch < cm->elInfo[i].nChannelsInEl; ch++) {
283
0
        phpsyOut[n]->psyOutElement[i]->psyOutChannel[ch] =
284
0
            phpsyOut[n]->pPsyOutChannels[chInc++];
285
0
      }
286
0
    }
287
0
  }
288
289
0
  return ErrorStatus;
290
0
}
291
292
/*****************************************************************************
293
294
    functionname: FDKaacEnc_psyMainInit
295
    description:  initializes psychoacoustic
296
    returns:      an error code
297
298
*****************************************************************************/
299
300
AAC_ENCODER_ERROR FDKaacEnc_psyMainInit(
301
    PSY_INTERNAL *hPsy, AUDIO_OBJECT_TYPE audioObjectType, CHANNEL_MAPPING *cm,
302
    INT sampleRate, INT granuleLength, INT bitRate, INT tnsMask, INT bandwidth,
303
0
    INT usePns, INT useIS, INT useMS, UINT syntaxFlags, ULONG initFlags) {
304
0
  AAC_ENCODER_ERROR ErrorStatus;
305
0
  int i, ch;
306
0
  int channelsEff = cm->nChannelsEff;
307
0
  int tnsChannels = 0;
308
0
  FB_TYPE filterBank;
309
310
0
  switch (FDKaacEnc_GetMonoStereoMode(cm->encMode)) {
311
    /* ... and map to tnsChannels */
312
0
    case EL_MODE_MONO:
313
0
      tnsChannels = 1;
314
0
      break;
315
0
    case EL_MODE_STEREO:
316
0
      tnsChannels = 2;
317
0
      break;
318
0
    default:
319
0
      tnsChannels = 0;
320
0
  }
321
322
0
  switch (audioObjectType) {
323
0
    default:
324
0
      filterBank = FB_LC;
325
0
      break;
326
0
    case AOT_ER_AAC_LD:
327
0
      filterBank = FB_LD;
328
0
      break;
329
0
    case AOT_ER_AAC_ELD:
330
0
      filterBank = FB_ELD;
331
0
      break;
332
0
  }
333
334
0
  hPsy->granuleLength = granuleLength;
335
336
0
  ErrorStatus = FDKaacEnc_InitPsyConfiguration(
337
0
      bitRate / channelsEff, sampleRate, bandwidth, LONG_WINDOW,
338
0
      hPsy->granuleLength, useIS, useMS, &(hPsy->psyConf[0]), filterBank);
339
0
  if (ErrorStatus != AAC_ENC_OK) return ErrorStatus;
340
341
0
  ErrorStatus = FDKaacEnc_InitTnsConfiguration(
342
0
      (bitRate * tnsChannels) / channelsEff, sampleRate, tnsChannels,
343
0
      LONG_WINDOW, hPsy->granuleLength, isLowDelay(audioObjectType),
344
0
      (syntaxFlags & AC_SBR_PRESENT) ? 1 : 0, &(hPsy->psyConf[0].tnsConf),
345
0
      &hPsy->psyConf[0], (INT)(tnsMask & 2), (INT)(tnsMask & 8));
346
347
0
  if (ErrorStatus != AAC_ENC_OK) return ErrorStatus;
348
349
0
  if (granuleLength > 512) {
350
0
    ErrorStatus = FDKaacEnc_InitPsyConfiguration(
351
0
        bitRate / channelsEff, sampleRate, bandwidth, SHORT_WINDOW,
352
0
        hPsy->granuleLength, useIS, useMS, &hPsy->psyConf[1], filterBank);
353
354
0
    if (ErrorStatus != AAC_ENC_OK) return ErrorStatus;
355
356
0
    ErrorStatus = FDKaacEnc_InitTnsConfiguration(
357
0
        (bitRate * tnsChannels) / channelsEff, sampleRate, tnsChannels,
358
0
        SHORT_WINDOW, hPsy->granuleLength, isLowDelay(audioObjectType),
359
0
        (syntaxFlags & AC_SBR_PRESENT) ? 1 : 0, &hPsy->psyConf[1].tnsConf,
360
0
        &hPsy->psyConf[1], (INT)(tnsMask & 1), (INT)(tnsMask & 4));
361
362
0
    if (ErrorStatus != AAC_ENC_OK) return ErrorStatus;
363
0
  }
364
365
0
  for (i = 0; i < cm->nElements; i++) {
366
0
    for (ch = 0; ch < cm->elInfo[i].nChannelsInEl; ch++) {
367
0
      if (initFlags) {
368
        /* reset states */
369
0
        FDKaacEnc_psyInitStates(hPsy, hPsy->psyElement[i]->psyStatic[ch],
370
0
                                audioObjectType);
371
0
      }
372
373
0
      FDKaacEnc_InitPreEchoControl(
374
0
          hPsy->psyElement[i]->psyStatic[ch]->sfbThresholdnm1,
375
0
          &hPsy->psyElement[i]->psyStatic[ch]->calcPreEcho,
376
0
          hPsy->psyConf[0].sfbCnt, hPsy->psyConf[0].sfbPcmQuantThreshold,
377
0
          &hPsy->psyElement[i]->psyStatic[ch]->mdctScalenm1);
378
0
    }
379
0
  }
380
381
0
  ErrorStatus = FDKaacEnc_InitPnsConfiguration(
382
0
      &hPsy->psyConf[0].pnsConf, bitRate / channelsEff, sampleRate, usePns,
383
0
      hPsy->psyConf[0].sfbCnt, hPsy->psyConf[0].sfbOffset,
384
0
      cm->elInfo[0].nChannelsInEl, (hPsy->psyConf[0].filterbank == FB_LC));
385
0
  if (ErrorStatus != AAC_ENC_OK) return ErrorStatus;
386
387
0
  if (granuleLength > 512) {
388
0
    ErrorStatus = FDKaacEnc_InitPnsConfiguration(
389
0
        &hPsy->psyConf[1].pnsConf, bitRate / channelsEff, sampleRate, usePns,
390
0
        hPsy->psyConf[1].sfbCnt, hPsy->psyConf[1].sfbOffset,
391
0
        cm->elInfo[1].nChannelsInEl, (hPsy->psyConf[1].filterbank == FB_LC));
392
0
    if (ErrorStatus != AAC_ENC_OK) return ErrorStatus;
393
0
  }
394
395
0
  return ErrorStatus;
396
0
}
397
398
/*****************************************************************************
399
400
    functionname: FDKaacEnc_psyMain
401
    description:  psychoacoustic
402
    returns:      an error code
403
404
        This function assumes that enough input data is in the modulo buffer.
405
406
*****************************************************************************/
407
AAC_ENCODER_ERROR FDKaacEnc_psyMain(INT channels, PSY_ELEMENT *psyElement,
408
                                    PSY_DYNAMIC *psyDynamic,
409
                                    PSY_CONFIGURATION *psyConf,
410
                                    PSY_OUT_ELEMENT *RESTRICT psyOutElement,
411
                                    INT_PCM *pInput, const UINT inputBufSize,
412
0
                                    INT *chIdx, INT totalChannels) {
413
0
  const INT commonWindow = 1;
414
0
  INT maxSfbPerGroup[(2)];
415
0
  INT mdctSpectrum_e;
416
0
  INT ch;   /* counts through channels          */
417
0
  INT w;    /* counts through windows           */
418
0
  INT sfb;  /* counts through scalefactor bands */
419
0
  INT line; /* counts through lines             */
420
421
0
  PSY_CONFIGURATION *RESTRICT hPsyConfLong = &psyConf[0];
422
0
  PSY_CONFIGURATION *RESTRICT hPsyConfShort = &psyConf[1];
423
0
  PSY_OUT_CHANNEL **RESTRICT psyOutChannel = psyOutElement->psyOutChannel;
424
0
  FIXP_SGL sfbTonality[(2)][MAX_SFB_LONG];
425
426
0
  PSY_STATIC **RESTRICT psyStatic = psyElement->psyStatic;
427
428
0
  PSY_DATA *RESTRICT psyData[(2)];
429
0
  TNS_DATA *RESTRICT tnsData[(2)];
430
0
  PNS_DATA *RESTRICT pnsData[(2)];
431
432
0
  INT zeroSpec = TRUE; /* means all spectral lines are zero */
433
434
0
  INT blockSwitchingOffset;
435
436
0
  PSY_CONFIGURATION *RESTRICT hThisPsyConf[(2)];
437
0
  INT windowLength[(2)];
438
0
  INT nWindows[(2)];
439
0
  INT wOffset;
440
441
0
  INT maxSfb[(2)];
442
0
  INT *pSfbMaxScaleSpec[(2)];
443
0
  FIXP_DBL *pSfbEnergy[(2)];
444
0
  FIXP_DBL *pSfbSpreadEnergy[(2)];
445
0
  FIXP_DBL *pSfbEnergyLdData[(2)];
446
0
  FIXP_DBL *pSfbEnergyMS[(2)];
447
0
  FIXP_DBL *pSfbThreshold[(2)];
448
449
0
  INT isShortWindow[(2)];
450
451
  /* number of incoming time samples to be processed */
452
0
  const INT nTimeSamples = psyConf->granuleLength;
453
454
0
  switch (hPsyConfLong->filterbank) {
455
0
    case FB_LC:
456
0
      blockSwitchingOffset =
457
0
          nTimeSamples + (9 * nTimeSamples / (2 * TRANS_FAC));
458
0
      break;
459
0
    case FB_LD:
460
0
    case FB_ELD:
461
0
      blockSwitchingOffset = nTimeSamples;
462
0
      break;
463
0
    default:
464
0
      return AAC_ENC_UNSUPPORTED_FILTERBANK;
465
0
  }
466
467
0
  for (ch = 0; ch < channels; ch++) {
468
0
    psyData[ch] = &psyDynamic->psyData[ch];
469
0
    tnsData[ch] = &psyDynamic->tnsData[ch];
470
0
    pnsData[ch] = &psyDynamic->pnsData[ch];
471
472
0
    psyData[ch]->mdctSpectrum = psyOutChannel[ch]->mdctSpectrum;
473
0
  }
474
475
  /* block switching */
476
0
  if (hPsyConfLong->filterbank != FB_ELD) {
477
0
    int err;
478
479
0
    for (ch = 0; ch < channels; ch++) {
480
0
      C_ALLOC_SCRATCH_START(pTimeSignal, INT_PCM, (1024))
481
482
      /* copy input data and use for block switching */
483
0
      FDKmemcpy(pTimeSignal, pInput + chIdx[ch] * inputBufSize,
484
0
                nTimeSamples * sizeof(INT_PCM));
485
486
0
      FDKaacEnc_BlockSwitching(&psyStatic[ch]->blockSwitchingControl,
487
0
                               nTimeSamples, psyStatic[ch]->isLFE, pTimeSignal);
488
489
      /* fill up internal input buffer, to 2xframelength samples */
490
0
      FDKmemcpy(psyStatic[ch]->psyInputBuffer + blockSwitchingOffset,
491
0
                pTimeSignal,
492
0
                (2 * nTimeSamples - blockSwitchingOffset) * sizeof(INT_PCM));
493
494
0
      C_ALLOC_SCRATCH_END(pTimeSignal, INT_PCM, (1024))
495
0
    }
496
497
    /* synch left and right block type */
498
0
    err = FDKaacEnc_SyncBlockSwitching(
499
0
        &psyStatic[0]->blockSwitchingControl,
500
0
        (channels > 1) ? &psyStatic[1]->blockSwitchingControl : NULL, channels,
501
0
        commonWindow);
502
503
0
    if (err) {
504
0
      return AAC_ENC_UNSUPPORTED_AOT; /* mixed up LC and LD */
505
0
    }
506
507
0
  } else {
508
0
    for (ch = 0; ch < channels; ch++) {
509
      /* copy input data and use for block switching */
510
0
      FDKmemcpy(psyStatic[ch]->psyInputBuffer + blockSwitchingOffset,
511
0
                pInput + chIdx[ch] * inputBufSize,
512
0
                nTimeSamples * sizeof(INT_PCM));
513
0
    }
514
0
  }
515
516
0
  for (ch = 0; ch < channels; ch++)
517
0
    isShortWindow[ch] =
518
0
        (psyStatic[ch]->blockSwitchingControl.lastWindowSequence ==
519
0
         SHORT_WINDOW);
520
521
  /* set parameters according to window length */
522
0
  for (ch = 0; ch < channels; ch++) {
523
0
    if (isShortWindow[ch]) {
524
0
      hThisPsyConf[ch] = hPsyConfShort;
525
0
      windowLength[ch] = psyConf->granuleLength / TRANS_FAC;
526
0
      nWindows[ch] = TRANS_FAC;
527
0
      maxSfb[ch] = MAX_SFB_SHORT;
528
529
0
      pSfbMaxScaleSpec[ch] = psyData[ch]->sfbMaxScaleSpec.Short[0];
530
0
      pSfbEnergy[ch] = psyData[ch]->sfbEnergy.Short[0];
531
0
      pSfbSpreadEnergy[ch] = psyData[ch]->sfbSpreadEnergy.Short[0];
532
0
      pSfbEnergyLdData[ch] = psyData[ch]->sfbEnergyLdData.Short[0];
533
0
      pSfbEnergyMS[ch] = psyData[ch]->sfbEnergyMS.Short[0];
534
0
      pSfbThreshold[ch] = psyData[ch]->sfbThreshold.Short[0];
535
536
0
    } else {
537
0
      hThisPsyConf[ch] = hPsyConfLong;
538
0
      windowLength[ch] = psyConf->granuleLength;
539
0
      nWindows[ch] = 1;
540
0
      maxSfb[ch] = MAX_GROUPED_SFB;
541
542
0
      pSfbMaxScaleSpec[ch] = psyData[ch]->sfbMaxScaleSpec.Long;
543
0
      pSfbEnergy[ch] = psyData[ch]->sfbEnergy.Long;
544
0
      pSfbSpreadEnergy[ch] = psyData[ch]->sfbSpreadEnergy.Long;
545
0
      pSfbEnergyLdData[ch] = psyData[ch]->sfbEnergyLdData.Long;
546
0
      pSfbEnergyMS[ch] = psyData[ch]->sfbEnergyMS.Long;
547
0
      pSfbThreshold[ch] = psyData[ch]->sfbThreshold.Long;
548
0
    }
549
0
  }
550
551
  /* Transform and get mdctScaling for all channels and windows. */
552
0
  for (ch = 0; ch < channels; ch++) {
553
    /* update number of active bands */
554
0
    if (psyStatic[ch]->isLFE) {
555
0
      psyData[ch]->sfbActive = hThisPsyConf[ch]->sfbActiveLFE;
556
0
      psyData[ch]->lowpassLine = hThisPsyConf[ch]->lowpassLineLFE;
557
0
    } else {
558
0
      psyData[ch]->sfbActive = hThisPsyConf[ch]->sfbActive;
559
0
      psyData[ch]->lowpassLine = hThisPsyConf[ch]->lowpassLine;
560
0
    }
561
562
0
    if (hThisPsyConf[ch]->filterbank == FB_ELD) {
563
0
      if (FDKaacEnc_Transform_Real_Eld(
564
0
              psyStatic[ch]->psyInputBuffer, psyData[ch]->mdctSpectrum,
565
0
              psyStatic[ch]->blockSwitchingControl.lastWindowSequence,
566
0
              psyStatic[ch]->blockSwitchingControl.windowShape,
567
0
              &psyStatic[ch]->blockSwitchingControl.lastWindowShape,
568
0
              nTimeSamples, &mdctSpectrum_e, hThisPsyConf[ch]->filterbank,
569
0
              psyStatic[ch]->overlapAddBuffer) != 0) {
570
0
        return AAC_ENC_UNSUPPORTED_FILTERBANK;
571
0
      }
572
0
    } else {
573
0
      if (FDKaacEnc_Transform_Real(
574
0
              psyStatic[ch]->psyInputBuffer, psyData[ch]->mdctSpectrum,
575
0
              psyStatic[ch]->blockSwitchingControl.lastWindowSequence,
576
0
              psyStatic[ch]->blockSwitchingControl.windowShape,
577
0
              &psyStatic[ch]->blockSwitchingControl.lastWindowShape,
578
0
              &psyStatic[ch]->mdctPers, nTimeSamples, &mdctSpectrum_e,
579
0
              hThisPsyConf[ch]->filterbank) != 0) {
580
0
        return AAC_ENC_UNSUPPORTED_FILTERBANK;
581
0
      }
582
0
    }
583
584
0
    for (w = 0; w < nWindows[ch]; w++) {
585
0
      wOffset = w * windowLength[ch];
586
587
      /* Low pass / highest sfb */
588
0
      FDKmemclear(
589
0
          &psyData[ch]->mdctSpectrum[psyData[ch]->lowpassLine + wOffset],
590
0
          (windowLength[ch] - psyData[ch]->lowpassLine) * sizeof(FIXP_DBL));
591
592
0
      if ((hPsyConfLong->filterbank != FB_LC) &&
593
0
          (psyData[ch]->lowpassLine >= FADE_OUT_LEN)) {
594
        /* Do blending to reduce gibbs artifacts */
595
0
        for (int i = 0; i < FADE_OUT_LEN; i++) {
596
0
          psyData[ch]->mdctSpectrum[psyData[ch]->lowpassLine + wOffset -
597
0
                                    FADE_OUT_LEN + i] =
598
0
              fMult(psyData[ch]->mdctSpectrum[psyData[ch]->lowpassLine +
599
0
                                              wOffset - FADE_OUT_LEN + i],
600
0
                    fadeOutFactor[i]);
601
0
        }
602
0
      }
603
604
      /* Check for zero spectrum. These loops will usually terminate very, very
605
       * early. */
606
0
      for (line = 0; (line < psyData[ch]->lowpassLine) && (zeroSpec == TRUE);
607
0
           line++) {
608
0
        if (psyData[ch]->mdctSpectrum[line + wOffset] != (FIXP_DBL)0) {
609
0
          zeroSpec = FALSE;
610
0
          break;
611
0
        }
612
0
      }
613
614
0
    } /* w loop */
615
616
0
    psyData[ch]->mdctScale = mdctSpectrum_e;
617
618
    /* rotate internal time samples */
619
0
    FDKmemmove(psyStatic[ch]->psyInputBuffer,
620
0
               psyStatic[ch]->psyInputBuffer + nTimeSamples,
621
0
               nTimeSamples * sizeof(INT_PCM));
622
623
    /* ... and get remaining samples from input buffer */
624
0
    FDKmemcpy(psyStatic[ch]->psyInputBuffer + nTimeSamples,
625
0
              pInput + (2 * nTimeSamples - blockSwitchingOffset) +
626
0
                  chIdx[ch] * inputBufSize,
627
0
              (blockSwitchingOffset - nTimeSamples) * sizeof(INT_PCM));
628
629
0
  } /* ch */
630
631
  /* Do some rescaling to get maximum possible accuracy for energies */
632
0
  if (zeroSpec == FALSE) {
633
    /* Calc possible spectrum leftshift for each sfb (1 means: 1 bit left shift
634
     * is possible without overflow) */
635
0
    INT minSpecShift = MAX_SHIFT_DBL;
636
0
    INT nrgShift = MAX_SHIFT_DBL;
637
0
    INT finalShift = MAX_SHIFT_DBL;
638
0
    FIXP_DBL currNrg = 0;
639
0
    FIXP_DBL maxNrg = 0;
640
641
0
    for (ch = 0; ch < channels; ch++) {
642
0
      for (w = 0; w < nWindows[ch]; w++) {
643
0
        wOffset = w * windowLength[ch];
644
0
        FDKaacEnc_CalcSfbMaxScaleSpec(
645
0
            psyData[ch]->mdctSpectrum + wOffset, hThisPsyConf[ch]->sfbOffset,
646
0
            pSfbMaxScaleSpec[ch] + w * maxSfb[ch], psyData[ch]->sfbActive);
647
648
0
        for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++)
649
0
          minSpecShift = fixMin(minSpecShift,
650
0
                                (pSfbMaxScaleSpec[ch] + w * maxSfb[ch])[sfb]);
651
0
      }
652
0
    }
653
654
    /* Calc possible energy leftshift for each sfb (1 means: 1 bit left shift is
655
     * possible without overflow) */
656
0
    for (ch = 0; ch < channels; ch++) {
657
0
      for (w = 0; w < nWindows[ch]; w++) {
658
0
        wOffset = w * windowLength[ch];
659
0
        currNrg = FDKaacEnc_CheckBandEnergyOptim(
660
0
            psyData[ch]->mdctSpectrum + wOffset,
661
0
            pSfbMaxScaleSpec[ch] + w * maxSfb[ch], hThisPsyConf[ch]->sfbOffset,
662
0
            psyData[ch]->sfbActive, pSfbEnergy[ch] + w * maxSfb[ch],
663
0
            pSfbEnergyLdData[ch] + w * maxSfb[ch], minSpecShift - 4);
664
665
0
        maxNrg = fixMax(maxNrg, currNrg);
666
0
      }
667
0
    }
668
669
0
    if (maxNrg != (FIXP_DBL)0) {
670
0
      nrgShift = (CountLeadingBits(maxNrg) >> 1) + (minSpecShift - 4);
671
0
    }
672
673
    /* 2check: Hasn't this decision to be made for both channels? */
674
    /* For short windows 1 additional bit headroom is necessary to prevent
675
     * overflows when summing up energies in FDKaacEnc_groupShortData() */
676
0
    if (isShortWindow[0]) nrgShift--;
677
678
    /* both spectrum and energies mustn't overflow */
679
0
    finalShift = fixMin(minSpecShift, nrgShift);
680
681
    /* do not shift more than 3 bits more to the left than signal without
682
     * blockfloating point would be to avoid overflow of scaled PCM quantization
683
     * thresholds */
684
0
    if (finalShift > psyData[0]->mdctScale + 3)
685
0
      finalShift = psyData[0]->mdctScale + 3;
686
687
0
    FDK_ASSERT(finalShift >= 0); /* right shift is not allowed */
688
689
    /* correct sfbEnergy and sfbEnergyLdData with new finalShift */
690
0
    FIXP_DBL ldShift = finalShift * FL2FXCONST_DBL(2.0 / 64);
691
0
    for (ch = 0; ch < channels; ch++) {
692
0
      INT maxSfb_ch = maxSfb[ch];
693
0
      INT w_maxSfb_ch = 0;
694
0
      for (w = 0; w < nWindows[ch]; w++) {
695
0
        for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) {
696
0
          INT scale = fixMax(0, (pSfbMaxScaleSpec[ch] + w_maxSfb_ch)[sfb] - 4);
697
0
          scale = fixMin((scale - finalShift) << 1, DFRACT_BITS - 1);
698
0
          if (scale >= 0)
699
0
            (pSfbEnergy[ch] + w_maxSfb_ch)[sfb] >>= (scale);
700
0
          else
701
0
            (pSfbEnergy[ch] + w_maxSfb_ch)[sfb] <<= (-scale);
702
0
          (pSfbThreshold[ch] + w_maxSfb_ch)[sfb] =
703
0
              fMult((pSfbEnergy[ch] + w_maxSfb_ch)[sfb], C_RATIO);
704
0
          (pSfbEnergyLdData[ch] + w_maxSfb_ch)[sfb] += ldShift;
705
0
        }
706
0
        w_maxSfb_ch += maxSfb_ch;
707
0
      }
708
0
    }
709
710
0
    if (finalShift != 0) {
711
0
      for (ch = 0; ch < channels; ch++) {
712
0
        INT wLen = windowLength[ch];
713
0
        INT lowpassLine = psyData[ch]->lowpassLine;
714
0
        wOffset = 0;
715
0
        FIXP_DBL *mdctSpectrum = &psyData[ch]->mdctSpectrum[0];
716
0
        for (w = 0; w < nWindows[ch]; w++) {
717
0
          FIXP_DBL *spectrum = &mdctSpectrum[wOffset];
718
0
          for (line = 0; line < lowpassLine; line++) {
719
0
            spectrum[line] <<= finalShift;
720
0
          }
721
0
          wOffset += wLen;
722
723
          /* update sfbMaxScaleSpec */
724
0
          for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++)
725
0
            (pSfbMaxScaleSpec[ch] + w * maxSfb[ch])[sfb] -= finalShift;
726
0
        }
727
        /* update mdctScale */
728
0
        psyData[ch]->mdctScale -= finalShift;
729
0
      }
730
0
    }
731
732
0
  } else {
733
    /* all spectral lines are zero */
734
0
    for (ch = 0; ch < channels; ch++) {
735
0
      psyData[ch]->mdctScale =
736
0
          0; /* otherwise mdctScale would be for example 7 and PCM quantization
737
              * thresholds would be shifted 14 bits to the right causing some of
738
              * them to become 0 (which causes problems later) */
739
      /* clear sfbMaxScaleSpec */
740
0
      for (w = 0; w < nWindows[ch]; w++) {
741
0
        for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) {
742
0
          (pSfbMaxScaleSpec[ch] + w * maxSfb[ch])[sfb] = 0;
743
0
          (pSfbEnergy[ch] + w * maxSfb[ch])[sfb] = (FIXP_DBL)0;
744
0
          (pSfbEnergyLdData[ch] + w * maxSfb[ch])[sfb] = FL2FXCONST_DBL(-1.0f);
745
0
          (pSfbThreshold[ch] + w * maxSfb[ch])[sfb] = (FIXP_DBL)0;
746
0
        }
747
0
      }
748
0
    }
749
0
  }
750
751
  /* Advance psychoacoustics: Tonality and TNS */
752
0
  if ((channels >= 1) && (psyStatic[0]->isLFE)) {
753
0
    tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT] = 0;
754
0
    tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[LOFILT] = 0;
755
0
  } else {
756
0
    for (ch = 0; ch < channels; ch++) {
757
0
      if (!isShortWindow[ch]) {
758
        /* tonality */
759
0
        FDKaacEnc_CalculateFullTonality(
760
0
            psyData[ch]->mdctSpectrum, pSfbMaxScaleSpec[ch],
761
0
            pSfbEnergyLdData[ch], sfbTonality[ch], psyData[ch]->sfbActive,
762
0
            hThisPsyConf[ch]->sfbOffset, hThisPsyConf[ch]->pnsConf.usePns);
763
0
      }
764
0
    } /* ch */
765
766
0
    if (hPsyConfLong->tnsConf.tnsActive || hPsyConfShort->tnsConf.tnsActive) {
767
0
      INT tnsActive[TRANS_FAC] = {0};
768
0
      INT nrgScaling[2] = {0, 0};
769
0
      INT tnsSpecShift = 0;
770
771
0
      for (ch = 0; ch < channels; ch++) {
772
0
        for (w = 0; w < nWindows[ch]; w++) {
773
0
          wOffset = w * windowLength[ch];
774
          /* TNS */
775
0
          FDKaacEnc_TnsDetect(
776
0
              tnsData[ch], &hThisPsyConf[ch]->tnsConf,
777
0
              &psyOutChannel[ch]->tnsInfo, hThisPsyConf[ch]->sfbCnt,
778
0
              psyData[ch]->mdctSpectrum + wOffset, w,
779
0
              psyStatic[ch]->blockSwitchingControl.lastWindowSequence);
780
0
        }
781
0
      }
782
783
0
      if (channels == 2) {
784
0
        FDKaacEnc_TnsSync(
785
0
            tnsData[1], tnsData[0], &psyOutChannel[1]->tnsInfo,
786
0
            &psyOutChannel[0]->tnsInfo,
787
788
0
            psyStatic[1]->blockSwitchingControl.lastWindowSequence,
789
0
            psyStatic[0]->blockSwitchingControl.lastWindowSequence,
790
0
            &hThisPsyConf[1]->tnsConf);
791
0
      }
792
793
0
      if (channels >= 1) {
794
0
        FDK_ASSERT(1 == commonWindow); /* all checks for TNS do only work for
795
                                          common windows (which is always set)*/
796
0
        for (w = 0; w < nWindows[0]; w++) {
797
0
          if (isShortWindow[0])
798
0
            tnsActive[w] =
799
0
                tnsData[0]->dataRaw.Short.subBlockInfo[w].tnsActive[HIFILT] ||
800
0
                tnsData[0]->dataRaw.Short.subBlockInfo[w].tnsActive[LOFILT] ||
801
0
                tnsData[channels - 1]
802
0
                    ->dataRaw.Short.subBlockInfo[w]
803
0
                    .tnsActive[HIFILT] ||
804
0
                tnsData[channels - 1]
805
0
                    ->dataRaw.Short.subBlockInfo[w]
806
0
                    .tnsActive[LOFILT];
807
0
          else
808
0
            tnsActive[w] =
809
0
                tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT] ||
810
0
                tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[LOFILT] ||
811
0
                tnsData[channels - 1]
812
0
                    ->dataRaw.Long.subBlockInfo.tnsActive[HIFILT] ||
813
0
                tnsData[channels - 1]
814
0
                    ->dataRaw.Long.subBlockInfo.tnsActive[LOFILT];
815
0
        }
816
0
      }
817
818
0
      for (ch = 0; ch < channels; ch++) {
819
0
        if (tnsActive[0] && !isShortWindow[ch]) {
820
          /* Scale down spectrum if tns is active in one of the two channels
821
           * with same lastWindowSequence */
822
          /* first part of threshold calculation; it's not necessary to update
823
           * sfbMaxScaleSpec */
824
0
          INT shift = 1;
825
0
          for (sfb = 0; sfb < hThisPsyConf[ch]->lowpassLine; sfb++) {
826
0
            psyData[ch]->mdctSpectrum[sfb] =
827
0
                psyData[ch]->mdctSpectrum[sfb] >> shift;
828
0
          }
829
830
          /* update thresholds */
831
0
          for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) {
832
0
            pSfbThreshold[ch][sfb] >>= (2 * shift);
833
0
          }
834
835
0
          psyData[ch]->mdctScale += shift; /* update mdctScale */
836
837
          /* calc sfbEnergies after tnsEncode again ! */
838
0
        }
839
0
      }
840
841
0
      for (ch = 0; ch < channels; ch++) {
842
0
        for (w = 0; w < nWindows[ch]; w++) {
843
0
          wOffset = w * windowLength[ch];
844
0
          FDKaacEnc_TnsEncode(
845
0
              &psyOutChannel[ch]->tnsInfo, tnsData[ch],
846
0
              hThisPsyConf[ch]->sfbCnt, &hThisPsyConf[ch]->tnsConf,
847
0
              hThisPsyConf[ch]->sfbOffset[psyData[ch]->sfbActive],
848
              /*hThisPsyConf[ch]->lowpassLine*/ /* filter stops
849
                                                   before that
850
                                                   line ! */
851
0
                  psyData[ch]->mdctSpectrum +
852
0
                  wOffset,
853
0
              w, psyStatic[ch]->blockSwitchingControl.lastWindowSequence);
854
855
0
          if (tnsActive[w]) {
856
            /* Calc sfb-bandwise mdct-energies for left and right channel again,
857
             */
858
            /* if tns active in current channel or in one channel with same
859
             * lastWindowSequence left and right */
860
0
            FDKaacEnc_CalcSfbMaxScaleSpec(psyData[ch]->mdctSpectrum + wOffset,
861
0
                                          hThisPsyConf[ch]->sfbOffset,
862
0
                                          pSfbMaxScaleSpec[ch] + w * maxSfb[ch],
863
0
                                          psyData[ch]->sfbActive);
864
0
          }
865
0
        }
866
0
      }
867
868
0
      for (ch = 0; ch < channels; ch++) {
869
0
        for (w = 0; w < nWindows[ch]; w++) {
870
0
          if (tnsActive[w]) {
871
0
            if (isShortWindow[ch]) {
872
0
              FDKaacEnc_CalcBandEnergyOptimShort(
873
0
                  psyData[ch]->mdctSpectrum + w * windowLength[ch],
874
0
                  pSfbMaxScaleSpec[ch] + w * maxSfb[ch],
875
0
                  hThisPsyConf[ch]->sfbOffset, psyData[ch]->sfbActive,
876
0
                  pSfbEnergy[ch] + w * maxSfb[ch]);
877
0
            } else {
878
0
              nrgScaling[ch] = /* with tns, energy calculation can overflow; ->
879
                                  scaling */
880
0
                  FDKaacEnc_CalcBandEnergyOptimLong(
881
0
                      psyData[ch]->mdctSpectrum, pSfbMaxScaleSpec[ch],
882
0
                      hThisPsyConf[ch]->sfbOffset, psyData[ch]->sfbActive,
883
0
                      pSfbEnergy[ch], pSfbEnergyLdData[ch]);
884
0
              tnsSpecShift =
885
0
                  fixMax(tnsSpecShift, nrgScaling[ch]); /* nrgScaling is set
886
                                                           only if nrg would
887
                                                           have an overflow */
888
0
            }
889
0
          } /* if tnsActive */
890
0
        }
891
0
      } /* end channel loop */
892
893
      /* adapt scaling to prevent nrg overflow, only for long blocks */
894
0
      for (ch = 0; ch < channels; ch++) {
895
0
        if ((tnsSpecShift != 0) && !isShortWindow[ch]) {
896
          /* scale down spectrum, nrg's and thresholds, if there was an overflow
897
           * in sfbNrg calculation after tns */
898
0
          for (line = 0; line < hThisPsyConf[ch]->lowpassLine; line++) {
899
0
            psyData[ch]->mdctSpectrum[line] >>= tnsSpecShift;
900
0
          }
901
0
          INT scale = (tnsSpecShift - nrgScaling[ch]) << 1;
902
0
          for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) {
903
0
            pSfbEnergyLdData[ch][sfb] -=
904
0
                scale * FL2FXCONST_DBL(1.0 / LD_DATA_SCALING);
905
0
            pSfbEnergy[ch][sfb] >>= scale;
906
0
            pSfbThreshold[ch][sfb] >>= (tnsSpecShift << 1);
907
0
          }
908
0
          psyData[ch]->mdctScale += tnsSpecShift; /* update mdctScale; not
909
                                                     necessary to update
910
                                                     sfbMaxScaleSpec */
911
0
        }
912
0
      } /* end channel loop */
913
914
0
    } /* TNS active */
915
0
    else {
916
      /* In case of disable TNS, reset its dynamic data. Some of its elements is
917
       * required in PNS detection below. */
918
0
      FDKmemclear(psyDynamic->tnsData, sizeof(psyDynamic->tnsData));
919
0
    }
920
0
  } /* !isLFE */
921
922
  /* Advance thresholds */
923
0
  for (ch = 0; ch < channels; ch++) {
924
0
    INT headroom;
925
926
0
    FIXP_DBL clipEnergy;
927
0
    INT energyShift = psyData[ch]->mdctScale * 2;
928
0
    INT clipNrgShift = energyShift - THR_SHIFTBITS;
929
0
    if (isShortWindow[ch])
930
0
      headroom = 6;
931
0
    else
932
0
      headroom = 0;
933
934
0
    if (clipNrgShift >= 0)
935
0
      clipEnergy = hThisPsyConf[ch]->clipEnergy >> clipNrgShift;
936
0
    else if (clipNrgShift >= -headroom)
937
0
      clipEnergy = hThisPsyConf[ch]->clipEnergy << -clipNrgShift;
938
0
    else
939
0
      clipEnergy = (FIXP_DBL)MAXVAL_DBL;
940
941
0
    for (w = 0; w < nWindows[ch]; w++) {
942
0
      INT i;
943
      /* limit threshold to avoid clipping */
944
0
      for (i = 0; i < psyData[ch]->sfbActive; i++) {
945
0
        *(pSfbThreshold[ch] + w * maxSfb[ch] + i) =
946
0
            fixMin(*(pSfbThreshold[ch] + w * maxSfb[ch] + i), clipEnergy);
947
0
      }
948
949
      /* spreading */
950
0
      FDKaacEnc_SpreadingMax(psyData[ch]->sfbActive,
951
0
                             hThisPsyConf[ch]->sfbMaskLowFactor,
952
0
                             hThisPsyConf[ch]->sfbMaskHighFactor,
953
0
                             pSfbThreshold[ch] + w * maxSfb[ch]);
954
955
      /* PCM quantization threshold */
956
0
      energyShift += PCM_QUANT_THR_SCALE;
957
0
      if (energyShift >= 0) {
958
0
        energyShift = fixMin(DFRACT_BITS - 1, energyShift);
959
0
        for (i = 0; i < psyData[ch]->sfbActive; i++) {
960
0
          *(pSfbThreshold[ch] + w * maxSfb[ch] + i) = fixMax(
961
0
              *(pSfbThreshold[ch] + w * maxSfb[ch] + i) >> THR_SHIFTBITS,
962
0
              (hThisPsyConf[ch]->sfbPcmQuantThreshold[i] >> energyShift));
963
0
        }
964
0
      } else {
965
0
        energyShift = fixMin(DFRACT_BITS - 1, -energyShift);
966
0
        for (i = 0; i < psyData[ch]->sfbActive; i++) {
967
0
          *(pSfbThreshold[ch] + w * maxSfb[ch] + i) = fixMax(
968
0
              *(pSfbThreshold[ch] + w * maxSfb[ch] + i) >> THR_SHIFTBITS,
969
0
              (hThisPsyConf[ch]->sfbPcmQuantThreshold[i] << energyShift));
970
0
        }
971
0
      }
972
973
0
      if (!psyStatic[ch]->isLFE) {
974
        /* preecho control */
975
0
        if (psyStatic[ch]->blockSwitchingControl.lastWindowSequence ==
976
0
            STOP_WINDOW) {
977
          /* prevent FDKaacEnc_PreEchoControl from comparing stop
978
             thresholds with short thresholds */
979
0
          for (i = 0; i < psyData[ch]->sfbActive; i++) {
980
0
            psyStatic[ch]->sfbThresholdnm1[i] = (FIXP_DBL)MAXVAL_DBL;
981
0
          }
982
983
0
          psyStatic[ch]->mdctScalenm1 = 0;
984
0
          psyStatic[ch]->calcPreEcho = 0;
985
0
        }
986
987
0
        FDKaacEnc_PreEchoControl(
988
0
            psyStatic[ch]->sfbThresholdnm1, psyStatic[ch]->calcPreEcho,
989
0
            psyData[ch]->sfbActive, hThisPsyConf[ch]->maxAllowedIncreaseFactor,
990
0
            hThisPsyConf[ch]->minRemainingThresholdFactor,
991
0
            pSfbThreshold[ch] + w * maxSfb[ch], psyData[ch]->mdctScale,
992
0
            &psyStatic[ch]->mdctScalenm1);
993
994
0
        psyStatic[ch]->calcPreEcho = 1;
995
996
0
        if (psyStatic[ch]->blockSwitchingControl.lastWindowSequence ==
997
0
            START_WINDOW) {
998
          /* prevent FDKaacEnc_PreEchoControl in next frame to compare start
999
             thresholds with short thresholds */
1000
0
          for (i = 0; i < psyData[ch]->sfbActive; i++) {
1001
0
            psyStatic[ch]->sfbThresholdnm1[i] = (FIXP_DBL)MAXVAL_DBL;
1002
0
          }
1003
1004
0
          psyStatic[ch]->mdctScalenm1 = 0;
1005
0
          psyStatic[ch]->calcPreEcho = 0;
1006
0
        }
1007
0
      }
1008
1009
      /* spread energy to avoid hole detection */
1010
0
      FDKmemcpy(pSfbSpreadEnergy[ch] + w * maxSfb[ch],
1011
0
                pSfbEnergy[ch] + w * maxSfb[ch],
1012
0
                psyData[ch]->sfbActive * sizeof(FIXP_DBL));
1013
1014
0
      FDKaacEnc_SpreadingMax(psyData[ch]->sfbActive,
1015
0
                             hThisPsyConf[ch]->sfbMaskLowFactorSprEn,
1016
0
                             hThisPsyConf[ch]->sfbMaskHighFactorSprEn,
1017
0
                             pSfbSpreadEnergy[ch] + w * maxSfb[ch]);
1018
0
    }
1019
0
  }
1020
1021
  /* Calc bandwise energies for mid and side channel. Do it only if 2 channels
1022
   * exist */
1023
0
  if (channels == 2) {
1024
0
    for (w = 0; w < nWindows[1]; w++) {
1025
0
      wOffset = w * windowLength[1];
1026
0
      FDKaacEnc_CalcBandNrgMSOpt(
1027
0
          psyData[0]->mdctSpectrum + wOffset,
1028
0
          psyData[1]->mdctSpectrum + wOffset,
1029
0
          pSfbMaxScaleSpec[0] + w * maxSfb[0],
1030
0
          pSfbMaxScaleSpec[1] + w * maxSfb[1], hThisPsyConf[1]->sfbOffset,
1031
0
          psyData[0]->sfbActive, pSfbEnergyMS[0] + w * maxSfb[0],
1032
0
          pSfbEnergyMS[1] + w * maxSfb[1],
1033
0
          (psyStatic[1]->blockSwitchingControl.lastWindowSequence !=
1034
0
           SHORT_WINDOW),
1035
0
          psyData[0]->sfbEnergyMSLdData, psyData[1]->sfbEnergyMSLdData);
1036
0
    }
1037
0
  }
1038
1039
  /* group short data (maxSfb[ch] for short blocks is determined here) */
1040
0
  for (ch = 0; ch < channels; ch++) {
1041
0
    if (isShortWindow[ch]) {
1042
0
      int sfbGrp;
1043
0
      int noSfb = psyStatic[ch]->blockSwitchingControl.noOfGroups *
1044
0
                  hPsyConfShort->sfbCnt;
1045
      /* At this point, energies and thresholds are copied/regrouped from the
1046
       * ".Short" to the ".Long" arrays */
1047
0
      FDKaacEnc_groupShortData(
1048
0
          psyData[ch]->mdctSpectrum, &psyData[ch]->sfbThreshold,
1049
0
          &psyData[ch]->sfbEnergy, &psyData[ch]->sfbEnergyMS,
1050
0
          &psyData[ch]->sfbSpreadEnergy, hPsyConfShort->sfbCnt,
1051
0
          psyData[ch]->sfbActive, hPsyConfShort->sfbOffset,
1052
0
          hPsyConfShort->sfbMinSnrLdData, psyData[ch]->groupedSfbOffset,
1053
0
          &maxSfbPerGroup[ch], psyOutChannel[ch]->sfbMinSnrLdData,
1054
0
          psyStatic[ch]->blockSwitchingControl.noOfGroups,
1055
0
          psyStatic[ch]->blockSwitchingControl.groupLen,
1056
0
          psyConf[1].granuleLength);
1057
1058
      /* calculate ldData arrays (short values are in .Long-arrays after
1059
       * FDKaacEnc_groupShortData) */
1060
0
      for (sfbGrp = 0; sfbGrp < noSfb; sfbGrp += hPsyConfShort->sfbCnt) {
1061
0
        LdDataVector(&psyData[ch]->sfbEnergy.Long[sfbGrp],
1062
0
                     &psyOutChannel[ch]->sfbEnergyLdData[sfbGrp],
1063
0
                     psyData[ch]->sfbActive);
1064
0
      }
1065
1066
      /* calc sfbThrld and set Values smaller 2^-31 to 2^-33*/
1067
0
      for (sfbGrp = 0; sfbGrp < noSfb; sfbGrp += hPsyConfShort->sfbCnt) {
1068
0
        LdDataVector(&psyData[ch]->sfbThreshold.Long[sfbGrp],
1069
0
                     &psyOutChannel[ch]->sfbThresholdLdData[sfbGrp],
1070
0
                     psyData[ch]->sfbActive);
1071
0
        for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) {
1072
0
          psyOutChannel[ch]->sfbThresholdLdData[sfbGrp + sfb] =
1073
0
              fixMax(psyOutChannel[ch]->sfbThresholdLdData[sfbGrp + sfb],
1074
0
                     FL2FXCONST_DBL(-0.515625f));
1075
0
        }
1076
0
      }
1077
1078
0
      if (channels == 2) {
1079
0
        for (sfbGrp = 0; sfbGrp < noSfb; sfbGrp += hPsyConfShort->sfbCnt) {
1080
0
          LdDataVector(&psyData[ch]->sfbEnergyMS.Long[sfbGrp],
1081
0
                       &psyData[ch]->sfbEnergyMSLdData[sfbGrp],
1082
0
                       psyData[ch]->sfbActive);
1083
0
        }
1084
0
      }
1085
1086
0
      FDKmemcpy(psyOutChannel[ch]->sfbOffsets, psyData[ch]->groupedSfbOffset,
1087
0
                (MAX_GROUPED_SFB + 1) * sizeof(INT));
1088
1089
0
    } else {
1090
0
      int i;
1091
      /* maxSfb[ch] for long blocks */
1092
0
      for (sfb = psyData[ch]->sfbActive - 1; sfb >= 0; sfb--) {
1093
0
        for (line = hPsyConfLong->sfbOffset[sfb + 1] - 1;
1094
0
             line >= hPsyConfLong->sfbOffset[sfb]; line--) {
1095
0
          if (psyData[ch]->mdctSpectrum[line] != FL2FXCONST_SGL(0.0f)) break;
1096
0
        }
1097
0
        if (line > hPsyConfLong->sfbOffset[sfb]) break;
1098
0
      }
1099
0
      maxSfbPerGroup[ch] = sfb + 1;
1100
0
      maxSfbPerGroup[ch] =
1101
0
          fixMax(fixMin(5, psyData[ch]->sfbActive), maxSfbPerGroup[ch]);
1102
1103
      /* sfbNrgLdData is calculated in FDKaacEnc_advancePsychLong, copy in
1104
       * psyOut structure */
1105
0
      FDKmemcpy(psyOutChannel[ch]->sfbEnergyLdData,
1106
0
                psyData[ch]->sfbEnergyLdData.Long,
1107
0
                psyData[ch]->sfbActive * sizeof(FIXP_DBL));
1108
1109
0
      FDKmemcpy(psyOutChannel[ch]->sfbOffsets, hPsyConfLong->sfbOffset,
1110
0
                (MAX_GROUPED_SFB + 1) * sizeof(INT));
1111
1112
      /* sfbMinSnrLdData modified in adjust threshold, copy necessary */
1113
0
      FDKmemcpy(psyOutChannel[ch]->sfbMinSnrLdData,
1114
0
                hPsyConfLong->sfbMinSnrLdData,
1115
0
                psyData[ch]->sfbActive * sizeof(FIXP_DBL));
1116
1117
      /* sfbEnergyMSLdData ist already calculated in FDKaacEnc_CalcBandNrgMSOpt;
1118
       * only in long case */
1119
1120
      /* calc sfbThrld and set Values smaller 2^-31 to 2^-33*/
1121
0
      LdDataVector(psyData[ch]->sfbThreshold.Long,
1122
0
                   psyOutChannel[ch]->sfbThresholdLdData,
1123
0
                   psyData[ch]->sfbActive);
1124
0
      for (i = 0; i < psyData[ch]->sfbActive; i++) {
1125
0
        psyOutChannel[ch]->sfbThresholdLdData[i] =
1126
0
            fixMax(psyOutChannel[ch]->sfbThresholdLdData[i],
1127
0
                   FL2FXCONST_DBL(-0.515625f));
1128
0
      }
1129
0
    }
1130
0
  }
1131
1132
  /*
1133
      Intensity parameter intialization.
1134
   */
1135
0
  for (ch = 0; ch < channels; ch++) {
1136
0
    FDKmemclear(psyOutChannel[ch]->isBook, MAX_GROUPED_SFB * sizeof(INT));
1137
0
    FDKmemclear(psyOutChannel[ch]->isScale, MAX_GROUPED_SFB * sizeof(INT));
1138
0
  }
1139
1140
0
  for (ch = 0; ch < channels; ch++) {
1141
0
    INT win = (isShortWindow[ch] ? 1 : 0);
1142
0
    if (!psyStatic[ch]->isLFE) {
1143
      /* PNS Decision */
1144
0
      FDKaacEnc_PnsDetect(
1145
0
          &(psyConf[0].pnsConf), pnsData[ch],
1146
0
          psyStatic[ch]->blockSwitchingControl.lastWindowSequence,
1147
0
          psyData[ch]->sfbActive,
1148
0
          maxSfbPerGroup[ch], /* count of Sfb which are not zero. */
1149
0
          psyOutChannel[ch]->sfbThresholdLdData, psyConf[win].sfbOffset,
1150
0
          psyData[ch]->mdctSpectrum, psyData[ch]->sfbMaxScaleSpec.Long,
1151
0
          sfbTonality[ch], psyOutChannel[ch]->tnsInfo.order[0][0],
1152
0
          tnsData[ch]->dataRaw.Long.subBlockInfo.predictionGain[HIFILT],
1153
0
          tnsData[ch]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT],
1154
0
          psyOutChannel[ch]->sfbEnergyLdData, psyOutChannel[ch]->noiseNrg);
1155
0
    } /* !isLFE */
1156
0
  }   /* ch */
1157
1158
  /*
1159
      stereo Processing
1160
  */
1161
0
  if (channels == 2) {
1162
0
    psyOutElement->toolsInfo.msDigest = MS_NONE;
1163
0
    psyOutElement->commonWindow = commonWindow;
1164
0
    if (psyOutElement->commonWindow)
1165
0
      maxSfbPerGroup[0] = maxSfbPerGroup[1] =
1166
0
          fixMax(maxSfbPerGroup[0], maxSfbPerGroup[1]);
1167
0
    if (psyStatic[0]->blockSwitchingControl.lastWindowSequence !=
1168
0
        SHORT_WINDOW) {
1169
      /* PNS preprocessing depending on ms processing: PNS not in Short Window!
1170
       */
1171
0
      FDKaacEnc_PreProcessPnsChannelPair(
1172
0
          psyData[0]->sfbActive, (&psyData[0]->sfbEnergy)->Long,
1173
0
          (&psyData[1]->sfbEnergy)->Long, psyOutChannel[0]->sfbEnergyLdData,
1174
0
          psyOutChannel[1]->sfbEnergyLdData, psyData[0]->sfbEnergyMS.Long,
1175
0
          &(psyConf[0].pnsConf), pnsData[0], pnsData[1]);
1176
1177
0
      FDKaacEnc_IntensityStereoProcessing(
1178
0
          psyData[0]->sfbEnergy.Long, psyData[1]->sfbEnergy.Long,
1179
0
          psyData[0]->mdctSpectrum, psyData[1]->mdctSpectrum,
1180
0
          psyData[0]->sfbThreshold.Long, psyData[1]->sfbThreshold.Long,
1181
0
          psyOutChannel[1]->sfbThresholdLdData,
1182
0
          psyData[0]->sfbSpreadEnergy.Long, psyData[1]->sfbSpreadEnergy.Long,
1183
0
          psyOutChannel[0]->sfbEnergyLdData, psyOutChannel[1]->sfbEnergyLdData,
1184
0
          &psyOutElement->toolsInfo.msDigest, psyOutElement->toolsInfo.msMask,
1185
0
          psyConf[0].sfbCnt, psyConf[0].sfbCnt, maxSfbPerGroup[0],
1186
0
          psyConf[0].sfbOffset,
1187
0
          psyConf[0].allowIS && psyOutElement->commonWindow,
1188
0
          psyOutChannel[1]->isBook, psyOutChannel[1]->isScale, pnsData);
1189
1190
0
      FDKaacEnc_MsStereoProcessing(
1191
0
          psyData, psyOutChannel, psyOutChannel[1]->isBook,
1192
0
          &psyOutElement->toolsInfo.msDigest, psyOutElement->toolsInfo.msMask,
1193
0
          psyConf[0].allowMS, psyData[0]->sfbActive, psyData[0]->sfbActive,
1194
0
          maxSfbPerGroup[0], psyOutChannel[0]->sfbOffsets);
1195
1196
      /* PNS postprocessing */
1197
0
      FDKaacEnc_PostProcessPnsChannelPair(
1198
0
          psyData[0]->sfbActive, &(psyConf[0].pnsConf), pnsData[0], pnsData[1],
1199
0
          psyOutElement->toolsInfo.msMask, &psyOutElement->toolsInfo.msDigest);
1200
1201
0
    } else {
1202
0
      FDKaacEnc_IntensityStereoProcessing(
1203
0
          psyData[0]->sfbEnergy.Long, psyData[1]->sfbEnergy.Long,
1204
0
          psyData[0]->mdctSpectrum, psyData[1]->mdctSpectrum,
1205
0
          psyData[0]->sfbThreshold.Long, psyData[1]->sfbThreshold.Long,
1206
0
          psyOutChannel[1]->sfbThresholdLdData,
1207
0
          psyData[0]->sfbSpreadEnergy.Long, psyData[1]->sfbSpreadEnergy.Long,
1208
0
          psyOutChannel[0]->sfbEnergyLdData, psyOutChannel[1]->sfbEnergyLdData,
1209
0
          &psyOutElement->toolsInfo.msDigest, psyOutElement->toolsInfo.msMask,
1210
0
          psyStatic[0]->blockSwitchingControl.noOfGroups *
1211
0
              hPsyConfShort->sfbCnt,
1212
0
          psyConf[1].sfbCnt, maxSfbPerGroup[0], psyData[0]->groupedSfbOffset,
1213
0
          psyConf[0].allowIS && psyOutElement->commonWindow,
1214
0
          psyOutChannel[1]->isBook, psyOutChannel[1]->isScale, pnsData);
1215
1216
      /* it's OK to pass the ".Long" arrays here. They contain grouped short
1217
       * data since FDKaacEnc_groupShortData() */
1218
0
      FDKaacEnc_MsStereoProcessing(
1219
0
          psyData, psyOutChannel, psyOutChannel[1]->isBook,
1220
0
          &psyOutElement->toolsInfo.msDigest, psyOutElement->toolsInfo.msMask,
1221
0
          psyConf[1].allowMS,
1222
0
          psyStatic[0]->blockSwitchingControl.noOfGroups *
1223
0
              hPsyConfShort->sfbCnt,
1224
0
          hPsyConfShort->sfbCnt, maxSfbPerGroup[0],
1225
0
          psyOutChannel[0]->sfbOffsets);
1226
0
    }
1227
0
  } /* (channels == 2) */
1228
1229
  /*
1230
    PNS Coding
1231
  */
1232
0
  for (ch = 0; ch < channels; ch++) {
1233
0
    if (psyStatic[ch]->isLFE) {
1234
      /* no PNS coding */
1235
0
      for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) {
1236
0
        psyOutChannel[ch]->noiseNrg[sfb] = NO_NOISE_PNS;
1237
0
      }
1238
0
    } else {
1239
0
      FDKaacEnc_CodePnsChannel(
1240
0
          psyData[ch]->sfbActive, &(hThisPsyConf[ch]->pnsConf),
1241
0
          pnsData[ch]->pnsFlag, psyData[ch]->sfbEnergyLdData.Long,
1242
0
          psyOutChannel[ch]->noiseNrg, /* this is the energy that will be
1243
                                          written to the bitstream */
1244
0
          psyOutChannel[ch]->sfbThresholdLdData);
1245
0
    }
1246
0
  }
1247
1248
  /*
1249
      build output
1250
  */
1251
0
  for (ch = 0; ch < channels; ch++) {
1252
0
    INT mask;
1253
0
    int grp;
1254
0
    psyOutChannel[ch]->maxSfbPerGroup = maxSfbPerGroup[ch];
1255
0
    psyOutChannel[ch]->mdctScale = psyData[ch]->mdctScale;
1256
0
    if (isShortWindow[ch] == 0) {
1257
0
      psyOutChannel[ch]->sfbCnt = hPsyConfLong->sfbActive;
1258
0
      psyOutChannel[ch]->sfbPerGroup = hPsyConfLong->sfbActive;
1259
0
      psyOutChannel[ch]->lastWindowSequence =
1260
0
          psyStatic[ch]->blockSwitchingControl.lastWindowSequence;
1261
0
      psyOutChannel[ch]->windowShape =
1262
0
          psyStatic[ch]->blockSwitchingControl.windowShape;
1263
0
    } else {
1264
0
      INT sfbCnt = psyStatic[ch]->blockSwitchingControl.noOfGroups *
1265
0
                   hPsyConfShort->sfbCnt;
1266
1267
0
      psyOutChannel[ch]->sfbCnt = sfbCnt;
1268
0
      psyOutChannel[ch]->sfbPerGroup = hPsyConfShort->sfbCnt;
1269
0
      psyOutChannel[ch]->lastWindowSequence = SHORT_WINDOW;
1270
0
      psyOutChannel[ch]->windowShape = SINE_WINDOW;
1271
0
    }
1272
    /* generate grouping mask */
1273
0
    mask = 0;
1274
0
    for (grp = 0; grp < psyStatic[ch]->blockSwitchingControl.noOfGroups;
1275
0
         grp++) {
1276
0
      int j;
1277
0
      mask <<= 1;
1278
0
      for (j = 1; j < psyStatic[ch]->blockSwitchingControl.groupLen[grp]; j++) {
1279
0
        mask = (mask << 1) | 1;
1280
0
      }
1281
0
    }
1282
0
    psyOutChannel[ch]->groupingMask = mask;
1283
1284
    /* build interface */
1285
0
    FDKmemcpy(psyOutChannel[ch]->groupLen,
1286
0
              psyStatic[ch]->blockSwitchingControl.groupLen,
1287
0
              MAX_NO_OF_GROUPS * sizeof(INT));
1288
0
    FDKmemcpy(psyOutChannel[ch]->sfbEnergy, (&psyData[ch]->sfbEnergy)->Long,
1289
0
              MAX_GROUPED_SFB * sizeof(FIXP_DBL));
1290
0
    FDKmemcpy(psyOutChannel[ch]->sfbSpreadEnergy,
1291
0
              (&psyData[ch]->sfbSpreadEnergy)->Long,
1292
0
              MAX_GROUPED_SFB * sizeof(FIXP_DBL));
1293
    //        FDKmemcpy(psyOutChannel[ch]->mdctSpectrum,
1294
    //        psyData[ch]->mdctSpectrum, (1024)*sizeof(FIXP_DBL));
1295
0
  }
1296
1297
0
  return AAC_ENC_OK;
1298
0
}
1299
1300
0
void FDKaacEnc_PsyClose(PSY_INTERNAL **phPsyInternal, PSY_OUT **phPsyOut) {
1301
0
  int n, i;
1302
1303
0
  if (phPsyInternal != NULL) {
1304
0
    PSY_INTERNAL *hPsyInternal = *phPsyInternal;
1305
1306
0
    if (hPsyInternal) {
1307
0
      for (i = 0; i < (8); i++) {
1308
0
        if (hPsyInternal->pStaticChannels[i]) {
1309
0
          if (hPsyInternal->pStaticChannels[i]->psyInputBuffer)
1310
0
            FreeRam_aacEnc_PsyInputBuffer(
1311
0
                &hPsyInternal->pStaticChannels[i]
1312
0
                     ->psyInputBuffer); /* AUDIO INPUT BUFFER */
1313
1314
0
          FreeRam_aacEnc_PsyStatic(
1315
0
              &hPsyInternal->pStaticChannels[i]); /* PSY_STATIC */
1316
0
        }
1317
0
      }
1318
1319
0
      for (i = 0; i < ((8)); i++) {
1320
0
        if (hPsyInternal->psyElement[i])
1321
0
          FreeRam_aacEnc_PsyElement(
1322
0
              &hPsyInternal->psyElement[i]); /* PSY_ELEMENT */
1323
0
      }
1324
1325
0
      FreeRam_aacEnc_PsyInternal(phPsyInternal);
1326
0
    }
1327
0
  }
1328
1329
0
  if (phPsyOut != NULL) {
1330
0
    for (n = 0; n < (1); n++) {
1331
0
      if (phPsyOut[n]) {
1332
0
        for (i = 0; i < (8); i++) {
1333
0
          if (phPsyOut[n]->pPsyOutChannels[i])
1334
0
            FreeRam_aacEnc_PsyOutChannel(
1335
0
                &phPsyOut[n]->pPsyOutChannels[i]); /* PSY_OUT_CHANNEL */
1336
0
        }
1337
1338
0
        for (i = 0; i < ((8)); i++) {
1339
0
          if (phPsyOut[n]->psyOutElement[i])
1340
0
            FreeRam_aacEnc_PsyOutElements(
1341
0
                &phPsyOut[n]->psyOutElement[i]); /* PSY_OUT_ELEMENTS */
1342
0
        }
1343
1344
0
        FreeRam_aacEnc_PsyOut(&phPsyOut[n]);
1345
0
      }
1346
0
    }
1347
0
  }
1348
0
}