/* ------------------------------------------------------------------
 * 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.
 * -------------------------------------------------------------------
 */
/*

 Filename: trans4m_freq_2_time_fxp.cpp
  Function: trans4m_freq_2_time_fxp

------------------------------------------------------------------------------
 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



------------------------------------------------------------------------------
*/


/*----------------------------------------------------------------------------
; INCLUDES
----------------------------------------------------------------------------*/

#include "config.h"

#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)


static 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)


static 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
----------------------------------------------------------------------------*/
#include    "config.h"

#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 (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 (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 */




