#include <stdio.h>
#include "types.h"

#include "sound.h"
#include "x6502.h"
#include "fce.h"
#include "filter.h"
#include "svga.h"

#include "fcoeffs.h"

static int64 mrindex;
static int64 mrratio;
//static int dmethod=1;


void SexyFilter(int32 *in, int32 *out, int32 count)
{
 static int64 acc1,acc2;
 int32 mul1,mul2,vmul;

 mul1=(94<<16)/FSettings.SndRate;
 mul2=(24<<16)/FSettings.SndRate;
 vmul=(FSettings.SoundVolume<<16)/100;

 while(count)
 {  
  int64 ino=(int64)*in*vmul;
  
  acc1+=((ino-acc1)*mul1)>>16;
  acc2+=((ino-acc1-acc2)*mul2)>>16;
  *in=0;
  {
   int32 t=(acc1-ino+acc2)>>16;
   if(t>32767) t=32767;
   if(t<-32768) t=-32768;
   *out=t;
  }
  in++;
  out++;
  count--;
 }
}
/* Returns number of samples written to out. */
/* leftover is set to the number of samples that need to be copied 
   from the end of in to the beginning of in.
*/

int32 NeoFilterSound(int32 *in, int32 *out, int32 inlen, int32 *leftover)
{
 int64 x;
 int64 max;
 int32 *outsave=out;
 int32 count=0;

	 if(GameExpSound.HiFill) GameExpSound.HiFill();

         max=((int64)inlen-1)<<16;

         for(x=mrindex;x<max;x+=mrratio)
         {
          int32 acc=0,acc2=0;

          #ifdef C80x86
          asm volatile(
                "pushl %%ebp\n\t"
                "kayo:\n\t"        
                "movl (%%esi,%%ecx),%%eax\n\t"
                "movl 4(%%esi,%%ecx),%%ebp\n\t"
                "imul (%%edi),%%eax\n\t"
                "imul (%%edi),%%ebp\n\t"        
                "sarl $4,%%eax\n\t"
                "sarl $4,%%ebp\n\t"
                "addl %%eax,%%ebx\n\t"
                "addl %%ebp,%%edx\n\t"
                "addl $4,%%edi\n\t"
                "subl $4,%%ecx\n\t"
                "jnz kayo\n\t"
                "popl %%ebp\n\t"
                : "=b" (acc), "=d" (acc2)
                : "c"(NCOEFFS<<2), "S"(&in[(x>>16)-NCOEFFS]), "D" (coeffs), "b" (acc), "d" (acc2)
                : "%eax"
                );
          #else
	  { int32 y;
          for(y=0;y<NCOEFFS;y++)
          {
           acc+=(in[(x>>16)-y]*coeffs[y])>>4;
           acc2+=(in[(x>>16)-y+1]*coeffs[y])>>4;
          }
	  }
          #endif
          acc=((int64)acc*(65536-(x&65535))+(int64)acc2*(x&65535))>>(16+14);
  
          //if(acc>=(1<<29)) printf("ack\n");

          *out=acc;

          out++;
          count++;
         }
         mrindex=x-max;
         mrindex+=NCOEFFS*65536;
         *leftover=NCOEFFS+1;
 if(GameExpSound.NeoFill)
  GameExpSound.NeoFill(outsave,count);

 SexyFilter(outsave,outsave,count);

 return(count);
}

void MakeFilters(int32 rate)
{
 int32 *tabs[6]={C44100NTSC,C44100PAL,C48000NTSC,C48000PAL,C96000NTSC,
        C96000PAL};
 int32 *tmp;
 int32 x;
 mrindex=(int64)(NCOEFFS+1)<<16;
 mrratio=(int64)((double)(PAL?PAL_CPU:NTSC_CPU)/rate*65536);
 tmp=tabs[(PAL?1:0)|(rate==48000?2:0)|(rate==96000?4:0)];

 for(x=0;x<NCOEFFS>>1;x++)
 {
  //printf("%d:%d, %d\n",x,NCOEFFS-1-x,coeffs[x]);
  coeffs[x]=coeffs[NCOEFFS-1-x]=tmp[x];
 }
}
