more menu work, scalers, sound
[fceu.git] / sound.c
1 /* FCE Ultra - NES/Famicom Emulator
2  *
3  * Copyright notice for this file:
4  *  Copyright (C) 2002 Ben Parnell
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 /********************************************************/
22 /*******                sound.c                         */
23 /*******                                                */
24 /*******  Sound emulation code and waveform synthesis   */
25 /*******  routines.  A few ideas were inspired          */
26 /*******  by code from Marat Fayzullin's EMUlib         */
27 /*******                                                */
28 /********************************************************/
29
30 #include <stdlib.h>
31 #include <stdio.h>
32
33 #include <string.h>
34
35 #include "types.h"
36 #include "x6502.h"
37
38 #include "fce.h"
39 #include "svga.h"
40 #include "sound.h"
41
42 uint32 soundtsinc;
43 uint32 soundtsi;
44
45 uint32 Wave[2048];
46 int32 WaveFinal[2048];
47 int16 WaveFinalMono[2048];
48
49 EXPSOUND GameExpSound={0,0,0};
50
51 uint8 trimode=0;
52 uint8 tricoop=0;
53 uint8 PSG[0x18];
54
55 uint8 decvolume[3];
56 uint8 realvolume[3];
57
58 static int32 count[5];
59 static int64 sqacc[2]={0,0};
60 uint8 sqnon=0;
61
62 uint32 soundtsoffs=0;
63
64 #undef printf
65 uint16 nreg;
66
67 int32 lengthcount[4];
68
69 extern int soundvol;
70
71 static const uint8 Slengthtable[0x20]=
72 {
73  0x5,0x7f,0xA,0x1,0x14,0x2,0x28,0x3,0x50,0x4,0x1E,0x5,0x7,0x6,0x0E,0x7,
74  0x6,0x08,0xC,0x9,0x18,0xa,0x30,0xb,0x60,0xc,0x24,0xd,0x8,0xe,0x10,0xf
75 };
76
77 static uint32 lengthtable[0x20];
78
79 static const uint32 SNoiseFreqTable[0x10]=
80 {
81  2,4,8,0x10,0x20,0x30,0x40,0x50,0x65,0x7f,0xbe,0xfe,0x17d,0x1fc,0x3f9,0x7f2
82 };
83 static uint32 NoiseFreqTable[0x10];
84
85 int64 nesincsizeLL;
86 int64 nesincsize;
87
88 static const uint8 NTSCPCMTable[0x10]=
89 {
90  0xd6,0xbe,0xaa,0xa0,0x8f,0x7f,0x71,0x6b,
91  0x5f,0x50,0x47,0x40,0x35,0x2a,0x24,0x1b
92 };
93
94 static const uint8 PALPCMTable[0x10]=   // These values are just guessed.
95 {
96  0xc6,0xb0,0x9d,0x94,0x84,0x75,0x68,0x63,
97  0x58,0x4a,0x41,0x3b,0x31,0x27,0x21,0x19
98 };
99
100 uint32 PSG_base;
101
102 // $4010        -        Frequency
103 // $4011        -        Actual data outputted
104 // $4012        -        Address register: $c000 + V*64
105 // $4013        -        Size register:  Size in bytes = (V+1)*64
106
107
108 static int64 PCMacc=0;
109 static int PCMfreq;
110 int32 PCMIRQCount;
111 uint8 PCMBitIndex=0;
112 uint32 PCMAddressIndex=0;
113 int32 PCMSizeIndex=0;
114 uint8 PCMBuffer=0;
115 int vdis=0;
116
117 static void Dummyfunc(void) {};
118
119 static void (*DoNoise)(void)=Dummyfunc;
120 static void (*DoTriangle)(void)=Dummyfunc;
121 static void (*DoPCM)(void)=Dummyfunc;
122 static void (*DoSQ1)(void)=Dummyfunc;
123 static void (*DoSQ2)(void)=Dummyfunc;
124
125 static void CalcDPCMIRQ(void)
126 {
127  uint32 freq;
128  uint32 honk;
129  uint32 cycles;
130
131  if(PAL)
132   freq=(PALPCMTable[PSG[0x10]&0xF]<<4);
133  else
134   freq=(NTSCPCMTable[PSG[0x10]&0xF]<<4);
135
136  cycles=(((PSG[0x13]<<4)+1));
137  cycles*=freq/14;
138  honk=((PSG[0x13]<<4)+1)*freq;
139  honk-=cycles;
140  //if(PAL) honk/=107;
141  //else honk/=(double)113.66666666;
142  PCMIRQCount=honk*48;
143  //PCMIRQCount=honk*3; //180;
144  //if(PAL) PCMIRQCount*=.93;
145  vdis=0;
146 }
147
148 static void PrepDPCM()
149 {
150  PCMAddressIndex=0x4000+(PSG[0x12]<<6);
151  PCMSizeIndex=(PSG[0x13]<<4)+1;
152  PCMBitIndex=0;
153  //PCMBuffer=ARead[0x8000+PCMAddressIndex](0x8000+PCMAddressIndex);
154  if(PAL)
155   PCMfreq=PALPCMTable[PSG[0x10]&0xF];
156  else
157   PCMfreq=NTSCPCMTable[PSG[0x10]&0xF];
158  PCMacc=(int64)PCMfreq<<50;
159 }
160
161 uint8 sweepon[2]={0,0};
162 int32 curfreq[2]={0,0};
163
164
165 uint8 SIRQStat=0;
166
167 uint8 SweepCount[2];
168 uint8 DecCountTo1[3];
169
170 uint8 fcnt=0;
171 int32 fhcnt=0;
172 int32 fhinc;
173
174 static uint8 laster;
175
176 /* Instantaneous?  Maybe the new freq value is being calculated all of the time... */
177 static int FASTAPASS(2) CheckFreq(uint32 cf, uint8 sr)
178 {
179  uint32 mod;
180  if(!(sr&0x8))
181  {
182   mod=cf>>(sr&7);
183   if((mod+cf)&0x800)
184    return(0);
185  }
186  return(1);
187 }
188
189 static DECLFW(Write0x11)
190 {
191  DoPCM();
192  PSG[0x11]=V&0x7F;
193 }
194
195 static uint8 DutyCount[2]={0,0};
196
197 static DECLFW(Write_PSG)
198 {
199  //if((A>=0x4004 && A<=0x4007) || A==0x4015)
200   //printf("$%04x:$%02x, %d\n",A,V,SOUNDTS);
201  A&=0x1f;
202  switch(A)
203  {
204   case 0x0:
205            DoSQ1();
206            if(V&0x10)
207             realvolume[0]=V&0xF;
208            break;
209   case 0x1:
210            sweepon[0]=V&0x80;
211            break;
212   case 0x2:
213            DoSQ1();
214            curfreq[0]&=0xFF00;
215            curfreq[0]|=V;
216            break;
217   case 0x3:
218            if(PSG[0x15]&1)
219            {
220             DoSQ1();
221             lengthcount[0]=lengthtable[(V>>3)&0x1f];
222             sqnon|=1;
223            }
224            sweepon[0]=PSG[1]&0x80;
225            curfreq[0]=PSG[0x2]|((V&7)<<8);
226            decvolume[0]=0xF;
227            DecCountTo1[0]=(PSG[0]&0xF)+1;
228            SweepCount[0]=((PSG[0x1]>>4)&7)+1;
229            DutyCount[0]=0;
230            sqacc[0]=((int64)curfreq[0]+1)<<50;
231            break;
232
233   case 0x4:
234            DoSQ2();
235            if(V&0x10)
236             realvolume[1]=V&0xF;
237            break;
238   case 0x5:
239           sweepon[1]=V&0x80;
240           break;
241   case 0x6:
242           DoSQ2();
243           curfreq[1]&=0xFF00;
244           curfreq[1]|=V;
245           break;
246   case 0x7:
247           if(PSG[0x15]&2)
248           {
249            DoSQ2();
250            lengthcount[1]=lengthtable[(V>>3)&0x1f];
251            sqnon|=2;
252           }
253           sweepon[1]=PSG[0x5]&0x80;
254           curfreq[1]=PSG[0x6]|((V&7)<<8);
255           decvolume[1]=0xF;
256           DecCountTo1[1]=(PSG[0x4]&0xF)+1;
257           SweepCount[1]=((PSG[0x5]>>4)&7)+1;
258           DutyCount[1]=0;
259           sqacc[1]=((int64)curfreq[1]+1)<<50;
260           break;
261   case 0x8:
262           DoTriangle();
263           if(laster&0x80)
264           {
265             tricoop=V&0x7F;
266             trimode=V&0x80;
267           }
268           if(!(V&0x7F))
269            tricoop=0;
270           laster=V&0x80;
271           break;
272   case 0xa:DoTriangle();
273            break;
274   case 0xb:
275           if(PSG[0x15]&0x4)
276           {
277            DoTriangle();
278            sqnon|=4;
279            lengthcount[2]=lengthtable[(V>>3)&0x1f];
280           }
281           laster=0x80;
282           tricoop=PSG[0x8]&0x7f;
283           trimode=PSG[0x8]&0x80;
284           break;
285   case 0xC:DoNoise();
286            if(V&0x10)
287             realvolume[2]=V&0xF;
288            break;
289   case 0xE:DoNoise();break;
290   case 0xF:
291            if(PSG[0x15]&8)
292            {
293             DoNoise();
294             sqnon|=8;
295             lengthcount[3]=lengthtable[(V>>3)&0x1f];
296            }
297            decvolume[2]=0xF;
298            DecCountTo1[2]=(PSG[0xC]&0xF)+1;
299            break;
300  case 0x10:DoPCM();
301            if(!(V&0x80))
302             X6502_IRQEnd(FCEU_IQDPCM);
303            break;
304  case 0x15:
305            {
306             int t=V^PSG[0x15];
307
308             if(t&1)
309              DoSQ1();
310             if(t&2)
311              DoSQ2();
312             if(t&4)
313              DoTriangle();
314             if(t&8)
315              DoNoise();
316             if(t&0x10)
317              DoPCM();
318             sqnon&=V;
319             if(V&0x10)
320             {
321              if(!(PSG[0x15]&0x10))
322              {
323               PrepDPCM();
324               CalcDPCMIRQ();
325              }
326              else if(vdis)
327               CalcDPCMIRQ();
328             }
329             else
330              PCMIRQCount=0;
331             X6502_IRQEnd(FCEU_IQDPCM);
332            }
333            break;
334  }
335  PSG[A]=V;
336 }
337
338 DECLFR(Read_PSG)
339 {
340    uint8 ret;
341    if(PSG[0x15]&0x10)
342     DoPCM();
343    ret=(PSG[0x15]&(sqnon|0x10))|SIRQStat;
344    SIRQStat&=~0x40;
345    X6502_IRQEnd(/*FCEU_IQDPCM|*/FCEU_IQFCOUNT);
346    return ret;
347 }
348
349 DECLFR(Read_PSGDummy)
350 {
351    uint8 ret;
352
353    ret=(PSG[0x15]&sqnon)|SIRQStat;
354    SIRQStat&=~0x40;
355    X6502_IRQEnd(/*FCEU_IQDPCM|*/FCEU_IQFCOUNT);
356    return ret;
357 }
358
359 static void FASTAPASS(1) FrameSoundStuff(int V)
360 {
361  int P;
362
363  DoSQ1();
364  DoSQ2();
365  DoNoise();
366
367  switch((V&1))
368  {
369   case 1:       /* Envelope decay, linear counter, length counter, freq sweep */
370         if(PSG[0x15]&4 && sqnon&4)
371          if(!(PSG[8]&0x80))
372          {
373           if(lengthcount[2]>0)
374           {
375             lengthcount[2]--;
376             if(lengthcount[2]<=0)
377              {
378               DoTriangle();
379               sqnon&=~4;
380              }
381            }
382          }
383
384         for(P=0;P<2;P++)
385         {
386          if(PSG[0x15]&(P+1) && sqnon&(P+1))
387          {
388           if(!(PSG[P<<2]&0x20))
389           {
390            if(lengthcount[P]>0)
391            {
392             lengthcount[P]--;
393             if(lengthcount[P]<=0)
394              {
395               sqnon&=~(P+1);
396              }
397            }
398           }
399          }
400                 /* Frequency Sweep Code Here */
401                 /* xxxx 0000 */
402                 /* xxxx = hz.  120/(x+1)*/
403           if(sweepon[P])
404           {
405            int32 mod=0;
406
407            if(SweepCount[P]>0) SweepCount[P]--;
408            if(SweepCount[P]<=0)
409            {
410             SweepCount[P]=((PSG[(P<<2)+0x1]>>4)&7)+1; //+1;
411             {
412              if(PSG[(P<<2)+0x1]&0x8)
413              {
414               mod-=(P^1)+((curfreq[P])>>(PSG[(P<<2)+0x1]&7));
415
416               if(curfreq[P] && (PSG[(P<<2)+0x1]&7)/* && sweepon[P]&0x80*/)
417               {
418                curfreq[P]+=mod;
419               }
420              }
421              else
422              {
423               mod=curfreq[P]>>(PSG[(P<<2)+0x1]&7);
424               if((mod+curfreq[P])&0x800)
425               {
426                sweepon[P]=0;
427                curfreq[P]=0;
428               }
429               else
430               {
431                if(curfreq[P] && (PSG[(P<<2)+0x1]&7)/* && sweepon[P]&0x80*/)
432                {
433                 curfreq[P]+=mod;
434                }
435               }
436              }
437             }
438            }
439           }
440          }
441
442        if(PSG[0x15]&0x8 && sqnon&8)
443         {
444          if(!(PSG[0xC]&0x20))
445          {
446           if(lengthcount[3]>0)
447           {
448            lengthcount[3]--;
449            if(lengthcount[3]<=0)
450            {
451             sqnon&=~8;
452            }
453           }
454          }
455         }
456
457   case 0:       /* Envelope decay + linear counter */
458          if(!trimode)
459          {
460            laster=0;
461            if(tricoop)
462            {
463             if(tricoop==1) DoTriangle();
464             tricoop--;
465            }
466          }
467
468         for(P=0;P<2;P++)
469         {
470           if(DecCountTo1[P]>0) DecCountTo1[P]--;
471           if(DecCountTo1[P]<=0)
472           {
473            DecCountTo1[P]=(PSG[P<<2]&0xF)+1;
474            if(decvolume[P] || PSG[P<<2]&0x20)
475            {
476             decvolume[P]--;
477             /* Step from 0 to full volume seems to take twice as long
478                as the other steps.  I don't know if this is the correct
479                way to double its length, though(or if it even matters).
480             */
481             if((PSG[P<<2]&0x20) && (decvolume[P]==0))
482              DecCountTo1[P]<<=1;
483             decvolume[P]&=15;
484            }
485           }
486           if(!(PSG[P<<2]&0x10))
487            realvolume[P]=decvolume[P];
488         }
489
490          if(DecCountTo1[2]>0) DecCountTo1[2]--;
491          if(DecCountTo1[2]<=0)
492          {
493           DecCountTo1[2]=(PSG[0xC]&0xF)+1;
494           if(decvolume[2] || PSG[0xC]&0x20)
495           {
496             decvolume[2]--;
497             /* Step from 0 to full volume seems to take twice as long
498                as the other steps.  I don't know if this is the correct
499                way to double its length, though(or if it even matters).
500             */
501             if((PSG[0xC]&0x20) && (decvolume[2]==0))
502              DecCountTo1[2]<<=1;
503             decvolume[2]&=15;
504           }
505          }
506          if(!(PSG[0xC]&0x10))
507           realvolume[2]=decvolume[2];
508
509         break;
510  }
511
512 }
513
514 void FrameSoundUpdate(void)
515 {
516  // Linear counter:  Bit 0-6 of $4008
517  // Length counter:  Bit 4-7 of $4003, $4007, $400b, $400f
518
519  if(fcnt==3)
520  {
521         if(PSG[0x17]&0x80)
522          fhcnt+=fhinc;
523         if(!(PSG[0x17]&0xC0))
524         {
525          SIRQStat|=0x40;
526          X6502_IRQBegin(FCEU_IQFCOUNT);
527         }
528  }
529  //if(SIRQStat&0x40) X6502_IRQBegin(FCEU_IQFCOUNT);
530  FrameSoundStuff(fcnt);
531  fcnt=(fcnt+1)&3;
532 }
533
534 static uint32 ChannelBC[5];
535
536 static uint32 RectAmp[2][8];
537
538 static void FASTAPASS(1) CalcRectAmp(int P)
539 {
540   static int tal[4]={1,2,4,6};
541   int V;
542   int x;
543   uint32 *b=RectAmp[P];
544   int m;
545
546   //if(PSG[P<<2]&0x10)
547    V=realvolume[P]<<4;
548   //V=(PSG[P<<2]&15)<<4;
549   //else
550   // V=decvolume[P]<<4;
551   m=tal[(PSG[P<<2]&0xC0)>>6];
552   for(x=0;x<m;x++,b++)
553    *b=0;
554   for(;x<8;x++,b++)
555    *b=V;
556 }
557
558 static void RDoPCM(void)
559 {
560    int32 V;
561    int32 start,end;
562    int64 freq;
563    uint32 out=PSG[0x11]<<3;
564
565    start=ChannelBC[4];
566    end=(SOUNDTS<<16)/soundtsinc;
567    if(end<=start) return;
568    ChannelBC[4]=end;
569
570    if(PSG[0x15]&0x10)
571    {
572       freq=PCMfreq;
573       freq<<=50;
574
575       for(V=start;V<end;V++)
576       {
577        PCMacc-=nesincsizeLL;
578        if(PCMacc<=0)
579        {
580         if(!PCMBitIndex)
581         {
582          PCMSizeIndex--;
583          if(!PCMSizeIndex)
584          {
585           if(PSG[0x10]&0x40)
586            PrepDPCM();
587           else
588           {
589            PSG[0x15]&=~0x10;
590            for(;V<end;V++)
591             Wave[V>>4]+=PSG[0x11]<<3;
592            goto endopcmo;
593           }
594          }
595          else
596          {
597           PCMBuffer=ARead[0x8000+PCMAddressIndex](0x8000+PCMAddressIndex);
598           PCMAddressIndex=(PCMAddressIndex+1)&0x7fff;
599          }
600         }
601
602         {
603          int t=(((PCMBuffer>>PCMBitIndex)&1)<<2)-2;
604          uint8 bah=PSG[0x11];
605
606          PCMacc+=freq;
607          PSG[0x11]+=t;
608          if(PSG[0x11]&0x80)
609           PSG[0x11]=bah;
610          else
611           out=PSG[0x11]<<3;
612         }
613         PCMBitIndex=(PCMBitIndex+1)&7;
614        }
615        Wave[V>>4]+=out; //(PSG[0x11]-64)<<3;
616       }
617    }
618    else
619    {
620      if((end-start)>64)
621      {
622       for(V=start;V<=(start|15);V++)
623        Wave[V>>4]+=out;
624       out<<=4;
625       for(V=(start>>4)+1;V<(end>>4);V++)
626        Wave[V]+=out;
627       out>>=4;
628       for(V=end&(~15);V<end;V++)
629        Wave[V>>4]+=out;
630      }
631      else
632       for(V=start;V<end;V++)
633        Wave[V>>4]+=out;
634    }
635     endopcmo:;
636 }
637
638 static void RDoSQ1(void)
639 {
640    int32 V;
641    int32 start,end;
642    int64 freq;
643
644    CalcRectAmp(0);
645    start=ChannelBC[0];
646    end=(SOUNDTS<<16)/soundtsinc;
647    if(end<=start) return;
648    ChannelBC[0]=end;
649
650    if(curfreq[0]<8 || curfreq[0]>0x7ff)
651     return;
652    if(!CheckFreq(curfreq[0],PSG[0x1]))
653     return;
654
655    if(PSG[0x15]&1 && sqnon&1)
656    {
657     uint32 out=RectAmp[0][DutyCount[0]];
658     freq=curfreq[0]+1;
659     {
660       freq<<=50;
661       for(V=start;V<end;V++)
662       {
663        Wave[V>>4]+=out;
664        sqacc[0]-=nesincsizeLL;
665        if(sqacc[0]<=0)
666        {
667         rea:
668         sqacc[0]+=freq;
669         DutyCount[0]++;
670         if(sqacc[0]<=0) goto rea;
671
672         DutyCount[0]&=7;
673         out=RectAmp[0][DutyCount[0]];
674        }
675
676       }
677      }
678     }
679 }
680
681 static void RDoSQ2(void)
682 {
683    int32 V;
684    int32 start,end;
685    int64 freq;
686
687    CalcRectAmp(1);
688    start=ChannelBC[1];
689    end=(SOUNDTS<<16)/soundtsinc;
690    if(end<=start) return;
691    ChannelBC[1]=end;
692
693    if(curfreq[1]<8 || curfreq[1]>0x7ff)
694     return;
695    if(!CheckFreq(curfreq[1],PSG[0x5]))
696     return;
697
698    if(PSG[0x15]&2 && sqnon&2)
699    {
700     uint32 out=RectAmp[1][DutyCount[1]];
701     freq=curfreq[1]+1;
702
703     {
704       freq<<=50;
705       for(V=start;V<end;V++)
706       {
707        Wave[V>>4]+=out;
708        sqacc[1]-=nesincsizeLL;
709        if(sqacc[1]<=0)
710        {
711         rea:
712         sqacc[1]+=freq;
713         DutyCount[1]++;
714         if(sqacc[1]<=0) goto rea;
715
716         DutyCount[1]&=7;
717         out=RectAmp[1][DutyCount[1]];
718        }
719
720       }
721      }
722     }
723 }
724
725
726 static void RDoTriangle(void)
727 {
728    static uint32 tcout=0;
729    int32 V;
730    int32 start,end; //,freq;
731    int64 freq=(((PSG[0xa]|((PSG[0xb]&7)<<8))+1));
732
733    start=ChannelBC[2];
734    end=(SOUNDTS<<16)/soundtsinc;
735    if(end<=start) return;
736    ChannelBC[2]=end;
737
738     if(! (PSG[0x15]&0x4 && sqnon&4 && tricoop) )
739     {   // Counter is halted, but we still need to output.
740      for(V=start;V<end;V++)
741        Wave[V>>4]+=tcout;
742     }
743     else if(freq<=4) // 55.9Khz - Might be barely audible on a real NES, but
744                // it's too costly to generate audio at this high of a frequency
745                // (55.9Khz * 32 for the stepping).
746                // The same could probably be said for ~27.8Khz, so we'll
747                // take care of that too.  We'll just output the average
748                // value(15/2 - scaled properly for our output format, of course).
749                // We'll also take care of ~18Khz and ~14Khz too, since they should be barely audible.
750                // (Some proof or anything to confirm/disprove this would be nice.).
751     {
752      for(V=start;V<end;V++)
753       Wave[V>>4]+=((0xF<<4)+(0xF<<2))>>1;
754     }
755     else
756     {
757      static int64 triacc=0;
758      static uint8 tc=0;
759
760       freq<<=49;
761       for(V=start;V<end;V++)
762       {
763        triacc-=nesincsizeLL;
764        if(triacc<=0)
765        {
766         rea:
767         triacc+=freq; //t;
768         tc=(tc+1)&0x1F;
769         if(triacc<=0) goto rea;
770
771         tcout=(tc&0xF);
772         if(tc&0x10) tcout^=0xF;
773         tcout=(tcout<<4)+(tcout<<2);
774        }
775        Wave[V>>4]+=tcout;
776       }
777     }
778 }
779
780 static void RDoNoise(void)
781 {
782    int32 inc,V;
783    int32 start,end;
784
785    start=ChannelBC[3];
786    end=(SOUNDTS<<16)/soundtsinc;
787    if(end<=start) return;
788    ChannelBC[3]=end;
789
790    if(PSG[0x15]&0x8 && sqnon&8)
791    {
792       uint32 outo;
793       uint32 amptab[2];
794       uint8 amplitude;
795
796       amplitude=realvolume[2];
797       //if(PSG[0xC]&0x10)
798       // amplitude=(PSG[0xC]&0xF);
799       //else
800       // amplitude=decvolume[2]&0xF;
801
802       inc=NoiseFreqTable[PSG[0xE]&0xF];
803       amptab[0]=((amplitude<<2)+amplitude+amplitude)<<1;
804       amptab[1]=0;
805       outo=amptab[nreg&1];
806
807       if(amplitude)
808       {
809        if(PSG[0xE]&0x80)        // "short" noise
810         for(V=start;V<end;V++)
811         {
812          Wave[V>>4]+=outo;
813          if(count[3]>=inc)
814          {
815           uint8 feedback;
816
817           feedback=((nreg>>8)&1)^((nreg>>14)&1);
818           nreg=(nreg<<1)+feedback;
819           nreg&=0x7fff;
820           outo=amptab[nreg&1];
821           count[3]-=inc;
822          }
823          count[3]+=0x1000;
824         }
825        else
826         for(V=start;V<end;V++)
827         {
828          Wave[V>>4]+=outo;
829          if(count[3]>=inc)
830          {
831           uint8 feedback;
832
833           feedback=((nreg>>13)&1)^((nreg>>14)&1);
834           nreg=(nreg<<1)+feedback;
835           nreg&=0x7fff;
836           outo=amptab[nreg&1];
837           count[3]-=inc;
838          }
839          count[3]+=0x1000;
840         }
841       }
842
843    }
844 }
845
846 DECLFW(Write_IRQFM)
847 {
848  PSG[0x17]=V;
849  V=(V&0xC0)>>6;
850  fcnt=0;
851  if(V&0x2)
852   FrameSoundUpdate();
853  fcnt=1;
854  fhcnt=fhinc;
855  X6502_IRQEnd(FCEU_IQFCOUNT);
856  SIRQStat&=~0x40;
857  //IRQFrameMode=V; // IRQFrameMode is PSG[0x17] upper bits
858 }
859
860 void SetNESSoundMap(void)
861 {
862   SetWriteHandler(0x4000,0x4013,Write_PSG);
863   SetWriteHandler(0x4011,0x4011,Write0x11);
864   SetWriteHandler(0x4015,0x4015,Write_PSG);
865   SetWriteHandler(0x4017,0x4017,Write_IRQFM);
866   SetReadHandler(0x4015,0x4015,Read_PSG);
867 }
868
869 static int32 WaveNSF[2048];
870
871 int32 highp;                   // 0 through 65536, 0 = no high pass, 65536 = max high pass
872
873 int32 lowp;                    // 0 through 65536, 65536 = max low pass(total attenuation)
874                                 // 65536 = no low pass
875 static void FilterSound(uint32 *in, int32 *out, int16 *outMono, int count)
876 {
877  static int64 acc=0, acc2=0;
878  //int index=0;
879  //int16* tmp;
880  //int16* outorig=out;
881  //int32 prev=-99999;
882  for(;count;count--,in++)//,out++)//,index++)
883  {
884   int64 diff;
885
886   diff=((int64)*in<<24)-acc;
887
888   acc+=(diff*highp)>>16;
889   acc2+=((diff-acc2)*lowp)>>16;
890   *in=0;
891
892   // don't change the sound here
893 //  *out=(acc2*(int64)FSettings.SoundVolume)>>(24+16);
894   // volume, 4 times louder by default??
895 //  *out = acc2 >> 24;
896  // just a bit louder.  Hope it's okay
897  /*
898   *out = acc2 >> 22;
899   if(*out<-32767) *out=-32767;
900   if(*out>32767) *out=32767;
901   // go one back
902
903   // do MONO
904   tmp=(int16 *)(out-1);
905   // don't do this the first time
906   if (prev == -99999) continue;
907   // the middle one should be interpolated
908   tmp[1]=(int16)((*out + prev) >> 1);
909   prev = *out;
910   */
911   //outMono[index] = (int16)*out;
912   *outMono = (int16)(acc2 >> 24);
913   //if(*outMono<-16384) *outMono=-16384;
914   //if(*outMono>16384) *outMono=16384;
915   outMono++;
916
917   // out=((int64)(acc2>>24)*(int64)FSettings.SoundVolume)>>16; //acc2>>24;
918
919  }
920  // do one more
921 }
922
923
924
925
926 static int32 inbuf=0;
927 int FlushEmulateSound(void)
928 {
929   int x;
930   uint32 end;
931
932   if(!timestamp) return(0);
933
934   if(!FSettings.SndRate || (soundvol == 0))
935   {
936    end=0;
937    goto nosoundo;
938   }
939
940   end=(SOUNDTS<<16)/soundtsinc;
941   DoSQ1();
942   DoSQ2();
943   DoTriangle();
944   DoNoise();
945   DoPCM();
946
947   if(GameExpSound.Fill)
948    GameExpSound.Fill(end&0xF);
949
950 //  FilterSound(Wave,WaveFinal,end>>4);
951   FilterSound(Wave,WaveFinal,WaveFinalMono,end>>4);
952 //  printf("count %d, num ints %d\n", end, (end >> 4));
953   if(FCEUGameInfo.type==GIT_NSF)
954   {
955    int x;//,s=0,si=end/1024;
956    for(x=0;x<1024;x++)
957    {
958     //WaveNSF[x]=WaveFinal[s>>4];
959     WaveNSF[x]=WaveFinalMono[x];
960     //s+=si;
961    }
962   }
963
964   if(end&0xF)
965    Wave[0]=Wave[(end>>4)];
966   Wave[(end>>4)]=0;
967
968   nosoundo:
969   for(x=0;x<5;x++)
970    ChannelBC[x]=end&0xF;
971   soundtsoffs=(soundtsinc*(end&0xF))>>16;
972   end>>=4;
973   inbuf=end;
974   return(end);
975 }
976
977 int GetSoundBuffer(int32 **W)
978 {
979  *W=WaveNSF;
980  return inbuf;
981 }
982
983 void PowerSound(void)
984 {
985         int x;
986
987         SetNESSoundMap();
988
989         for(x=0;x<0x16;x++)
990          if(x!=0x14)
991           BWrite[0x4000+x](0x4000+x,0);
992         PSG[0x17]=0; //x40;
993         fhcnt=fhinc;
994         fcnt=0;
995         nreg=1;
996         soundtsoffs=0;
997 }
998
999 void ResetSound(void)
1000 {
1001         int x;
1002         for(x=0;x<0x16;x++)
1003          if(x!=1 && x!=5 && x!=0x14) BWrite[0x4000+x](0x4000+x,0);
1004         PSG[0x17]=0;
1005         fhcnt=fhinc;
1006         fcnt=0;
1007         nreg=1;
1008 }
1009
1010 void SetSoundVariables(void)
1011 {
1012   int x;
1013
1014   fhinc=PAL?16626:14915;        // *2 CPU clock rate
1015   fhinc*=24;
1016   for(x=0;x<0x20;x++)
1017    lengthtable[x]=Slengthtable[x]<<1;
1018
1019   if(FSettings.SndRate)
1020   {
1021    DoNoise=RDoNoise;
1022    DoTriangle=RDoTriangle;
1023    DoPCM=RDoPCM;
1024    DoSQ1=RDoSQ1;
1025    DoSQ2=RDoSQ2;
1026   }
1027   else
1028   {
1029    DoNoise=DoTriangle=DoPCM=DoSQ1=DoSQ2=Dummyfunc;
1030   }
1031
1032   if(!FSettings.SndRate) return;
1033   if(GameExpSound.RChange)
1034    GameExpSound.RChange();
1035
1036   nesincsizeLL=(int64)((int64)562949953421312*(double)(PAL?PAL_CPU:NTSC_CPU)/(FSettings.SndRate OVERSAMPLE));
1037   nesincsize=(int64)(((int64)1<<17)*(double)(PAL?PAL_CPU:NTSC_CPU)/(FSettings.SndRate * 16));
1038   PSG_base=(uint32)(PAL?(long double)PAL_CPU/16:(long double)NTSC_CPU/16);
1039
1040   for(x=0;x<0x10;x++)
1041   {
1042    long double z;
1043    z=SNoiseFreqTable[x]<<1;
1044    z=(PAL?PAL_CPU:NTSC_CPU)/z;
1045    z=(long double)((uint32)((FSettings.SndRate OVERSAMPLE)<<12))/z;
1046    NoiseFreqTable[x]=z;
1047   }
1048   soundtsinc=(uint32)((uint64)(PAL?(long double)PAL_CPU*65536:(long double)NTSC_CPU*65536)/(FSettings.SndRate OVERSAMPLE));
1049   memset(Wave,0,2048*4);
1050   for(x=0;x<5;x++)
1051    ChannelBC[x]=0;
1052   highp=(250<<16)/FSettings.SndRate;  // Arbitrary
1053   lowp=((int64)25000<<16)/FSettings.SndRate; // Arbitrary
1054
1055   if(highp>(1<<16)) highp=1<<16;
1056   if(lowp>(1<<16)) lowp=1<<16;
1057 }
1058
1059 void FixOldSaveStateSFreq(void)
1060 {
1061         int x;
1062         for(x=0;x<2;x++)
1063         {
1064          curfreq[x]=PSG[0x2+(x<<2)]|((PSG[0x3+(x<<2)]&7)<<8);
1065         }
1066 }
1067
1068 void FCEUI_Sound(int Rate)
1069 {
1070  FSettings.SndRate=Rate;
1071  SetSoundVariables();
1072 }
1073
1074 void FCEUI_SetSoundVolume(uint32 volume)
1075 {
1076  FSettings.SoundVolume=volume;
1077 }