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