summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/codecs/aacdec/trans4m_freq_2_time_fxp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/codecs/aacdec/trans4m_freq_2_time_fxp.cpp')
-rw-r--r--media/libstagefright/codecs/aacdec/trans4m_freq_2_time_fxp.cpp2604
1 files changed, 2604 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/aacdec/trans4m_freq_2_time_fxp.cpp b/media/libstagefright/codecs/aacdec/trans4m_freq_2_time_fxp.cpp
new file mode 100644
index 0000000..6ccc023
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/trans4m_freq_2_time_fxp.cpp
@@ -0,0 +1,2604 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: trans4m_freq_2_time_fxp.c
+ Function: trans4m_freq_2_time_fxp
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+ changed to decrement loop
+ change wnd_shape from structure to passing parameters
+ modified window tables from UInt to UInt16 to assure proper operation
+ without dubious typecast
+ changed logic to hit most common states first.
+ modified Time_data from Int to Int32 to hold
+ possible overflow before saturation process.
+
+ Description:
+ Increase processing on some loop by using more pointers
+ changed interface to avoid passing a pointer for wnd_shape_prev_bk, this
+ element is not change in this function because of this function use
+ in the LTP module
+
+ Description:
+ Added rounding to multiplication
+
+ Description:
+ Update input description and eliminate unneeded comments
+
+ Description:
+ LONG_START_WINDOW was using SHORT_WINDOW instead of
+ HALF_SHORT_WINDOW, causing a for loop to exceed its count
+
+ Description:
+ Modified structure of code so exp is not tested before it
+ is initialized. Also, new structure avoids double-testing
+ of exp_freq = ALL_ZEROS_BUFFER.
+
+ Description:
+ The result of a shift is undefined if the right operand is greater than
+ or equal to the number of bits in the left expression's type
+ To avoid undefined shift by 32, a check of the shift has been
+ added, so the function proceeds only when the exponent is less
+ than 32. By design the shift up is related to the global gain,
+ and controlled by the encoder, so saturation is not allowed.
+ In both short and long window, processing is skip if an all zero
+ input buffer or excessive down shift is detected.
+
+ Description:
+ Changes according to code review comments. Also, modified if-else
+ structure so the imdct_fxp is not called with an all zero input buffer
+
+ Description:
+ Replaced function buffer_normalization by buffer_adaptation, to ease
+ use of 16 bits. Function buffer_normalization becomes obsolete.
+
+ Description:
+ Modified call to imdct_fxp to reflect extended precision use. Added
+ routine buffer_adaptation to extract 16 MSB and keep highest.
+ precision. Modify casting to ensure proper operations for different
+ platforms
+
+ Description:
+ Eliminate double access to memory by loading data directly to the
+ time array. Also reduced cycle count and added precision by combining
+ downshifting in only one operation. Added adaptive rounding factor.
+ Change exponent threshold when operations are waived. It is use to be 32
+ but by combining downshifting, this new threshold is now 16. This may
+ avoid unneeded calculations for extremely small numbers.
+
+ Description:
+ Per review comments:
+ - Added comments to clarify buffer_adaptation function
+ - Deleted reference to include file "buffer_normalization.h"
+ - Modified IF-ELSE so long_windows case is considered first
+ - Eliminated extra IF when computing the rounding, so when exp ==0
+ less cycles are used shifting than in an extra if-else
+ - Corrected negative shift when computing rounding factor
+ - Added condition when exp > 16 (for long windows)
+
+ Description:
+ Modified IF-ELSE structure so now ALL_ZEROS_BUFFER condition is share
+ with exp > 16 condition. This avoid code duplication for both cases.
+
+ Description:
+ - Modified function interface to add output_buffer
+ - Eliminated the 32 bit version of the current output, calculations
+ are placed directly in output_buffer. In this way the buffer
+ Time_data needs only to be 1024 Int32, instead of 2048 (per channel).
+ Also, added the limit macro inside the function (this reduces access
+ to memory).
+ - Updated Pseudo - Code
+
+ Description:
+ Per review comments:
+ Corrected line sizes and mispelling, added comments and swap
+ order or switch statement for ONLY_LONG_SEQUENCE.
+
+ Description:
+ Eliminated adaptive rounding due to potential saturation.
+
+ Description:
+ Eliminated use of buffer adaptation by shifting this functionality inside
+ the imdct_fxp() routine. Also modified the call to imdct_fxp to accomodate
+ new function interface.
+ Modified macro limit() to save cycles when testing the most common case:
+ no saturation.
+
+ Description:
+ Changed new function interface for imdct_fxp().
+
+ Description:
+ Replaced for-loop with memset and memcopy.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ Frequency_data = vector with spectral information, size 2048
+ type Int32
+
+ Time_data = buffer with data from previous Frequency to Time
+ conversion, used for overlap and add, size 1024
+ type Int32
+
+ Output_buffer = place holder for current output, size 1024
+ type Int16
+
+ wnd_seq = window sequence
+ type WINDOW_SEQUENCE
+
+ wnd_shape_prev_bk = previous window shape type
+ type Int
+
+ wnd_shape_this_bk = current window shape type
+ type Int
+
+ Q_format = Q format for the input frequency data
+ type Int
+
+ freq_2_time_buffer[] = scratch memory for computing FFT
+ type Int32
+
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ Output_buffer
+ Time_data
+ Frequency_data
+ pWnd_shape_prev_bk
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+The time/frequency representation of the signal is mapped onto the time
+domain by feeding it into the filterbank module. This module consists of
+an inverse modified discrete cosine transform (IMDCT), and a window and an
+overlap-add function. In order to adapt the time/frequency resolution of the
+filterbank to the characteristics of the input signal, a block switching tool
+is also adopted. N represents the window length, where N is a function of the
+window_sequence. For each channel, the N/2 time-frequency values are
+transformed into the N time domain values via the IMDCT. After applying the
+window function, for each channel, the first half of the sequence is added to
+the second half of the previous block windowed sequence to reconstruct the
+output samples for each channel outi,n.
+
+The adaptation of the time-frequency resolution of the filterbank to the
+characteristics of the input signal is done by shifting between transforms
+whose input lengths are either 2048 or 256 samples. By enabling the block
+switching tool, the following transitions are meaningful:
+
+from ONLY_LONG_SEQUENCE to { LONG_START_SEQUENCE
+ ONLY_LONG_SEQUENCE
+
+from LONG_START_SEQUENCE to { LONG_STOP_SEQUENCE
+ EIGHT_SHORT_SEQUENCE
+
+from LONG_STOP_SEQUENCE to { LONG_START_SEQUENCE
+ ONLY_LONG_SEQUENCE
+
+from EIGHT_SHORT_SEQUENCE to { LONG_STOP_SEQUENCE
+ EIGHT_SHORT_SEQUENCE
+
+Window shape decisions are made by the encoder on a frame-by-frame-basis.
+The window selected is applicable to the second half of the window function
+only, since the first half is constrained to use the appropriate window
+shape from the preceding frame.
+The 2048 time-domain values x'(i)(n), (i window, n sample) to be windowed are
+the last 1024 values of the previous window_sequence concatenated with 1024
+values of the current block. The formula below shows this fact:
+
+ | x(i-1)(n+1024) for 0 < n < 1024
+ x'(i)(n) {
+ | x(i)(n) for 1024 < n < 2048
+
+
+Buffer Time_data data from previous Frequency to Time conversion, used
+for overlap and add
+
+Once the window shape is selected, the window_shape syntax element is
+initialized. Together with the chosen window_sequence all information needed
+for windowing exist.
+With the window halves described below all window_sequences can be assembled.
+For window_shape == 1, the window coefficients are given by the Kaiser -
+Bessel derived (KBD) window.
+Otherwise, for window_shape == 0, a sine window is employed.
+
+The window length N can be 2048 or 256 for the KBD and the sine window.
+All four window_sequences explained below have a total length of 2048
+samples.
+For all kinds of window_sequences the window_shape of the left half of
+the first transform window is determined by the window shape of the previous
+block.
+
+In the case of EIGHT_SHORT_SEQUENCE the processing is done in-place and
+in descendent order to avoid using extra memory.
+The ordering is as follows:
+
+ Pn: Previous data for window n
+ Cn: Current data for window n
+
+
+ 128 freq.
+ samples
+ FREQ ++++++
+IN ===========================
+ \
+ \
+ -> 256 time
+ samples
+
+ P8 C8
+ 8 #######++++++
+ P7 C7
+ 7 #######++++++
+ : :
+ : :
+ P2 C2
+ 2 #######++++++
+ P1 C1
+ 1 #######++++++
+ TIME
+OUT ==============================================================
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This module shall implement a scheme to switch between window types
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ISO 14496-3:1999, pag 111
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+
+ IF ( wnd_seq == EIGHT_SHORT_SEQUENCE)
+ THEN
+
+ FOR ( i=0; i<LONG_WINDOW; i++)
+ Time_data[LONG_WINDOW + i] = 0;
+ ENDFOR
+
+ FOR ( wnd=NUM_SHORT_WINDOWS-1; wnd>=0; wnd--)
+
+ pFreqInfo = &Frequency_data[ wnd*SHORT_WINDOW];
+
+ CALL IMDCT( pFreqInfo, SHORT_BLOCK1);
+ MODIFYING(pFreqInfo)
+
+
+ IF (wnd == 0)
+ THEN
+ pShort_Window_1 = &Short_Window[wnd_shape_prev_bk][0];
+ ELSE
+ pShort_Window_1 = &Short_Window[wnd_shape_this_bk][0];
+ ENDIF
+
+ pShort_Window_2 =
+ &Short_Window[wnd_shape->this_bk][SHORT_WINDOW_m_1];
+
+ FOR( i=0, j=SHORT_WINDOW; i<SHORT_WINDOW; i++, j--)
+ pFreqInfo[ i] *= pShort_Window_1[i];
+ pFreqInfo[SHORT_WINDOW+i] *= pShort_Window_2[j];
+ ENDFOR
+
+
+ FOR( i=0; i<SHORT_BLOCK1; i++)
+ Time_data[W_L_STOP_1 + SHORT_WINDOW*wnd + i] += pFreqInfo[i];
+ ENDFOR
+
+ ENDFOR
+
+ FOR ( i=0; i<LONG_WINDOW; i++)
+ temp = Time_data[i];
+ Output_buffer[i] = Time_data[i];
+ Time_data[i] = temp;
+ ENDFOR
+ ELSE
+
+ CALL IMDCT( Frequency_data, LONG_BLOCK1)
+ MODIFYING(Frequency_data)
+
+ SWITCH ( wnd_seq)
+
+ CASE ( ONLY_LONG_SEQUENCE)
+
+ pLong_Window_1 = &Long_Window[wnd_shape_prev_bk][0];
+ pLong_Window_2 =
+ &Long_Window[wnd_shape_this_bk][LONG_WINDOW_m_1];
+
+ FOR (i=0; i<LONG_WINDOW; i++)
+ Frequency_data[ i] *= *pLong_Window_1++;
+ Frequency_data[LONG_WINDOW+i] *= *pLong_Window_2--;
+ ENDFOR
+
+ BREAK
+
+ CASE ( LONG_START_SEQUENCE)
+
+ pLong_Window_1 = &Long_Window[wnd_shape_prev_bk][0];
+
+ FOR ( i=0; i<LONG_WINDOW; i++)
+ Frequency_data[ i] *= *pLong_Window_1++;
+ ENDFOR
+
+ pShort_Window_1 =
+ &Short_Window[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+
+ FOR ( i=0; i<SHORT_WINDOW; i++)
+ Frequency_data[W_L_START_1 + i] *= *pShort_Window_1--;
+ ENDFOR
+
+ FOR ( i=W_L_START_2; i<LONG_BLOCK1; i++)
+ Frequency_data[W_L_START_2 + i] = 0;
+ ENDFOR
+
+ BREAK
+
+
+ CASE ( LONG_STOP_SEQUENCE )
+
+ FOR ( i=0; i<W_L_STOP_1; i++)
+ Frequency_data[ i] = 0;
+ ENDFOR
+
+ pShort_Window_1 = &Short_Window[wnd_shape_prev_bk][0];
+
+ FOR ( i=0; i<SHORT_WINDOW; i++)
+ Frequency_data[W_L_STOP_1+ i] *= *pShort_Window_1++;
+ ENDFOR
+
+ pLong_Window_1 =
+ &Long_Window[wnd_shape_this_bk][LONG_WINDOW_m_1];
+
+ FOR ( i=0; i<LONG_WINDOW; i++)
+ Frequency_data[LONG_WINDOW + i] *= *pLong_Window_1--;
+ ENDFOR
+
+ BREAK
+
+ }
+
+
+ FOR ( i=0; i<LONG_WINDOW; i++)
+ Output_buffer[i] = Frequency_data[i] + Time_data[i];
+ Time_data[i] = Frequency_data[LONG_WINDOW+i];
+ ENDFOR
+
+ }
+
+ ENDIF
+
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+#include "aac_mem_funcs.h"
+#include "window_block_fxp.h"
+#include "imdct_fxp.h"
+
+#include "fxp_mul32.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; limit(x) saturates any number that exceeds a 16-bit representation into a
+; 16 bit number.
+----------------------------------------------------------------------------*/
+
+#define ROUNDING_SCALED (ROUNDING<<(16 - SCALING))
+
+
+#if defined(PV_ARM_V5)
+
+
+__inline Int16 sat(Int32 y)
+{
+ Int32 x;
+ Int32 z;
+ __asm
+ {
+ mov x, ROUNDING_SCALED
+ mov y, y, lsl #(15-SCALING)
+ qdadd z, x, y
+ mov y, z, lsr #16
+ }
+ return((Int16)y);
+}
+
+#define limiter( y, x) y = sat(x);
+
+
+
+#elif defined(PV_ARM_GCC_V5)
+
+
+__inline Int16 sat(Int32 y)
+{
+ register Int32 x;
+ register Int32 ra = (Int32)y;
+ register Int32 z = ROUNDING_SCALED;
+
+
+ asm volatile(
+ "mov %0, %1, lsl #5\n\t" // (15-SCALING) assembler does not take symbols
+ "qdadd %0, %2, %0\n\t"
+ "mov %0, %0, lsr #16"
+ : "=&r*i"(x)
+ : "r"(ra),
+ "r"(z));
+
+ return ((Int16)x);
+}
+
+#define limiter( y, x) y = sat(x);
+
+
+#elif defined(PV_ARM_MSC_EVC_V5)
+
+
+#define limiter( y, x) z = x<< (15-SCALING); \
+ y = _DAddSatInt( ROUNDING_SCALED, z)>>16;
+
+
+#else
+
+#define limiter( y, x) z = ((x + ROUNDING )>>SCALING); \
+ if ((z>>15) != (z>>31)) \
+ { \
+ z = (z >> 31) ^ INT16_MAX; \
+ } \
+ y = (Int16)(z);
+
+#endif
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+void trans4m_freq_2_time_fxp_1(
+ Int32 Frequency_data[],
+ Int32 Time_data[],
+ Int16 Output_buffer[],
+ WINDOW_SEQUENCE wnd_seq,
+ Int wnd_shape_prev_bk,
+ Int wnd_shape_this_bk,
+ Int Q_format,
+ Int32 abs_max_per_window[],
+ Int32 freq_2_time_buffer[])
+
+{
+ Int exp;
+ Int shift;
+
+ Int i;
+ Int wnd;
+#if !(defined( PV_ARM_GCC_V5)||(PV_ARM_V5))
+ Int32 z;
+#endif
+
+ Int16 *pFreqInfo;
+ Int32 temp;
+ Int32 test;
+
+ Int16 *pFreq_2_Time_data_1;
+ Int16 *pFreq_2_Time_data_2;
+
+ const Int16 *pLong_Window_1;
+ const Int16 *pLong_Window_2;
+ const Int16 *pShort_Window_1;
+ const Int16 *pShort_Window_2;
+
+ Int32 *pOverlap_and_Add_Buffer_1;
+ Int32 *pOverlap_and_Add_Buffer_2;
+
+ Int16 *pOutput_buffer;
+ Int16 *pOutput_buffer_2;
+
+ const Int16 * Long_Window_fxp[NUM_WINDOW_SHAPES];
+ const Int16 * Short_Window_fxp[NUM_WINDOW_SHAPES];
+
+ Long_Window_fxp[0] = Long_Window_sine_fxp;
+ Long_Window_fxp[1] = Long_Window_KBD_fxp;
+ Short_Window_fxp[0] = Short_Window_sine_fxp;
+ Short_Window_fxp[1] = Short_Window_KBD_fxp;
+
+
+ if (wnd_seq != EIGHT_SHORT_SEQUENCE)
+ {
+
+ pFreqInfo = (Int16 *)Frequency_data;
+
+
+ exp = imdct_fxp(
+ (Int32 *)pFreqInfo,
+ freq_2_time_buffer,
+ LONG_BLOCK1,
+ Q_format,
+ abs_max_per_window[0]);
+
+
+
+ /*
+ * The C Programming Language, Second Edition, Kernighan & Ritchie,
+ * page 206.
+ * "The result [of a shift] is undefined if the right operand is
+ * negative, or greater than or equal to the number of bits in the
+ * left expression's type"
+ * => avoid shift by 32 or 16
+ */
+
+ if (exp < 16)
+ {
+
+ pFreq_2_Time_data_1 = pFreqInfo;
+
+ switch (wnd_seq)
+ {
+
+ case ONLY_LONG_SEQUENCE:
+ default:
+
+ pOutput_buffer = Output_buffer;
+
+ pOverlap_and_Add_Buffer_1 = Time_data;
+
+ {
+ const Int16 *pLong_Window_2 = &Long_Window_fxp[wnd_shape_this_bk][LONG_WINDOW_m_1];
+
+ Int32 * pFreq2T = (Int32 *)pFreqInfo;
+ Int32 * win = (Int32 *) & Long_Window_fxp[wnd_shape_prev_bk][0];
+ Int shift = exp + 15 - SCALING;
+
+
+ Int32 * pFreq2T_2 = &pFreq2T[HALF_LONG_WINDOW];
+
+
+ for (i = HALF_LONG_WINDOW; i != 0; i--)
+ {
+ Int16 win1, win2;
+ Int32 temp2, test2;
+
+ Int32 winx;
+
+ temp2 = *(pFreq2T++);
+ winx = *(win++);
+
+ test = *(pOverlap_and_Add_Buffer_1++);
+ test2 = *(pOverlap_and_Add_Buffer_1--);
+ temp = fxp_mul_16_by_16bb(temp2, winx) >> shift;
+ temp2 = fxp_mul_16_by_16tt(temp2, winx) >> shift;
+ limiter(*(pOutput_buffer++), (temp + test));
+ limiter(*(pOutput_buffer++), (temp2 + test2));
+
+ temp2 = *(pFreq2T_2++);
+
+ win1 = *(pLong_Window_2--);
+ win2 = *(pLong_Window_2--);
+ temp = fxp_mul_16_by_16bb(temp2, win1) >> shift;
+ test2 = fxp_mul_16_by_16tb(temp2, win2) >> shift;
+ *(pOverlap_and_Add_Buffer_1++) = temp;
+ *(pOverlap_and_Add_Buffer_1++) = test2;
+
+ }
+ }
+
+ break;
+
+ case LONG_START_SEQUENCE:
+
+
+ pFreq_2_Time_data_2 =
+ &pFreq_2_Time_data_1[ HALF_LONG_WINDOW];
+
+ pLong_Window_1 = &Long_Window_fxp[wnd_shape_prev_bk][0];
+ pLong_Window_2 = &pLong_Window_1[ HALF_LONG_WINDOW];
+
+ pOverlap_and_Add_Buffer_1 = &Time_data[0];
+ pOverlap_and_Add_Buffer_2 = &Time_data[HALF_LONG_WINDOW];
+
+ pOutput_buffer = Output_buffer;
+ pOutput_buffer_2 = pOutput_buffer + HALF_LONG_WINDOW;
+
+
+ shift = exp + 15 - SCALING;
+
+ for (i = HALF_LONG_WINDOW; i != 0; i--)
+ {
+
+ Int16 win1, win2;
+ Int16 dat1, dat2;
+ Int32 test1, test2;
+
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pLong_Window_1++);
+ test1 = *(pOverlap_and_Add_Buffer_1++);
+
+ dat2 = *(pFreq_2_Time_data_2++);
+ win2 = *(pLong_Window_2++);
+ test2 = *(pOverlap_and_Add_Buffer_2++);
+
+ limiter(*(pOutput_buffer++), (test1 + (fxp_mul_16_by_16(dat1, win1) >> shift)));
+
+ limiter(*(pOutput_buffer_2++), (test2 + (fxp_mul_16_by_16(dat2, win2) >> shift)));
+
+ }
+
+ /*
+ * data unchanged from LONG_WINDOW to W_L_START_1
+ * only scaled accordingly
+ */
+
+ pOverlap_and_Add_Buffer_1 = &Time_data[0];
+ pFreq_2_Time_data_1 = &pFreqInfo[LONG_WINDOW];
+
+ exp -= SCALING;
+
+ if (exp >= 0)
+ {
+
+ for (i = (W_L_START_1 - LONG_WINDOW) >> 1; i != 0; i--)
+ {
+ *(pOverlap_and_Add_Buffer_1++) =
+ *(pFreq_2_Time_data_1++) >> exp;
+ *(pOverlap_and_Add_Buffer_1++) =
+ *(pFreq_2_Time_data_1++) >> exp;
+
+ }
+
+ }
+ else if (exp < 0)
+ {
+
+ Int shift = -exp;
+ for (i = (W_L_START_1 - LONG_WINDOW) >> 1; i != 0 ; i--)
+ {
+ Int32 temp2 = ((Int32) * (pFreq_2_Time_data_1++)) << shift;
+ *(pOverlap_and_Add_Buffer_1++) = temp2;
+ temp2 = ((Int32) * (pFreq_2_Time_data_1++)) << shift;
+ *(pOverlap_and_Add_Buffer_1++) = temp2;
+ }
+
+ }
+ else
+ {
+
+ for (i = (W_L_START_1 - LONG_WINDOW) >> 1; i != 0; i--)
+ {
+ *(pOverlap_and_Add_Buffer_1++) =
+ *(pFreq_2_Time_data_1++);
+ *(pOverlap_and_Add_Buffer_1++) =
+ *(pFreq_2_Time_data_1++);
+
+ }
+
+ }
+
+
+ pFreq_2_Time_data_1 = &pFreqInfo[W_L_START_1];
+ pFreq_2_Time_data_2 =
+ &pFreq_2_Time_data_1[HALF_SHORT_WINDOW];
+
+ pShort_Window_1 =
+ &Short_Window_fxp[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+
+ pShort_Window_2 = pShort_Window_1 - HALF_SHORT_WINDOW;
+
+ pOverlap_and_Add_Buffer_2 = pOverlap_and_Add_Buffer_1 +
+ HALF_SHORT_WINDOW;
+
+
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+ Int16 win1, win2;
+ Int16 dat1, dat2;
+ Int32 temp2;
+ dat1 = (*pFreq_2_Time_data_1++);
+ dat2 = (*pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_1--);
+ win2 = *(pShort_Window_2--);
+
+ temp = fxp_mul_16_by_16(dat1, win1) >> shift;
+ *(pOverlap_and_Add_Buffer_1++) = temp;
+
+ temp2 = fxp_mul_16_by_16(dat2, win2) >> shift;
+ *(pOverlap_and_Add_Buffer_2++) = temp2;
+
+
+ }
+
+
+ pOverlap_and_Add_Buffer_1 += HALF_SHORT_WINDOW;
+
+ pv_memset(
+ pOverlap_and_Add_Buffer_1,
+ 0,
+ (LONG_BLOCK1 - W_L_START_2)
+ *sizeof(*pOverlap_and_Add_Buffer_1));
+
+
+ break;
+
+
+ case LONG_STOP_SEQUENCE:
+
+ pOverlap_and_Add_Buffer_1 = &Time_data[ W_L_STOP_2];
+
+ pOutput_buffer = &Output_buffer[W_L_STOP_2];
+
+ pFreq_2_Time_data_1 = &pFreqInfo[W_L_STOP_2];
+
+ exp -= SCALING; /* !!!! */
+
+ if (exp > 0)
+ {
+ Int16 tmp1 = (*(pFreq_2_Time_data_1++) >> exp);
+ temp = *(pOverlap_and_Add_Buffer_1++);
+
+ for (i = (LONG_WINDOW - W_L_STOP_2); i != 0; i--)
+ {
+ limiter(*(pOutput_buffer++), (temp + tmp1));
+
+ tmp1 = *(pFreq_2_Time_data_1++) >> exp;
+ temp = *(pOverlap_and_Add_Buffer_1++);
+
+ }
+ }
+ else if (exp < 0)
+ {
+ shift = -exp;
+ Int32 temp1 = ((Int32) * (pFreq_2_Time_data_1++)) << shift;
+ temp = *(pOverlap_and_Add_Buffer_1++);
+
+ for (i = (LONG_WINDOW - W_L_STOP_2); i != 0; i--)
+ {
+ limiter(*(pOutput_buffer++), (temp + temp1));
+
+ temp1 = ((Int32) * (pFreq_2_Time_data_1++)) << shift;
+ temp = *(pOverlap_and_Add_Buffer_1++);
+
+ }
+ }
+ else
+ {
+ Int16 tmp1 = *(pFreq_2_Time_data_1++);
+ temp = *(pOverlap_and_Add_Buffer_1++);
+
+ for (i = (LONG_WINDOW - W_L_STOP_2); i != 0; i--)
+ {
+ limiter(*(pOutput_buffer++), (temp + tmp1));
+
+ tmp1 = *(pFreq_2_Time_data_1++);
+ temp = *(pOverlap_and_Add_Buffer_1++);
+
+ }
+ }
+
+
+ pShort_Window_1 = &Short_Window_fxp[wnd_shape_prev_bk][0];
+ pShort_Window_2 = &pShort_Window_1[HALF_SHORT_WINDOW];
+
+ pFreq_2_Time_data_1 = &pFreqInfo[W_L_STOP_1];
+ pFreq_2_Time_data_2 =
+ &pFreq_2_Time_data_1[HALF_SHORT_WINDOW];
+
+ pOverlap_and_Add_Buffer_1 = &Time_data[ W_L_STOP_1];
+ pOverlap_and_Add_Buffer_2 = pOverlap_and_Add_Buffer_1
+ + HALF_SHORT_WINDOW;
+
+ pOutput_buffer = &Output_buffer[W_L_STOP_1];
+ pOutput_buffer_2 = pOutput_buffer + HALF_SHORT_WINDOW;
+
+ exp += SCALING; /* +8 back to what it was */
+
+ shift = exp + 15 - SCALING;
+
+
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+ Int16 win1;
+ Int16 dat1;
+
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ temp = *(pOverlap_and_Add_Buffer_1++);
+
+ test = fxp_mul_16_by_16(dat1, win1);
+
+ limiter(*(pOutput_buffer++), (temp + (test >> shift)));
+
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2++);
+ temp = *(pOverlap_and_Add_Buffer_2++);
+ test = fxp_mul_16_by_16(dat1, win1);
+ limiter(*(pOutput_buffer_2++), (temp + (test >> shift)));
+
+ }
+
+
+ pFreq_2_Time_data_2 = &pFreqInfo[LONG_WINDOW];
+
+ pOverlap_and_Add_Buffer_1 = Time_data;
+
+ pOutput_buffer = Output_buffer;
+
+ pLong_Window_2 =
+ &Long_Window_fxp[wnd_shape_this_bk][LONG_WINDOW_m_1];
+
+
+ /*
+ * Copy previous time in current buffer, also copy overlap
+ * and add buffer
+ */
+
+ for (i = W_L_STOP_1; i != 0; i--)
+ {
+ Int16 win1;
+ Int16 dat1;
+
+ win1 = *(pLong_Window_2--);
+ dat1 = *pFreq_2_Time_data_2++;
+
+ limiter(*(pOutput_buffer++), *(pOverlap_and_Add_Buffer_1));
+
+
+ temp = fxp_mul_16_by_16(dat1, win1) >> shift;
+ *(pOverlap_and_Add_Buffer_1++) = temp ;
+
+ }
+
+ for (i = (LONG_WINDOW - W_L_STOP_1); i != 0; i--)
+ {
+ temp = fxp_mul_16_by_16(*pFreq_2_Time_data_2++, *(pLong_Window_2--)) >> shift;
+ *(pOverlap_and_Add_Buffer_1++) = temp ;
+ }
+
+
+ break;
+
+
+
+ } /* switch (wnd_seq) */
+
+ } /* if (exp < 16) */
+
+ else
+ {
+ /* all zeros buffer or excessive down shift */
+
+ /* Overlap and add, setup buffer for next iteration */
+ pOverlap_and_Add_Buffer_1 = &Time_data[0];
+
+ pOutput_buffer = Output_buffer;
+
+ temp = (*pOverlap_and_Add_Buffer_1++);
+
+ for (i = LONG_WINDOW; i != 0; i--)
+ {
+
+ limiter(*(pOutput_buffer++), temp);
+
+ temp = (*pOverlap_and_Add_Buffer_1++);
+
+ }
+
+ pv_memset(Time_data, 0, LONG_WINDOW*sizeof(Time_data[0]));
+
+
+ }
+
+ }
+ else
+ {
+
+ Int32 *pScrath_mem;
+ Int32 *pScrath_mem_entry;
+ Int32 *pFrequency_data = Frequency_data;
+
+ Int32 * pOverlap_and_Add_Buffer_1;
+ Int32 * pOverlap_and_Add_Buffer_2;
+ Int32 * pOverlap_and_Add_Buffer_1x;
+ Int32 * pOverlap_and_Add_Buffer_2x;
+
+ /*
+ * Frequency_data is 2*LONG_WINDOW length but only
+ * the first LONG_WINDOW elements are filled in,
+ * then the second part can be used as scratch mem,
+ * then grab data from one window at a time in
+ * reverse order.
+ * The upper LONG_WINDOW Int32 are used to hold the
+ * computed overlap and add, used in the next call to
+ * this function, and also as sctrach memory
+ */
+
+ /*
+ * Frequency_data usage for the case EIGHT_SHORT_SEQUENCE
+
+ |<----- Input Freq. data ----->|< Overlap & Add ->| Unused |-Scratch-|
+ | | Store for next | | memory |
+ | | call | | |
+ | | | | |
+ |//////////////////////////////|\\\\\\\\\\\\\\\\\\|--------|+++++++++|
+ | | | | |
+ 0 LONG_WINDOW LONG_WINDOW | 2*LONG_WINDOW
+ + | |
+ W_L_STOP_2 | |
+ |<-- -->|
+ SHORT_WINDOW +
+ HALF_SHORT_WINDOW
+ *
+ */
+
+ pOverlap_and_Add_Buffer_1 = &pFrequency_data[
+ LONG_WINDOW + 3*SHORT_WINDOW + HALF_SHORT_WINDOW];
+
+ /*
+ * Initialize to zero, only the firt short window used in overlap
+ * and add
+ */
+ pv_memset(
+ pOverlap_and_Add_Buffer_1,
+ 0,
+ SHORT_WINDOW*sizeof(*pOverlap_and_Add_Buffer_1));
+
+ /*
+ * Showt windows are evaluated in decresing order. Windows from 7
+ * to 0 are break down in four cases: window numbers 7 to 5, 4, 3,
+ * and 2 to 0.
+ * The data from short windows 3 and 4 is situated at the boundary
+ * between the 'overlap and add' buffer and the output buffer.
+ */
+ for (wnd = NUM_SHORT_WINDOWS - 1; wnd >= NUM_SHORT_WINDOWS / 2 + 1; wnd--)
+ {
+
+ pFreqInfo = (Int16 *) & pFrequency_data[ wnd*SHORT_WINDOW];
+
+ exp = imdct_fxp(
+ (Int32 *)pFreqInfo,
+ freq_2_time_buffer,
+ SHORT_BLOCK1,
+ Q_format,
+ abs_max_per_window[wnd]);
+
+ pOverlap_and_Add_Buffer_1 =
+ &pFrequency_data[ W_L_STOP_1 + SHORT_WINDOW*wnd];
+
+
+ pOverlap_and_Add_Buffer_2 =
+ pOverlap_and_Add_Buffer_1 + SHORT_WINDOW;
+
+ /*
+ * If all element are zero or if the exponent is bigger than
+ * 16 ( it becomes an undefined shift) -> skip
+ */
+
+ if (exp < 16)
+ {
+
+
+ pFreq_2_Time_data_1 = &pFreqInfo[0];
+ pFreq_2_Time_data_2 = &pFreqInfo[SHORT_WINDOW];
+
+
+ /*
+ * Each of the eight short blocks is windowed separately.
+ * Window shape decisions are made on a frame-by-frame
+ * basis.
+ */
+
+ pShort_Window_1 = &Short_Window_fxp[wnd_shape_this_bk][0];
+
+ pShort_Window_2 =
+ &Short_Window_fxp[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+
+
+
+
+ /*
+ * For short windows from 7 to 5
+ * | =========================
+ * | | 5 6 7
+ * _--_ _--_ _--_ _--_ | _-|-_ _--_ _--_ _--_
+ * / \/ \/ \/ \|/ | \/ \/ \/ \
+ * / /\ /\ /\ /|\ | /\ /\ /\ \
+ * / / \ / \ / \ / | \ | / \ / \ / \ \
+ * / / \/ \/ \/ | \|/ \/ \ \ \
+ * --------------------------------|---[///////////////////////]--------
+ *
+ */
+
+
+ shift = exp + 15 - SCALING;
+
+
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ Int16 win1, win2;
+ Int16 dat1, dat2;
+
+ dat2 = *(pFreq_2_Time_data_2++);
+ win2 = *(pShort_Window_2--);
+ temp = *pOverlap_and_Add_Buffer_2;
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+
+ *(pOverlap_and_Add_Buffer_2++) = temp + (fxp_mul_16_by_16(dat2, win2) >> shift);
+
+ *(pOverlap_and_Add_Buffer_1++) = fxp_mul_16_by_16(dat1, win1) >> shift;
+
+ }
+
+ } /* if (exp < 16) */
+ else
+ {
+ pv_memset(
+ pOverlap_and_Add_Buffer_1,
+ 0,
+ SHORT_WINDOW*sizeof(*pOverlap_and_Add_Buffer_1));
+ }
+
+
+ }/* for ( wnd=NUM_SHORT_WINDOWS-1; wnd>=NUM_SHORT_WINDOWS/2; wnd--) */
+
+
+ wnd = NUM_SHORT_WINDOWS / 2;
+
+ pFreqInfo = (Int16 *) & pFrequency_data[ wnd*SHORT_WINDOW];
+
+ /*
+ * scratch memory is allocated in an unused part of memory
+ */
+
+
+ pScrath_mem = &pFrequency_data[ 2*LONG_WINDOW - HALF_SHORT_WINDOW];
+
+ pOverlap_and_Add_Buffer_1 = &pFrequency_data[ LONG_WINDOW];
+
+ pOverlap_and_Add_Buffer_2 = pOverlap_and_Add_Buffer_1
+ + HALF_SHORT_WINDOW;
+
+
+ exp = imdct_fxp(
+ (Int32 *)pFreqInfo,
+ freq_2_time_buffer,
+ SHORT_BLOCK1,
+ Q_format,
+ abs_max_per_window[wnd]);
+
+ /*
+ * If all element are zero or if the exponent is bigger than
+ * 16 ( it becomes an undefined shift) -> skip
+ */
+
+
+ if (exp < 16)
+ {
+
+ pFreq_2_Time_data_1 = &pFreqInfo[0];
+ pFreq_2_Time_data_2 = &pFreqInfo[SHORT_WINDOW];
+
+ pShort_Window_1 = &Short_Window_fxp[wnd_shape_this_bk][0];
+
+ pShort_Window_2 =
+ &Short_Window_fxp[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+
+
+ /*
+ * For short window 4
+ * ====|===========
+ * | 4
+ * | | | |
+ * _--_ _--_ _--_ _-|-_ | _-|-_ _-|-_ _--_ _--_
+ * / \/ \/ \/ | \|/ | \/ | \/ \/ \
+ * / /\ /\ /\ | /|\ | /\ | /\ /\ \
+ * / / \ / \ / \ | / | \ | / \ | / \ / \ \
+ * / / \/ \/ \|/ | \|/ \|/ \/ \ \
+ * ------------------------------[\\\|\\\|//////]-------------------
+ * | | A | B | C |
+ * |
+ * W_L_STOP_1
+ */
+
+ shift = exp + 15 - SCALING;
+ {
+ Int16 win1;
+ Int16 dat1;
+ /* -------- segment A ---------------*/
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+ *(pScrath_mem++) = fxp_mul_16_by_16(dat1, win1) >> (shift);
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ }
+
+ /* -------- segment B ---------------*/
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+ *(pOverlap_and_Add_Buffer_1++) = fxp_mul_16_by_16(dat1, win1) >> shift;
+
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ }
+
+ /* -------- segment C ---------------*/
+ temp = *pOverlap_and_Add_Buffer_2;
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ *(pOverlap_and_Add_Buffer_2++) = temp + (fxp_mul_16_by_16(dat1, win1) >> shift);
+
+ temp = *pOverlap_and_Add_Buffer_2;
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+ }
+ }
+
+ } /* if (exp < 16) */
+ else
+ {
+ pv_memset(
+ pScrath_mem,
+ 0,
+ HALF_SHORT_WINDOW*sizeof(*pScrath_mem));
+
+ pv_memset(
+ pOverlap_and_Add_Buffer_1,
+ 0,
+ HALF_SHORT_WINDOW*sizeof(*pOverlap_and_Add_Buffer_1));
+ }
+
+
+ wnd = NUM_SHORT_WINDOWS / 2 - 1;
+
+ pFreqInfo = (Int16 *) & pFrequency_data[ wnd*SHORT_WINDOW];
+
+ pScrath_mem_entry =
+ &pFrequency_data[2*LONG_WINDOW - HALF_SHORT_WINDOW - SHORT_WINDOW];
+ pScrath_mem = pScrath_mem_entry;
+
+ pOverlap_and_Add_Buffer_1 = &pFrequency_data[ LONG_WINDOW];
+
+ /* point to end of buffer less HALF_SHORT_WINDOW */
+
+ pOutput_buffer_2 = &Output_buffer[LONG_WINDOW - HALF_SHORT_WINDOW];
+ pOutput_buffer = pOutput_buffer_2;
+
+ pOverlap_and_Add_Buffer_1x = &Time_data[W_L_STOP_1 + SHORT_WINDOW*(wnd+1)]; /* !!!! */
+
+ exp = imdct_fxp(
+ (Int32 *)pFreqInfo,
+ freq_2_time_buffer,
+ SHORT_BLOCK1,
+ Q_format,
+ abs_max_per_window[wnd]);
+
+ /*
+ * If all element are zero or if the exponent is bigger than
+ * 16 ( it becomes an undefined shift) -> skip
+ */
+
+ if (exp < 16)
+ {
+
+ pFreq_2_Time_data_1 = &pFreqInfo[0];
+ pFreq_2_Time_data_2 = &pFreqInfo[SHORT_WINDOW];
+
+
+ /*
+ * For short window 3
+ * ===========|====
+ * 3 |
+ * | | | |
+ * _--_ _--_ _-|-_ _-|-_ | _-|-_ _--_ _--_ _--_
+ * / \/ \/ | \/ | \|/ | \/ \/ \/ \
+ * / /\ /\ | /\ | /|\ | /\ /\ /\ \
+ * / / \ / \ | / \ | / | \ | / \ / \ / \ \
+ * / / \/ \|/ \|/ | \|/ \/ \ \ \
+ * -----|------------------[\\\\\\|///|///]--------------------------
+ * | | A | B | C |
+ *
+ * W_L_STOP_1
+ */
+
+
+ pShort_Window_1 = &Short_Window_fxp[wnd_shape_this_bk][0];
+
+ pShort_Window_2 =
+ &Short_Window_fxp[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+
+ shift = exp + 15 - SCALING;
+
+
+ Int16 win1;
+ Int16 dat1;
+ /* -------- segment A ---------------*/
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ *(pScrath_mem++) = fxp_mul_16_by_16(dat1, win1) >> shift;
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ }
+
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+
+ /* -------- segment B ---------------*/
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+ test = fxp_mul_16_by_16(dat1, win1) >> shift;
+
+ temp = *(pScrath_mem++) + test;
+
+
+ test = *(pOverlap_and_Add_Buffer_1x++); /* !!!! */
+
+ limiter(*(pOutput_buffer++), (temp + test));
+
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+
+ }
+
+ /* -------- segment C ---------------*/
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+ temp = fxp_mul_16_by_16(dat1, win1) >> (shift);
+
+ *(pOverlap_and_Add_Buffer_1++) += temp;
+
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+ }
+
+ } /* if (exp < 16) */
+ else
+ {
+
+ pv_memset(
+ pScrath_mem,
+ 0,
+ SHORT_WINDOW*sizeof(*pScrath_mem));
+
+ pScrath_mem += SHORT_WINDOW;
+
+ temp = *(pScrath_mem++);
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+ limiter(*(pOutput_buffer++), temp);
+ temp = *(pScrath_mem++);
+
+
+ }
+ }
+
+
+ for (wnd = NUM_SHORT_WINDOWS / 2 - 2; wnd >= 0; wnd--)
+ {
+
+
+ pOutput_buffer_2 -= SHORT_WINDOW;
+ pOutput_buffer = pOutput_buffer_2;
+
+ /*
+ * The same memory is used as scratch in every iteration
+ */
+ pScrath_mem = pScrath_mem_entry;
+
+ pOverlap_and_Add_Buffer_2x =
+ &Time_data[W_L_STOP_1 + SHORT_WINDOW*(wnd+1)];
+
+ pFreqInfo = (Int16 *) & pFrequency_data[ wnd*SHORT_WINDOW];
+
+
+
+ exp = imdct_fxp(
+ (Int32 *)pFreqInfo,
+ freq_2_time_buffer,
+ SHORT_BLOCK1,
+ Q_format,
+ abs_max_per_window[wnd]);
+
+ /*
+ * If all element are zero or if the exponent is bigger than
+ * 16 ( it becomes an undefined shift) -> skip
+ */
+
+ if (exp < 16)
+ {
+
+ pFreq_2_Time_data_1 = &pFreqInfo[0];
+ pFreq_2_Time_data_2 = &pFreqInfo[SHORT_WINDOW];
+
+
+ /*
+ * Each of the eight short blocks is windowed separately.
+ * Window shape decisions are made on a frame-by-frame
+ * basis.
+ */
+
+ pShort_Window_1 = &Short_Window_fxp[wnd_shape_this_bk][0];
+
+ if (wnd == 0)
+ {
+ pShort_Window_1 =
+ &Short_Window_fxp[wnd_shape_prev_bk][0];
+ }
+
+ pShort_Window_2 =
+ &Short_Window_fxp[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+
+
+ /*
+ * For short windows from 2 to 0
+ *
+ * =========================
+ * |
+ * 0 1 2 | |
+ * _--_ _--_ _--_ _-|-_ | _--_ _--_ _--_ _--_
+ * / \/ \/ \/ | \|/ \/ \/ \/ \
+ * / /\ /\ /\ | /|\ /\ /\ /\ \
+ * / / \ / \ / \ | / | \ / \ / \ / \ \
+ * / / \/ \/ \|/ | \/ \/ \ \ \
+ * ----[\\\\\\\\\\\\\\\\\\\\\\\\]---|-----------------------------
+ * |
+ *
+ * W_L_STOP_1
+ */
+
+ shift = exp + 15 - SCALING;
+
+ Int16 dat1 = *(pFreq_2_Time_data_2++);
+ Int16 win1 = *(pShort_Window_2--);
+
+ temp = *(pScrath_mem);
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ test = fxp_mul_16_by_16(dat1, win1) >> shift;
+
+ temp += test;
+
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+
+ limiter(*(pOutput_buffer++), (temp + *(pOverlap_and_Add_Buffer_2x++)));
+
+
+ *(pScrath_mem++) = fxp_mul_16_by_16(dat1, win1) >> shift;
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+ temp = *(pScrath_mem);
+
+ }
+
+ } /* if (exp < 16) */
+ else
+ {
+ test = *(pScrath_mem);
+ temp = *(pOverlap_and_Add_Buffer_2x++);
+
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ limiter(*(pOutput_buffer++), (temp + test));
+
+ *(pScrath_mem++) = 0;
+ test = *(pScrath_mem);
+ temp = *(pOverlap_and_Add_Buffer_2x++);
+
+ }
+ }
+
+ } /* for ( wnd=NUM_SHORT_WINDOWS/2-1; wnd>=0; wnd--) */
+
+ pOverlap_and_Add_Buffer_2x = &Time_data[W_L_STOP_1];
+
+ pScrath_mem = pScrath_mem_entry;
+
+ pOutput_buffer_2 -= SHORT_WINDOW;
+ pOutput_buffer = pOutput_buffer_2;
+
+ test = *(pScrath_mem++);
+ temp = *(pOverlap_and_Add_Buffer_2x++);
+
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ limiter(*(pOutput_buffer++), (temp + test));
+
+ test = *(pScrath_mem++);
+ temp = *(pOverlap_and_Add_Buffer_2x++);
+
+ }
+
+ pOverlap_and_Add_Buffer_1x = Time_data;
+
+ pOutput_buffer = Output_buffer;
+
+
+ temp = *(pOverlap_and_Add_Buffer_1x++);
+
+ for (i = W_L_STOP_1; i != 0; i--)
+ {
+ limiter(*(pOutput_buffer++), temp);
+
+ temp = *(pOverlap_and_Add_Buffer_1x++);
+ }
+
+ pOverlap_and_Add_Buffer_1x = &Time_data[0];
+
+ pOverlap_and_Add_Buffer_2 = &pFrequency_data[LONG_WINDOW];
+
+ /*
+ * update overlap and add buffer,
+ * so is ready for next iteration
+ */
+
+ for (int i = 0; i < W_L_STOP_2; i++)
+ {
+ temp = *(pOverlap_and_Add_Buffer_2++);
+ *(pOverlap_and_Add_Buffer_1x++) = temp;
+ }
+
+ pv_memset(
+ pOverlap_and_Add_Buffer_1x,
+ 0,
+ W_L_STOP_1*sizeof(*pOverlap_and_Add_Buffer_1x));
+
+ } /* if ( wnd_seq != EIGHT_SHORT_SEQUENCE) */
+
+}
+
+#endif
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+
+void trans4m_freq_2_time_fxp_2(
+ Int32 Frequency_data[],
+ Int32 Time_data[],
+ WINDOW_SEQUENCE wnd_seq,
+ Int wnd_shape_prev_bk,
+ Int wnd_shape_this_bk,
+ Int Q_format,
+ Int32 abs_max_per_window[],
+ Int32 freq_2_time_buffer[],
+ Int16 *Interleaved_output)
+
+{
+
+ Int exp;
+ Int shift;
+
+ Int i;
+ Int wnd;
+#if !(defined( PV_ARM_GCC_V5)||(PV_ARM_V5))
+ Int32 z;
+#endif
+ Int16 *pFreqInfo;
+ Int32 temp;
+ Int32 test;
+
+ Int16 *pFreq_2_Time_data_1;
+ Int16 *pFreq_2_Time_data_2;
+
+ const Int16 *pLong_Window_1;
+ const Int16 *pLong_Window_2;
+ const Int16 *pShort_Window_1;
+ const Int16 *pShort_Window_2;
+
+ Int32 *pOverlap_and_Add_Buffer_1;
+ Int32 *pOverlap_and_Add_Buffer_2;
+
+ Int16 *pInterleaved_output;
+ Int16 *pInterleaved_output_2;
+
+
+ const Int16 * Long_Window_fxp[NUM_WINDOW_SHAPES];
+ const Int16 * Short_Window_fxp[NUM_WINDOW_SHAPES];
+
+ Long_Window_fxp[0] = Long_Window_sine_fxp;
+ Long_Window_fxp[1] = Long_Window_KBD_fxp;
+ Short_Window_fxp[0] = Short_Window_sine_fxp;
+ Short_Window_fxp[1] = Short_Window_KBD_fxp;
+
+ if (wnd_seq != EIGHT_SHORT_SEQUENCE)
+ {
+
+ pFreqInfo = (Int16 *)Frequency_data;
+
+
+ exp = imdct_fxp(
+ (Int32 *)pFreqInfo,
+ freq_2_time_buffer,
+ LONG_BLOCK1,
+ Q_format,
+ abs_max_per_window[0]);
+
+
+ /*
+ * The C Programming Language, Second Edition, Kernighan & Ritchie,
+ * page 206.
+ * "The result [of a shift] is undefined if the right operand is
+ * negative, or greater than or equal to the number of bits in the
+ * left expression's type"
+ * => avoid shift by 32 or 16
+ */
+
+ if (exp < 16)
+ {
+
+ pFreq_2_Time_data_1 = pFreqInfo;
+
+
+ switch (wnd_seq)
+ {
+
+ case ONLY_LONG_SEQUENCE:
+ default:
+
+ {
+ pOverlap_and_Add_Buffer_1 = Time_data;
+
+ pInterleaved_output = Interleaved_output;
+
+ {
+
+ const Int16 *pLong_Window_2 = &Long_Window_fxp[wnd_shape_this_bk][LONG_WINDOW_m_1];
+
+ Int32 * pFreq2T = (Int32 *)pFreqInfo;
+ Int32 * pFreq2T_2 = &pFreq2T[HALF_LONG_WINDOW];
+ Int32 * win = (Int32 *) & Long_Window_fxp[wnd_shape_prev_bk][0];
+
+ Int shift = exp + 15 - SCALING;
+
+ for (i = HALF_LONG_WINDOW; i != 0; i--)
+ {
+ Int16 win1, win2;
+ Int32 temp2, test2;
+
+ Int32 winx;
+
+ temp2 = *(pFreq2T++);
+ winx = *(win++);
+
+ test = *(pOverlap_and_Add_Buffer_1++);
+ test2 = *(pOverlap_and_Add_Buffer_1--);
+ temp = fxp_mul_16_by_16bb(temp2, winx) >> shift;
+ temp2 = fxp_mul_16_by_16tt(temp2, winx) >> shift;
+
+ limiter(*(pInterleaved_output), (temp + test));
+
+ limiter(*(pInterleaved_output + 2), (temp2 + test2));
+ pInterleaved_output += 4;
+
+ temp2 = *(pFreq2T_2++);
+
+ win1 = *(pLong_Window_2--);
+ win2 = *(pLong_Window_2--);
+ temp = fxp_mul_16_by_16bb(temp2, win1) >> shift;
+ test2 = fxp_mul_16_by_16tb(temp2, win2) >> shift;
+
+ *(pOverlap_and_Add_Buffer_1++) = temp;
+ *(pOverlap_and_Add_Buffer_1++) = test2;
+ }
+
+ }
+
+ }
+
+ break;
+
+ case LONG_START_SEQUENCE:
+
+ pFreq_2_Time_data_2 =
+ &pFreq_2_Time_data_1[ HALF_LONG_WINDOW];
+
+ pLong_Window_1 = &Long_Window_fxp[wnd_shape_prev_bk][0];
+ pLong_Window_2 = &pLong_Window_1[ HALF_LONG_WINDOW];
+
+ pOverlap_and_Add_Buffer_1 = &Time_data[0];
+ pOverlap_and_Add_Buffer_2 = &Time_data[HALF_LONG_WINDOW];
+
+
+ pInterleaved_output = Interleaved_output;
+ pInterleaved_output_2 = pInterleaved_output + (2 * HALF_LONG_WINDOW);
+
+
+ /*
+ * process first LONG_WINDOW elements
+ */
+
+ shift = exp + 15 - SCALING;
+
+ for (i = HALF_LONG_WINDOW; i != 0; i--)
+ {
+ Int16 win1, win2;
+ Int16 dat1, dat2;
+ Int32 test1, test2;
+
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pLong_Window_1++);
+ test1 = *(pOverlap_and_Add_Buffer_1++);
+
+ dat2 = *(pFreq_2_Time_data_2++);
+ win2 = *(pLong_Window_2++);
+ test2 = *(pOverlap_and_Add_Buffer_2++);
+
+ limiter(*(pInterleaved_output), (test1 + (fxp_mul_16_by_16(dat1, win1) >> shift)));
+
+ pInterleaved_output += 2;
+
+ limiter(*(pInterleaved_output_2), (test2 + (fxp_mul_16_by_16(dat2, win2) >> shift)));
+
+ pInterleaved_output_2 += 2;
+ }
+
+
+ /*
+ * data unchanged from LONG_WINDOW to W_L_START_1
+ * only scaled accordingly
+ */
+
+ pOverlap_and_Add_Buffer_1 = &Time_data[0];
+ pFreq_2_Time_data_1 = &pFreqInfo[LONG_WINDOW];
+
+ exp -= SCALING;
+
+ if (exp >= 0)
+ {
+
+ for (i = (W_L_START_1 - LONG_WINDOW) >> 1; i != 0; i--)
+ {
+ *(pOverlap_and_Add_Buffer_1++) =
+ *(pFreq_2_Time_data_1++) >> exp;
+ *(pOverlap_and_Add_Buffer_1++) =
+ *(pFreq_2_Time_data_1++) >> exp;
+
+ }
+
+ }
+ else if (exp < 0)
+ {
+
+ Int shift = -exp;
+ for (i = (W_L_START_1 - LONG_WINDOW) >> 1; i != 0 ; i--)
+ {
+ Int32 temp2 = ((Int32) * (pFreq_2_Time_data_1++)) << shift;
+ *(pOverlap_and_Add_Buffer_1++) = temp2;
+ temp2 = ((Int32) * (pFreq_2_Time_data_1++)) << shift;
+ *(pOverlap_and_Add_Buffer_1++) = temp2;
+ }
+
+ }
+ else
+ {
+
+ for (i = (W_L_START_1 - LONG_WINDOW) >> 1; i != 0; i--)
+ {
+ *(pOverlap_and_Add_Buffer_1++) =
+ *(pFreq_2_Time_data_1++);
+ *(pOverlap_and_Add_Buffer_1++) =
+ *(pFreq_2_Time_data_1++);
+
+ }
+
+ }
+
+
+ pFreq_2_Time_data_1 = &pFreqInfo[W_L_START_1];
+ pFreq_2_Time_data_2 =
+ &pFreq_2_Time_data_1[HALF_SHORT_WINDOW];
+
+ pShort_Window_1 =
+ &Short_Window_fxp[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+
+ pShort_Window_2 = pShort_Window_1 - HALF_SHORT_WINDOW;
+
+ pOverlap_and_Add_Buffer_2 = pOverlap_and_Add_Buffer_1 +
+ HALF_SHORT_WINDOW;
+
+ {
+ Int16 win1, win2;
+ Int16 dat1, dat2;
+ Int32 temp2;
+
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+
+ dat1 = (*pFreq_2_Time_data_1++);
+ dat2 = (*pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_1--);
+ win2 = *(pShort_Window_2--);
+
+ temp = fxp_mul_16_by_16(dat1, win1) >> shift;
+ *(pOverlap_and_Add_Buffer_1++) = temp;
+
+ temp2 = fxp_mul_16_by_16(dat2, win2) >> shift;
+ *(pOverlap_and_Add_Buffer_2++) = temp2;
+
+ }
+ }
+
+ pOverlap_and_Add_Buffer_1 += HALF_SHORT_WINDOW;
+
+
+ pv_memset(
+ pOverlap_and_Add_Buffer_1,
+ 0,
+ (LONG_BLOCK1 - W_L_START_2)
+ *sizeof(*pOverlap_and_Add_Buffer_1));
+
+
+ break;
+
+
+ case LONG_STOP_SEQUENCE:
+
+ pOverlap_and_Add_Buffer_1 = &Time_data[ W_L_STOP_2];
+
+ pInterleaved_output = &Interleaved_output[2*W_L_STOP_2];
+
+ pFreq_2_Time_data_1 = &pFreqInfo[W_L_STOP_2];
+
+ exp -= SCALING;
+
+
+ if (exp > 0)
+ {
+ Int16 tmp1 = (*(pFreq_2_Time_data_1++) >> exp);
+ temp = *(pOverlap_and_Add_Buffer_1++);
+
+ for (i = (LONG_WINDOW - W_L_STOP_2); i != 0; i--)
+ {
+ limiter(*(pInterleaved_output), (temp + tmp1));
+
+ pInterleaved_output += 2;
+ tmp1 = *(pFreq_2_Time_data_1++) >> exp;
+ temp = *(pOverlap_and_Add_Buffer_1++);
+ }
+ }
+ else if (exp < 0)
+ {
+ shift = -exp;
+
+ Int32 temp1 = ((Int32) * (pFreq_2_Time_data_1++)) << shift;
+ temp = *(pOverlap_and_Add_Buffer_1++);
+
+ for (i = (LONG_WINDOW - W_L_STOP_2); i != 0; i--)
+ {
+ limiter(*(pInterleaved_output), (temp + temp1));
+
+ pInterleaved_output += 2;
+ temp1 = ((Int32) * (pFreq_2_Time_data_1++)) << shift;
+ temp = *(pOverlap_and_Add_Buffer_1++);
+ }
+ }
+ else
+ {
+ Int16 tmp1 = *(pFreq_2_Time_data_1++);
+ temp = *(pOverlap_and_Add_Buffer_1++);
+ for (i = (LONG_WINDOW - W_L_STOP_2); i != 0; i--)
+ {
+ limiter(*(pInterleaved_output), (temp + tmp1));
+
+ pInterleaved_output += 2;
+ tmp1 = *(pFreq_2_Time_data_1++);
+ temp = *(pOverlap_and_Add_Buffer_1++);
+ }
+ }
+
+
+
+ pShort_Window_1 = &Short_Window_fxp[wnd_shape_prev_bk][0];
+ pShort_Window_2 = &pShort_Window_1[HALF_SHORT_WINDOW];
+
+ pFreq_2_Time_data_1 = &pFreqInfo[W_L_STOP_1];
+ pFreq_2_Time_data_2 =
+ &pFreq_2_Time_data_1[HALF_SHORT_WINDOW];
+
+ pOverlap_and_Add_Buffer_1 = &Time_data[ W_L_STOP_1];
+ pOverlap_and_Add_Buffer_2 = pOverlap_and_Add_Buffer_1
+ + HALF_SHORT_WINDOW;
+
+
+ pInterleaved_output = &Interleaved_output[2*W_L_STOP_1];
+ pInterleaved_output_2 = pInterleaved_output + (2 * HALF_SHORT_WINDOW);
+
+ exp += SCALING; /* +8 back to what it was */
+ shift = exp + 15 - SCALING;
+
+
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+
+ Int16 win1;
+ Int16 dat1;
+
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ temp = *(pOverlap_and_Add_Buffer_1++);
+
+ test = fxp_mul_16_by_16(dat1, win1);
+
+ limiter(*(pInterleaved_output), (temp + (test >> shift)));
+
+ pInterleaved_output += 2;
+
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2++);
+ temp = *(pOverlap_and_Add_Buffer_2++);
+ test = fxp_mul_16_by_16(dat1, win1);
+
+ limiter(*(pInterleaved_output_2), (temp + (test >> shift)));
+
+ pInterleaved_output_2 += 2;
+
+ }
+
+
+
+ pFreq_2_Time_data_2 = &pFreqInfo[LONG_WINDOW];
+
+ pOverlap_and_Add_Buffer_1 = Time_data;
+
+
+ pInterleaved_output = Interleaved_output;
+
+ pLong_Window_2 =
+ &Long_Window_fxp[wnd_shape_this_bk][LONG_WINDOW_m_1];
+
+
+ /*
+ * Copy previous time in current buffer, also copy overlap
+ * and add buffer
+ */
+
+ for (i = W_L_STOP_1; i != 0; i--)
+ {
+
+ Int16 win1;
+ Int16 dat1;
+
+ win1 = *(pLong_Window_2--);
+ dat1 = *pFreq_2_Time_data_2++;
+
+ limiter(*(pInterleaved_output), *(pOverlap_and_Add_Buffer_1));
+
+ pInterleaved_output += 2;
+
+ temp = fxp_mul_16_by_16(dat1, win1) >> shift;
+ *(pOverlap_and_Add_Buffer_1++) = temp ;
+
+ }
+
+ for (i = (LONG_WINDOW - W_L_STOP_1); i != 0; i--)
+ {
+
+ temp = fxp_mul_16_by_16(*pFreq_2_Time_data_2++, *(pLong_Window_2--)) >> shift;
+ *(pOverlap_and_Add_Buffer_1++) = temp ;
+
+ }
+
+ break;
+
+
+
+ } /* switch (wnd_seq) */
+
+ } /* if (exp < 16) */
+
+ else
+ {
+ /* all zeros buffer or excessive down shift */
+
+ /* Overlap and add, setup buffer for next iteration */
+ pOverlap_and_Add_Buffer_1 = &Time_data[0];
+
+ pInterleaved_output = Interleaved_output;
+
+
+ temp = (*pOverlap_and_Add_Buffer_1++);
+ for (i = LONG_WINDOW; i != 0; i--)
+ {
+
+ limiter(*(pInterleaved_output), temp);
+
+ pInterleaved_output += 2;
+ temp = (*pOverlap_and_Add_Buffer_1++);
+ }
+ pv_memset(Time_data, 0, LONG_WINDOW*sizeof(Time_data[0]));
+ }
+
+ }
+ else
+ {
+
+ Int32 *pScrath_mem;
+ Int32 *pScrath_mem_entry;
+ Int32 *pFrequency_data = Frequency_data;
+
+ Int32 * pOverlap_and_Add_Buffer_1;
+ Int32 * pOverlap_and_Add_Buffer_2;
+ Int32 * pOverlap_and_Add_Buffer_1x;
+ Int32 * pOverlap_and_Add_Buffer_2x;
+
+
+ /*
+ * Frequency_data is 2*LONG_WINDOW length but only
+ * the first LONG_WINDOW elements are filled in,
+ * then the second part can be used as scratch mem,
+ * then grab data from one window at a time in
+ * reverse order.
+ * The upper LONG_WINDOW Int32 are used to hold the
+ * computed overlap and add, used in the next call to
+ * this function, and also as sctrach memory
+ */
+
+ /*
+ * Frequency_data usage for the case EIGHT_SHORT_SEQUENCE
+
+ |<----- Input Freq. data ----->|< Overlap & Add ->| Unused |-Scratch-|
+ | | Store for next | | memory |
+ | | call | | |
+ | | | | |
+ |//////////////////////////////|\\\\\\\\\\\\\\\\\\|--------|+++++++++|
+ | | | | |
+ 0 LONG_WINDOW LONG_WINDOW | 2*LONG_WINDOW
+ + | |
+ W_L_STOP_2 | |
+ |<-- -->|
+ SHORT_WINDOW +
+ HALF_SHORT_WINDOW
+ *
+ */
+
+ pOverlap_and_Add_Buffer_1 = &pFrequency_data[
+ LONG_WINDOW + 3*SHORT_WINDOW + HALF_SHORT_WINDOW];
+
+ /*
+ * Initialize to zero, only the firt short window used in overlap
+ * and add
+ */
+ pv_memset(
+ pOverlap_and_Add_Buffer_1,
+ 0,
+ SHORT_WINDOW*sizeof(*pOverlap_and_Add_Buffer_1));
+
+ /*
+ * Showt windows are evaluated in decresing order. Windows from 7
+ * to 0 are break down in four cases: window numbers 7 to 5, 4, 3,
+ * and 2 to 0.
+ * The data from short windows 3 and 4 is situated at the boundary
+ * between the 'overlap and add' buffer and the output buffer.
+ */
+ for (wnd = NUM_SHORT_WINDOWS - 1; wnd >= NUM_SHORT_WINDOWS / 2 + 1; wnd--)
+ {
+
+ pFreqInfo = (Int16 *) & pFrequency_data[ wnd*SHORT_WINDOW];
+
+ exp = imdct_fxp(
+ (Int32 *)pFreqInfo,
+ freq_2_time_buffer,
+ SHORT_BLOCK1,
+ Q_format,
+ abs_max_per_window[wnd]);
+
+ /* W_L_STOP_1 == (LONG_WINDOW - SHORT_WINDOW)>>1 */
+ pOverlap_and_Add_Buffer_1 =
+ &pFrequency_data[ W_L_STOP_1 + SHORT_WINDOW*wnd];
+
+
+ pOverlap_and_Add_Buffer_2 =
+ pOverlap_and_Add_Buffer_1 + SHORT_WINDOW;
+
+ /*
+ * If all element are zero or if the exponent is bigger than
+ * 16 ( it becomes an undefined shift) -> skip
+ */
+
+ if (exp < 16)
+ {
+
+
+ pFreq_2_Time_data_1 = &pFreqInfo[0];
+ pFreq_2_Time_data_2 = &pFreqInfo[SHORT_WINDOW];
+
+
+ /*
+ * Each of the eight short blocks is windowed separately.
+ * Window shape decisions are made on a frame-by-frame
+ * basis.
+ */
+
+ pShort_Window_1 = &Short_Window_fxp[wnd_shape_this_bk][0];
+
+ pShort_Window_2 =
+ &Short_Window_fxp[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+
+
+
+
+ /*
+ * For short windows from 7 to 5
+ * | =========================
+ * | | 5 6 7
+ * _--_ _--_ _--_ _--_ | _-|-_ _--_ _--_ _--_
+ * / \/ \/ \/ \|/ | \/ \/ \/ \
+ * / /\ /\ /\ /|\ | /\ /\ /\ \
+ * / / \ / \ / \ / | \ | / \ / \ / \ \
+ * / / \/ \/ \/ | \|/ \/ \ \ \
+ * --------------------------------|---[///////////////////////]--------
+ *
+ */
+
+
+ shift = exp + 15 - SCALING;
+
+
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ Int16 win1, win2;
+ Int16 dat1, dat2;
+
+ dat2 = *(pFreq_2_Time_data_2++);
+ win2 = *(pShort_Window_2--);
+ temp = *pOverlap_and_Add_Buffer_2;
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+
+ *(pOverlap_and_Add_Buffer_2++) = temp + (fxp_mul_16_by_16(dat2, win2) >> shift);
+
+ *(pOverlap_and_Add_Buffer_1++) = fxp_mul_16_by_16(dat1, win1) >> shift;
+
+ }
+
+ } /* if (exp < 16) */
+ else
+ {
+ pv_memset(
+ pOverlap_and_Add_Buffer_1,
+ 0,
+ SHORT_WINDOW*sizeof(*pOverlap_and_Add_Buffer_1));
+ }
+
+
+ }/* for ( wnd=NUM_SHORT_WINDOWS-1; wnd>=NUM_SHORT_WINDOWS/2; wnd--) */
+
+
+ wnd = NUM_SHORT_WINDOWS / 2;
+
+ pFreqInfo = (Int16 *) & pFrequency_data[ wnd*SHORT_WINDOW];
+
+ /*
+ * scratch memory is allocated in an unused part of memory
+ */
+
+
+ pScrath_mem = &pFrequency_data[ 2*LONG_WINDOW - HALF_SHORT_WINDOW];
+
+ pOverlap_and_Add_Buffer_1 = &pFrequency_data[ LONG_WINDOW];
+
+ pOverlap_and_Add_Buffer_2 = pOverlap_and_Add_Buffer_1
+ + HALF_SHORT_WINDOW;
+
+
+ exp = imdct_fxp(
+ (Int32 *)pFreqInfo,
+ freq_2_time_buffer,
+ SHORT_BLOCK1,
+ Q_format,
+ abs_max_per_window[wnd]);
+
+ /*
+ * If all element are zero or if the exponent is bigger than
+ * 16 ( it becomes an undefined shift) -> skip
+ */
+
+
+ if (exp < 16)
+ {
+
+ pFreq_2_Time_data_1 = &pFreqInfo[0];
+ pFreq_2_Time_data_2 = &pFreqInfo[SHORT_WINDOW];
+
+ pShort_Window_1 = &Short_Window_fxp[wnd_shape_this_bk][0];
+
+ pShort_Window_2 =
+ &Short_Window_fxp[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+
+
+ /*
+ * For short window 4
+ * ====|===========
+ * | 4
+ * | | | |
+ * _--_ _--_ _--_ _-|-_ | _-|-_ _-|-_ _--_ _--_
+ * / \/ \/ \/ | \|/ | \/ | \/ \/ \
+ * / /\ /\ /\ | /|\ | /\ | /\ /\ \
+ * / / \ / \ / \ | / | \ | / \ | / \ / \ \
+ * / / \/ \/ \|/ | \|/ \|/ \/ \ \
+ * ------------------------------[\\\|\\\|//////]-------------------
+ * | | A | B | C |
+ * |
+ * W_L_STOP_1
+ */
+
+ shift = exp + 15 - SCALING;
+ {
+ Int16 win1;
+ Int16 dat1;
+ /* -------- segment A ---------------*/
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+ *(pScrath_mem++) = fxp_mul_16_by_16(dat1, win1) >> shift;
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ }
+
+ /* -------- segment B ---------------*/
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+ *(pOverlap_and_Add_Buffer_1++) = fxp_mul_16_by_16(dat1, win1) >> shift;
+
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ }
+
+ /* -------- segment C ---------------*/
+ temp = *pOverlap_and_Add_Buffer_2;
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ *(pOverlap_and_Add_Buffer_2++) = temp + (fxp_mul_16_by_16(dat1, win1) >> shift);
+
+ temp = *pOverlap_and_Add_Buffer_2;
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+ }
+ }
+
+ } /* if (exp < 16) */
+ else
+ {
+ pv_memset(
+ pScrath_mem,
+ 0,
+ HALF_SHORT_WINDOW*sizeof(*pScrath_mem));
+
+ pv_memset(
+ pOverlap_and_Add_Buffer_1,
+ 0,
+ HALF_SHORT_WINDOW*sizeof(*pOverlap_and_Add_Buffer_1));
+ }
+
+
+ wnd = NUM_SHORT_WINDOWS / 2 - 1;
+
+ pFreqInfo = (Int16 *) & pFrequency_data[ wnd*SHORT_WINDOW];
+
+ pScrath_mem_entry =
+ &pFrequency_data[2*LONG_WINDOW - HALF_SHORT_WINDOW - SHORT_WINDOW];
+
+
+ pScrath_mem = pScrath_mem_entry;
+
+ pOverlap_and_Add_Buffer_1 = &pFrequency_data[ LONG_WINDOW];
+
+ /* point to end of buffer less HALF_SHORT_WINDOW */
+
+ pInterleaved_output_2 = &Interleaved_output[2*(LONG_WINDOW - HALF_SHORT_WINDOW)];
+ pInterleaved_output = pInterleaved_output_2;
+
+ pOverlap_and_Add_Buffer_1x = &Time_data[W_L_STOP_1 + SHORT_WINDOW*(wnd+1)];
+
+
+ exp = imdct_fxp(
+ (Int32 *)pFreqInfo,
+ freq_2_time_buffer,
+ SHORT_BLOCK1,
+ Q_format,
+ abs_max_per_window[wnd]);
+
+ /*
+ * If all element are zero or if the exponent is bigger than
+ * 16 ( it becomes an undefined shift) -> skip
+ */
+
+ if (exp < 16)
+ {
+
+ pFreq_2_Time_data_1 = &pFreqInfo[0];
+ pFreq_2_Time_data_2 = &pFreqInfo[SHORT_WINDOW];
+
+
+ /*
+ * For short window 3
+ * ===========|====
+ * 3 |
+ * | | | |
+ * _--_ _--_ _-|-_ _-|-_ | _-|-_ _--_ _--_ _--_
+ * / \/ \/ | \/ | \|/ | \/ \/ \/ \
+ * / /\ /\ | /\ | /|\ | /\ /\ /\ \
+ * / / \ / \ | / \ | / | \ | / \ / \ / \ \
+ * / / \/ \|/ \|/ | \|/ \/ \ \ \
+ * -----|------------------[\\\\\\|///|///]--------------------------
+ * | | A | B | C |
+ *
+ * W_L_STOP_1
+ */
+
+
+ pShort_Window_1 = &Short_Window_fxp[wnd_shape_this_bk][0];
+
+ pShort_Window_2 =
+ &Short_Window_fxp[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+
+ shift = exp + 15 - SCALING;
+
+ Int16 win1;
+ Int16 dat1;
+ /* -------- segment A ---------------*/
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ *(pScrath_mem++) = fxp_mul_16_by_16(dat1, win1) >> shift;
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ }
+
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+
+
+ /* -------- segment B ---------------*/
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+ test = fxp_mul_16_by_16(dat1, win1) >> shift;
+
+ temp = *(pScrath_mem++) + test;
+
+ test = *(pOverlap_and_Add_Buffer_1x++);
+ limiter(*(pInterleaved_output), (temp + test));
+
+
+ pInterleaved_output += 2;
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+
+ }
+
+ /* -------- segment C ---------------*/
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+
+ temp = fxp_mul_16_by_16(dat1, win1) >> shift;
+
+ *(pOverlap_and_Add_Buffer_1++) += temp;
+
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+ }
+
+
+ } /* if (exp < 16) */
+ else
+ {
+
+ pv_memset(
+ pScrath_mem,
+ 0,
+ SHORT_WINDOW*sizeof(*pScrath_mem));
+
+ pScrath_mem += SHORT_WINDOW;
+
+ temp = *(pScrath_mem++);
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+ limiter(*(pInterleaved_output), (temp));
+
+ pInterleaved_output += 2;
+ temp = *(pScrath_mem++);
+
+ }
+ }
+
+
+ for (wnd = NUM_SHORT_WINDOWS / 2 - 2; wnd >= 0; wnd--)
+ {
+
+
+ pInterleaved_output_2 -= (SHORT_WINDOW * 2);
+ pInterleaved_output = pInterleaved_output_2;
+
+ /*
+ * The same memory is used as scratch in every iteration
+ */
+ pScrath_mem = pScrath_mem_entry;
+
+ pOverlap_and_Add_Buffer_2x =
+ &Time_data[W_L_STOP_1 + SHORT_WINDOW*(wnd+1)];
+
+ pFreqInfo = (Int16 *) & pFrequency_data[ wnd*SHORT_WINDOW];
+
+
+
+ exp = imdct_fxp(
+ (Int32 *)pFreqInfo,
+ freq_2_time_buffer,
+ SHORT_BLOCK1,
+ Q_format,
+ abs_max_per_window[wnd]);
+
+ /*
+ * If all element are zero or if the exponent is bigger than
+ * 16 ( it becomes an undefined shift) -> skip
+ */
+
+ if (exp < 16)
+ {
+
+ pFreq_2_Time_data_1 = &pFreqInfo[0];
+ pFreq_2_Time_data_2 = &pFreqInfo[SHORT_WINDOW];
+
+
+ /*
+ * Each of the eight short blocks is windowed separately.
+ * Window shape decisions are made on a frame-by-frame
+ * basis.
+ */
+
+ pShort_Window_1 = &Short_Window_fxp[wnd_shape_this_bk][0];
+
+ if (wnd == 0)
+ {
+ pShort_Window_1 =
+ &Short_Window_fxp[wnd_shape_prev_bk][0];
+ }
+
+ pShort_Window_2 =
+ &Short_Window_fxp[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+
+
+ /*
+ * For short windows from 2 to 0
+ *
+ * =========================
+ * |
+ * 0 1 2 | |
+ * _--_ _--_ _--_ _-|-_ | _--_ _--_ _--_ _--_
+ * / \/ \/ \/ | \|/ \/ \/ \/ \
+ * / /\ /\ /\ | /|\ /\ /\ /\ \
+ * / / \ / \ / \ | / | \ / \ / \ / \ \
+ * / / \/ \/ \|/ | \/ \/ \ \ \
+ * ----[\\\\\\\\\\\\\\\\\\\\\\\\]---|-----------------------------
+ * |
+ *
+ * W_L_STOP_1
+ */
+
+ shift = exp + 15 - SCALING;
+
+ Int16 dat1 = *(pFreq_2_Time_data_2++);
+ Int16 win1 = *(pShort_Window_2--);
+
+ temp = *(pScrath_mem);
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ test = fxp_mul_16_by_16(dat1, win1) >> shift;
+
+ temp += test;
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+
+ limiter(*(pInterleaved_output), (temp + *(pOverlap_and_Add_Buffer_2x++)));
+
+ pInterleaved_output += 2;
+
+ *(pScrath_mem++) = fxp_mul_16_by_16(dat1, win1) >> shift;
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+ temp = *(pScrath_mem);
+
+ }
+
+ } /* if (exp < 16) */
+ else
+ {
+ test = *(pScrath_mem);
+ temp = *(pOverlap_and_Add_Buffer_2x++);
+
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ limiter(*(pInterleaved_output), (temp + test));
+
+ pInterleaved_output += 2;
+
+ *(pScrath_mem++) = 0;
+ test = *(pScrath_mem);
+ temp = *(pOverlap_and_Add_Buffer_2x++);
+ }
+ }
+
+ } /* for ( wnd=NUM_SHORT_WINDOWS/2-1; wnd>=0; wnd--) */
+
+ pOverlap_and_Add_Buffer_2x = &Time_data[W_L_STOP_1];
+
+ pScrath_mem = pScrath_mem_entry;
+
+ pInterleaved_output_2 -= (SHORT_WINDOW * 2);
+ pInterleaved_output = pInterleaved_output_2;
+
+ test = *(pScrath_mem++);
+ temp = *(pOverlap_and_Add_Buffer_2x++);
+
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ limiter(*(pInterleaved_output), (temp + test));
+
+ pInterleaved_output += 2;
+ test = *(pScrath_mem++);
+ temp = *(pOverlap_and_Add_Buffer_2x++);
+
+ }
+
+ pOverlap_and_Add_Buffer_1x = Time_data;
+
+ pInterleaved_output = Interleaved_output;
+
+
+ temp = *(pOverlap_and_Add_Buffer_1x++);
+ for (i = W_L_STOP_1; i != 0; i--)
+ {
+ limiter(*(pInterleaved_output), temp);
+
+ pInterleaved_output += 2;
+ temp = *(pOverlap_and_Add_Buffer_1x++);
+
+ }
+
+ pOverlap_and_Add_Buffer_1x = &Time_data[0];
+
+ pOverlap_and_Add_Buffer_2 = &pFrequency_data[LONG_WINDOW];
+
+ /*
+ * update overlap and add buffer,
+ * so is ready for next iteration
+ */
+
+ for (int i = 0; i < W_L_STOP_2; i++)
+ {
+ temp = *(pOverlap_and_Add_Buffer_2++);
+ *(pOverlap_and_Add_Buffer_1x++) = temp;
+ }
+
+ pv_memset(
+ pOverlap_and_Add_Buffer_1x,
+ 0,
+ W_L_STOP_1*sizeof(*pOverlap_and_Add_Buffer_1x));
+
+ } /* if ( wnd_seq != EIGHT_SHORT_SEQUENCE) */
+
+
+
+
+} /* trans4m_freq_2_time_fxp */
+
+
+
+