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