continue with pandora port
[fceu.git] / sound.c
diff --git a/sound.c b/sound.c
index 9fb3216..f95b050 100644 (file)
--- a/sound.c
+++ b/sound.c
 #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,7 +52,7 @@ 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;
@@ -64,7 +60,7 @@ uint32 soundtsoffs=0;
 #undef printf
 uint16 nreg;
 
-int32 lengthcount[4];
+static int32 lengthcount[4];
 
 extern int soundvol;
 
@@ -82,8 +78,10 @@ static const uint32 SNoiseFreqTable[0x10]=
 };
 static uint32 NoiseFreqTable[0x10];
 
-int64 nesincsizeLL;
-int64 nesincsize;
+int32 nesincsize;
+uint32 soundtsinc;
+uint32 soundtsi;
+
 
 static const uint8 NTSCPCMTable[0x10]=
 {
@@ -105,7 +103,7 @@ 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;
@@ -114,13 +112,13 @@ int32 PCMSizeIndex=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)
 {
@@ -155,7 +153,7 @@ static void PrepDPCM()
   PCMfreq=PALPCMTable[PSG[0x10]&0xF];
  else
   PCMfreq=NTSCPCMTable[PSG[0x10]&0xF];
- PCMacc=(int64)PCMfreq<<50;
+ PCMacc=PCMfreq<<18;
 }
 
 uint8 sweepon[2]={0,0};
@@ -188,7 +186,7 @@ static int FASTAPASS(2) CheckFreq(uint32 cf, uint8 sr)
 
 static DECLFW(Write0x11)
 {
- DoPCM();
+ DoPCM(0);
  PSG[0x11]=V&0x7F;
 }
 
@@ -202,7 +200,7 @@ static DECLFW(Write_PSG)
  switch(A)
  {
   case 0x0:
-           DoSQ1();
+           DoSQ1(0);
            if(V&0x10)
             realvolume[0]=V&0xF;
            break;
@@ -210,14 +208,14 @@ static DECLFW(Write_PSG)
            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;
           }
@@ -227,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();
+          DoSQ2(0);
            if(V&0x10)
             realvolume[1]=V&0xF;
           break;
@@ -239,14 +237,14 @@ static DECLFW(Write_PSG)
           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;
          }
@@ -256,10 +254,10 @@ static DECLFW(Write_PSG)
          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;
@@ -269,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];
          }
@@ -282,22 +280,22 @@ 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;
            break;
- case 0x10:DoPCM();
+ case 0x10:DoPCM(0);
           if(!(V&0x80))
            X6502_IRQEnd(FCEU_IQDPCM);
           break;
@@ -306,15 +304,15 @@ static DECLFW(Write_PSG)
            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)
             {
@@ -339,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);
@@ -359,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))
  {
@@ -375,7 +374,7 @@ static void FASTAPASS(1) FrameSoundStuff(int V)
             lengthcount[2]--;
             if(lengthcount[2]<=0)
              {
-              DoTriangle();
+              DoTriangle(0);
               sqnon&=~4;
              }
            }
@@ -460,7 +459,7 @@ static void FASTAPASS(1) FrameSoundStuff(int V)
            laster=0;
            if(tricoop)
            {
-            if(tricoop==1) DoTriangle();
+            if(tricoop==1) DoTriangle(0);
             tricoop--;
            }
          }
@@ -555,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=(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-=nesincsize;
        if(PCMacc<=0)
        {
        if(!PCMBitIndex)
@@ -635,33 +634,36 @@ static void RDoPCM(void)
     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]-=nesincsize;
        if(sqacc[0]<=0)
        {
         rea:
@@ -672,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=(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]-=nesincsize;
        if(sqacc[1]<=0)
        {
         rea:
@@ -716,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=(SOUNDTS<<16)/soundtsinc;
+   if(end==0) end=(SOUNDTS<<16)/soundtsinc;
    if(end<=start) return;
    ChannelBC[2]=end;
 
@@ -754,13 +757,13 @@ static void RDoTriangle(void)
     }
     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-=nesincsize;
        if(triacc<=0)
        {
         rea:
@@ -777,13 +780,13 @@ static void RDoTriangle(void)
     }
 }
 
-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;
 
@@ -839,12 +842,12 @@ static void RDoNoise(void)
          count[3]+=0x1000;
         }
       }
-
    }
 }
 
 DECLFW(Write_IRQFM)
 {
+ PSG[0x17]=V;
  V=(V&0xC0)>>6;
  fcnt=0;
  if(V&0x2)
@@ -853,7 +856,7 @@ DECLFW(Write_IRQFM)
  fhcnt=fhinc;
  X6502_IRQEnd(FCEU_IQFCOUNT);
  SIRQStat&=~0x40;
-// IRQFrameMode=V;
+ //IRQFrameMode=V; // IRQFrameMode is PSG[0x17] upper bits
 }
 
 void SetNESSoundMap(void)
@@ -865,63 +868,36 @@ void SetNESSoundMap(void)
   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;
+ 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)
 {
@@ -937,28 +913,16 @@ int FlushEmulateSound(void)
   }
 
   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)];
@@ -973,9 +937,9 @@ int FlushEmulateSound(void)
   return(end);
 }
 
-int GetSoundBuffer(int32 **W)
+int GetSoundBuffer(int16 **W)
 {
- *W=WaveNSF;
+ *W=WaveFinalMono;
  return inbuf;
 }
 
@@ -1032,8 +996,8 @@ void SetSoundVariables(void)
   if(GameExpSound.RChange)
    GameExpSound.RChange();
 
-  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));
+  // 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++)
@@ -1045,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)
@@ -1072,5 +1038,5 @@ void FCEUI_Sound(int Rate)
 
 void FCEUI_SetSoundVolume(uint32 volume)
 {
- FSettings.SoundVolume=(volume<<16)/100;
+ FSettings.SoundVolume=volume;
 }