/*****************************************************************************
**
**   ITU-T G.722.1 (2005-05) - Fixed point implementation for main body and Annex C
**   > Software Release 2.1 (2008-06)
**     (Simple repackaging; no change from 2005-05 Release 2.0 code)
**
**   © 2004 Polycom, Inc.
**
**   All rights reserved.
**
*****************************************************************************/

/*****************************************************************************
* Filename: rmlt_coefs_to_samples.c
*
* Purpose:  Convert Reversed MLT (Modulated Lapped Transform) 
*           Coefficients to Samples
*
*     The "Reversed MLT" is an overlapped block transform which uses
*     even symmetry * on the left, odd symmetry on the right and a
*     Type IV DCT as the block transform.  * It is thus similar to a
*     MLT which uses odd symmetry on the left, even symmetry * on the
*     right and a Type IV DST as the block transform.  In fact, it is
*     equivalent * to reversing the order of the samples, performing
*     an MLT and then negating all * the even-numbered coefficients.
*
*****************************************************************************/

/***************************************************************************
 Include files                                                           
***************************************************************************/
#include "defs.h"
#include "tables.h"
#include "count.h"

/***************************************************************************
 Function:     rmlt_coefs_to_samples 

 Syntax:       void rmlt_coefs_to_samples(Word16 *coefs,       
                                          Word16 *old_samples, 
                                          Word16 *out_samples, 
                                          Word16 dct_length,
                                          Word16 mag_shift)    
            
               inputs:    Word16 *coefs
                          Word16 *old_samples
                          Word16 dct_length
                          Word16 mag_shift
                          
                          
               outputs:   Word16 *out_samples
               
 Description:  Converts the mlt_coefs to samples

 Design Notes:
 
 WMOPS:     7kHz |    24kbit    |    32kbit
          -------|--------------|----------------
            AVG  |     1.91     |    1.91
          -------|--------------|----------------  
            MAX  |     1.91     |    1.91
          -------|--------------|---------------- 
				
           14kHz |    24kbit    |    32kbit      |     48kbit
          -------|--------------|----------------|----------------
            AVG  |     3.97     |    3.97        |     3.97   
          -------|--------------|----------------|----------------
            MAX  |     3.97     |    3.97        |     3.97   
          -------|--------------|----------------|----------------

***************************************************************************/

void rmlt_coefs_to_samples(Word16 *coefs,     
                           Word16 *old_samples,
                           Word16 *out_samples,           
                           Word16 dct_length,
                           Word16 mag_shift)             
{

    
    Word16	index, vals_left;
    Word16	new_samples[MAX_DCT_LENGTH];
    Word16	*new_ptr, *old_ptr;
    Word16	*win_new, *win_old;
    Word16	*out_ptr;
    Word16  half_dct_size;
    Word32  sum;

    

    half_dct_size = shr(dct_length,1);
    
    /* Perform a Type IV (inverse) DCT on the coefficients */
    dct_type_iv_s(coefs, new_samples, dct_length);
    
    test();
    if (mag_shift > 0) 
    {
        for(index=0;index<dct_length;index++)
        {
            new_samples[index] = shr(new_samples[index],mag_shift);
            move16();
        }
    }
    else 
    {
        test();
        if (mag_shift < 0) 
        {
            mag_shift = negate(mag_shift);
            for(index=0;index<dct_length;index++)
            {
                new_samples[index] = shl(new_samples[index],mag_shift);
                move16();
            }
        }

    }

    /* Get the first half of the windowed samples */
    
    out_ptr = out_samples;
    move16();
    test();
    if (dct_length==DCT_LENGTH)
    {
        win_new = rmlt_to_samples_window;
        move16();
        win_old = rmlt_to_samples_window + dct_length;
        move16();
    }
    else
    {
        win_new = max_rmlt_to_samples_window;
        move16();
        win_old = max_rmlt_to_samples_window + dct_length;
        move16();
    }
    old_ptr = old_samples;
    move16();
    new_ptr = new_samples + half_dct_size;
    move16();
    
    for (vals_left = half_dct_size;    vals_left > 0;    vals_left--)
    {
        sum = 0L;
        move32();
        sum = L_mac(sum,*win_new++, *--new_ptr);
        sum = L_mac(sum,*--win_old, *old_ptr++);
        *out_ptr++ = round16(L_shl(sum,2));
        move16();

    }
    
    /* Get the second half of the windowed samples */
    
    for (vals_left = half_dct_size;    vals_left > 0;    vals_left--)
    {
        sum = 0L;
        move32();
        sum = L_mac(sum,*win_new++, *new_ptr++);
        sum = L_mac(sum,negate(*--win_old), *--old_ptr);
        *out_ptr++ = round16(L_shl(sum,2));
        move16();
    }
        
    /* Save the second half of the new samples for   */
    /* next time, when they will be the old samples. */
    
    /* pointer arithmetic */
    new_ptr = new_samples + half_dct_size;
    move16();
    old_ptr = old_samples;
    move16();
    for (vals_left = half_dct_size;    vals_left > 0;    vals_left--)
    {
        *old_ptr++ = *new_ptr++;
        move16();
    }
}
