X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=fceu.git;a=blobdiff_plain;f=sound.c;h=f95b0505abd111b22532bde7d4fd0e84cd84cafa;hp=61c8fcdcedb31bbb034dbf3e510c177e86fa50ff;hb=44343b8775fd8c9cfa1a2f865be369e09d1984ff;hpb=5232c20c0fa2c80964fe1d3f597c239bcf93d6fc diff --git a/sound.c b/sound.c index 61c8fcd..f95b050 100644 --- a/sound.c +++ b/sound.c @@ -25,7 +25,7 @@ /******* routines. A few ideas were inspired */ /******* by code from Marat Fayzullin's EMUlib */ /******* */ -/********************************************************/ +/********************************************************/ #include #include @@ -39,14 +39,10 @@ #include "svga.h" #include "sound.h" -uint32 soundtsinc; -uint32 soundtsi; - -uint32 Wave[2048]; -int32 WaveFinal[2048]; -int16 WaveFinalMono[2048]; +uint32 Wave[2048+512]; +int16 WaveFinalMono[2048+512]; -EXPSOUND GameExpSound={0,0,0}; +EXPSOUND GameExpSound={0,0,0,0,0,0}; uint8 trimode=0; uint8 tricoop=0; @@ -56,13 +52,15 @@ uint8 decvolume[3]; 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; + #undef printf uint16 nreg; - -int32 lengthcount[4]; + +static int32 lengthcount[4]; extern int soundvol; @@ -80,7 +78,10 @@ static const uint32 SNoiseFreqTable[0x10]= }; static uint32 NoiseFreqTable[0x10]; -int64 nesincsizeLL; +int32 nesincsize; +uint32 soundtsinc; +uint32 soundtsi; + static const uint8 NTSCPCMTable[0x10]= { @@ -102,22 +103,22 @@ uint32 PSG_base; // $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; uint32 PCMAddressIndex=0; int32 PCMSizeIndex=0; -uint8 PCMBuffer=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) { @@ -131,9 +132,9 @@ static void CalcDPCMIRQ(void) freq=(NTSCPCMTable[PSG[0x10]&0xF]<<4); cycles=(((PSG[0x13]<<4)+1)); - cycles*=freq/14; + cycles*=freq/14; honk=((PSG[0x13]<<4)+1)*freq; - honk-=cycles; + honk-=cycles; //if(PAL) honk/=107; //else honk/=(double)113.66666666; PCMIRQCount=honk*48; @@ -144,15 +145,15 @@ static void CalcDPCMIRQ(void) static void PrepDPCM() { - PCMAddressIndex=0x4000+(PSG[0x12]<<6); + PCMAddressIndex=0x4000+(PSG[0x12]<<6); PCMSizeIndex=(PSG[0x13]<<4)+1; - PCMBitIndex=0; + PCMBitIndex=0; //PCMBuffer=ARead[0x8000+PCMAddressIndex](0x8000+PCMAddressIndex); if(PAL) PCMfreq=PALPCMTable[PSG[0x10]&0xF]; else PCMfreq=NTSCPCMTable[PSG[0x10]&0xF]; - PCMacc=(int64)PCMfreq<<50; + PCMacc=PCMfreq<<18; } uint8 sweepon[2]={0,0}; @@ -185,7 +186,7 @@ static int FASTAPASS(2) CheckFreq(uint32 cf, uint8 sr) static DECLFW(Write0x11) { - DoPCM(); + DoPCM(0); PSG[0x11]=V&0x7F; } @@ -194,12 +195,12 @@ static uint8 DutyCount[2]={0,0}; static DECLFW(Write_PSG) { //if((A>=0x4004 && A<=0x4007) || A==0x4015) - //printf("$%04x:$%02x, %d\n",A,V,timestamp); + //printf("$%04x:$%02x, %d\n",A,V,SOUNDTS); A&=0x1f; switch(A) { case 0x0: - DoSQ1(); + DoSQ1(0); if(V&0x10) realvolume[0]=V&0xF; break; @@ -207,16 +208,16 @@ static DECLFW(Write_PSG) sweepon[0]=V&0x80; break; case 0x2: - DoSQ1(); + DoSQ1(0); curfreq[0]&=0xFF00; curfreq[0]|=V; break; - case 0x3: + case 0x3: if(PSG[0x15]&1) { - DoSQ1(); + DoSQ1(0); lengthcount[0]=lengthtable[(V>>3)&0x1f]; - sqnon|=1; + sqnon|=1; } sweepon[0]=PSG[1]&0x80; curfreq[0]=PSG[0x2]|((V&7)<<8); @@ -224,11 +225,11 @@ static DECLFW(Write_PSG) 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(); + case 0x4: + DoSQ2(0); if(V&0x10) realvolume[1]=V&0xF; break; @@ -236,27 +237,27 @@ static DECLFW(Write_PSG) sweepon[1]=V&0x80; break; case 0x6: - DoSQ2(); + DoSQ2(0); curfreq[1]&=0xFF00; curfreq[1]|=V; break; - case 0x7: + case 0x7: if(PSG[0x15]&2) { - DoSQ2(); + DoSQ2(0); lengthcount[1]=lengthtable[(V>>3)&0x1f]; sqnon|=2; } sweepon[1]=PSG[0x5]&0x80; - curfreq[1]=PSG[0x6]|((V&7)<<8); + curfreq[1]=PSG[0x6]|((V&7)<<8); decvolume[1]=0xF; 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(); + case 0x8: + DoTriangle(0); if(laster&0x80) { tricoop=V&0x7F; @@ -266,12 +267,12 @@ static DECLFW(Write_PSG) 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]; } @@ -279,39 +280,39 @@ static DECLFW(Write_PSG) 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; + DecCountTo1[2]=(PSG[0xC]&0xF)+1; break; - case 0x10:DoPCM(); + case 0x10:DoPCM(0); if(!(V&0x80)) X6502_IRQEnd(FCEU_IQDPCM); break; - case 0x15: + case 0x15: { 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) { @@ -328,15 +329,6 @@ static DECLFW(Write_PSG) 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; } @@ -345,7 +337,7 @@ DECLFR(Read_PSG) { uint8 ret; if(PSG[0x15]&0x10) - DoPCM(); + DoPCM(0); ret=(PSG[0x15]&(sqnon|0x10))|SIRQStat; SIRQStat&=~0x40; X6502_IRQEnd(/*FCEU_IQDPCM|*/FCEU_IQFCOUNT); @@ -365,10 +357,11 @@ DECLFR(Read_PSGDummy) 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)) { @@ -381,10 +374,10 @@ static void FASTAPASS(1) FrameSoundStuff(int V) lengthcount[2]--; if(lengthcount[2]<=0) { - DoTriangle(); + DoTriangle(0); sqnon&=~4; } - } + } } for(P=0;P<2;P++) @@ -395,7 +388,7 @@ static void FASTAPASS(1) FrameSoundStuff(int V) { if(lengthcount[P]>0) { - lengthcount[P]--; + lengthcount[P]--; if(lengthcount[P]<=0) { sqnon&=~(P+1); @@ -410,14 +403,14 @@ static void FASTAPASS(1) FrameSoundStuff(int V) { int32 mod=0; - if(SweepCount[P]>0) SweepCount[P]--; + if(SweepCount[P]>0) SweepCount[P]--; if(SweepCount[P]<=0) { SweepCount[P]=((PSG[(P<<2)+0x1]>>4)&7)+1; //+1; { if(PSG[(P<<2)+0x1]&0x8) { - mod-=(P^1)+((curfreq[P])>>(PSG[(P<<2)+0x1]&7)); + mod-=(P^1)+((curfreq[P])>>(PSG[(P<<2)+0x1]&7)); if(curfreq[P] && (PSG[(P<<2)+0x1]&7)/* && sweepon[P]&0x80*/) { @@ -442,7 +435,7 @@ static void FASTAPASS(1) FrameSoundStuff(int V) } } } - } + } } if(PSG[0x15]&0x8 && sqnon&8) @@ -462,11 +455,11 @@ static void FASTAPASS(1) FrameSoundStuff(int V) case 0: /* Envelope decay + linear counter */ if(!trimode) - { + { laster=0; if(tricoop) { - if(tricoop==1) DoTriangle(); + if(tricoop==1) DoTriangle(0); tricoop--; } } @@ -561,26 +554,26 @@ static void FASTAPASS(1) CalcRectAmp(int P) *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=(timestamp<<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;V0x7ff) 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>4]+=out; - sqacc[0]-=nesincsizeLL; + sqacc[0]-=nesincsize; if(sqacc[0]<=0) { rea: @@ -678,40 +674,42 @@ static void RDoSQ1(void) 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=(timestamp<<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>4]+=out; - sqacc[1]-=nesincsizeLL; + sqacc[1]-=nesincsize; if(sqacc[1]<=0) { rea: @@ -722,22 +720,21 @@ static void RDoSQ2(void) 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=(timestamp<<16)/soundtsinc; + if(end==0) end=(SOUNDTS<<16)/soundtsinc; if(end<=start) return; ChannelBC[2]=end; @@ -760,13 +757,13 @@ static void RDoTriangle(void) } else { - static int64 triacc=0; - static uint8 tc=0; + static int32 triacc=0; + static uint8 tc=0; - freq<<=49; + freq<<=17; for(V=start;V>4]+=outo; if(count[3]>=inc) - { - uint8 feedback; + { + uint8 feedback; feedback=((nreg>>8)&1)^((nreg>>14)&1); nreg=(nreg<<1)+feedback; @@ -845,81 +842,67 @@ static void RDoNoise(void) 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]; - -int64 highp; // 0 through 65536, 0 = no high pass, 65536 = max high pass +int32 highp; // 0 through 65536, 0 = no high pass, 65536 = max high pass -int64 lowp; // 0 through 65536, 65536 = max low pass(total attenuation) +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; + int sh=2; + if (soundvol < 5) sh += 5 - soundvol; + + 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 >> sh; // * 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) { - uint32 end; int x; - + uint32 end; if(!timestamp) return(0); @@ -929,46 +912,35 @@ int FlushEmulateSound(void) goto nosoundo; } - end=(timestamp<<16)/soundtsinc; - DoSQ1(); - DoSQ2(); - DoTriangle(); - DoNoise(); - DoPCM(); + end=(SOUNDTS<<16)/soundtsinc; + 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)]; - Wave[(end>>4)]=0; + Wave[(end>>4)]=0; nosoundo: for(x=0;x<5;x++) ChannelBC[x]=end&0xF; - timestampbase+=timestamp; - timestamp=(soundtsinc*(end&0xF))>>16; - timestampbase-=timestamp; - return(end>>4); + soundtsoffs=(soundtsinc*(end&0xF))>>16; + end>>=4; + inbuf=end; + return(end); } -void GetSoundBuffer(int32 **W) +int GetSoundBuffer(int16 **W) { - *W=WaveNSF; + *W=WaveFinalMono; + return inbuf; } void PowerSound(void) @@ -984,6 +956,7 @@ void PowerSound(void) fhcnt=fhinc; fcnt=0; nreg=1; + soundtsoffs=0; } void ResetSound(void) @@ -999,7 +972,7 @@ void ResetSound(void) void SetSoundVariables(void) { - int x; + int x; fhinc=PAL?16626:14915; // *2 CPU clock rate fhinc*=24; @@ -1013,7 +986,7 @@ void SetSoundVariables(void) DoPCM=RDoPCM; DoSQ1=RDoSQ1; DoSQ2=RDoSQ2; - } + } else { DoNoise=DoTriangle=DoPCM=DoSQ1=DoSQ2=Dummyfunc; @@ -1023,7 +996,8 @@ void SetSoundVariables(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=(int32)(((int64)1<<17)*(double)(PAL?PAL_CPU:NTSC_CPU)/(FSettings.SndRate * 16)); // 308845 - 1832727 PSG_base=(uint32)(PAL?(long double)PAL_CPU/16:(long double)NTSC_CPU/16); for(x=0;x<0x10;x++) @@ -1035,14 +1009,16 @@ void SetSoundVariables(void) 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) @@ -1062,5 +1038,5 @@ void FCEUI_Sound(int Rate) void FCEUI_SetSoundVolume(uint32 volume) { - FSettings.SoundVolume=(volume<<16)/100; + FSettings.SoundVolume=volume; }