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