diff options
author | Andreas Huber <andih@google.com> | 2009-12-07 09:56:32 -0800 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2009-12-07 11:02:28 -0800 |
commit | f44de515d3b6098a0b585865c1a0c7b20d3075a6 (patch) | |
tree | 028b1d81643bbb332464b42b50a0f79ba5359142 /media/libstagefright/codecs/aacdec/trans4m_freq_2_time_fxp.cpp | |
parent | bf697e37550d9e8376089b0b5e498613bede798c (diff) | |
download | frameworks_av-f44de515d3b6098a0b585865c1a0c7b20d3075a6.zip frameworks_av-f44de515d3b6098a0b585865c1a0c7b20d3075a6.tar.gz frameworks_av-f44de515d3b6098a0b585865c1a0c7b20d3075a6.tar.bz2 |
Initial check in of stagefright software AAC decoder based on PV source code.
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.cpp | 2604 |
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 */ + + + + |