summaryrefslogtreecommitdiffstats
path: root/fdk-aac/libSBRenc/src/fram_gen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'fdk-aac/libSBRenc/src/fram_gen.cpp')
-rw-r--r--fdk-aac/libSBRenc/src/fram_gen.cpp1965
1 files changed, 1965 insertions, 0 deletions
diff --git a/fdk-aac/libSBRenc/src/fram_gen.cpp b/fdk-aac/libSBRenc/src/fram_gen.cpp
new file mode 100644
index 0000000..7ed6e79
--- /dev/null
+++ b/fdk-aac/libSBRenc/src/fram_gen.cpp
@@ -0,0 +1,1965 @@
+/* -----------------------------------------------------------------------------
+Software License for The Fraunhofer FDK AAC Codec Library for Android
+
+© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+Forschung e.V. All rights reserved.
+
+ 1. INTRODUCTION
+The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
+that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
+scheme for digital audio. This FDK AAC Codec software is intended to be used on
+a wide variety of Android devices.
+
+AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
+general perceptual audio codecs. AAC-ELD is considered the best-performing
+full-bandwidth communications codec by independent studies and is widely
+deployed. AAC has been standardized by ISO and IEC as part of the MPEG
+specifications.
+
+Patent licenses for necessary patent claims for the FDK AAC Codec (including
+those of Fraunhofer) may be obtained through Via Licensing
+(www.vialicensing.com) or through the respective patent owners individually for
+the purpose of encoding or decoding bit streams in products that are compliant
+with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
+Android devices already license these patent claims through Via Licensing or
+directly from the patent owners, and therefore FDK AAC Codec software may
+already be covered under those patent licenses when it is used for those
+licensed purposes only.
+
+Commercially-licensed AAC software libraries, including floating-point versions
+with enhanced sound quality, are also available from Fraunhofer. Users are
+encouraged to check the Fraunhofer website for additional applications
+information and documentation.
+
+2. COPYRIGHT LICENSE
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted without payment of copyright license fees provided that you
+satisfy the following conditions:
+
+You must retain the complete text of this software license in redistributions of
+the FDK AAC Codec or your modifications thereto in source code form.
+
+You must retain the complete text of this software license in the documentation
+and/or other materials provided with redistributions of the FDK AAC Codec or
+your modifications thereto in binary form. You must make available free of
+charge copies of the complete source code of the FDK AAC Codec and your
+modifications thereto to recipients of copies in binary form.
+
+The name of Fraunhofer may not be used to endorse or promote products derived
+from this library without prior written permission.
+
+You may not charge copyright license fees for anyone to use, copy or distribute
+the FDK AAC Codec software or your modifications thereto.
+
+Your modified versions of the FDK AAC Codec must carry prominent notices stating
+that you changed the software and the date of any change. For modified versions
+of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
+must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
+AAC Codec Library for Android."
+
+3. NO PATENT LICENSE
+
+NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
+limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
+Fraunhofer provides no warranty of patent non-infringement with respect to this
+software.
+
+You may use this FDK AAC Codec software or modifications thereto only for
+purposes that are authorized by appropriate patent licenses.
+
+4. DISCLAIMER
+
+This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
+holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
+including but not limited to the implied warranties of merchantability and
+fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
+or consequential damages, including but not limited to procurement of substitute
+goods or services; loss of use, data, or profits, or business interruption,
+however caused and on any theory of liability, whether in contract, strict
+liability, or tort (including negligence), arising in any way out of the use of
+this software, even if advised of the possibility of such damage.
+
+5. CONTACT INFORMATION
+
+Fraunhofer Institute for Integrated Circuits IIS
+Attention: Audio and Multimedia Departments - FDK AAC LL
+Am Wolfsmantel 33
+91058 Erlangen, Germany
+
+www.iis.fraunhofer.de/amm
+amm-info@iis.fraunhofer.de
+----------------------------------------------------------------------------- */
+
+/**************************** SBR encoder library ******************************
+
+ Author(s):
+
+ Description:
+
+*******************************************************************************/
+
+#include "fram_gen.h"
+#include "sbr_misc.h"
+
+#include "genericStds.h"
+
+static const SBR_FRAME_INFO frameInfo1_2048 = {1, {0, 16}, {FREQ_RES_HIGH},
+ 0, 1, {0, 16}};
+
+static const SBR_FRAME_INFO frameInfo2_2048 = {
+ 2, {0, 8, 16}, {FREQ_RES_HIGH, FREQ_RES_HIGH}, 0, 2, {0, 8, 16}};
+
+static const SBR_FRAME_INFO frameInfo4_2048 = {
+ 4,
+ {0, 4, 8, 12, 16},
+ {FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH},
+ 0,
+ 2,
+ {0, 8, 16}};
+
+static const SBR_FRAME_INFO frameInfo1_2304 = {1, {0, 18}, {FREQ_RES_HIGH},
+ 0, 1, {0, 18}};
+
+static const SBR_FRAME_INFO frameInfo2_2304 = {
+ 2, {0, 9, 18}, {FREQ_RES_HIGH, FREQ_RES_HIGH}, 0, 2, {0, 9, 18}};
+
+static const SBR_FRAME_INFO frameInfo4_2304 = {
+ 4,
+ {0, 5, 9, 14, 18},
+ {FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH},
+ 0,
+ 2,
+ {0, 9, 18}};
+
+static const SBR_FRAME_INFO frameInfo1_1920 = {1, {0, 15}, {FREQ_RES_HIGH},
+ 0, 1, {0, 15}};
+
+static const SBR_FRAME_INFO frameInfo2_1920 = {
+ 2, {0, 8, 15}, {FREQ_RES_HIGH, FREQ_RES_HIGH}, 0, 2, {0, 8, 15}};
+
+static const SBR_FRAME_INFO frameInfo4_1920 = {
+ 4,
+ {0, 4, 8, 12, 15},
+ {FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH},
+ 0,
+ 2,
+ {0, 8, 15}};
+
+static const SBR_FRAME_INFO frameInfo1_1152 = {1, {0, 9}, {FREQ_RES_HIGH},
+ 0, 1, {0, 9}};
+
+static const SBR_FRAME_INFO frameInfo2_1152 = {
+ 2, {0, 5, 9}, {FREQ_RES_HIGH, FREQ_RES_HIGH}, 0, 2, {0, 5, 9}};
+
+static const SBR_FRAME_INFO frameInfo4_1152 = {
+ 4,
+ {0, 2, 5, 7, 9},
+ {FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH},
+ 0,
+ 2,
+ {0, 5, 9}};
+
+/* AACLD frame info */
+static const SBR_FRAME_INFO frameInfo1_512LD = {1, {0, 8}, {FREQ_RES_HIGH},
+ 0, 1, {0, 8}};
+
+static const SBR_FRAME_INFO frameInfo2_512LD = {
+ 2, {0, 4, 8}, {FREQ_RES_HIGH, FREQ_RES_HIGH}, 0, 2, {0, 4, 8}};
+
+static const SBR_FRAME_INFO frameInfo4_512LD = {
+ 4,
+ {0, 2, 4, 6, 8},
+ {FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH},
+ 0,
+ 2,
+ {0, 4, 8}};
+
+static int calcFillLengthMax(
+ int tranPos, /*!< input : transient position (ref: tran det) */
+ int numberTimeSlots /*!< input : number of timeslots */
+);
+
+static void fillFrameTran(
+ const int *v_tuningSegm, /*!< tuning: desired segment lengths */
+ const int *v_tuningFreq, /*!< tuning: desired frequency resolutions */
+ int tran, /*!< input : position of transient */
+ int *v_bord, /*!< memNew: borders */
+ int *length_v_bord, /*!< memNew: # borders */
+ int *v_freq, /*!< memNew: frequency resolutions */
+ int *length_v_freq, /*!< memNew: # frequency resolutions */
+ int *bmin, /*!< hlpNew: first mandatory border */
+ int *bmax /*!< hlpNew: last mandatory border */
+);
+
+static void fillFramePre(INT dmax, INT *v_bord, INT *length_v_bord, INT *v_freq,
+ INT *length_v_freq, INT bmin, INT rest);
+
+static void fillFramePost(INT *parts, INT *d, INT dmax, INT *v_bord,
+ INT *length_v_bord, INT *v_freq, INT *length_v_freq,
+ INT bmax, INT bufferFrameStart, INT numberTimeSlots,
+ INT fmax);
+
+static void fillFrameInter(INT *nL, const int *v_tuningSegm, INT *v_bord,
+ INT *length_v_bord, INT bmin, INT *v_freq,
+ INT *length_v_freq, INT *v_bordFollow,
+ INT *length_v_bordFollow, INT *v_freqFollow,
+ INT *length_v_freqFollow, INT i_fillFollow, INT dmin,
+ INT dmax, INT numberTimeSlots);
+
+static void calcFrameClass(FRAME_CLASS *frameClass, FRAME_CLASS *frameClassOld,
+ INT tranFlag, INT *spreadFlag);
+
+static void specialCase(INT *spreadFlag, INT allowSpread, INT *v_bord,
+ INT *length_v_bord, INT *v_freq, INT *length_v_freq,
+ INT *parts, INT d);
+
+static void calcCmonBorder(INT *i_cmon, INT *i_tran, INT *v_bord,
+ INT *length_v_bord, INT tran, INT bufferFrameStart,
+ INT numberTimeSlots);
+
+static void keepForFollowUp(INT *v_bordFollow, INT *length_v_bordFollow,
+ INT *v_freqFollow, INT *length_v_freqFollow,
+ INT *i_tranFollow, INT *i_fillFollow, INT *v_bord,
+ INT *length_v_bord, INT *v_freq, INT i_cmon,
+ INT i_tran, INT parts, INT numberTimeSlots);
+
+static void calcCtrlSignal(HANDLE_SBR_GRID hSbrGrid, FRAME_CLASS frameClass,
+ INT *v_bord, INT length_v_bord, INT *v_freq,
+ INT length_v_freq, INT i_cmon, INT i_tran,
+ INT spreadFlag, INT nL);
+
+static void ctrlSignal2FrameInfo(HANDLE_SBR_GRID hSbrGrid,
+ HANDLE_SBR_FRAME_INFO hFrameInfo,
+ FREQ_RES *freq_res_fixfix);
+
+/* table for 8 time slot index */
+static const int envelopeTable_8[8][5] = {
+ /* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */
+ /* borders from left to right side; -1 = not in use */
+ /*[|T-|------]*/ {2, 0, 0, 1, -1},
+ /*[|-T-|-----]*/ {2, 0, 0, 2, -1},
+ /*[--|T-|----]*/ {3, 1, 1, 2, 4},
+ /*[---|T-|---]*/ {3, 1, 1, 3, 5},
+ /*[----|T-|--]*/ {3, 1, 1, 4, 6},
+ /*[-----|T--|]*/ {2, 1, 1, 5, -1},
+ /*[------|T-|]*/ {2, 1, 1, 6, -1},
+ /*[-------|T|]*/ {2, 1, 1, 7, -1},
+};
+
+/* table for 16 time slot index */
+static const int envelopeTable_16[16][6] = {
+ /* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */
+ /* length from left to right side; -1 = not in use */
+ /*[|T---|------------|]*/ {2, 0, 0, 4, -1, -1},
+ /*[|-T---|-----------|]*/ {2, 0, 0, 5, -1, -1},
+ /*[|--|T---|----------]*/ {3, 1, 1, 2, 6, -1},
+ /*[|---|T---|---------]*/ {3, 1, 1, 3, 7, -1},
+ /*[|----|T---|--------]*/ {3, 1, 1, 4, 8, -1},
+ /*[|-----|T---|-------]*/ {3, 1, 1, 5, 9, -1},
+ /*[|------|T---|------]*/ {3, 1, 1, 6, 10, -1},
+ /*[|-------|T---|-----]*/ {3, 1, 1, 7, 11, -1},
+ /*[|--------|T---|----]*/ {3, 1, 1, 8, 12, -1},
+ /*[|---------|T---|---]*/ {3, 1, 1, 9, 13, -1},
+ /*[|----------|T---|--]*/ {3, 1, 1, 10, 14, -1},
+ /*[|-----------|T----|]*/ {2, 1, 1, 11, -1, -1},
+ /*[|------------|T---|]*/ {2, 1, 1, 12, -1, -1},
+ /*[|-------------|T--|]*/ {2, 1, 1, 13, -1, -1},
+ /*[|--------------|T-|]*/ {2, 1, 1, 14, -1, -1},
+ /*[|---------------|T|]*/ {2, 1, 1, 15, -1, -1},
+};
+
+/* table for 15 time slot index */
+static const int envelopeTable_15[15][6] = {
+ /* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */
+ /* length from left to right side; -1 = not in use */
+ /*[|T---|------------]*/ {2, 0, 0, 4, -1, -1},
+ /*[|-T---|-----------]*/ {2, 0, 0, 5, -1, -1},
+ /*[|--|T---|---------]*/ {3, 1, 1, 2, 6, -1},
+ /*[|---|T---|--------]*/ {3, 1, 1, 3, 7, -1},
+ /*[|----|T---|-------]*/ {3, 1, 1, 4, 8, -1},
+ /*[|-----|T---|------]*/ {3, 1, 1, 5, 9, -1},
+ /*[|------|T---|-----]*/ {3, 1, 1, 6, 10, -1},
+ /*[|-------|T---|----]*/ {3, 1, 1, 7, 11, -1},
+ /*[|--------|T---|---]*/ {3, 1, 1, 8, 12, -1},
+ /*[|---------|T---|--]*/ {3, 1, 1, 9, 13, -1},
+ /*[|----------|T----|]*/ {2, 1, 1, 10, -1, -1},
+ /*[|-----------|T---|]*/ {2, 1, 1, 11, -1, -1},
+ /*[|------------|T--|]*/ {2, 1, 1, 12, -1, -1},
+ /*[|-------------|T-|]*/ {2, 1, 1, 13, -1, -1},
+ /*[|--------------|T|]*/ {2, 1, 1, 14, -1, -1},
+};
+
+static const int minFrameTranDistance = 4;
+
+static const FREQ_RES freqRes_table_8[] = {
+ FREQ_RES_LOW, FREQ_RES_LOW, FREQ_RES_LOW, FREQ_RES_LOW, FREQ_RES_LOW,
+ FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH};
+
+static const FREQ_RES freqRes_table_16[16] = {
+ /* size of envelope */
+ /* 0-4 */ FREQ_RES_LOW,
+ FREQ_RES_LOW,
+ FREQ_RES_LOW,
+ FREQ_RES_LOW,
+ FREQ_RES_LOW,
+ /* 5-9 */ FREQ_RES_LOW,
+ FREQ_RES_HIGH,
+ FREQ_RES_HIGH,
+ FREQ_RES_HIGH,
+ FREQ_RES_HIGH,
+ /* 10-16 */ FREQ_RES_HIGH,
+ FREQ_RES_HIGH,
+ FREQ_RES_HIGH,
+ FREQ_RES_HIGH,
+ FREQ_RES_HIGH,
+ FREQ_RES_HIGH};
+
+static void generateFixFixOnly(HANDLE_SBR_FRAME_INFO hSbrFrameInfo,
+ HANDLE_SBR_GRID hSbrGrid, int tranPosInternal,
+ int numberTimeSlots, UCHAR fResTransIsLow);
+
+/*!
+ Functionname: FDKsbrEnc_frameInfoGenerator
+
+ Description: produces the FRAME_INFO struct for the current frame
+
+ Arguments: hSbrEnvFrame - pointer to sbr envelope handle
+ v_pre_transient_info - pointer to transient info vector
+ v_transient_info - pointer to previous transient info
+vector v_tuning - pointer to tuning vector
+
+ Return: frame_info - pointer to SBR_FRAME_INFO struct
+
+*******************************************************************************/
+HANDLE_SBR_FRAME_INFO
+FDKsbrEnc_frameInfoGenerator(HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame,
+ UCHAR *v_transient_info, const INT rightBorderFIX,
+ UCHAR *v_transient_info_pre, int ldGrid,
+ const int *v_tuning) {
+ INT numEnv, tranPosInternal = 0, bmin = 0, bmax = 0, parts, d, i_cmon = 0,
+ i_tran = 0, nL;
+ INT fmax = 0;
+
+ INT *v_bord = hSbrEnvFrame->v_bord;
+ INT *v_freq = hSbrEnvFrame->v_freq;
+ INT *v_bordFollow = hSbrEnvFrame->v_bordFollow;
+ INT *v_freqFollow = hSbrEnvFrame->v_freqFollow;
+
+ INT *length_v_bordFollow = &hSbrEnvFrame->length_v_bordFollow;
+ INT *length_v_freqFollow = &hSbrEnvFrame->length_v_freqFollow;
+ INT *length_v_bord = &hSbrEnvFrame->length_v_bord;
+ INT *length_v_freq = &hSbrEnvFrame->length_v_freq;
+ INT *spreadFlag = &hSbrEnvFrame->spreadFlag;
+ INT *i_tranFollow = &hSbrEnvFrame->i_tranFollow;
+ INT *i_fillFollow = &hSbrEnvFrame->i_fillFollow;
+ FRAME_CLASS *frameClassOld = &hSbrEnvFrame->frameClassOld;
+ FRAME_CLASS frameClass = FIXFIX;
+
+ INT allowSpread = hSbrEnvFrame->allowSpread;
+ INT numEnvStatic = hSbrEnvFrame->numEnvStatic;
+ INT staticFraming = hSbrEnvFrame->staticFraming;
+ INT dmin = hSbrEnvFrame->dmin;
+ INT dmax = hSbrEnvFrame->dmax;
+
+ INT bufferFrameStart = hSbrEnvFrame->SbrGrid.bufferFrameStart;
+ INT numberTimeSlots = hSbrEnvFrame->SbrGrid.numberTimeSlots;
+ INT frameMiddleSlot = hSbrEnvFrame->frameMiddleSlot;
+
+ INT tranPos = v_transient_info[0];
+ INT tranFlag = v_transient_info[1];
+
+ const int *v_tuningSegm = v_tuning;
+ const int *v_tuningFreq = v_tuning + 3;
+
+ hSbrEnvFrame->v_tuningSegm = v_tuningSegm;
+
+ if (ldGrid) {
+ /* in case there was a transient at the very end of the previous frame,
+ * start with a transient envelope */
+ if (!tranFlag && v_transient_info_pre[1] &&
+ (numberTimeSlots - v_transient_info_pre[0] < minFrameTranDistance)) {
+ tranFlag = 1;
+ tranPos = 0;
+ }
+ }
+
+ /*
+ * Synopsis:
+ *
+ * The frame generator creates the time-/frequency-grid for one SBR frame.
+ * Input signals are provided by the transient detector and the frame
+ * splitter (transientDetectNew() & FrameSplitter() in tran_det.c). The
+ * framing is controlled by adjusting tuning parameters stored in
+ * FRAME_GEN_TUNING. The parameter values are dependent on frame lengths
+ * and bitrates, and may in the future be signal dependent.
+ *
+ * The envelope borders are stored for frame generator internal use in
+ * aBorders. The contents of aBorders represent positions along the time
+ * axis given in the figures in fram_gen.h (the "frame-generator" rows).
+ * The unit is "time slot". The figures in fram_gen.h also define the
+ * detection ranges for the transient detector. For every border in
+ * aBorders, there is a corresponding entry in aFreqRes, which defines the
+ * frequency resolution of the envelope following (delimited by) the
+ * border.
+ *
+ * When no transients are present, FIXFIX class frames are used. The
+ * frame splitter decides whether to use one or two envelopes in the
+ * FIXFIX frame. "Sparse transients" (separated by a few frames without
+ * transients) are handeled by [FIXVAR, VARFIX] pairs or (depending on
+ * tuning and transient position relative the nominal frame boundaries)
+ * by [FIXVAR, VARVAR, VARFIX] triples. "Tight transients" (in
+ * consecutive frames) are handeled by [..., VARVAR, VARVAR, ...]
+ * sequences.
+ *
+ * The generator assumes that transients are "sparse", and designs
+ * borders for [FIXVAR, VARFIX] pairs right away, where the first frame
+ * corresponds to the present frame. At the next call of the generator
+ * it is known whether the transient actually is "sparse" or not. If
+ * 'yes', the already calculated VARFIX borders are used. If 'no', new
+ * borders, meeting the requirements of the "tight" transient, are
+ * calculated.
+ *
+ * The generator produces two outputs: A "clear-text bitstream" stored in
+ * SBR_GRID, and a straight-forward representation of the grid stored in
+ * SBR_FRAME_INFO. The former is subsequently converted to the actual
+ * bitstream sbr_grid() (encodeSbrGrid() in bit_sbr.c). The latter is
+ * used by other encoder functions, such as the envelope estimator
+ * (calculateSbrEnvelope() in env_est.c) and the noise floor and missing
+ * harmonics detector (TonCorrParamExtr() in nf_est.c).
+ */
+
+ if (staticFraming) {
+ /*--------------------------------------------------------------------------
+ Ignore transient detector
+ ---------------------------------------------------------------------------*/
+
+ frameClass = FIXFIX;
+ numEnv = numEnvStatic; /* {1,2,4,8} */
+ *frameClassOld = FIXFIX; /* for change to dyn */
+ hSbrEnvFrame->SbrGrid.bs_num_env = numEnv;
+ hSbrEnvFrame->SbrGrid.frameClass = frameClass;
+ } else {
+ /*--------------------------------------------------------------------------
+ Calculate frame class to use
+ ---------------------------------------------------------------------------*/
+ if (rightBorderFIX) {
+ tranFlag = 0;
+ *spreadFlag = 0;
+ }
+ calcFrameClass(&frameClass, frameClassOld, tranFlag, spreadFlag);
+
+ /* patch for new frame class FIXFIXonly for AAC LD */
+ if (tranFlag && ldGrid) {
+ frameClass = FIXFIXonly;
+ *frameClassOld = FIXFIX;
+ }
+
+ /*
+ * every transient is processed below by inserting
+ *
+ * - one border at the onset of the transient
+ * - one or more "decay borders" (after the onset of the transient)
+ * - optionally one "attack border" (before the onset of the transient)
+ *
+ * those borders are referred to as "mandatory borders" and are
+ * defined by the 'segmentLength' array in FRAME_GEN_TUNING
+ *
+ * the frequency resolutions of the corresponding envelopes are
+ * defined by the 'segmentRes' array in FRAME_GEN_TUNING
+ */
+
+ /*--------------------------------------------------------------------------
+ Design frame (or follow-up old design)
+ ---------------------------------------------------------------------------*/
+ if (tranFlag) {
+ /* Always for FixVar, often but not always for VarVar */
+
+ /*--------------------------------------------------------------------------
+ Design part of T/F-grid around the new transient
+ ---------------------------------------------------------------------------*/
+
+ tranPosInternal =
+ frameMiddleSlot + tranPos + bufferFrameStart; /* FH 00-06-26 */
+ /*
+ add mandatory borders around transient
+ */
+
+ fillFrameTran(v_tuningSegm, v_tuningFreq, tranPosInternal, v_bord,
+ length_v_bord, v_freq, length_v_freq, &bmin, &bmax);
+
+ /* make sure we stay within the maximum SBR frame overlap */
+ fmax = calcFillLengthMax(tranPos, numberTimeSlots);
+ }
+
+ switch (frameClass) {
+ case FIXFIXonly:
+ FDK_ASSERT(ldGrid);
+ tranPosInternal = tranPos;
+ generateFixFixOnly(&(hSbrEnvFrame->SbrFrameInfo),
+ &(hSbrEnvFrame->SbrGrid), tranPosInternal,
+ numberTimeSlots, hSbrEnvFrame->fResTransIsLow);
+
+ return &(hSbrEnvFrame->SbrFrameInfo);
+
+ case FIXVAR:
+
+ /*--------------------------------------------------------------------------
+ Design remaining parts of T/F-grid (assuming next frame is VarFix)
+ ---------------------------------------------------------------------------*/
+
+ /*--------------------------------------------------------------------------
+ Fill region before new transient:
+ ---------------------------------------------------------------------------*/
+ fillFramePre(dmax, v_bord, length_v_bord, v_freq, length_v_freq, bmin,
+ bmin - bufferFrameStart); /* FH 00-06-26 */
+
+ /*--------------------------------------------------------------------------
+ Fill region after new transient:
+ ---------------------------------------------------------------------------*/
+ fillFramePost(&parts, &d, dmax, v_bord, length_v_bord, v_freq,
+ length_v_freq, bmax, bufferFrameStart, numberTimeSlots,
+ fmax);
+
+ /*--------------------------------------------------------------------------
+ Take care of special case:
+ ---------------------------------------------------------------------------*/
+ if (parts == 1 && d < dmin) /* no fill, short last envelope */
+ specialCase(spreadFlag, allowSpread, v_bord, length_v_bord, v_freq,
+ length_v_freq, &parts, d);
+
+ /*--------------------------------------------------------------------------
+ Calculate common border (split-point)
+ ---------------------------------------------------------------------------*/
+ calcCmonBorder(&i_cmon, &i_tran, v_bord, length_v_bord, tranPosInternal,
+ bufferFrameStart, numberTimeSlots); /* FH 00-06-26 */
+
+ /*--------------------------------------------------------------------------
+ Extract data for proper follow-up in next frame
+ ---------------------------------------------------------------------------*/
+ keepForFollowUp(v_bordFollow, length_v_bordFollow, v_freqFollow,
+ length_v_freqFollow, i_tranFollow, i_fillFollow, v_bord,
+ length_v_bord, v_freq, i_cmon, i_tran, parts,
+ numberTimeSlots); /* FH 00-06-26 */
+
+ /*--------------------------------------------------------------------------
+ Calculate control signal
+ ---------------------------------------------------------------------------*/
+ calcCtrlSignal(&hSbrEnvFrame->SbrGrid, frameClass, v_bord,
+ *length_v_bord, v_freq, *length_v_freq, i_cmon, i_tran,
+ *spreadFlag, DC);
+ break;
+ case VARFIX:
+ /*--------------------------------------------------------------------------
+ Follow-up old transient - calculate control signal
+ ---------------------------------------------------------------------------*/
+ calcCtrlSignal(&hSbrEnvFrame->SbrGrid, frameClass, v_bordFollow,
+ *length_v_bordFollow, v_freqFollow, *length_v_freqFollow,
+ DC, *i_tranFollow, *spreadFlag, DC);
+ break;
+ case VARVAR:
+ if (*spreadFlag) { /* spread across three frames */
+ /*--------------------------------------------------------------------------
+ Follow-up old transient - calculate control signal
+ ---------------------------------------------------------------------------*/
+ calcCtrlSignal(&hSbrEnvFrame->SbrGrid, frameClass, v_bordFollow,
+ *length_v_bordFollow, v_freqFollow,
+ *length_v_freqFollow, DC, *i_tranFollow, *spreadFlag,
+ DC);
+
+ *spreadFlag = 0;
+
+ /*--------------------------------------------------------------------------
+ Extract data for proper follow-up in next frame
+ ---------------------------------------------------------------------------*/
+ v_bordFollow[0] = hSbrEnvFrame->SbrGrid.bs_abs_bord_1 -
+ numberTimeSlots; /* FH 00-06-26 */
+ v_freqFollow[0] = 1;
+ *length_v_bordFollow = 1;
+ *length_v_freqFollow = 1;
+
+ *i_tranFollow = -DC;
+ *i_fillFollow = -DC;
+ } else {
+ /*--------------------------------------------------------------------------
+ Design remaining parts of T/F-grid (assuming next frame is VarFix)
+ adapt or fill region before new transient:
+ ---------------------------------------------------------------------------*/
+ fillFrameInter(&nL, v_tuningSegm, v_bord, length_v_bord, bmin, v_freq,
+ length_v_freq, v_bordFollow, length_v_bordFollow,
+ v_freqFollow, length_v_freqFollow, *i_fillFollow, dmin,
+ dmax, numberTimeSlots);
+
+ /*--------------------------------------------------------------------------
+ Fill after transient:
+ ---------------------------------------------------------------------------*/
+ fillFramePost(&parts, &d, dmax, v_bord, length_v_bord, v_freq,
+ length_v_freq, bmax, bufferFrameStart, numberTimeSlots,
+ fmax);
+
+ /*--------------------------------------------------------------------------
+ Take care of special case:
+ ---------------------------------------------------------------------------*/
+ if (parts == 1 && d < dmin) /*% no fill, short last envelope */
+ specialCase(spreadFlag, allowSpread, v_bord, length_v_bord, v_freq,
+ length_v_freq, &parts, d);
+
+ /*--------------------------------------------------------------------------
+ Calculate common border (split-point)
+ ---------------------------------------------------------------------------*/
+ calcCmonBorder(&i_cmon, &i_tran, v_bord, length_v_bord,
+ tranPosInternal, bufferFrameStart, numberTimeSlots);
+
+ /*--------------------------------------------------------------------------
+ Extract data for proper follow-up in next frame
+ ---------------------------------------------------------------------------*/
+ keepForFollowUp(v_bordFollow, length_v_bordFollow, v_freqFollow,
+ length_v_freqFollow, i_tranFollow, i_fillFollow,
+ v_bord, length_v_bord, v_freq, i_cmon, i_tran, parts,
+ numberTimeSlots);
+
+ /*--------------------------------------------------------------------------
+ Calculate control signal
+ ---------------------------------------------------------------------------*/
+ calcCtrlSignal(&hSbrEnvFrame->SbrGrid, frameClass, v_bord,
+ *length_v_bord, v_freq, *length_v_freq, i_cmon, i_tran,
+ 0, nL);
+ }
+ break;
+ case FIXFIX:
+ if (tranPos == 0)
+ numEnv = 1;
+ else
+ numEnv = 2;
+
+ hSbrEnvFrame->SbrGrid.bs_num_env = numEnv;
+ hSbrEnvFrame->SbrGrid.frameClass = frameClass;
+
+ break;
+ default:
+ FDK_ASSERT(0);
+ }
+ }
+
+ /*-------------------------------------------------------------------------
+ Convert control signal to frame info struct
+ ---------------------------------------------------------------------------*/
+ ctrlSignal2FrameInfo(&hSbrEnvFrame->SbrGrid, &hSbrEnvFrame->SbrFrameInfo,
+ hSbrEnvFrame->freq_res_fixfix);
+
+ return &hSbrEnvFrame->SbrFrameInfo;
+}
+
+/***************************************************************************/
+/*!
+ \brief Gnerates frame info for FIXFIXonly frame class used for low delay
+ version
+
+ \return nothing
+ ****************************************************************************/
+static void generateFixFixOnly(HANDLE_SBR_FRAME_INFO hSbrFrameInfo,
+ HANDLE_SBR_GRID hSbrGrid, int tranPosInternal,
+ int numberTimeSlots, UCHAR fResTransIsLow) {
+ int nEnv, i, k = 0, tranIdx;
+ const int *pTable = NULL;
+ const FREQ_RES *freqResTable = NULL;
+
+ switch (numberTimeSlots) {
+ case 8: {
+ pTable = envelopeTable_8[tranPosInternal];
+ }
+ freqResTable = freqRes_table_8;
+ break;
+ case 15:
+ pTable = envelopeTable_15[tranPosInternal];
+ freqResTable = freqRes_table_16;
+ break;
+ case 16:
+ pTable = envelopeTable_16[tranPosInternal];
+ freqResTable = freqRes_table_16;
+ break;
+ }
+
+ /* look number of envolpes in table */
+ nEnv = pTable[0];
+ /* look up envolpe distribution in table */
+ for (i = 1; i < nEnv; i++) hSbrFrameInfo->borders[i] = pTable[i + 2];
+
+ /* open and close frame border */
+ hSbrFrameInfo->borders[0] = 0;
+ hSbrFrameInfo->borders[nEnv] = numberTimeSlots;
+
+ /* adjust segment-frequency-resolution according to the segment-length */
+ for (i = 0; i < nEnv; i++) {
+ k = hSbrFrameInfo->borders[i + 1] - hSbrFrameInfo->borders[i];
+ if (!fResTransIsLow)
+ hSbrFrameInfo->freqRes[i] = freqResTable[k];
+ else
+ hSbrFrameInfo->freqRes[i] = FREQ_RES_LOW;
+
+ hSbrGrid->v_f[i] = hSbrFrameInfo->freqRes[i];
+ }
+
+ hSbrFrameInfo->nEnvelopes = nEnv;
+ hSbrFrameInfo->shortEnv = pTable[2];
+ /* transient idx */
+ tranIdx = pTable[1];
+
+ /* add noise floors */
+ hSbrFrameInfo->bordersNoise[0] = 0;
+ hSbrFrameInfo->bordersNoise[1] =
+ hSbrFrameInfo->borders[tranIdx ? tranIdx : 1];
+ hSbrFrameInfo->bordersNoise[2] = numberTimeSlots;
+ hSbrFrameInfo->nNoiseEnvelopes = 2;
+
+ hSbrGrid->frameClass = FIXFIXonly;
+ hSbrGrid->bs_abs_bord = tranPosInternal;
+ hSbrGrid->bs_num_env = nEnv;
+}
+
+/*******************************************************************************
+ Functionname: FDKsbrEnc_initFrameInfoGenerator
+ *******************************************************************************
+
+ Description:
+
+ Arguments: hSbrEnvFrame - pointer to sbr envelope handle
+ allowSpread - commandline parameter
+ numEnvStatic - commandline parameter
+ staticFraming - commandline parameter
+
+ Return: none
+
+*******************************************************************************/
+void FDKsbrEnc_initFrameInfoGenerator(HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame,
+ INT allowSpread, INT numEnvStatic,
+ INT staticFraming, INT timeSlots,
+ const FREQ_RES *freq_res_fixfix,
+ UCHAR fResTransIsLow,
+ INT ldGrid) { /* FH 00-06-26 */
+
+ FDKmemclear(hSbrEnvFrame, sizeof(SBR_ENVELOPE_FRAME));
+
+ /* Initialisation */
+ hSbrEnvFrame->frameClassOld = FIXFIX;
+ hSbrEnvFrame->spreadFlag = 0;
+
+ hSbrEnvFrame->allowSpread = allowSpread;
+ hSbrEnvFrame->numEnvStatic = numEnvStatic;
+ hSbrEnvFrame->staticFraming = staticFraming;
+ hSbrEnvFrame->freq_res_fixfix[0] = freq_res_fixfix[0];
+ hSbrEnvFrame->freq_res_fixfix[1] = freq_res_fixfix[1];
+ hSbrEnvFrame->fResTransIsLow = fResTransIsLow;
+
+ hSbrEnvFrame->length_v_bord = 0;
+ hSbrEnvFrame->length_v_bordFollow = 0;
+
+ hSbrEnvFrame->length_v_freq = 0;
+ hSbrEnvFrame->length_v_freqFollow = 0;
+
+ hSbrEnvFrame->i_tranFollow = 0;
+ hSbrEnvFrame->i_fillFollow = 0;
+
+ hSbrEnvFrame->SbrGrid.numberTimeSlots = timeSlots;
+
+ if (ldGrid) {
+ /*case CODEC_AACLD:*/
+ hSbrEnvFrame->dmin = 2;
+ hSbrEnvFrame->dmax = 16;
+ hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_512LD;
+ hSbrEnvFrame->SbrGrid.bufferFrameStart = 0;
+ } else
+ switch (timeSlots) {
+ case NUMBER_TIME_SLOTS_1920:
+ hSbrEnvFrame->dmin = 4;
+ hSbrEnvFrame->dmax = 12;
+ hSbrEnvFrame->SbrGrid.bufferFrameStart = 0;
+ hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_1920;
+ break;
+ case NUMBER_TIME_SLOTS_2048:
+ hSbrEnvFrame->dmin = 4;
+ hSbrEnvFrame->dmax = 12;
+ hSbrEnvFrame->SbrGrid.bufferFrameStart = 0;
+ hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_2048;
+ break;
+ case NUMBER_TIME_SLOTS_1152:
+ hSbrEnvFrame->dmin = 2;
+ hSbrEnvFrame->dmax = 8;
+ hSbrEnvFrame->SbrGrid.bufferFrameStart = 0;
+ hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_1152;
+ break;
+ case NUMBER_TIME_SLOTS_2304:
+ hSbrEnvFrame->dmin = 4;
+ hSbrEnvFrame->dmax = 15;
+ hSbrEnvFrame->SbrGrid.bufferFrameStart = 0;
+ hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_2304;
+ break;
+ default:
+ FDK_ASSERT(0);
+ }
+}
+
+/*******************************************************************************
+ Functionname: fillFrameTran
+ *******************************************************************************
+
+ Description: Add mandatory borders, as described by the tuning vector
+ and the current transient position
+
+ Arguments:
+ modified:
+ v_bord - int pointer to v_bord vector
+ length_v_bord - length of v_bord vector
+ v_freq - int pointer to v_freq vector
+ length_v_freq - length of v_freq vector
+ bmin - int pointer to bmin (call by reference)
+ bmax - int pointer to bmax (call by reference)
+ not modified:
+ tran - position of transient
+ v_tuningSegm - int pointer to v_tuningSegm vector
+ v_tuningFreq - int pointer to v_tuningFreq vector
+
+ Return: none
+
+*******************************************************************************/
+static void fillFrameTran(
+ const int *v_tuningSegm, /*!< tuning: desired segment lengths */
+ const int *v_tuningFreq, /*!< tuning: desired frequency resolutions */
+ int tran, /*!< input : position of transient */
+ int *v_bord, /*!< memNew: borders */
+ int *length_v_bord, /*!< memNew: # borders */
+ int *v_freq, /*!< memNew: frequency resolutions */
+ int *length_v_freq, /*!< memNew: # frequency resolutions */
+ int *bmin, /*!< hlpNew: first mandatory border */
+ int *bmax /*!< hlpNew: last mandatory border */
+) {
+ int bord, i;
+
+ *length_v_bord = 0;
+ *length_v_freq = 0;
+
+ /* add attack env leading border (optional) */
+ if (v_tuningSegm[0]) {
+ /* v_bord = [(Ba)] start of attack env */
+ FDKsbrEnc_AddRight(v_bord, length_v_bord, (tran - v_tuningSegm[0]));
+
+ /* v_freq = [(Fa)] res of attack env */
+ FDKsbrEnc_AddRight(v_freq, length_v_freq, v_tuningFreq[0]);
+ }
+
+ /* add attack env trailing border/first decay env leading border */
+ bord = tran;
+ FDKsbrEnc_AddRight(v_bord, length_v_bord, tran); /* v_bord = [(Ba),Bd1] */
+
+ /* add first decay env trailing border/2:nd decay env leading border */
+ if (v_tuningSegm[1]) {
+ bord += v_tuningSegm[1];
+
+ /* v_bord = [(Ba),Bd1,Bd2] */
+ FDKsbrEnc_AddRight(v_bord, length_v_bord, bord);
+
+ /* v_freq = [(Fa),Fd1] */
+ FDKsbrEnc_AddRight(v_freq, length_v_freq, v_tuningFreq[1]);
+ }
+
+ /* add 2:nd decay env trailing border (optional) */
+ if (v_tuningSegm[2] != 0) {
+ bord += v_tuningSegm[2];
+
+ /* v_bord = [(Ba),Bd1, Bd2,(Bd3)] */
+ FDKsbrEnc_AddRight(v_bord, length_v_bord, bord);
+
+ /* v_freq = [(Fa),Fd1,(Fd2)] */
+ FDKsbrEnc_AddRight(v_freq, length_v_freq, v_tuningFreq[2]);
+ }
+
+ /* v_freq = [(Fa),Fd1,(Fd2),1] */
+ FDKsbrEnc_AddRight(v_freq, length_v_freq, 1);
+
+ /* calc min and max values of mandatory borders */
+ *bmin = v_bord[0];
+ for (i = 0; i < *length_v_bord; i++)
+ if (v_bord[i] < *bmin) *bmin = v_bord[i];
+
+ *bmax = v_bord[0];
+ for (i = 0; i < *length_v_bord; i++)
+ if (v_bord[i] > *bmax) *bmax = v_bord[i];
+}
+
+/*******************************************************************************
+ Functionname: fillFramePre
+ *******************************************************************************
+
+ Description: Add borders before mandatory borders, if needed
+
+ Arguments:
+ modified:
+ v_bord - int pointer to v_bord vector
+ length_v_bord - length of v_bord vector
+ v_freq - int pointer to v_freq vector
+ length_v_freq - length of v_freq vector
+ not modified:
+ dmax - int value
+ bmin - int value
+ rest - int value
+
+ Return: none
+
+*******************************************************************************/
+static void fillFramePre(INT dmax, INT *v_bord, INT *length_v_bord, INT *v_freq,
+ INT *length_v_freq, INT bmin, INT rest) {
+ /*
+ input state:
+ v_bord = [(Ba),Bd1, Bd2 ,(Bd3)]
+ v_freq = [(Fa),Fd1,(Fd2),1 ]
+ */
+
+ INT parts, d, j, S, s = 0, segm, bord;
+
+ /*
+ start with one envelope
+ */
+
+ parts = 1;
+ d = rest;
+
+ /*
+ calc # of additional envelopes and corresponding lengths
+ */
+
+ while (d > dmax) {
+ parts++;
+
+ segm = rest / parts;
+ S = (segm - 2) >> 1;
+ s = fixMin(8, 2 * S + 2);
+ d = rest - (parts - 1) * s;
+ }
+
+ /*
+ add borders before mandatory borders
+ */
+
+ bord = bmin;
+
+ for (j = 0; j <= parts - 2; j++) {
+ bord = bord - s;
+
+ /* v_bord = [...,(Bf),(Ba),Bd1, Bd2 ,(Bd3)] */
+ FDKsbrEnc_AddLeft(v_bord, length_v_bord, bord);
+
+ /* v_freq = [...,(1 ),(Fa),Fd1,(Fd2), 1 ] */
+ FDKsbrEnc_AddLeft(v_freq, length_v_freq, 1);
+ }
+}
+
+/***************************************************************************/
+/*!
+ \brief Overlap control
+
+ Calculate max length of trailing fill segments, such that we always get a
+ border within the frame overlap region
+
+ \return void
+
+****************************************************************************/
+static int calcFillLengthMax(
+ int tranPos, /*!< input : transient position (ref: tran det) */
+ int numberTimeSlots /*!< input : number of timeslots */
+) {
+ int fmax;
+
+ /*
+ calculate transient position within envelope buffer
+ */
+ switch (numberTimeSlots) {
+ case NUMBER_TIME_SLOTS_2048:
+ if (tranPos < 4)
+ fmax = 6;
+ else if (tranPos == 4 || tranPos == 5)
+ fmax = 4;
+ else
+ fmax = 8;
+ break;
+
+ case NUMBER_TIME_SLOTS_1920:
+ if (tranPos < 4)
+ fmax = 5;
+ else if (tranPos == 4 || tranPos == 5)
+ fmax = 3;
+ else
+ fmax = 7;
+ break;
+
+ default:
+ fmax = 8;
+ break;
+ }
+
+ return fmax;
+}
+
+/*******************************************************************************
+ Functionname: fillFramePost
+ *******************************************************************************
+
+ Description: -Add borders after mandatory borders, if needed
+ Make a preliminary design of next frame,
+ assuming no transient is present there
+
+ Arguments:
+ modified:
+ parts - int pointer to parts (call by reference)
+ d - int pointer to d (call by reference)
+ v_bord - int pointer to v_bord vector
+ length_v_bord - length of v_bord vector
+ v_freq - int pointer to v_freq vector
+ length_v_freq - length of v_freq vector
+ not modified:
+ bmax - int value
+ dmax - int value
+
+ Return: none
+
+*******************************************************************************/
+static void fillFramePost(INT *parts, INT *d, INT dmax, INT *v_bord,
+ INT *length_v_bord, INT *v_freq, INT *length_v_freq,
+ INT bmax, INT bufferFrameStart, INT numberTimeSlots,
+ INT fmax) {
+ INT j, rest, segm, S, s = 0, bord;
+
+ /*
+ input state:
+ v_bord = [...,(Bf),(Ba),Bd1, Bd2 ,(Bd3)]
+ v_freq = [...,(1 ),(Fa),Fd1,(Fd2),1 ]
+ */
+
+ rest = bufferFrameStart + 2 * numberTimeSlots - bmax;
+ *d = rest;
+
+ if (*d > 0) {
+ *parts = 1; /* start with one envelope */
+
+ /* calc # of additional envelopes and corresponding lengths */
+
+ while (*d > dmax) {
+ *parts = *parts + 1;
+
+ segm = rest / (*parts);
+ S = (segm - 2) >> 1;
+ s = fixMin(fmax, 2 * S + 2);
+ *d = rest - (*parts - 1) * s;
+ }
+
+ /* add borders after mandatory borders */
+
+ bord = bmax;
+ for (j = 0; j <= *parts - 2; j++) {
+ bord += s;
+
+ /* v_bord = [...,(Bf),(Ba),Bd1, Bd2 ,(Bd3),(Bf)] */
+ FDKsbrEnc_AddRight(v_bord, length_v_bord, bord);
+
+ /* v_freq = [...,(1 ),(Fa),Fd1,(Fd2), 1 , 1! ,1] */
+ FDKsbrEnc_AddRight(v_freq, length_v_freq, 1);
+ }
+ } else {
+ *parts = 1;
+
+ /* remove last element from v_bord and v_freq */
+
+ *length_v_bord = *length_v_bord - 1;
+ *length_v_freq = *length_v_freq - 1;
+ }
+}
+
+/*******************************************************************************
+ Functionname: fillFrameInter
+ *******************************************************************************
+
+ Description:
+
+ Arguments: nL -
+ v_tuningSegm -
+ v_bord -
+ length_v_bord -
+ bmin -
+ v_freq -
+ length_v_freq -
+ v_bordFollow -
+ length_v_bordFollow -
+ v_freqFollow -
+ length_v_freqFollow -
+ i_fillFollow -
+ dmin -
+ dmax -
+
+ Return: none
+
+*******************************************************************************/
+static void fillFrameInter(INT *nL, const int *v_tuningSegm, INT *v_bord,
+ INT *length_v_bord, INT bmin, INT *v_freq,
+ INT *length_v_freq, INT *v_bordFollow,
+ INT *length_v_bordFollow, INT *v_freqFollow,
+ INT *length_v_freqFollow, INT i_fillFollow, INT dmin,
+ INT dmax, INT numberTimeSlots) {
+ INT middle, b_new, numBordFollow, bordMaxFollow, i;
+
+ if (numberTimeSlots != NUMBER_TIME_SLOTS_1152) {
+ /* % remove fill borders: */
+ if (i_fillFollow >= 1) {
+ *length_v_bordFollow = i_fillFollow;
+ *length_v_freqFollow = i_fillFollow;
+ }
+
+ numBordFollow = *length_v_bordFollow;
+ bordMaxFollow = v_bordFollow[numBordFollow - 1];
+
+ /* remove even more borders if needed */
+ middle = bmin - bordMaxFollow;
+ while (middle < 0) {
+ numBordFollow--;
+ bordMaxFollow = v_bordFollow[numBordFollow - 1];
+ middle = bmin - bordMaxFollow;
+ }
+
+ *length_v_bordFollow = numBordFollow;
+ *length_v_freqFollow = numBordFollow;
+ *nL = numBordFollow - 1;
+
+ b_new = *length_v_bord;
+
+ if (middle <= dmax) {
+ if (middle >= dmin) { /* concatenate */
+ FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow,
+ *length_v_bordFollow);
+ FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow,
+ *length_v_freqFollow);
+ }
+
+ else {
+ if (v_tuningSegm[0] != 0) { /* remove one new border and concatenate */
+ *length_v_bord = b_new - 1;
+ FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow,
+ *length_v_bordFollow);
+
+ *length_v_freq = b_new - 1;
+ FDKsbrEnc_AddVecLeft(v_freq + 1, length_v_freq, v_freqFollow,
+ *length_v_freqFollow);
+ } else {
+ if (*length_v_bordFollow >
+ 1) { /* remove one old border and concatenate */
+ FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow,
+ *length_v_bordFollow - 1);
+ FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow,
+ *length_v_bordFollow - 1);
+
+ *nL = *nL - 1;
+ } else { /* remove new "transient" border and concatenate */
+
+ for (i = 0; i < *length_v_bord - 1; i++) v_bord[i] = v_bord[i + 1];
+
+ for (i = 0; i < *length_v_freq - 1; i++) v_freq[i] = v_freq[i + 1];
+
+ *length_v_bord = b_new - 1;
+ *length_v_freq = b_new - 1;
+
+ FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow,
+ *length_v_bordFollow);
+ FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow,
+ *length_v_freqFollow);
+ }
+ }
+ }
+ } else { /* middle > dmax */
+
+ fillFramePre(dmax, v_bord, length_v_bord, v_freq, length_v_freq, bmin,
+ middle);
+ FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow,
+ *length_v_bordFollow);
+ FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow,
+ *length_v_freqFollow);
+ }
+
+ } else { /* numberTimeSlots==NUMBER_TIME_SLOTS_1152 */
+
+ INT l, m;
+
+ /*------------------------------------------------------------------------
+ remove fill borders
+ ------------------------------------------------------------------------*/
+ if (i_fillFollow >= 1) {
+ *length_v_bordFollow = i_fillFollow;
+ *length_v_freqFollow = i_fillFollow;
+ }
+
+ numBordFollow = *length_v_bordFollow;
+ bordMaxFollow = v_bordFollow[numBordFollow - 1];
+
+ /*------------------------------------------------------------------------
+ remove more borders if necessary to eliminate overlap
+ ------------------------------------------------------------------------*/
+
+ /* check for overlap */
+ middle = bmin - bordMaxFollow;
+
+ /* intervals:
+ i) middle < 0 : overlap, must remove borders
+ ii) 0 <= middle < dmin : no overlap but too tight, must remove
+ borders iii) dmin <= middle <= dmax : ok, just concatenate iv) dmax
+ <= middle : too wide, must add borders
+ */
+
+ /* first remove old non-fill-borders... */
+ while (middle < 0) {
+ /* ...but don't remove all of them */
+ if (numBordFollow == 1) break;
+
+ numBordFollow--;
+ bordMaxFollow = v_bordFollow[numBordFollow - 1];
+ middle = bmin - bordMaxFollow;
+ }
+
+ /* if this isn't enough, remove new non-fill borders */
+ if (middle < 0) {
+ for (l = 0, m = 0; l < *length_v_bord; l++) {
+ if (v_bord[l] > bordMaxFollow) {
+ v_bord[m] = v_bord[l];
+ v_freq[m] = v_freq[l];
+ m++;
+ }
+ }
+
+ *length_v_bord = l;
+ *length_v_freq = l;
+
+ bmin = v_bord[0];
+ }
+
+ /*------------------------------------------------------------------------
+ update modified follow-up data
+ ------------------------------------------------------------------------*/
+
+ *length_v_bordFollow = numBordFollow;
+ *length_v_freqFollow = numBordFollow;
+
+ /* left relative borders correspond to follow-up */
+ *nL = numBordFollow - 1;
+
+ /*------------------------------------------------------------------------
+ take care of intervals ii through iv
+ ------------------------------------------------------------------------*/
+
+ /* now middle should be >= 0 */
+ middle = bmin - bordMaxFollow;
+
+ if (middle <= dmin) /* (ii) */
+ {
+ b_new = *length_v_bord;
+
+ if (v_tuningSegm[0] != 0) {
+ /* remove new "luxury" border and concatenate */
+ *length_v_bord = b_new - 1;
+ FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow,
+ *length_v_bordFollow);
+
+ *length_v_freq = b_new - 1;
+ FDKsbrEnc_AddVecLeft(v_freq + 1, length_v_freq, v_freqFollow,
+ *length_v_freqFollow);
+
+ } else if (*length_v_bordFollow > 1) {
+ /* remove old border and concatenate */
+ FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow,
+ *length_v_bordFollow - 1);
+ FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow,
+ *length_v_bordFollow - 1);
+
+ *nL = *nL - 1;
+ } else {
+ /* remove new border and concatenate */
+ for (i = 0; i < *length_v_bord - 1; i++) v_bord[i] = v_bord[i + 1];
+
+ for (i = 0; i < *length_v_freq - 1; i++) v_freq[i] = v_freq[i + 1];
+
+ *length_v_bord = b_new - 1;
+ *length_v_freq = b_new - 1;
+
+ FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow,
+ *length_v_bordFollow);
+ FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow,
+ *length_v_freqFollow);
+ }
+ } else if ((middle >= dmin) && (middle <= dmax)) /* (iii) */
+ {
+ /* concatenate */
+ FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow,
+ *length_v_bordFollow);
+ FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow,
+ *length_v_freqFollow);
+
+ } else /* (iv) */
+ {
+ fillFramePre(dmax, v_bord, length_v_bord, v_freq, length_v_freq, bmin,
+ middle);
+ FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow,
+ *length_v_bordFollow);
+ FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow,
+ *length_v_freqFollow);
+ }
+ }
+}
+
+/*******************************************************************************
+ Functionname: calcFrameClass
+ *******************************************************************************
+
+ Description:
+
+ Arguments: INT* frameClass, INT* frameClassOld, INT tranFlag, INT* spreadFlag)
+
+ Return: none
+
+*******************************************************************************/
+static void calcFrameClass(FRAME_CLASS *frameClass, FRAME_CLASS *frameClassOld,
+ INT tranFlag, INT *spreadFlag) {
+ switch (*frameClassOld) {
+ case FIXFIXonly:
+ case FIXFIX:
+ if (tranFlag)
+ *frameClass = FIXVAR;
+ else
+ *frameClass = FIXFIX;
+ break;
+ case FIXVAR:
+ if (tranFlag) {
+ *frameClass = VARVAR;
+ *spreadFlag = 0;
+ } else {
+ if (*spreadFlag)
+ *frameClass = VARVAR;
+ else
+ *frameClass = VARFIX;
+ }
+ break;
+ case VARFIX:
+ if (tranFlag)
+ *frameClass = FIXVAR;
+ else
+ *frameClass = FIXFIX;
+ break;
+ case VARVAR:
+ if (tranFlag) {
+ *frameClass = VARVAR;
+ *spreadFlag = 0;
+ } else {
+ if (*spreadFlag)
+ *frameClass = VARVAR;
+ else
+ *frameClass = VARFIX;
+ }
+ break;
+ };
+
+ *frameClassOld = *frameClass;
+}
+
+/*******************************************************************************
+ Functionname: specialCase
+ *******************************************************************************
+
+ Description:
+
+ Arguments: spreadFlag
+ allowSpread
+ v_bord
+ length_v_bord
+ v_freq
+ length_v_freq
+ parts
+ d
+
+ Return: none
+
+*******************************************************************************/
+static void specialCase(INT *spreadFlag, INT allowSpread, INT *v_bord,
+ INT *length_v_bord, INT *v_freq, INT *length_v_freq,
+ INT *parts, INT d) {
+ INT L;
+
+ L = *length_v_bord;
+
+ if (allowSpread) { /* add one "step 8" */
+ *spreadFlag = 1;
+ FDKsbrEnc_AddRight(v_bord, length_v_bord, v_bord[L - 1] + 8);
+ FDKsbrEnc_AddRight(v_freq, length_v_freq, 1);
+ (*parts)++;
+ } else {
+ if (d == 1) { /* stretch one slot */
+ *length_v_bord = L - 1;
+ *length_v_freq = L - 1;
+ } else {
+ if ((v_bord[L - 1] - v_bord[L - 2]) > 2) { /* compress one quant step */
+ v_bord[L - 1] = v_bord[L - 1] - 2;
+ v_freq[*length_v_freq - 1] = 0; /* use low res for short segment */
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+ Functionname: calcCmonBorder
+ *******************************************************************************
+
+ Description:
+
+ Arguments: i_cmon
+ i_tran
+ v_bord
+ length_v_bord
+ tran
+
+ Return: none
+
+*******************************************************************************/
+static void calcCmonBorder(INT *i_cmon, INT *i_tran, INT *v_bord,
+ INT *length_v_bord, INT tran, INT bufferFrameStart,
+ INT numberTimeSlots) { /* FH 00-06-26 */
+ INT i;
+
+ for (i = 0; i < *length_v_bord; i++)
+ if (v_bord[i] >= bufferFrameStart + numberTimeSlots) { /* FH 00-06-26 */
+ *i_cmon = i;
+ break;
+ }
+
+ /* keep track of transient: */
+ for (i = 0; i < *length_v_bord; i++)
+ if (v_bord[i] >= tran) {
+ *i_tran = i;
+ break;
+ } else
+ *i_tran = EMPTY;
+}
+
+/*******************************************************************************
+ Functionname: keepForFollowUp
+ *******************************************************************************
+
+ Description:
+
+ Arguments: v_bordFollow
+ length_v_bordFollow
+ v_freqFollow
+ length_v_freqFollow
+ i_tranFollow
+ i_fillFollow
+ v_bord
+ length_v_bord
+ v_freq
+ i_cmon
+ i_tran
+ parts)
+
+ Return: none
+
+*******************************************************************************/
+static void keepForFollowUp(INT *v_bordFollow, INT *length_v_bordFollow,
+ INT *v_freqFollow, INT *length_v_freqFollow,
+ INT *i_tranFollow, INT *i_fillFollow, INT *v_bord,
+ INT *length_v_bord, INT *v_freq, INT i_cmon,
+ INT i_tran, INT parts,
+ INT numberTimeSlots) { /* FH 00-06-26 */
+ INT L, i, j;
+
+ L = *length_v_bord;
+
+ (*length_v_bordFollow) = 0;
+ (*length_v_freqFollow) = 0;
+
+ for (j = 0, i = i_cmon; i < L; i++, j++) {
+ v_bordFollow[j] = v_bord[i] - numberTimeSlots; /* FH 00-06-26 */
+ v_freqFollow[j] = v_freq[i];
+ (*length_v_bordFollow)++;
+ (*length_v_freqFollow)++;
+ }
+ if (i_tran != EMPTY)
+ *i_tranFollow = i_tran - i_cmon;
+ else
+ *i_tranFollow = EMPTY;
+ *i_fillFollow = L - (parts - 1) - i_cmon;
+}
+
+/*******************************************************************************
+ Functionname: calcCtrlSignal
+ *******************************************************************************
+
+ Description:
+
+ Arguments: hSbrGrid
+ frameClass
+ v_bord
+ length_v_bord
+ v_freq
+ length_v_freq
+ i_cmon
+ i_tran
+ spreadFlag
+ nL
+
+ Return: none
+
+*******************************************************************************/
+static void calcCtrlSignal(HANDLE_SBR_GRID hSbrGrid, FRAME_CLASS frameClass,
+ INT *v_bord, INT length_v_bord, INT *v_freq,
+ INT length_v_freq, INT i_cmon, INT i_tran,
+ INT spreadFlag, INT nL) {
+ INT i, r, a, n, p, b, aL, aR, ntot, nmax, nR;
+
+ INT *v_f = hSbrGrid->v_f;
+ INT *v_fLR = hSbrGrid->v_fLR;
+ INT *v_r = hSbrGrid->bs_rel_bord;
+ INT *v_rL = hSbrGrid->bs_rel_bord_0;
+ INT *v_rR = hSbrGrid->bs_rel_bord_1;
+
+ INT length_v_r = 0;
+ INT length_v_rR = 0;
+ INT length_v_rL = 0;
+
+ switch (frameClass) {
+ case FIXVAR:
+ /* absolute border: */
+
+ a = v_bord[i_cmon];
+
+ /* relative borders: */
+ length_v_r = 0;
+ i = i_cmon;
+
+ while (i >= 1) {
+ r = v_bord[i] - v_bord[i - 1];
+ FDKsbrEnc_AddRight(v_r, &length_v_r, r);
+ i--;
+ }
+
+ /* number of relative borders: */
+ n = length_v_r;
+
+ /* freq res: */
+ for (i = 0; i < i_cmon; i++) v_f[i] = v_freq[i_cmon - 1 - i];
+ v_f[i_cmon] = 1;
+
+ /* pointer: */
+ p = (i_cmon >= i_tran && i_tran != EMPTY) ? (i_cmon - i_tran + 1) : (0);
+
+ hSbrGrid->frameClass = frameClass;
+ hSbrGrid->bs_abs_bord = a;
+ hSbrGrid->n = n;
+ hSbrGrid->p = p;
+
+ break;
+ case VARFIX:
+ /* absolute border: */
+ a = v_bord[0];
+
+ /* relative borders: */
+ length_v_r = 0;
+
+ for (i = 1; i < length_v_bord; i++) {
+ r = v_bord[i] - v_bord[i - 1];
+ FDKsbrEnc_AddRight(v_r, &length_v_r, r);
+ }
+
+ /* number of relative borders: */
+ n = length_v_r;
+
+ /* freq res: */
+ FDKmemcpy(v_f, v_freq, length_v_freq * sizeof(INT));
+
+ /* pointer: */
+ p = (i_tran >= 0 && i_tran != EMPTY) ? (i_tran + 1) : (0);
+
+ hSbrGrid->frameClass = frameClass;
+ hSbrGrid->bs_abs_bord = a;
+ hSbrGrid->n = n;
+ hSbrGrid->p = p;
+
+ break;
+ case VARVAR:
+ if (spreadFlag) {
+ /* absolute borders: */
+ b = length_v_bord;
+
+ aL = v_bord[0];
+ aR = v_bord[b - 1];
+
+ /* number of relative borders: */
+ ntot = b - 2;
+
+ nmax = 2; /* n: {0,1,2} */
+ if (ntot > nmax) {
+ nL = nmax;
+ nR = ntot - nmax;
+ } else {
+ nL = ntot;
+ nR = 0;
+ }
+
+ /* relative borders: */
+ length_v_rL = 0;
+ for (i = 1; i <= nL; i++) {
+ r = v_bord[i] - v_bord[i - 1];
+ FDKsbrEnc_AddRight(v_rL, &length_v_rL, r);
+ }
+
+ length_v_rR = 0;
+ i = b - 1;
+ while (i >= b - nR) {
+ r = v_bord[i] - v_bord[i - 1];
+ FDKsbrEnc_AddRight(v_rR, &length_v_rR, r);
+ i--;
+ }
+
+ /* pointer (only one due to constraint in frame info): */
+ p = (i_tran > 0 && i_tran != EMPTY) ? (b - i_tran) : (0);
+
+ /* freq res: */
+
+ for (i = 0; i < b - 1; i++) v_fLR[i] = v_freq[i];
+ } else {
+ length_v_bord = i_cmon + 1;
+
+ /* absolute borders: */
+ b = length_v_bord;
+
+ aL = v_bord[0];
+ aR = v_bord[b - 1];
+
+ /* number of relative borders: */
+ ntot = b - 2;
+ nR = ntot - nL;
+
+ /* relative borders: */
+ length_v_rL = 0;
+ for (i = 1; i <= nL; i++) {
+ r = v_bord[i] - v_bord[i - 1];
+ FDKsbrEnc_AddRight(v_rL, &length_v_rL, r);
+ }
+
+ length_v_rR = 0;
+ i = b - 1;
+ while (i >= b - nR) {
+ r = v_bord[i] - v_bord[i - 1];
+ FDKsbrEnc_AddRight(v_rR, &length_v_rR, r);
+ i--;
+ }
+
+ /* pointer (only one due to constraint in frame info): */
+ p = (i_cmon >= i_tran && i_tran != EMPTY) ? (i_cmon - i_tran + 1) : (0);
+
+ /* freq res: */
+ for (i = 0; i < b - 1; i++) v_fLR[i] = v_freq[i];
+ }
+
+ hSbrGrid->frameClass = frameClass;
+ hSbrGrid->bs_abs_bord_0 = aL;
+ hSbrGrid->bs_abs_bord_1 = aR;
+ hSbrGrid->bs_num_rel_0 = nL;
+ hSbrGrid->bs_num_rel_1 = nR;
+ hSbrGrid->p = p;
+
+ break;
+
+ default:
+ /* do nothing */
+ break;
+ }
+}
+
+/*******************************************************************************
+ Functionname: createDefFrameInfo
+ *******************************************************************************
+
+ Description: Copies the default (static) frameInfo structs to the frameInfo
+ passed by reference; only used for FIXFIX frames
+
+ Arguments: hFrameInfo - HANLDE_SBR_FRAME_INFO
+ nEnv - INT
+ nTimeSlots - INT
+
+ Return: none; hSbrFrameInfo contains a copy of the default frameInfo
+
+ Written: Andreas Schneider
+ Revised:
+*******************************************************************************/
+static void createDefFrameInfo(HANDLE_SBR_FRAME_INFO hSbrFrameInfo, INT nEnv,
+ INT nTimeSlots) {
+ switch (nEnv) {
+ case 1:
+ switch (nTimeSlots) {
+ case NUMBER_TIME_SLOTS_1920:
+ FDKmemcpy(hSbrFrameInfo, &frameInfo1_1920, sizeof(SBR_FRAME_INFO));
+ break;
+ case NUMBER_TIME_SLOTS_2048:
+ FDKmemcpy(hSbrFrameInfo, &frameInfo1_2048, sizeof(SBR_FRAME_INFO));
+ break;
+ case NUMBER_TIME_SLOTS_1152:
+ FDKmemcpy(hSbrFrameInfo, &frameInfo1_1152, sizeof(SBR_FRAME_INFO));
+ break;
+ case NUMBER_TIME_SLOTS_2304:
+ FDKmemcpy(hSbrFrameInfo, &frameInfo1_2304, sizeof(SBR_FRAME_INFO));
+ break;
+ case NUMBER_TIME_SLOTS_512LD:
+ FDKmemcpy(hSbrFrameInfo, &frameInfo1_512LD, sizeof(SBR_FRAME_INFO));
+ break;
+ default:
+ FDK_ASSERT(0);
+ }
+ break;
+ case 2:
+ switch (nTimeSlots) {
+ case NUMBER_TIME_SLOTS_1920:
+ FDKmemcpy(hSbrFrameInfo, &frameInfo2_1920, sizeof(SBR_FRAME_INFO));
+ break;
+ case NUMBER_TIME_SLOTS_2048:
+ FDKmemcpy(hSbrFrameInfo, &frameInfo2_2048, sizeof(SBR_FRAME_INFO));
+ break;
+ case NUMBER_TIME_SLOTS_1152:
+ FDKmemcpy(hSbrFrameInfo, &frameInfo2_1152, sizeof(SBR_FRAME_INFO));
+ break;
+ case NUMBER_TIME_SLOTS_2304:
+ FDKmemcpy(hSbrFrameInfo, &frameInfo2_2304, sizeof(SBR_FRAME_INFO));
+ break;
+ case NUMBER_TIME_SLOTS_512LD:
+ FDKmemcpy(hSbrFrameInfo, &frameInfo2_512LD, sizeof(SBR_FRAME_INFO));
+ break;
+ default:
+ FDK_ASSERT(0);
+ }
+ break;
+ case 4:
+ switch (nTimeSlots) {
+ case NUMBER_TIME_SLOTS_1920:
+ FDKmemcpy(hSbrFrameInfo, &frameInfo4_1920, sizeof(SBR_FRAME_INFO));
+ break;
+ case NUMBER_TIME_SLOTS_2048:
+ FDKmemcpy(hSbrFrameInfo, &frameInfo4_2048, sizeof(SBR_FRAME_INFO));
+ break;
+ case NUMBER_TIME_SLOTS_1152:
+ FDKmemcpy(hSbrFrameInfo, &frameInfo4_1152, sizeof(SBR_FRAME_INFO));
+ break;
+ case NUMBER_TIME_SLOTS_2304:
+ FDKmemcpy(hSbrFrameInfo, &frameInfo4_2304, sizeof(SBR_FRAME_INFO));
+ break;
+ case NUMBER_TIME_SLOTS_512LD:
+ FDKmemcpy(hSbrFrameInfo, &frameInfo4_512LD, sizeof(SBR_FRAME_INFO));
+ break;
+ default:
+ FDK_ASSERT(0);
+ }
+ break;
+ default:
+ FDK_ASSERT(0);
+ }
+}
+
+/*******************************************************************************
+ Functionname: ctrlSignal2FrameInfo
+ *******************************************************************************
+
+ Description: Convert "clear-text" sbr_grid() to "frame info" used by the
+ envelope and noise floor estimators.
+ This is basically (except for "low level" calculations) the
+ bitstream decoder defined in the MPEG-4 standard, sub clause
+ 4.6.18.3.3, Time / Frequency Grid. See inline comments for
+ explanation of the shorten and noise border algorithms.
+
+ Arguments: hSbrGrid - source
+ hSbrFrameInfo - destination
+ freq_res_fixfix - frequency resolution for FIXFIX frames
+
+ Return: void; hSbrFrameInfo contains the updated FRAME_INFO struct
+
+*******************************************************************************/
+static void ctrlSignal2FrameInfo(
+ HANDLE_SBR_GRID hSbrGrid, /* input : the grid handle */
+ HANDLE_SBR_FRAME_INFO hSbrFrameInfo, /* output: the frame info handle */
+ FREQ_RES
+ *freq_res_fixfix /* in/out: frequency resolution for FIXFIX frames */
+) {
+ INT frameSplit = 0;
+ INT nEnv = 0, border = 0, i, k, p /*?*/;
+ INT *v_r = hSbrGrid->bs_rel_bord;
+ INT *v_f = hSbrGrid->v_f;
+
+ FRAME_CLASS frameClass = hSbrGrid->frameClass;
+ INT bufferFrameStart = hSbrGrid->bufferFrameStart;
+ INT numberTimeSlots = hSbrGrid->numberTimeSlots;
+
+ switch (frameClass) {
+ case FIXFIX:
+ createDefFrameInfo(hSbrFrameInfo, hSbrGrid->bs_num_env, numberTimeSlots);
+
+ frameSplit = (hSbrFrameInfo->nEnvelopes > 1);
+ for (i = 0; i < hSbrFrameInfo->nEnvelopes; i++) {
+ hSbrGrid->v_f[i] = hSbrFrameInfo->freqRes[i] =
+ freq_res_fixfix[frameSplit];
+ }
+ break;
+
+ case FIXVAR:
+ case VARFIX:
+ nEnv = hSbrGrid->n + 1; /* read n [SBR_NUM_BITS bits] */ /*? snd*/
+ FDK_ASSERT(nEnv <= MAX_ENVELOPES_FIXVAR_VARFIX);
+
+ hSbrFrameInfo->nEnvelopes = nEnv;
+
+ border = hSbrGrid->bs_abs_bord; /* read the absolute border */
+
+ if (nEnv == 1)
+ hSbrFrameInfo->nNoiseEnvelopes = 1;
+ else
+ hSbrFrameInfo->nNoiseEnvelopes = 2;
+
+ break;
+
+ default:
+ /* do nothing */
+ break;
+ }
+
+ switch (frameClass) {
+ case FIXVAR:
+ hSbrFrameInfo->borders[0] =
+ bufferFrameStart; /* start-position of 1st envelope */
+
+ hSbrFrameInfo->borders[nEnv] = border;
+
+ for (k = 0, i = nEnv - 1; k < nEnv - 1; k++, i--) {
+ border -= v_r[k];
+ hSbrFrameInfo->borders[i] = border;
+ }
+
+ /* make either envelope nr. nEnv + 1 - p short; or don't shorten if p == 0
+ */
+ p = hSbrGrid->p;
+ if (p == 0) {
+ hSbrFrameInfo->shortEnv = 0;
+ } else {
+ hSbrFrameInfo->shortEnv = nEnv + 1 - p;
+ }
+
+ for (k = 0, i = nEnv - 1; k < nEnv; k++, i--) {
+ hSbrFrameInfo->freqRes[i] = (FREQ_RES)v_f[k];
+ }
+
+ /* if either there is no short envelope or the last envelope is short...
+ */
+ if (p == 0 || p == 1) {
+ hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[nEnv - 1];
+ } else {
+ hSbrFrameInfo->bordersNoise[1] =
+ hSbrFrameInfo->borders[hSbrFrameInfo->shortEnv];
+ }
+
+ break;
+
+ case VARFIX:
+ /* in this case 'border' indicates the start of the 1st envelope */
+ hSbrFrameInfo->borders[0] = border;
+
+ for (k = 0; k < nEnv - 1; k++) {
+ border += v_r[k];
+ hSbrFrameInfo->borders[k + 1] = border;
+ }
+
+ hSbrFrameInfo->borders[nEnv] = bufferFrameStart + numberTimeSlots;
+
+ p = hSbrGrid->p;
+ if (p == 0 || p == 1) {
+ hSbrFrameInfo->shortEnv = 0;
+ } else {
+ hSbrFrameInfo->shortEnv = p - 1;
+ }
+
+ for (k = 0; k < nEnv; k++) {
+ hSbrFrameInfo->freqRes[k] = (FREQ_RES)v_f[k];
+ }
+
+ switch (p) {
+ case 0:
+ hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[1];
+ break;
+ case 1:
+ hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[nEnv - 1];
+ break;
+ default:
+ hSbrFrameInfo->bordersNoise[1] =
+ hSbrFrameInfo->borders[hSbrFrameInfo->shortEnv];
+ break;
+ }
+ break;
+
+ case VARVAR:
+ nEnv = hSbrGrid->bs_num_rel_0 + hSbrGrid->bs_num_rel_1 + 1;
+ FDK_ASSERT(nEnv <= MAX_ENVELOPES_VARVAR); /* just to be sure */
+ hSbrFrameInfo->nEnvelopes = nEnv;
+
+ hSbrFrameInfo->borders[0] = border = hSbrGrid->bs_abs_bord_0;
+
+ for (k = 0, i = 1; k < hSbrGrid->bs_num_rel_0; k++, i++) {
+ border += hSbrGrid->bs_rel_bord_0[k];
+ hSbrFrameInfo->borders[i] = border;
+ }
+
+ border = hSbrGrid->bs_abs_bord_1;
+ hSbrFrameInfo->borders[nEnv] = border;
+
+ for (k = 0, i = nEnv - 1; k < hSbrGrid->bs_num_rel_1; k++, i--) {
+ border -= hSbrGrid->bs_rel_bord_1[k];
+ hSbrFrameInfo->borders[i] = border;
+ }
+
+ p = hSbrGrid->p;
+ if (p == 0) {
+ hSbrFrameInfo->shortEnv = 0;
+ } else {
+ hSbrFrameInfo->shortEnv = nEnv + 1 - p;
+ }
+
+ for (k = 0; k < nEnv; k++) {
+ hSbrFrameInfo->freqRes[k] = (FREQ_RES)hSbrGrid->v_fLR[k];
+ }
+
+ if (nEnv == 1) {
+ hSbrFrameInfo->nNoiseEnvelopes = 1;
+ hSbrFrameInfo->bordersNoise[0] = hSbrGrid->bs_abs_bord_0;
+ hSbrFrameInfo->bordersNoise[1] = hSbrGrid->bs_abs_bord_1;
+ } else {
+ hSbrFrameInfo->nNoiseEnvelopes = 2;
+ hSbrFrameInfo->bordersNoise[0] = hSbrGrid->bs_abs_bord_0;
+
+ if (p == 0 || p == 1) {
+ hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[nEnv - 1];
+ } else {
+ hSbrFrameInfo->bordersNoise[1] =
+ hSbrFrameInfo->borders[hSbrFrameInfo->shortEnv];
+ }
+ hSbrFrameInfo->bordersNoise[2] = hSbrGrid->bs_abs_bord_1;
+ }
+ break;
+
+ default:
+ /* do nothing */
+ break;
+ }
+
+ if (frameClass == VARFIX || frameClass == FIXVAR) {
+ hSbrFrameInfo->bordersNoise[0] = hSbrFrameInfo->borders[0];
+ if (nEnv == 1) {
+ hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[nEnv];
+ } else {
+ hSbrFrameInfo->bordersNoise[2] = hSbrFrameInfo->borders[nEnv];
+ }
+ }
+}