Example #1
0
        public void Clock()
        {
            // Depending on the frame count, we set a flag to tell
            // us where we are in the sequence. Essentially, changes
            // to notes only occur at these intervals, meaning, in a
            // way, this is responsible for ensuring musical time is
            // maintained.
            bool bQuarterFrameClock = false;
            bool bHalfFrameClock    = false;

            dGlobalTime += (0.3333333333 / 1789773);


            if (clock_counter % 6 == 0)
            {
                frame_clock_counter++;


                // 4-Step Sequence Mode
                if (frame_clock_counter == 3729)
                {
                    bQuarterFrameClock = true;
                }

                if (frame_clock_counter == 7457)
                {
                    bQuarterFrameClock = true;
                    bHalfFrameClock    = true;
                }

                if (frame_clock_counter == 11186)
                {
                    bQuarterFrameClock = true;
                }

                if (frame_clock_counter == 14916)
                {
                    bQuarterFrameClock  = true;
                    bHalfFrameClock     = true;
                    frame_clock_counter = 0;
                }

                // Update functional units

                // Quater frame "beats" adjust the volume envelope
                if (bQuarterFrameClock)
                {
                    pulse1_env.Clock(pulse1_halt);
                    pulse2_env.Clock(pulse2_halt);
                    noise_env.Clock(noise_halt);
                }


                // Half frame "beats" adjust the note length and
                // frequency sweepers
                if (bHalfFrameClock)
                {
                    pulse1_lc.Clock(pulse1_enable, pulse1_halt);
                    pulse2_lc.Clock(pulse2_enable, pulse2_halt);
                    noise_lc.Clock(noise_enable, noise_halt);
                    pulse1_sweep.Clock(pulse1_seq.reload, false);
                    pulse2_sweep.Clock(pulse2_seq.reload, true);
                }

                //	if (bUseRawMode)
                {
                    // Update Pulse1 Channel ================================
                    pulse1_seq.Clock(pulse1_enable, s =>
                    {
                        // Shift right by 1 bit, wrapping around
                        s = ((s & 0x0001) << 7) | ((s & 0x00FE) >> 1);
                    });

                    //	pulse1_sample = (double)pulse1_seq.output;
                }
                //else
                {
                    pulse1_osc.frequency = 1789773.0 / (16.0 * (double)(pulse1_seq.reload + 1));
                    pulse1_osc.amplitude = (double)(pulse1_env.output - 1) / 16.0;
                    pulse1_sample        = pulse1_osc.Sample(dGlobalTime);

                    if (pulse1_lc.counter > 0 && pulse1_seq.timer >= 8 && !pulse1_sweep.mute && pulse1_env.output > 2)
                    {
                        pulse1_output += (pulse1_sample - pulse1_output) * 0.5;
                    }
                    else
                    {
                        pulse1_output = 0;
                    }
                }

                //if (bUseRawMode)
                {
                    // Update Pulse1 Channel ================================
                    pulse2_seq.Clock(pulse2_enable, s =>
                    {
                        // Shift right by 1 bit, wrapping around
                        s = ((s & 0x0001) << 7) | ((s & 0x00FE) >> 1);
                    });

                    //	pulse2_sample = (double)pulse2_seq.output;
                }
                //	else
                {
                    pulse2_osc.frequency = 1789773.0 / (16.0 * (double)(pulse2_seq.reload + 1));
                    pulse2_osc.amplitude = (double)(pulse2_env.output - 1) / 16.0;
                    pulse2_sample        = pulse2_osc.Sample(dGlobalTime);

                    if (pulse2_lc.counter > 0 && pulse2_seq.timer >= 8 && !pulse2_sweep.mute && pulse2_env.output > 2)
                    {
                        pulse2_output += (pulse2_sample - pulse2_output) * 0.5;
                    }
                    else
                    {
                        pulse2_output = 0;
                    }
                }


                noise_seq.Clock(noise_enable, s =>
                {
                    s = (((s & 0x0001) ^ ((s & 0x0002) >> 1)) << 14) | ((s & 0x7FFF) >> 1);
                });

                if (noise_lc.counter > 0 && noise_seq.timer >= 8)
                {
                    noise_output = (double)noise_seq.output * ((double)(noise_env.output - 1) / 16.0);
                }

                if (!pulse1_enable)
                {
                    pulse1_output = 0;
                }
                if (!pulse2_enable)
                {
                    pulse2_output = 0;
                }
                if (!noise_enable)
                {
                    noise_output = 0;
                }
            }

            // Frequency sweepers change at high frequency
            pulse1_sweep.Track(pulse1_seq.reload);
            pulse2_sweep.Track(pulse2_seq.reload);

            pulse1_visual = (pulse1_enable && pulse1_env.output > 1 && !pulse1_sweep.mute) ? pulse1_seq.reload : 2047;
            pulse2_visual = (pulse2_enable && pulse2_env.output > 1 && !pulse2_sweep.mute) ? pulse2_seq.reload : 2047;
            noise_visual  = (noise_enable && noise_env.output > 1) ? noise_seq.reload : 2047;

            clock_counter++;
        }