Example #1
0
        public void Update()
        {
            if (mute || turbo)
            {
                for (int updateCycle = lastUpdateCycle; updateCycle < currentTime; updateCycle++)
                {
                    sampleRateDivider--;
                    if (sampleRateDivider <= 0)
                    {
                        output[outputPtr] = 0;
                        outputPtr++;
                        sampleRateDivider += sampleDivider;
                    }
                }
                lastUpdateCycle = currentTime;
                return;
            }
            for (int updateCycle = lastUpdateCycle; updateCycle < currentTime; updateCycle++)
            {
                byte square1Volume  = square1.Cycle();
                byte square2Volume  = square2.Cycle();
                byte triangleVolume = triangle.Cycle();
                byte noiseVolume    = noise.Cycle();
                byte dmcVolume      = dmc.buffer[dmcOutputPtr++];
                byte externalVolume = external.Cycle();//treating external volume as 0-255
#if DEBUGGER
                nes.debug.APUCycle(square1Volume, square2Volume, triangleVolume, noiseVolume, dmcVolume, externalVolume);
#endif
                square1Volume  = (byte)(square1Volume * volume.square1);
                square2Volume  = (byte)(square2Volume * volume.square2);
                triangleVolume = (byte)(triangleVolume * volume.triangle);
                noiseVolume    = (byte)(noiseVolume * volume.noise);
                dmcVolume      = (byte)(dmcVolume * volume.dmc);
                externalVolume = (byte)(externalVolume * volume.external);
                sampleTotal   += (short)((tndTableShort[(3 * triangleVolume) + (2 * noiseVolume) + dmcVolume] + pulseTableShort[square1Volume + square2Volume] + (externalVolume << 7)) ^ 0x8000);//just inserting external sound linearly.
                sampleCount++;
                sampleRateDivider--;
                if (sampleRateDivider <= 0) //&& outputPtr < output.Length)
                {
                    double sample = sampleTotal / (sampleCount * 1.0);
                    sampleRateDivider += sampleDivider;
                    rollingAveTotal   += sample;
                    rollingAve.Enqueue(sample);
                    if (rollingAveCount == rollingAveWindow)
                    {
                        rollingAveTotal -= rollingAve.Dequeue();
                    }
                    else
                    {
                        rollingAveCount++;
                    }
                    aveSample           = rollingAveTotal / (rollingAveCount * 1.0);                                       //aveSample reduces clicks by keeping waveform centered around 0, size of window can be adjusted with rollingAveWindow.
                    output[outputPtr++] = (short)(Math.Max(Math.Min(sample - aveSample, short.MaxValue), short.MinValue)); //I can't imagine clamping the audio could possibly sound worse then an overflow so this is how I shall do things (even though this will rarely even have an effect).
                    sampleTotal         = 0;
                    sampleCount         = 0;
                }
            }
            lastUpdateCycle = currentTime;
        }