shithub: aacenc

ref: e0aff59eb79425e8bdeaeeaeca59627a1db0fae8
dir: /imdct.c/

View raw version

#include <math.h>
#include <stdlib.h>

#include "tf_main.h"
#include "transfo.h"
#include "block.h"
#include "dolby_win.h"

#define DPI	3.14159265358979323846264338327950288

double zero = 0;

void vcopy( double src[], double dest[], int inc_src, int inc_dest, int vlen )
{
	int i;

	for( i=0; i<vlen; i++ ) {
		*dest = *src;
		dest += inc_dest;
		src  += inc_src;
	}
}

void vmult1(double src1[], double src2[], double dest[], int vlen )
{
	int i;

	for( i=0; i<vlen; i++ ) {
		*dest = *src1 * *src2;
		dest++;
		src1++;
		src2++;
	}
}

void vmult2( double src1[], double src2[], double dest[], int vlen)
{
	int i;

	for( i=0; i<vlen; i++ ) {
		*dest = *src1 * *src2;
		dest++;
		src1++;
		src2--;
	}
}

void vadd( double src1[], double src2[], double dest[], 
            int inc_src1, int inc_src2, int inc_dest, int vlen )
{
	int i;

	for( i=0; i<vlen; i++ ) {
		*dest = *src1 + *src2;
		dest += inc_dest;
		src1 += inc_src1;
		src2 += inc_src2;
	}
}
 

/* Calculate window */
void calc_window( double window[], int len, Window_shape wfun_select )
{
	int i;
	extern double dolby_win_1024[];
	extern double dolby_win_128[];

	switch(wfun_select)
    {
    case WS_FHG: 
		for( i=0; i<len; i++ )
			window[i] = sin((DPI/(2*len)) * (i + 0.5));
		break;
		
    case WS_DOLBY: 
		switch(len)
		{
		case BLOCK_LEN_SHORT:
			for( i=0; i<len; i++ ) 
				window[i] = dolby_win_128[i]; 
			break;
		case BLOCK_LEN_LONG:
			for( i=0; i<len; i++ ) 
				window[i] = dolby_win_1024[i]; 
			break;
		}
		break;
    }
}
#define MAX_SHIFT_LEN_LONG 4096

/* %%%%%%%%%%%%%%%%% MDCT - STUFF %%%%%%%%%%%%%%%% */

void mdct( double in_data[], double out_data[], int len )
{
	vcopy(in_data, out_data, 1, 1, len); 
	MDCT(out_data, len);
}

void buffer2freq(
  double           p_in_data[], 
  double           p_out_mdct[],
  double           p_overlap[],
  enum WINDOW_TYPE block_type,
  Window_shape     wfun_select,      /* offers the possibility to select different window functions */
  int              nlong,            /* shift length for long windows   */
  int              nmed,             /* shift length for medium windows */
  int              nshort,           /* shift length for short windows  */
  Mdct_in      overlap_select     /*  YT 970615 for son_PP */
)
{
  double         transf_buf[ 2*MAX_SHIFT_LEN_LONG ];
  double         windowed_buf[ 2*MAX_SHIFT_LEN_LONG ];
  double         *p_o_buf;
  int            k;

  double           window_long[MAX_SHIFT_LEN_LONG]; 
  double           window_long_prev[MAX_SHIFT_LEN_LONG]; 
  double           window_med[MAX_SHIFT_LEN_LONG]; 
  double           window_med_prev[MAX_SHIFT_LEN_LONG]; 
  double           window_short[MAX_SHIFT_LEN_LONG]; 
  double           window_short_prev[MAX_SHIFT_LEN_LONG]; 
  double           *window_short_prev_ptr;


  int nflat_ls    = (nlong-nshort)/ 2; 
  int transfak_ls =  nlong/nshort; 
  int nflat_lm    = (nlong-nmed)  / 2; 
  int transfak_lm =  nlong/nmed; 
  int nflat_ms    = (nmed-nshort) / 2; 
  int transfak_ms =  nmed/nshort; 
 
  static Window_shape wfun_select_prev=WS_FHG;
  static int firstTime=1;
  window_short_prev_ptr = window_short_prev ; 


// if( (nlong%nshort) || (nlong > MAX_SHIFT_LEN_LONG) || (nshort > MAX_SHIFT_LEN_LONG/2) ) { 
//    CommonExit( 1, "mdct_analysis: Problem with window length" ); } 
//  if( (nlong%nmed) || (nmed%nshort) || (nmed > MAX_SHIFT_LEN_LONG/2) ) { 
//    CommonExit( 1, "mdct_analysis: Problem with window length" );  } 
//  if( transfak_lm%2 ) { 
//    CommonExit( 1, "mdct_analysis: Problem with window length" );  } 
  
  /* --- PATCH: Use WS_FHG window shape if we start with SHORT windows --- */
  if  (block_type==LONG_SHORT_WINDOW || block_type==ONLY_SHORT_WINDOW ){
    wfun_select=WS_FHG; } 
  /* --- PATCH  End  --- */
  calc_window( window_long,      nlong, wfun_select ); 
  calc_window( window_long_prev, nlong, wfun_select_prev ); 
  calc_window( window_med, nmed, wfun_select ); 
  calc_window( window_med_prev, nmed, wfun_select_prev ); 
  calc_window( window_short,      nshort, wfun_select ); 
  calc_window( window_short_prev, nshort, wfun_select_prev ); 
  
  /* create / shift old values */
  /* We use p_overlap here as buffer holding the last frame time signal*/
/* YT 970615 for son_pp */
if(overlap_select != MNON_OVERLAPPED){
  if (firstTime){
    firstTime=0;
    vcopy( &zero, transf_buf, 0, 1, nlong );
  }
  else
    vcopy( p_overlap, transf_buf, 1, 1, nlong );

  /* Append new data */
  vcopy( p_in_data, transf_buf+nlong, 1, 1, nlong );
  vcopy( p_in_data, p_overlap,        1, 1, nlong );
}
else{
	vcopy( p_in_data, transf_buf, 1, 1, 2*nlong );
}

  /* Set ptr to transf-Buffer */
  p_o_buf = transf_buf;
  
  
  /* Separate action for each Block Type */
  switch( block_type ) {
   case ONLY_LONG_WINDOW :
     vmult1( p_o_buf, window_long_prev, windowed_buf, nlong );
     vmult2( p_o_buf+nlong, window_long+nlong-1, windowed_buf+nlong, nlong );
     mdct( windowed_buf, p_out_mdct, 2*nlong );    
     break;
   
   case LONG_SHORT_WINDOW :
    vmult1( p_o_buf, window_long_prev, windowed_buf, nlong );
    vcopy( p_o_buf+nlong, windowed_buf+nlong, 1, 1, nflat_ls );
    vmult2( p_o_buf+nlong+nflat_ls, window_short+nshort-1, windowed_buf+nlong+nflat_ls, nshort );
    vcopy( &zero, windowed_buf+2*nlong-1, 0, -1, nflat_ls );
    mdct( windowed_buf, p_out_mdct, 2*nlong );
    break;

   case SHORT_LONG_WINDOW :
    vcopy( &zero, windowed_buf, 0, 1, nflat_ls );
    vmult1( p_o_buf+nflat_ls, window_short_prev_ptr, windowed_buf+nflat_ls, nshort );
    vcopy( p_o_buf+nflat_ls+nshort, windowed_buf+nflat_ls+nshort, 1, 1, nflat_ls );
    vmult2( p_o_buf+nlong, window_long+nlong-1, windowed_buf+nlong, nlong );
    mdct( windowed_buf, p_out_mdct, 2*nlong );
    break;

   case ONLY_SHORT_WINDOW :
	if(overlap_select != MNON_OVERLAPPED){ /* YT 970615 for sonPP */
    	p_o_buf += nflat_ls;
	}
    for (k=transfak_ls-1; k-->=0; ) {
      vmult1( p_o_buf,        window_short_prev_ptr, windowed_buf, nshort );
      vmult2( p_o_buf+nshort, window_short+nshort-1, windowed_buf+nshort, nshort );
      mdct( windowed_buf, p_out_mdct, 2*nshort );

      p_out_mdct += nshort;
	/* YT 970615 for sonPP*/
	  if(overlap_select != MNON_OVERLAPPED) p_o_buf += nshort;
      else 	p_o_buf += 2*nshort;
      window_short_prev_ptr = window_short; 
    }
    break;
   default :
    break;
//      CommonExit( 1, "mdct_synthesis: Unknown window type" ); 
  }

  /* Set output data 
  vcopy(transf_buf, p_out_mdct,1, 1, nlong); */
  
  /* --- Save old window shape --- */
  wfun_select_prev = wfun_select;
}

void imdct(double in_data[], double out_data[], int len)
{
  vcopy(in_data, out_data, 1, 1, len/2);
  IMDCT(out_data, len);
}

void freq2buffer(
  double           p_in_data[], 
  double           p_out_data[],
  double           p_overlap[],
  enum WINDOW_TYPE block_type,
  int              nlong,            /* shift length for long windows   */
  int              nmed,             /* shift length for medium windows */
  int              nshort,           /* shift length for short windows  */
  Window_shape     wfun_select,      /* offers the possibility to select different window functions */
  Mdct_in	   overlap_select    /* select imdct output *TK*	*/
				     /* switch (overlap_select) {	*/
				     /* case OVERLAPPED:		*/
				     /*   p_out_data[]			*/
				     /*   = overlapped and added signal */
				     /*		(bufferlength: nlong)	*/
				     /* case MNON_OVERLAPPED:		*/
				     /*   p_out_data[]			*/
				     /*   = non overlapped signal	*/
				     /*		(bufferlength: 2*nlong)	*/
  )
{
  double           *o_buf, transf_buf[ 2*MAX_SHIFT_LEN_LONG ];
  double           overlap_buf[ 2*MAX_SHIFT_LEN_LONG ]; 
 
  double           window_long[MAX_SHIFT_LEN_LONG]; 
  double           window_long_prev[MAX_SHIFT_LEN_LONG]; 
  double           window_med[MAX_SHIFT_LEN_LONG]; 
  double           window_med_prev[MAX_SHIFT_LEN_LONG]; 
  double           window_short[MAX_SHIFT_LEN_LONG]; 
  double           window_short_prev[MAX_SHIFT_LEN_LONG]; 
  double           *window_short_prev_ptr;
 
  double  *fp; 
  int     k; 
 
  int nflat_ls    = (nlong-nshort)/ 2; 
  int transfak_ls =  nlong/nshort; 
  int nflat_lm    = (nlong-nmed)  / 2; 
  int transfak_lm =  nlong/nmed; 
  int nflat_ms    = (nmed-nshort) / 2; 
  int transfak_ms =  nmed/nshort;  
 
  static Window_shape wfun_select_prev=WS_FHG;
  window_short_prev_ptr=window_short_prev ; 


  if( (nlong%nshort) || (nlong > MAX_SHIFT_LEN_LONG) || (nshort > MAX_SHIFT_LEN_LONG/2) ) { 
//    CommonExit( 1, "mdct_synthesis: Problem with window length" ); 
  } 
  if( (nlong%nmed) || (nmed%nshort) || (nmed > MAX_SHIFT_LEN_LONG/2) ) { 
//    CommonExit( 1, "mdct_synthesis: Problem with window length" ); 
  } 
  if( transfak_lm%2 ) { 
//    CommonExit( 1, "mdct_synthesis: Problem with window length" ); 
  } 



  /* --- PATCH: Use WS_FHG window shape if we start 
                with SHORT windows            --- */
  if  (block_type==LONG_SHORT_WINDOW ||
       block_type==ONLY_SHORT_WINDOW ){
    wfun_select=WS_FHG;
  } 
  /* --- PATCH  End  --- */
  
  calc_window( window_long,      nlong, wfun_select ); 
  calc_window( window_long_prev, nlong, wfun_select_prev ); 
  calc_window( window_med, nmed, wfun_select ); 
  calc_window( window_med_prev, nmed, wfun_select_prev );
  calc_window( window_short,      nshort, wfun_select ); 
  calc_window( window_short_prev_ptr, nshort, wfun_select_prev ); 
  
 
  /* Assemble overlap buffer */ 
  vcopy( p_overlap, overlap_buf, 1, 1, nlong ); 
  o_buf = overlap_buf; 
 

  /* Separate action for each Block Type */ 
   switch( block_type ) { 
   case ONLY_LONG_WINDOW : 
    imdct( p_in_data, transf_buf, 2*nlong ); 
    vmult1( transf_buf, window_long_prev, transf_buf, nlong ); 
    if (overlap_select != MNON_OVERLAPPED) {
      vadd( transf_buf, o_buf, o_buf, 1, 1, 1, nlong ); 
      vmult2( transf_buf+nlong, window_long+nlong-1, o_buf+nlong, nlong ); 
    }
    else { /* overlap_select == NON_OVERLAPPED */
      vmult2( transf_buf+nlong, window_long+nlong-1, transf_buf+nlong, nlong );
    }

    break; 
 
  case LONG_SHORT_WINDOW : 
    imdct( p_in_data, transf_buf, 2*nlong ); 
    vmult1( transf_buf, window_long_prev, transf_buf, nlong ); 
    if (overlap_select != MNON_OVERLAPPED) {
      vadd( transf_buf, o_buf, o_buf, 1, 1, 1, nlong ); 
      vcopy( transf_buf+nlong, o_buf+nlong, 1, 1, nflat_ls ); 
      vmult2( transf_buf+nlong+nflat_ls, window_short+nshort-1, o_buf+nlong+nflat_ls, nshort ); 
      vcopy( &zero, o_buf+2*nlong-1, 0, -1, nflat_ls ); 
    }
    else { /* overlap_select == NON_OVERLAPPED */
      vmult2( transf_buf+nlong+nflat_ls, window_short+nshort-1, transf_buf+nlong+nflat_ls, nshort ); 
      vcopy( &zero, transf_buf+2*nlong-1, 0, -1, nflat_ls ); 
    }
    break; 
    
  case SHORT_LONG_WINDOW : 
    imdct( p_in_data, transf_buf, 2*nlong ); 
    vmult1( transf_buf+nflat_ls, window_short_prev_ptr, transf_buf+nflat_ls, nshort ); 
    if (overlap_select != MNON_OVERLAPPED) {
      vadd( transf_buf+nflat_ls, o_buf+nflat_ls, o_buf+nflat_ls, 1, 1, 1, nshort ); 
      vcopy( transf_buf+nflat_ls+nshort, o_buf+nflat_ls+nshort, 1, 1, nflat_ls ); 
      vmult2( transf_buf+nlong, window_long+nlong-1, o_buf+nlong, nlong ); 
    }
    else { /* overlap_select == NON_OVERLAPPED */
      vcopy( &zero, transf_buf, 0, 1, nflat_ls);
      vmult2( transf_buf+nlong, window_long+nlong-1, transf_buf+nlong, nlong);
    }
    break; 
 
  case ONLY_SHORT_WINDOW : 
    if (overlap_select != MNON_OVERLAPPED) {
      fp = o_buf + nflat_ls; 
    }
    else { /* overlap_select == NON_OVERLAPPED */
      fp = transf_buf;
    }
    for( k = transfak_ls-1; k-->= 0; ) { 
      if (overlap_select != MNON_OVERLAPPED) {
        imdct( p_in_data, transf_buf, 2*nshort ); 
        vmult1( transf_buf, window_short_prev_ptr, transf_buf, nshort ); 
        vadd( transf_buf, fp, fp, 1, 1, 1, nshort ); 
        vmult2( transf_buf+nshort, window_short+nshort-1, fp+nshort, nshort ); 
        p_in_data += nshort; 
        fp        += nshort; 
        window_short_prev_ptr = window_short; 
      }
      else { /* overlap_select == NON_OVERLAPPED */
        imdct( p_in_data, fp, 2*nshort );
        vmult1( fp, window_short_prev_ptr, fp, nshort ); 
        vmult2( fp+nshort, window_short+nshort-1, fp+nshort, nshort ); 
        p_in_data += nshort; 
        fp        += 2*nshort;
        window_short_prev_ptr = window_short; 
      }
    } 
    vcopy( &zero, o_buf+2*nlong-1, 0, -1, nflat_ls ); 
    break;     
   default :
	   break;
    //CommonExit( 1, "mdct_synthesis: Unknown window type" ); 
  } 
 
  if (overlap_select != MNON_OVERLAPPED) {
    vcopy( o_buf, p_out_data, 1, 1, nlong ); 
  }
  else { /* overlap_select == NON_OVERLAPPED */
    vcopy( transf_buf, p_out_data, 1, 1, 2*nlong ); 
  }
  
  /* save unused output data */ 
  vcopy( o_buf+nlong, p_overlap, 1, 1, nlong ); 

  /* --- Save old window shape --- */
  wfun_select_prev = wfun_select;
  
} 

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