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++; }