uint32 soundtsi;
uint32 Wave[2048];
-int32 WaveFinal[2048];
int16 WaveFinalMono[2048];
EXPSOUND GameExpSound={0,0,0};
uint8 realvolume[3];
static int32 count[5];
-static int64 sqacc[2]={0,0};
+static int32 sqacc[2]={0,0};
uint8 sqnon=0;
uint32 soundtsoffs=0;
};
static uint32 NoiseFreqTable[0x10];
-int64 nesincsizeLL;
+static int32 nesincsize32;
+int64 nesincsize;
static const uint8 NTSCPCMTable[0x10]=
{
// $4013 - Size register: Size in bytes = (V+1)*64
-static int64 PCMacc=0;
+static int32 PCMacc=0;
static int PCMfreq;
int32 PCMIRQCount;
uint8 PCMBitIndex=0;
uint8 PCMBuffer=0;
int vdis=0;
-static void Dummyfunc(void) {};
+static void Dummyfunc(int end) {};
-static void (*DoNoise)(void)=Dummyfunc;
-static void (*DoTriangle)(void)=Dummyfunc;
-static void (*DoPCM)(void)=Dummyfunc;
-static void (*DoSQ1)(void)=Dummyfunc;
-static void (*DoSQ2)(void)=Dummyfunc;
+static void (*DoNoise)(int end)=Dummyfunc;
+static void (*DoTriangle)(int end)=Dummyfunc;
+static void (*DoPCM)(int end)=Dummyfunc;
+static void (*DoSQ1)(int end)=Dummyfunc;
+static void (*DoSQ2)(int end)=Dummyfunc;
static void CalcDPCMIRQ(void)
{
PCMfreq=PALPCMTable[PSG[0x10]&0xF];
else
PCMfreq=NTSCPCMTable[PSG[0x10]&0xF];
- PCMacc=(int64)PCMfreq<<50;
+ PCMacc=PCMfreq<<18;
}
uint8 sweepon[2]={0,0};
static DECLFW(Write0x11)
{
- DoPCM();
+ DoPCM(0);
PSG[0x11]=V&0x7F;
}
switch(A)
{
case 0x0:
- DoSQ1();
+ DoSQ1(0);
if(V&0x10)
realvolume[0]=V&0xF;
break;
sweepon[0]=V&0x80;
break;
case 0x2:
- DoSQ1();
+ DoSQ1(0);
curfreq[0]&=0xFF00;
curfreq[0]|=V;
break;
case 0x3:
if(PSG[0x15]&1)
{
- DoSQ1();
+ DoSQ1(0);
lengthcount[0]=lengthtable[(V>>3)&0x1f];
sqnon|=1;
}
DecCountTo1[0]=(PSG[0]&0xF)+1;
SweepCount[0]=((PSG[0x1]>>4)&7)+1;
DutyCount[0]=0;
- sqacc[0]=((int64)curfreq[0]+1)<<50;
+ sqacc[0]=((int32)curfreq[0]+1)<<18;
break;
case 0x4:
- DoSQ2();
+ DoSQ2(0);
if(V&0x10)
realvolume[1]=V&0xF;
break;
sweepon[1]=V&0x80;
break;
case 0x6:
- DoSQ2();
+ DoSQ2(0);
curfreq[1]&=0xFF00;
curfreq[1]|=V;
break;
case 0x7:
if(PSG[0x15]&2)
{
- DoSQ2();
+ DoSQ2(0);
lengthcount[1]=lengthtable[(V>>3)&0x1f];
sqnon|=2;
}
DecCountTo1[1]=(PSG[0x4]&0xF)+1;
SweepCount[1]=((PSG[0x5]>>4)&7)+1;
DutyCount[1]=0;
- sqacc[1]=((int64)curfreq[1]+1)<<50;
+ sqacc[1]=((int32)curfreq[1]+1)<<18;
break;
case 0x8:
- DoTriangle();
+ DoTriangle(0);
if(laster&0x80)
{
tricoop=V&0x7F;
tricoop=0;
laster=V&0x80;
break;
- case 0xa:DoTriangle();
+ case 0xa:DoTriangle(0);
break;
case 0xb:
if(PSG[0x15]&0x4)
{
- DoTriangle();
+ DoTriangle(0);
sqnon|=4;
lengthcount[2]=lengthtable[(V>>3)&0x1f];
}
tricoop=PSG[0x8]&0x7f;
trimode=PSG[0x8]&0x80;
break;
- case 0xC:DoNoise();
+ case 0xC:DoNoise(0);
if(V&0x10)
realvolume[2]=V&0xF;
break;
- case 0xE:DoNoise();break;
+ case 0xE:DoNoise(0);break;
case 0xF:
if(PSG[0x15]&8)
{
- DoNoise();
+ DoNoise(0);
sqnon|=8;
lengthcount[3]=lengthtable[(V>>3)&0x1f];
}
decvolume[2]=0xF;
DecCountTo1[2]=(PSG[0xC]&0xF)+1;
break;
- case 0x10:DoPCM();
+ case 0x10:DoPCM(0);
if(!(V&0x80))
X6502_IRQEnd(FCEU_IQDPCM);
break;
int t=V^PSG[0x15];
if(t&1)
- DoSQ1();
+ DoSQ1(0);
if(t&2)
- DoSQ2();
+ DoSQ2(0);
if(t&4)
- DoTriangle();
+ DoTriangle(0);
if(t&8)
- DoNoise();
+ DoNoise(0);
if(t&0x10)
- DoPCM();
+ DoPCM(0);
sqnon&=V;
if(V&0x10)
{
X6502_IRQEnd(FCEU_IQDPCM);
}
break;
- case 0x17:
- V&=0xC0;
- fcnt=0;
- if(V&0x80)
- FrameSoundUpdate();
- fhcnt=fhinc;
- X6502_IRQEnd(FCEU_IQFCOUNT);
- SIRQStat&=~0x40;
- break;
}
PSG[A]=V;
}
{
uint8 ret;
if(PSG[0x15]&0x10)
- DoPCM();
+ DoPCM(0);
ret=(PSG[0x15]&(sqnon|0x10))|SIRQStat;
SIRQStat&=~0x40;
X6502_IRQEnd(/*FCEU_IQDPCM|*/FCEU_IQFCOUNT);
static void FASTAPASS(1) FrameSoundStuff(int V)
{
int P;
+ uint32 end = (SOUNDTS<<16)/soundtsinc;
- DoSQ1();
- DoSQ2();
- DoNoise();
+ DoSQ1(end);
+ DoSQ2(end);
+ DoNoise(end);
switch((V&1))
{
lengthcount[2]--;
if(lengthcount[2]<=0)
{
- DoTriangle();
+ DoTriangle(0);
sqnon&=~4;
}
}
laster=0;
if(tricoop)
{
- if(tricoop==1) DoTriangle();
+ if(tricoop==1) DoTriangle(0);
tricoop--;
}
}
*b=V;
}
-static void RDoPCM(void)
+static void RDoPCM(int32 end)
{
int32 V;
- int32 start,end;
- int64 freq;
+ int32 start;
+ int32 freq;
uint32 out=PSG[0x11]<<3;
start=ChannelBC[4];
- end=(SOUNDTS<<16)/soundtsinc;
+ if(end==0) end=(SOUNDTS<<16)/soundtsinc;
if(end<=start) return;
ChannelBC[4]=end;
if(PSG[0x15]&0x10)
{
freq=PCMfreq;
- freq<<=50;
+ freq<<=18;
for(V=start;V<end;V++)
{
- PCMacc-=nesincsizeLL;
+ PCMacc-=nesincsize32;
if(PCMacc<=0)
{
if(!PCMBitIndex)
endopcmo:;
}
-static void RDoSQ1(void)
+static void RDoSQ1(int32 end)
{
int32 V;
- int32 start,end;
- int64 freq;
+ int32 start;
+ int32 freq;
- CalcRectAmp(0);
start=ChannelBC[0];
- end=(SOUNDTS<<16)/soundtsinc;
+ if(end==0) end=(SOUNDTS<<16)/soundtsinc;
if(end<=start) return;
ChannelBC[0]=end;
+ if(!(PSG[0x15]&1 && sqnon&1))
+ return;
+
if(curfreq[0]<8 || curfreq[0]>0x7ff)
return;
if(!CheckFreq(curfreq[0],PSG[0x1]))
return;
- if(PSG[0x15]&1 && sqnon&1)
+ CalcRectAmp(0);
+
{
uint32 out=RectAmp[0][DutyCount[0]];
freq=curfreq[0]+1;
{
- freq<<=50;
+ freq<<=18;
for(V=start;V<end;V++)
{
Wave[V>>4]+=out;
- sqacc[0]-=nesincsizeLL;
+ sqacc[0]-=nesincsize32;
if(sqacc[0]<=0)
{
rea:
DutyCount[0]&=7;
out=RectAmp[0][DutyCount[0]];
}
-
}
- }
}
+ }
}
-static void RDoSQ2(void)
+static void RDoSQ2(int32 end)
{
int32 V;
- int32 start,end;
- int64 freq;
+ int32 start;
+ int32 freq;
- CalcRectAmp(1);
start=ChannelBC[1];
- end=(SOUNDTS<<16)/soundtsinc;
+ if(end==0) end=(SOUNDTS<<16)/soundtsinc;
if(end<=start) return;
ChannelBC[1]=end;
+ if(!(PSG[0x15]&2 && sqnon&2))
+ return;
+
if(curfreq[1]<8 || curfreq[1]>0x7ff)
return;
if(!CheckFreq(curfreq[1],PSG[0x5]))
return;
- if(PSG[0x15]&2 && sqnon&2)
+ CalcRectAmp(1);
+
{
uint32 out=RectAmp[1][DutyCount[1]];
freq=curfreq[1]+1;
{
- freq<<=50;
+ freq<<=18;
for(V=start;V<end;V++)
{
Wave[V>>4]+=out;
- sqacc[1]-=nesincsizeLL;
+ sqacc[1]-=nesincsize32;
if(sqacc[1]<=0)
{
rea:
DutyCount[1]&=7;
out=RectAmp[1][DutyCount[1]];
}
-
}
- }
}
+ }
}
-static void RDoTriangle(void)
+static void RDoTriangle(int32 end)
{
static uint32 tcout=0;
int32 V;
- int32 start,end; //,freq;
- int64 freq=(((PSG[0xa]|((PSG[0xb]&7)<<8))+1));
+ int32 start; //,freq;
+ int32 freq=(((PSG[0xa]|((PSG[0xb]&7)<<8))+1));
start=ChannelBC[2];
- end=(SOUNDTS<<16)/soundtsinc;
+ if(end==0) end=(SOUNDTS<<16)/soundtsinc;
if(end<=start) return;
ChannelBC[2]=end;
}
else
{
- static int64 triacc=0;
+ static int32 triacc=0;
static uint8 tc=0;
- freq<<=49;
+ freq<<=17;
for(V=start;V<end;V++)
{
- triacc-=nesincsizeLL;
+ triacc-=nesincsize32;
if(triacc<=0)
{
rea:
}
}
-static void RDoNoise(void)
+static void RDoNoise(int32 end)
{
int32 inc,V;
- int32 start,end;
+ int32 start;
start=ChannelBC[3];
- end=(SOUNDTS<<16)/soundtsinc;
+ if(end==0) end=(SOUNDTS<<16)/soundtsinc;
if(end<=start) return;
ChannelBC[3]=end;
count[3]+=0x1000;
}
}
-
}
}
+DECLFW(Write_IRQFM)
+{
+ PSG[0x17]=V;
+ V=(V&0xC0)>>6;
+ fcnt=0;
+ if(V&0x2)
+ FrameSoundUpdate();
+ fcnt=1;
+ fhcnt=fhinc;
+ X6502_IRQEnd(FCEU_IQFCOUNT);
+ SIRQStat&=~0x40;
+ //IRQFrameMode=V; // IRQFrameMode is PSG[0x17] upper bits
+}
+
void SetNESSoundMap(void)
{
SetWriteHandler(0x4000,0x4013,Write_PSG);
SetWriteHandler(0x4011,0x4011,Write0x11);
SetWriteHandler(0x4015,0x4015,Write_PSG);
- SetWriteHandler(0x4017,0x4017,Write_PSG);
+ SetWriteHandler(0x4017,0x4017,Write_IRQFM);
SetReadHandler(0x4015,0x4015,Read_PSG);
}
-static int32 WaveNSF[256];
-
int32 highp; // 0 through 65536, 0 = no high pass, 65536 = max high pass
int32 lowp; // 0 through 65536, 65536 = max low pass(total attenuation)
// 65536 = no low pass
-static void FilterSound(uint32 *in, int32 *out, int16 *outMono, int count)
+static int32 flt_acc=0, flt_acc2=0;
+
+static void FilterSound(uint32 *in, int16 *outMono, int count)
{
- static int64 acc=0, acc2=0;
- //int index=0;
- //int16* tmp;
- //int16* outorig=out;
- //int32 prev=-99999;
- for(;count;count--,in++)//,out++)//,index++)
+// static int min=0, max=0;
+
+ for(;count;count--,in++,outMono++)
{
- int64 diff;
+ int32 diff;
- diff=((int64)*in<<24)-acc;
+ diff = *in - flt_acc;
- acc+=(diff*highp)>>16;
- acc2+=((diff-acc2)*lowp)>>16;
+ flt_acc += (diff*highp)>>16;
+ flt_acc2+= (int32) (((int64)((diff-flt_acc2)*lowp))>>16);
*in=0;
- // don't change the sound here
-// *out=(acc2*(int64)FSettings.SoundVolume)>>(24+16);
- // volume, 4 times louder by default??
-// *out = acc2 >> 24;
- // just a bit louder. Hope it's okay
- /*
- *out = acc2 >> 22;
- if(*out<-32767) *out=-32767;
- if(*out>32767) *out=32767;
- // go one back
-
- // do MONO
- tmp=(int16 *)(out-1);
- // don't do this the first time
- if (prev == -99999) continue;
- // the middle one should be interpolated
- tmp[1]=(int16)((*out + prev) >> 1);
- prev = *out;
- */
- //outMono[index] = (int16)*out;
- *outMono = (int16)(acc2 >> 24);
- //if(*outMono<-16384) *outMono=-16384;
- //if(*outMono>16384) *outMono=16384;
- outMono++;
-
- // out=((int64)(acc2>>24)*(int64)FSettings.SoundVolume)>>16; //acc2>>24;
-
+ *outMono = flt_acc2*7 >> 2; // * 1.75
+// if (acc2 < min) { printf("min: %i %04x\n", acc2, acc2); min = acc2; }
+// if (acc2 > max) { printf("max: %i %04x\n", acc2, acc2); max = acc2; }
}
- // do one more
}
-
+static int32 inbuf=0;
int FlushEmulateSound(void)
{
int x;
}
end=(SOUNDTS<<16)/soundtsinc;
- DoSQ1();
- DoSQ2();
- DoTriangle();
- DoNoise();
- DoPCM();
+ DoSQ1(end);
+ DoSQ2(end);
+ DoTriangle(end);
+ DoNoise(end);
+ DoPCM(end);
if(GameExpSound.Fill)
GameExpSound.Fill(end&0xF);
-// FilterSound(Wave,WaveFinal,end>>4);
- FilterSound(Wave,WaveFinal,WaveFinalMono,end>>4);
-// printf("count %d, num ints %d\n", end, (end >> 4));
- if(FCEUGameInfo.type==GIT_NSF)
- {
- printf("IS NSF");
- int x,s=0,si=end/1024; // Only want 1/4 of the output buffer to be displayed
- for(x=0;x<256;x++)
- {
- WaveNSF[x]=WaveFinal[s>>4];
- s+=si;
- }
- }
+ FilterSound(Wave,WaveFinalMono,end>>4);
if(end&0xF)
Wave[0]=Wave[(end>>4)];
for(x=0;x<5;x++)
ChannelBC[x]=end&0xF;
soundtsoffs=(soundtsinc*(end&0xF))>>16;
- return(end>>4);
+ end>>=4;
+ inbuf=end;
+ return(end);
}
-void GetSoundBuffer(int32 **W)
+int GetSoundBuffer(int16 **W)
{
- *W=WaveNSF;
+ *W=WaveFinalMono;
+ return inbuf;
}
void PowerSound(void)
if(GameExpSound.RChange)
GameExpSound.RChange();
- nesincsizeLL=(int64)((int64)562949953421312*(long double)(PAL?PAL_CPU:NTSC_CPU)/(FSettings.SndRate OVERSAMPLE));
+ // nesincsizeLL=(int64)((int64)562949953421312*(double)(PAL?PAL_CPU:NTSC_CPU)/(FSettings.SndRate OVERSAMPLE));
+ nesincsize=(int64)(((int64)1<<17)*(double)(PAL?PAL_CPU:NTSC_CPU)/(FSettings.SndRate * 16)); // 308845 - 1832727
+ nesincsize32=(int32)nesincsize;
PSG_base=(uint32)(PAL?(long double)PAL_CPU/16:(long double)NTSC_CPU/16);
for(x=0;x<0x10;x++)
NoiseFreqTable[x]=z;
}
soundtsinc=(uint32)((uint64)(PAL?(long double)PAL_CPU*65536:(long double)NTSC_CPU*65536)/(FSettings.SndRate OVERSAMPLE));
- memset(Wave,0,2048*4);
+ memset(Wave,0,sizeof(Wave));
for(x=0;x<5;x++)
ChannelBC[x]=0;
highp=(250<<16)/FSettings.SndRate; // Arbitrary
- lowp=((int64)25000<<16)/FSettings.SndRate; // Arbitrary
+ lowp=(25000<<16)/FSettings.SndRate; // Arbitrary
if(highp>(1<<16)) highp=1<<16;
if(lowp>(1<<16)) lowp=1<<16;
+
+ flt_acc=flt_acc2=0;
}
void FixOldSaveStateSFreq(void)
void FCEUI_SetSoundVolume(uint32 volume)
{
- FSettings.SoundVolume=(volume<<16)/100;
+ FSettings.SoundVolume=volume;
}