fceugx/source/fceultra/filter.cpp

210 lines
4.4 KiB
C++
Raw Normal View History

2009-07-17 19:27:04 +02:00
/// \file
/// \brief Sound filtering code
#include "types.h"
#include "sound.h"
#include "x6502.h"
#include "fceu.h"
#include "filter.h"
#include "fcoeffs.h"
2016-09-18 05:43:24 +02:00
#include <cmath>
#include <cstdio>
2009-07-17 19:27:04 +02:00
static int32 sq2coeffs[SQ2NCOEFFS];
static int32 coeffs[NCOEFFS];
static uint32 mrindex;
static uint32 mrratio;
void SexyFilter2(int32 *in, int32 count)
{
#ifdef moo
static int64 acc=0;
double x,p;
int64 c;
x=2*M_PI*6000/FSettings.SndRate;
p=((double)2-cos(x)) - sqrt(pow((double)2-cos(x),2) -1 );
c=p*0x100000;
//printf("%f\n",(double)c/0x100000);
#endif
static int64 acc=0;
while(count--)
{
int64 dropcurrent;
dropcurrent=((*in<<16)-acc)>>3;
acc+=dropcurrent;
*in=acc>>16;
in++;
//acc=((int64)0x100000-c)* *in + ((c*acc)>>20);
//*in=acc>>20;
//in++;
}
}
void SexyFilter(int32 *in, int32 *out, int32 count)
{
static int64 acc1=0,acc2=0;
int32 mul1,mul2,vmul;
mul1=(94<<16)/FSettings.SndRate;
mul2=(24<<16)/FSettings.SndRate;
vmul=(FSettings.SoundVolume<<16)*3/4/100;
2010-08-29 23:15:42 +02:00
//FCEU_DispMessage("SoundVolume %d, vmul %d",0,FSettings.SoundVolume,vmul);
2009-07-17 19:27:04 +02:00
if(FSettings.soundq) vmul/=4;
else vmul*=2; /* TODO: Increase volume in low quality sound rendering code itself */
while(count)
2012-12-14 18:18:20 +01:00
{
2009-07-17 19:27:04 +02:00
int64 ino=(int64)*in*vmul;
acc1+=((ino-acc1)*mul1)>>16;
acc2+=((ino-acc1-acc2)*mul2)>>16;
//printf("%d ",*in);
2012-12-14 18:18:20 +01:00
*in=0;
{
2009-07-17 19:27:04 +02:00
int32 t=(acc1-ino+acc2)>>16;
//if(t>32767 || t<-32768) printf("Flow: %d\n",t);
if(t>32767) t=32767;
2012-12-14 18:18:20 +01:00
if(t<-32768) t=-32768;
2009-07-17 19:27:04 +02:00
*out=t;
2012-12-14 18:18:20 +01:00
}
in++;
out++;
count--;
2009-07-17 19:27:04 +02:00
}
}
/* Returns number of samples written to out. */
2012-12-14 18:18:20 +01:00
/* leftover is set to the number of samples that need to be copied
2009-07-17 19:27:04 +02:00
from the end of in to the beginning of in.
*/
//static uint32 mva=1000;
/* This filtering code assumes that almost all input values stay below 32767.
Do not adjust the volume in the wlookup tables and the expansion sound
code to be higher, or you *might* overflow the FIR code.
*/
int32 NeoFilterSound(int32 *in, int32 *out, uint32 inlen, int32 *leftover)
{
uint32 x;
uint32 max;
int32 *outsave=out;
int32 count=0;
// for(x=0;x<inlen;x++)
// {
// if(in[x]>mva){ mva=in[x]; printf("%ld\n",in[x]);}
// }
max=(inlen-1)<<16;
if(FSettings.soundq==2)
2012-01-09 02:59:06 +01:00
for(x=mrindex;x<max;x+=mrratio)
{
int32 acc=0,acc2=0;
unsigned int c;
int32 *S,*D;
2012-12-14 18:18:20 +01:00
2012-01-09 02:59:06 +01:00
for(c=SQ2NCOEFFS,S=&in[(x>>16)-SQ2NCOEFFS],D=sq2coeffs;c;c--,D++)
{
acc+=(S[c]**D)>>6;
acc2+=(S[1+c]**D)>>6;
}
acc=((int64)acc*(65536-(x&65535))+(int64)acc2*(x&65535))>>(16+11);
*out=acc;
2012-12-14 18:18:20 +01:00
out++;
count++;
2012-01-09 02:59:06 +01:00
}
2009-07-17 19:27:04 +02:00
else
2012-01-09 02:59:06 +01:00
for(x=mrindex;x<max;x+=mrratio)
{
int32 acc=0,acc2=0;
unsigned int c;
const int32 *S,*D;
2012-12-14 18:18:20 +01:00
2012-01-09 02:59:06 +01:00
for(c=NCOEFFS,S=&in[(x>>16)-NCOEFFS],D=coeffs;c;c--,D++)
{
acc+=(S[c]**D)>>6;
acc2+=(S[1+c]**D)>>6;
}
2012-12-14 18:18:20 +01:00
acc=((int64)acc*(65536-(x&65535))+(int64)acc2*(x&65535))>>(16+11);
2012-01-09 02:59:06 +01:00
*out=acc;
out++;
count++;
}
2009-07-17 19:27:04 +02:00
2012-01-09 02:59:06 +01:00
mrindex=x-max;
2009-07-17 19:27:04 +02:00
if(FSettings.soundq==2)
{
mrindex+=SQ2NCOEFFS*65536;
*leftover=SQ2NCOEFFS+1;
}
else
{
mrindex+=NCOEFFS*65536;
*leftover=NCOEFFS+1;
}
if(GameExpSound.NeoFill)
GameExpSound.NeoFill(outsave,count);
SexyFilter(outsave,outsave,count);
if(FSettings.lowpass)
SexyFilter2(outsave,count);
return(count);
}
void MakeFilters(int32 rate)
{
const int32 *tabs[6]={C44100NTSC,C44100PAL,C48000NTSC,C48000PAL,C96000NTSC,
C96000PAL};
const int32 *sq2tabs[6]={SQ2C44100NTSC,SQ2C44100PAL,SQ2C48000NTSC,SQ2C48000PAL,
SQ2C96000NTSC,SQ2C96000PAL};
const int32 *tmp;
int32 x;
uint32 nco;
if(FSettings.soundq==2)
nco=SQ2NCOEFFS;
else
nco=NCOEFFS;
mrindex=(nco+1)<<16;
mrratio=(PAL?(int64)(PAL_CPU*65536):(int64)(NTSC_CPU*65536))/rate;
if(FSettings.soundq==2)
tmp=sq2tabs[(PAL?1:0)|(rate==48000?2:0)|(rate==96000?4:0)];
else
tmp=tabs[(PAL?1:0)|(rate==48000?2:0)|(rate==96000?4:0)];
if(FSettings.soundq==2)
for(x=0;x<SQ2NCOEFFS>>1;x++)
sq2coeffs[x]=sq2coeffs[SQ2NCOEFFS-1-x]=tmp[x];
else
for(x=0;x<NCOEFFS>>1;x++)
coeffs[x]=coeffs[NCOEFFS-1-x]=tmp[x];
#ifdef MOO
/* Some tests involving precision and error. */
{
static int64 acc=0;
int x;
for(x=0;x<SQ2NCOEFFS;x++)
acc+=(int64)32767*sq2coeffs[x];
printf("Foo: %lld\n",acc);
}
#endif
}