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


This software module was originally developed by

Gerald Schuller (University of Hannover / ACTS-MoMuSys)

and edited by

in the course of development of the MPEG-2 NBC/MPEG-4 Audio standard
ISO/IEC 13818-7, 14496-1,2 and 3. This software module is an
implementation of a part of one or more MPEG-2 NBC/MPEG-4 Audio tools
as specified by the MPEG-2 NBC/MPEG-4 Audio standard. ISO/IEC gives
users of the MPEG-2 NBC/MPEG-4 Audio standards free license to this
software module or modifications thereof for use in hardware or
software products claiming conformance to the MPEG-2 NBC/ MPEG-4 Audio
standards. Those intending to use this software module in hardware or
software products are advised that this use may infringe existing
patents. The original developer of this software module and his/her
company, the subsequent editors and their companies, and ISO/IEC have
no liability for use of this software module or modifications thereof
in an implementation. Copyright is not released for non MPEG-2
NBC/MPEG-4 Audio conforming products. ACTS-MoMuSys partners retain
full right to use the code for his/her own purpose, assign or donate
the code to a third party and to inhibit third party from using the
code for non MPEG-2 NBC/MPEG-4 Audio conforming products. This
copyright notice must be included in all copies or derivative works.

Copyright (c) 1997.


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

#include <stdio.h>
#include <math.h>
#include <stddef.h>
#include <values.h>
/* #include "dct.h" */

#include "tf_main.h"



#define Float double   /*mache alles in double precision*/ 
/*#define double float */       /* mache alles in float precision*/
/*int use_dolby_short_win=0;*/  /* def fuer compatibilitaet */


/***for delay = 2*N  ******/


#define addelay 0 /*additional delay for analysis in blocks */

#define max 2048  /* max size of N, the number of channels */
#define maxm 0 /* maximum number of bi-diagonal matrices C */
#define maxfb 7000 /*maximum number of unknown matrix entries, size(fb) */
#define maxn 4  /*maximum number of low delay matrices G */
#define maxc 1 /*maximum number of channels (stereo) */
#define MAX_CHANNELS 1




#include "ldfb.h"








void multC(double y[],double x[],double c[], int N)
 /*Float y[max],x[max],c[2*max];
     int N;
*/
{
int i;
double *yp, *xp, *cp, *xpi, *cpi, xh[max], *xhp;


xhp=xh;
xp=x;
for(i=0;i<N;i++)
   {
   *xhp++ = *xp++;
   };
xp=xh;
yp=y;
cp=c;
xpi=&xh[N-1];
cpi=&c[2*N-1];

for(i=1;i<=N;i++)
   {
/*printf("%f, %f %f %f\n ", *xp, *cp, *cpi, *xpi); */
   *yp++=(*xp++ * *cp++) + (*xpi-- * *cpi--);
   }
};







void multF(double y[],double x[],double d[],int N)
     /*
Float y[max],x[max],d[2*max];
 int N;
*/
{
int i;
double *yp, *xp, *dp, *xpi, *dpi, *dph, *dphi, *ypi, *xhp, xh[max];

xhp=xh;
xp=x;
for(i=0;i<N;i++)
   {
   *xhp++ = *xp++;
   };
xp=xh;
yp=&y[N/2];
ypi=&y[N/2-1];
xpi=&xh[N-1];
dp=d;
dphi=&d[N-1];
dph=&d[N];
dpi=&d[2*N-1];

for(i=1;i<=N/2;i++)
   {
/*printf("%f, %f %f %f\n ", *xp, *cp, *cpi, *xpi); */
   *ypi-- =(*xp * *dp++) + (*xpi * *dphi--);
   *yp++ = (*xp++ * *dph++) + (*xpi-- * *dpi--);
   }
}






void multG(double y[],double x[],double g[],double z[],int N)
     /*
Float y[max],x[max],g[max],z[max];
int N;
*/
{
int i;
double *yp, *xp, *gp, *xpi, *zp, *xhp, xh[max];

xhp=xh;
xp=x;
for(i=0;i<N;i++)
   {
   *xhp++ = *xp++;
   };
yp=y;
xp=xh;
gp=g;
xpi=&xh[N-1];
zp=z;


for(i=1;i<=N/2;i++)
   {
/*printf("%f, %f %f %f\n ", *xp, *cp, *cpi, *xpi); */
   *yp++= *xpi-- + (*zp * *gp++);
   *zp++ = *xp++;
   };
for(i=1;i<=N/2;i++)
   {
   *yp++ = *xpi--;
   }
};



void multE(double y[],double x[],double g[],double z[],int N)
     /*
Float y[max],x[max],g[max],z[max];
int N;
*/
{
int i;
double *yp, *xp, *gp, *xpi, *zp, *xhp, xh[max];

xhp=xh;
xp=x;
for(i=0;i<N;i++)
   {
   *xhp++ = *xp++;
   };

yp=y;
xp=&xh[N/2];
gp=g;
xpi=&xh[N-1];
zp=z;



for(i=1;i<=N/2;i++)
   {
   *yp++ = *xpi--;
   }
for(i=1;i<=N/2;i++)
   {
/*printf("%f, %f %f %f\n ", *xp, *cp, *cpi, *xpi); */
   *yp++= *xpi-- + (*zp * *gp++);
   *zp++ = *xp++;
   };

};




void multH(double y[],double x[],double g[],double z[],int N)
     /*
Float y[max],x[max],g[max],z[max];
int N;
*/
{
int i;
double *yp, *xp, *gp, *xpi, *zp, *xhp, xh[max];

xhp=xh;
xp=x;
for(i=0;i<N;i++)
   {
   *xhp++ = *xp++;
   };

yp=y;
xp=&xh[N/2];
gp=g;
xpi=&xh[N-1];
zp=&z[N-1];



for(i=1;i<=N/2;i++)
   {
   *yp++ = *zp;
   *zp-- = *xpi--;
   }
for(i=1;i<=N/2;i++)
   {
/*printf("%f, %f %f %f\n ", *xp, *cp, *cpi, *xpi); */
   *yp++= *zp + (*xp++ * *gp++);
   *zp-- = *xpi--;
   };

};



void multH2(double y[],double x[],double g[],double z[],int N)
     /*
Float y[max],x[max],g[max],z[max];
int N;
*/
{
int i;
double *yp, *xp, *gp, *xpi, *zp, *xhp, xh[max];

xhp=xh;
xp=x;
for(i=0;i<N;i++)
   {
   *xhp++ = *xp++;
   };

yp=y;
xp=&xh[0];
gp=g;
xpi=&xh[N-1];
zp=&z[N-1];




for(i=1;i<=N/2;i++)
   {
/*printf("%f, %f %f %f\n ", *xp, *cp, *cpi, *xpi); */
   *yp++= *zp + (*xp++ * *gp++);
   *zp-- = *xpi--;
   };

for(i=1;i<=N/2;i++)
   {
   *yp++ = *zp;
   *zp-- = *xpi--;
   }

};


void multH0(double y[],double x[],double g[],double z[],int N)
     /*
Float y[max],x[max],g[max],z[max];
int N;
*/
{
int i;
double  *yp, *xp, *gp, *xpi, *zp, *xhp,*h0p, xh[max];

xhp=xh;
xp=x;
for(i=0;i<N;i++)
   {
   *xhp++ = *xp++;
   };

yp=y;
xp=&xh[0];
gp=&g[0];
h0p=&g[N+N/2-1];
xpi=&xh[N-1];
zp=&z[N-1];




for(i=1;i<=N/2;i++)
   {
/*printf("%f, %f %f %f\n ", *xp, *cp, *cpi, *xpi); */
   *yp++= *zp * *h0p-- + (*xp++ * *gp++);
   *zp-- = *xpi--;
   };

for(i=1;i<=N/2;i++)
   {
   *yp++ = *zp * *h0p--;
   *zp-- = *xpi--;
   }

};



void multFDi(double y[],double x[],double g[],double z[],int N)
     /*
Float y[max],x[max],g[max],z[max];
int N;
*/
{
int i;
double  *yp, *xp, *gp, *xpi, *zp, *xhp,*h0p, xh[max];

xhp=xh;
xp=x;
for(i=0;i<N;i++)
   {
   *xhp++ = *xp++;
   };

yp=y;
xp=&xh[N/2];
gp=&g[0];
h0p=&g[N+N/2-1];
xpi=&xh[N/2-1];
zp=&z[N/2-1];




for(i=1;i<=N/2;i++)
   {
/*printf("%f, %f %f %f\n ", *xp, *cp, *cpi, *xpi); */
   *yp++= *xpi-- * *h0p-- + (*xp++ * *gp++);
   };

xpi=&xh[N-1];
for(i=1;i<=N/2;i++)
   {
   *yp++ = *zp * *h0p--;
   *zp-- = *xpi--;
   }

};





void multH20(double y[],double x[],double g[],double z[],int N)
     /*
Float y[max],x[max],g[max],z[max];
int N;
*/
{
int i;
double  *yp, *xp, *gp, *xpi, *zp, *xhp,*h0p, xh[max];

xhp=xh;
xp=x;
for(i=0;i<N;i++)
   {
   *xhp++ = *xp++;
   };

yp=y;
xp=&xh[N/2];
gp=&g[0];
h0p=&g[N+N/2-1];
xpi=&xh[N-1];
zp=&z[N-1];


for(i=1;i<=N/2;i++)
   {
   *yp++ = *zp * *h0p--;
   *zp-- = *xpi--;
   }

for(i=1;i<=N/2;i++)
   {
/*printf("%f, %f %f %f\n ", *xp, *cp, *cpi, *xpi); */
   *yp++= *zp * *h0p-- + (*xp++ * *gp++);
   *zp-- = *xpi--;
   };



};





void multE0(double y[],double x[],double g[],double z[],int N)
     /*
Float y[max],x[max],g[max],z[max];
int N;
*/
{
int i;
double  *yp, *xp, *gp,*gp0, *xpi, *zp, *xhp, xh[max];

xhp=xh;
xp=x;
for(i=0;i<N;i++)
   {
   *xhp++ = *xp++;
   };

yp=y;
xp=&xh[N/2];
gp0=&g[N+N/2-1];
gp=&g[0];
xpi=&xh[N-1];
zp=z;



for(i=1;i<=N/2;i++)
   {
   *yp++ = *xpi-- * *gp0-- ;
   }
for(i=1;i<=N/2;i++)
   {
/*printf("%f, %f %f %f\n ", *xp, *cp, *cpi, *xpi); */
   *yp++= *xpi-- * *gp0-- + (*zp * *gp++);
   *zp++ = *xp++;
   };

};


void multG0(double y[],double x[],double g[],double z[],int N)
     /*
Float y[max],x[max],g[max],z[max];
int N;
*/
{
int i;
double  *yp, *xp, *gp,*gp0, *xpi, *zp, *xhp, xh[max];

xhp=xh;
xp=x;
for(i=0;i<N;i++)
   {
   *xhp++ = *xp++;
   };
yp=y;
xp=xh;
gp=g;
gp0=&g[N+N/2-1];
xpi=&xh[N-1];
zp=z;


for(i=1;i<=N/2;i++)
   {
/*printf("%f, %f %f %f\n ", *xp, *cp, *cpi, *xpi); */
   *yp++= *xpi-- * *gp0-- + (*zp * *gp++);
   *zp++ = *xp++;
   };
for(i=1;i<=N/2;i++)
   {
   *yp++ = *xpi-- * *gp0-- ;
   }
};







void multD(double y[],double x[],double z[],int N)
     /*
Float y[max],x[max],z[max];
int N;
*/
{
int i;
Float *yp, *xp, *zp, *xhp, xh[max];

xhp=xh;
xp=x;
for(i=0;i<N;i++)
   {
   *xhp++ = *xp++;
   };

yp=y;
xp=xh;
zp=z;


for(i=1;i<=N/2;i++)
   {
/*printf("%f, %f %f %f\n ", *xp, *cp, *cpi, *xpi); */
   *yp++= *zp ;
   *zp++ = *xp++;
   };
for(i=1;i<=N/2;i++)
   {
   *yp++ = *xp++;
   }
};


void multDinv(double y[],double x[],double z[],int N)
     /*
Float y[max],x[max],z[max];
int N;
*/
{
int i;
double  *yp, *xp, *zp, *xhp, xh[max];

xhp=xh;
xp=x;
for(i=0;i<N;i++)
   {
   *xhp++ = *xp++;
   };
yp=y;
xp=xh;
zp=z;


for(i=1;i<=N/2;i++)
   {
   *yp++ = *xp++;
   }

for(i=1;i<=N/2;i++)
   {
/*printf("%f, %f %f %f\n ", *xp, *cp, *cpi, *xpi); */
   *yp++= *zp ;
   *zp++ = *xp++;
   };

};



void multD2(double y[],double x[],double z1[],double z2[],int N)
     /*
Float y[max],x[max],z1[max],z2[max];
int N;
*/
{
int i;
double  *yp, *xp, *z1p, *z2p, *xhp, xh[max];

xhp=xh;
xp=x;
for(i=0;i<N;i++)
   {
   *xhp++ = *xp++;
   };
yp=y;
xp=xh;
z1p=z1;
z2p=z2;


for(i=1;i<=N/2;i++)
   {
/*printf("%f, %f %f %f\n ", *xp, *cp, *cpi, *xpi); */
   *yp++= *z2p ;
   *z2p++= *z1p;
   *z1p++ = *xp++;
   };
for(i=1;i<=N/2;i++)
   {
   *yp++ = *xp++;
   }
};



void multD2inv(double y[],double x[],double z1[],double z2[],int N)
     /*
Float y[max],x[max],z1[max],z2[max];
int N;
*/
{
int i;
double  *yp, *xp, *z1p, *z2p, *xhp, xh[max];

xhp=xh;
xp=x;
for(i=0;i<N;i++)
   {
   *xhp++ = *xp++;
   };
yp=y;
xp=xh;
z1p=z1;
z2p=z2;

for(i=1;i<=N/2;i++)
   {
   *yp++ = *xp++;
   }

for(i=1;i<=N/2;i++)
   {
/*printf("%f, %f %f %f\n ", *xp, *cp, *cpi, *xpi); */
   *yp++= *z2p ;
   *z2p++= *z1p;
   *z1p++ = *xp++;
   };

};








void affbmid(double out[],double fb[],int N,int n,double x[],int L,int blocks,int c,double z[])
     /*
Float *out, *fb, *x,*z;
int N,n,L,blocks,c;
*/
/*n: number of high del matrices*/
/*c: channel */
{
  /*static Float z1[maxm*max*maxc]={0}, z2[maxm*max*maxc]={0}, 
             z[maxn*max*maxc]={0};*/
int m,i,j, base,mof;
double  *zh, y[max], *yp, *xp, *outp;

/*c=0; channel number */
/*m=(L-n*N/2)/(2*N)-1;*/
/*number of low del matrices */
m=(L-(n-1)*N/2-1.5*N)/(N/2);

/*printf("m= %d\n ",m);*/
/*printf("x(1)= %f \n",x[0]);*/

outp=out;

for(j=0;j<blocks;j++)
   {  
   yp=y;
   xp=&x[j*N];

   for(i=0;i<N;i++)
      {
      *yp++ = *xp++;
      };


  /*  C matrices */ 
   /*
   for(i=0;i<m;i++)
      {
      multC(y,y,&fb[i*2*N],N);
      multD2(y,y,&z1[i*N/2+m*N/2*c],&z2[i*N/2+m*N/2*c],N);
      }


   multF(y,y,&fb[m*2*N],N);

   multD(y,y,&z[c*(n+1)*N/2],N);
   */

   mof=((m)*N/2+(n+1)*N);
   if( n>=1)
     /*multH0(y,y,&fb[0],&z[mof*c],N);*/
     {

       /*
     Float fbF[maxfb], *fbFp, *fbp;
     
     fbFp=&fbF[0];
     fbp=&fb[N];
     for(i=0;i<N/2;i++)
       *fbFp++ = *fbp++;

     fbp=&fb[0];
     for(i=0;i<N/2;i++)
       *fbFp++ = *fbp++;

     for(i=0;i<N/2;i++)
       *fbFp++ = 0.0;

     fbp=&fb[N/2];
     for(i=0;i<N/2;i++)
       *fbFp++ = *fbp++;
       */
     /*printf(" multFDi ");  */   
     multFDi(y,y,&fb[0],&z[mof*c],N);

  /*   multDinv(y,y,&z[mof*c+N/2],N);  */

     }



   else
     multE0(y,y,&fb[0],&z[mof*c],N);
  

   /* high delay matrices */
   base=1.5*N;

   for( i=0; i<(n-1);i++)
     {
     multH2(y,y,&fb[base+i*N/2],&z[(i+1)*N+mof*c],N);
     }

   base=1.5*N+(n-1)*N/2;
   /* low delay matrices */ 
 
   if(n%2 ==0)
     {
     for(i=0;i<m;i++)
         {
         multE(y,y,&fb[base + i*N/2],&z[(n)*N+i*N/2+mof*c],N);  
         }
     }
   else 
     {  
      for(i=0;i<m;i++)
         {
         multG(y,y,&fb[base + i*N/2],&z[(n)*N+i*N/2+mof*c],N);  
         }
     }

   /* odct(y,N);*/

   yp=y;

   for(i=0;i<N;i++)
      {
      *outp++ = *yp++;
      };


   }


}








void affbmidv(double out[],double fb[],int N1,int N2,int n,double x[],int L,int blocks,int c,double z[])
     /*
Float *out, *fb, *x, *z;
int N1,N2,n,L,blocks,c;
*/
/*n: number of high del matrices*/
/*c: channel */

{
  /* static Float  z1[maxm*max*maxc]={0}, z2[maxm*max*maxc]={0},
             z[maxn*max*maxc]={0};*/
static int count=0;
int m,i,j, base,mof,N, zahl;
double  *zh,*zh2, y[max], *yp, *yhp, *xp, *outp, xh[max],*xhp;

/*c=0; channel number */
/*m=(L-n*N/2)/(2*N)-1;*/
/*number of low del matrices */
/*
printf("hallo0\n");
*/

/*printf("m= %d \n",m);*/
/*printf("x(1)= %f \n",x[0]);*/
/*
printf("N1= %d\n",N1);
printf("N2= %d\n",N2);
*/
/*
printf("%f %d %d %d %f %d %d %d %f\n",fb[0],N1,N2,n,x[0],L,blocks,c,z[0]);
*/

count=0; /* nicht fuer stereo*/

if(N1==N2)
  {
  N=N1;
  m=(L-(n-1)*N/2-1.5*N)/(N/2);
  /* printf("N1=N2\n");*/
  }     /*if N1==N2 */
else /*N1!= N2 */
  {
  if(N2<N1)
    {
      /*  printf("N2<N1\n");*/
    N=N1;
    
    xhp=xh;
    xp=x;
    /*x mit Nullen auffuellen*/
    for(i=0;i<(N1/2);i++)
      {
      *xhp++ = *xp++;
      };
    
    for(i=0;i<(N2/2);i++)
      {
      *xhp++ = *xp++;
      };

    for(i=0;i<((N1-N2)/2);i++)
      {
      *xhp++ = 0;
      };
    x=xh;
    /*
for(zahl=0;zahl<1.5*N1;zahl++)
  printf("x= %f \n ",x[zahl]);
  */   
    }
  else /* N2>N1 */
    {
      /* printf("N2>N1\n");*/
     xhp=xh;
    xp=x;
    /*x mit Nullen auffuellen*/

    for(i=0;i<((N2-N1)/2);i++)
      {
      *xhp++ = 0;
      };
    for(i=0;i<(N1/2);i++)
      {
      *xhp++ = *xp++;
      };
    
    for(i=0;i<(N2/2);i++)
      {
      *xhp++ = *xp++;
      };

    
    x=xh;
      /*z mut Nullen auffuellen */
    N=N2;
    m=(L-(n-1)*N/2-1.5*N)/(N/2); /* # of low del matrices*/
    if(count<1)
      {
      for(j=(m-1);j>0;j--)
        {
        zh=&z[N1+N1/2+j*N1/2-1];
        zh2=&z[N2+N2/2+j*N2/2-1];
        for(i=0;i<((N2-N1)/2);i++)
          {
          *zh2-- = 0;
          };
        for(i=0;i<(N1/2);i++)
          {
          *zh2-- = *zh--;
          };

        }
      zh=&z[N1+N1/2-1];
      zh2=&z[N2+N1/2-1]; /*H and E1 */
      for(i=0;i<(N1);i++)
        {
        *zh2-- = *zh--;
        };

      zh=&z[N1/2];        /* H */
      for(i=0;i<((N2-N1));i++)
        {
        *zh++ = 0;
        };
      zh=&z[N2+N1/2];     /* E1 */
      for(i=0;i<((N2-N1)/2);i++)
        {
        *zh++ = 0;
        };
      /*
        printf("N2>N1\n");
for(zahl=0;zahl<2*N2;zahl++)
  printf("z= %f \n ",z[zahl]);
  */
      };
    }
  }

/*
printf("hallo\n");
printf("N= %d\n",N);
*/
  affbmid(y,fb,N,n,x,L,blocks,0,z);
  /* 
printf("fertig\n");  
*/


  if(N1==N2)
    {
    N=N1;
    count=0;
    odct(y,N1);
    for(i=0;i<N1;i++) y[i] *= 2.;

    }
  else
    {

    if(N2<N1)
      {
      odct(y,N1);
      for(i=0;i<N1;i++) y[i] *= 2.;

      count=count+1;
      if(count>=n)
        { /*reduce z's */
	  /*
for(zahl=0;zahl<1.5*N1;zahl++)
  printf("z= %f \n ",z[zahl]);
  */
        zh=&z[N1-N2/2];
        zh2=&z[N2/2];
        for(i=0;i<(N2);i++) /* H and E1 */
          {
          *zh2++ = *zh++;
          };
        }
      }
    else /*N2>N1 */ 
      {
     
      count=count+1;


      if(count<=n)
        {
	/*reduce y */
	  /* odct(y,N2);*/

 /*printf("N2>N1");
for(zahl=0;zahl<N2;zahl++)
  printf("y= %f \n ",y[zahl]);*/

        yp=&y[N1/2];
        yhp=&y[N2-N1/2];
        for(i=0;i<(N1/2);i++)
          {
          *yp++ = *yhp++;
          };
        odct(y,N1);
        for(i=0;i<N1;i++) y[i] *= 2.;

	}

      }
    } /* else ..N1!=N1*/
  /*  
printf("fast fertig\n");
*/

yp=y;
outp=out;
N=N1;

  for(i=0;i<N;i++)
    {
    *outp++ = *yp++;
    };
  /*
printf("zout= %f \n",z[0]);
*/

}












void sffbmid(double out[],double fb[],int N,int n,double x[],int L,int blocks,int c,double z[])
     /*
Float *out, *fb, *x, *z;
int N,n,L,blocks,c;
*/
{
  /*static Float z1[maxm*max*maxc]={0}, z2[maxm*max*maxc]={0}, 
             z[maxn*max*maxc]={0};*/
int m,i,j, base,mof;
double *zh, y[max], *yp, *xp, *outp;

/*c channel number*/
/*m=(L-n*N/2)/(2*N)-1; */
/*number of low del matrices */
m=(L-(n-1)*N/2-1.5*N)/(N/2);
/*printf("m= %d ",m);*/

outp=out;

for(j=0;j<blocks;j++)
   {  
   yp=y;
   xp=&x[j*N];

   for(i=0;i<N;i++)
      {
      *yp++ = *xp++;
      };

/* transform */
   /*  odct(y,N);*/

   mof=((m)*N/2+(n+1)*N);
   /* base=(m+2)*N;*/
   base=1.5*N+(n-1)*N/2;
   /* low delay matrices */ 

   if(n%2 ==0)
     {
     for(i=m-1;i>=0;i--)
         {
         multG(y,y,&fb[base + i*N/2],&z[(n)*N+i*N/2+mof*c],N);  
         }
     }
   else 
     { 
     for(i=m-1;i>=0;i--)
         {
         multE(y,y,&fb[base + i*N/2],&z[(n)*N+i*N/2+mof*c],N);  
         }
     }

   /* high delay matrices */
   base=1.5*N;

   for( i=n-2; i>=0;i--)
     {
     multH(y,y,&fb[base+i*N/2],&z[(i+1)*N+mof*c],N);
     }
   
   if( n>=1)
     /*multH20(y,y,&fb[0],&z[mof*c],N);*/

     {
     Float fbF[maxfb], *fbFp,*fbp;
     
     fbFp=&fbF[0];
     fbp=&fb[N/2];
     for(i=0;i<N/2;i++)
       *fbFp++ = *fbp++;

     fbp=&fb[0];
     for(i=0;i<N/2;i++)
       *fbFp++ = *fbp++;

     for(i=0;i<N/2;i++)
       *fbFp++ = 0.0;

     fbp=&fb[N];
     for(i=0;i<N/2;i++)
       *fbFp++ = *fbp++;

     multD(y,y,&z[mof*c],N);     

     multF(y,y,&fbF[0],N);    

     }

   else
     multG0(y,y,&fb[0],&z[mof*c],N);
  

   /*
   multDinv(y,y,&z[N/2*(n+1)*c],N);
   multF(y,y,&fb[m*2*N],N);
   */

  /*  C matrices */ 
   /*
   for(i=m-1;i>=0;i--)
      {
      multD2inv(y,y,&z1[i*N/2+m*N/2*c],&z2[i*N/2+m*N/2*c],N);
      multC(y,y,&fb[i*2*N],N);
      
      }
    */

   yp=y;
   for(i=0;i<N;i++)
      {
      *outp++ = *yp++;
      };


   }


}








void sffbmidv(double out[],double fb[],int N1,int N2,int n,double x[],int L,int blocks,int c,double z[])
     /*
Float *out, *fb, *x, *z;
int N1,N2,n,L,blocks,c;
*/
/*n: number of high del matrices*/
/*c: channel */

{
  /* static Float  z1[maxm*max*maxc]={0}, z2[maxm*max*maxc]={0},
             z[maxn*max*maxc]={0};*/
static int count=0;
int m,i,j, base,mof,N, zahl;
double  *zh,*zh2, y[max], *yp, *yhp, *xp, *outp, xh[max],*xhp;

/*c=0; channel number */
/*m=(L-n*N/2)/(2*N)-1;*/
/*number of low del matrices */
/*
printf("hallo0\n");
*/

/*printf("m= %d \n",m);*/
/*printf("x(1)= %f \n",x[0]);*/
/*
printf("N1= %d\n",N1);
printf("N2= %d\n",N2);
*/
count=0; /* nicht fuer stereo*/

if(N1==N2)
  {
  N=N1;
  m=(L-(n-1)*N/2-1.5*N)/(N/2);
  odct(x,N1);
  for(i=0;i<N1;i++) x[i] *= 1./N1;

/*   printf("N1=N2\n");*/
  }     /*if N1==N2 */
else /*N1!= N2 */
  {
  if(N2<N1)
    {
/*    printf("N2<N1\n");*/
    N=N1;
    odct(x,N2);
    for(i=0;i<N2;i++) x[i] *= 1./N2;

    xhp=xh;
    xp=x;
    /*x mit Nullen auffuellen*/
    for(i=0;i<(N2/2);i++)
      {
      *xhp++ = *xp++;
      };
    for(i=0;i<((N1-N2));i++)
      {
      *xhp++ = 0;
      };
    for(i=0;i<(N2/2);i++)
      {
      *xhp++ = *xp++;
      };
    x=xh;
    /*
for(zahl=0;zahl<1.5*N1;zahl++)
  printf("x= %f \n ",x[zahl]);
  */    
    }
  else /* N2>N1 */
    {
/*printf("N2>N1\n");*/
      /*z mut Nullen auffuellen */
    N=N2;
    m=(L-(n-1)*N/2-1.5*N)/(N/2); /* # of low del matrices*/
    odct(x,N2);
    for(i=0;i<N2;i++) x[i] *= 1./N2;

    if(count<1)
      {
      zh=&z[N1-1];
      zh2=&z[N2-1]; /*H  */
      for(i=0;i<(N1/2);i++)
        {
        *zh2-- = *zh--;
        };


      if(n%2==0)
        {
        zh=&z[N1+N1/2-1];
        zh2=&z[N2+N1/2-1]; /* E1 */
        for(i=0;i<(N1/2);i++)
          {
          *zh2-- = *zh--;
          };
          zh=&z[N2+N1/2];     /* E1 */
          for(i=0;i<((N2-N1)/2);i++)
            {
            *zh++ = 0;
            };
        }
      else
        {
        zh=&z[N1+N1/2-1];
        zh2=&z[N2+N2/2-1]; /* G1 */
        for(i=0;i<(N1/2);i++)
          {

          *zh2-- = *zh--;
          };
          zh=&z[N2];     /* G1 */
          for(i=0;i<((N2-N1)/2);i++)
            {
	     
            *zh++ = 0;
	  
            };
        }
      zh=&z[N1/2];
      for(i=0;i<((N2-N1));i++)
        {
        *zh++ = 0;
        };
      
     
      /*
      printf("N2>N1\n");
for(zahl=0;zahl<2*N2;zahl++)
  printf("z= %f \n ",z[zahl]);
  */
      };
    }
  }

/*
printf("hallo\n");
printf("N= %d\n",N);
*/
  sffbmid(y,fb,N,n,x,L,blocks,0,z);
  /*
printf("fertig\n");  
*/

  if(N1==N2)
    {
    N=N1;
    count=0;

    yp=y;
    outp=out;
    N=N1/2+N2/2;

    for(i=0;i<N;i++)
      {
      *outp++ = *yp++;
      };
    

    }
  else
    {

    if(N2<N1)
      {
      
      count=count+1;
      if(count>=n)
        { /*reduce z's */
	  /*
for(zahl=0;zahl<1.5*N1;zahl++)
  printf("z= %f \n ",z[zahl]);
  */
        zh=&z[N1-N2/2];
        zh2=&z[N2/2];
        for(i=0;i<(N2/2);i++) /* H  */
          {
          *zh2++ = *zh++;
          };
        if(n%2==0)
          {
          zh=&z[N1];
          zh2=&z[N2];
          for(i=0;i<(N2/2);i++) /* G1 */
            {
            *zh2++ = *zh++;
            };
          }
        else
          {
          m=(L-(n-1)*N/2-1.5*N)/(N/2); /* # of low del matrices*/
          for(j=0;j<m;j++)
	    {
            zh=&z[N1+N1/2-N2/2+j*N1/2];
            zh2=&z[N2+j*N2/2];
            for(i=0;i<(N2/2);i++) /* E1 */
              {
              *zh2++ = *zh++;
              };
            }
          }
	/*yp=&y[0];*/
          yp=out;
	  /*  yhp=&y[(N2-N1)/2];*/
          yhp=&y[0];
          for(i=0;i<((N2+N1)/2);i++)
            {
            *yp++ = *yhp++;
            };
        }

      }
    else /*N2>N1 */ 
      {
     
      count=count+1;


      if(count<=n)
        {
	/*reduce y */
	  

 
	  
	  /*yp=&y[0];*/
        yp=out;
        yhp=&y[N2/2-N1/2];
        for(i=0;i<(N2/2+N1/2);i++)
          {
          *yp++ = *yhp++;
          };
	  
        
	}

      }
    } /* else ..N1!=N1*/
  /*
printf("fast fertig\n");
*/

  /*
yp=y;
outp=out;
N=N1/2+N2/2;

  for(i=0;i<N;i++)
    {
    *outp++ = *yp++;
    };
    */



}















/*****************Odd DCT ************/



#define TRUE 1
#define FALSE 0

int iniflag = TRUE;
Float ctab[2*LDCTMAX];

void odct(Float x[],int n)
{
  int i,j,k,len,ba,of;
  Float f,v;

  if(iniflag) init_dctmat();

  k = LDCTMAX/n;			/* Eingangsmult. fuer ODCT */
  for(i=0;i<n;i++) x[i] = x[i]*ctab[k*(2*i+1)];
  len = n/2;				/* Butterfly-Spannweite */
  while(len>=1) {
    k = LDCTMAX/len;
    for(of=0;of<len;of++) {		/* Offset in der Gruppe */
      f = ctab[k*(2*of+1)];
      for(ba=0;ba<n;ba+=2*len) {	/* Offset der Gruppe */
	if(of<((len+1)/2)) {		/* Vertauschung innerhalb */
	  i = ba+len+of;		/*  der zweiten Haelfte   */
	  j = ba+2*len-1-of;		/*  der Gruppe            */
	  v = x[i];
	  x[i] = x[j];
	  x[j] = v;
	}
	i = ba+of;			/* Butterfly berechnen */
	j = i+len;
	v = (x[i]-x[j])*f;
	x[i] += x[j];
	x[j] = v;
      }
    }
    len /= 2;
  }
  bitrev1(x,n);				/* Bit-Reversal */

  len = n/2;				/* Ausgangs-Additionen */
  while(len>1) {
    for(i=0;i<n-len;i++)
      if((2*i/len)%2)
	x[i] += x[i+len];
    len /= 2;
  }

  for(i=0;i<n-1;i++) x[i] += x[i+1];
  /*f = sqrt(2./n);*/
  /*for(i=0;i<n;i++) x[i] *= f; */
}

void init_dctmat()
{
  int i;
  for(i=0;i<2*LDCTMAX;i++)
    ctab[i] = .5/cos(M_PI*(Float)i/LDCTMAX/4.);
  iniflag = FALSE;
}

void bitrev1(Float x[],int n)
{
  int i,j,k;
  Float v;

  j = 0;
  for(i=1;i<n-1;i++) {
    k = n/2;
    while(k<=j) {
      j -= k;
      k /= 2;
    }
    j += k;
    if(i<j) {
      v = x[i];
      x[i] = x[j];
      x[j] = v;
    }
  }
}





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

