// The gate bit is handled by the EnvelopeGenerator. public WaveformGenerator() { sync_source = this; set_chip_model(SIDDefs.chip_model.MOS6581); reset(); }
public Voice() { wave = new WaveformGenerator(); envelope = new EnvelopeGenerator(); muted = false; set_chip_model(SIDDefs.chip_model.MOS6581); }
// deserializing protected void LoadFromReader(BinaryReader reader) { wave = new WaveformGenerator(reader); envelope = new EnvelopeGenerator(reader); muted = reader.ReadBoolean(); wave_zero = reader.ReadInt32(); voice_DC = reader.ReadInt32(); }
public void UpdateAfterLoad(Voice v0, Voice v1, Voice v2) { switch (sync_source_id) { case 0: sync_source = v0.wave; break; case 1: sync_source = v1.wave; break; case 2: sync_source = v2.wave; break; default: #if DEBUG throw new Exception("unknown Source_WaveID: " + sync_source_id.ToString()); #endif case -1: sync_source = null; break; } switch (sync_dest_id) { case 0: sync_dest = v0.wave; break; case 1: sync_dest = v1.wave; break; case 2: sync_dest = v2.wave; break; default: #if DEBUG throw new Exception("unknown Dest_WaveID: " + sync_dest_id.ToString()); #endif case -1: sync_dest = null; break; } }
/// <summary> /// SID clocking - delta_t cycles /// </summary> /// <param name="delta_t"></param> public void clock(int delta_t) { if (delta_t <= 0) { return; } // Age bus value. bus_value_ttl -= delta_t; if (bus_value_ttl <= 0) { bus_value = 0; bus_value_ttl = 0; } // Clock amplitude modulators. voice0.envelope.clock(delta_t); voice1.envelope.clock(delta_t); voice2.envelope.clock(delta_t); // Clock and synchronize oscillators. // Loop until we reach the current cycle. int delta_t_osc = delta_t; while (delta_t_osc != 0) { int delta_t_min = delta_t_osc; // Find minimum number of cycles to an oscillator accumulator MSB toggle. // We have to clock on each MSB on / MSB off for hard sync to operate correctly. WaveformGenerator wave = voice0.wave; // It is only necessary to clock on the MSB of an oscillator // that is a sync source and has freq != 0. if ((wave.sync_dest.sync != 0) && (wave.freq != 0)) { int freq = wave.freq; int accumulator = wave.accumulator; // Clock on MSB off if MSB is on, clock on MSB on if MSB is off. int delta_accumulator = ((accumulator & 0x800000) != 0 ? 0x1000000 : 0x800000) - accumulator; int delta_t_next = (delta_accumulator / freq); if ((delta_accumulator % freq) != 0) { ++delta_t_next; } if (delta_t_next < delta_t_min) { delta_t_min = delta_t_next; } } wave = voice1.wave; // It is only necessary to clock on the MSB of an oscillator // that is a sync source and has freq != 0. if ((wave.sync_dest.sync != 0) && (wave.freq != 0)) { int freq = wave.freq; int accumulator = wave.accumulator; // Clock on MSB off if MSB is on, clock on MSB on if MSB is off. int delta_accumulator = ((accumulator & 0x800000) != 0 ? 0x1000000 : 0x800000) - accumulator; int delta_t_next = (delta_accumulator / freq); if ((delta_accumulator % freq) != 0) { ++delta_t_next; } if (delta_t_next < delta_t_min) { delta_t_min = delta_t_next; } } wave = voice2.wave; // It is only necessary to clock on the MSB of an oscillator // that is a sync source and has freq != 0. if ((wave.sync_dest.sync != 0) && (wave.freq != 0)) { int freq = wave.freq; int accumulator = wave.accumulator; // Clock on MSB off if MSB is on, clock on MSB on if MSB is off. int delta_accumulator = ((accumulator & 0x800000) != 0 ? 0x1000000 : 0x800000) - accumulator; int delta_t_next = (delta_accumulator / freq); if ((delta_accumulator % freq) != 0) { ++delta_t_next; } if (delta_t_next < delta_t_min) { delta_t_min = delta_t_next; } } // Clock oscillators. voice0.wave.clock(delta_t_min); voice1.wave.clock(delta_t_min); voice2.wave.clock(delta_t_min); // Synchronize oscillators. voice0.wave.synchronize(); voice1.wave.synchronize(); voice2.wave.synchronize(); delta_t_osc -= delta_t_min; } // Clock filter. filter.clock(delta_t, voice0.output, voice1.output, voice2.output, ext_in); // Clock external filter. extfilt.clock(delta_t, filter.output); }
public State read_state() { State state = new State(); int j = 0; WaveformGenerator wave = voice0.wave; EnvelopeGenerator envelope = voice0.envelope; state.sid_register[j + 0] = (char)(wave.freq & 0xff); state.sid_register[j + 1] = (char)(wave.freq >> 8); state.sid_register[j + 2] = (char)(wave.pw & 0xff); state.sid_register[j + 3] = (char)(wave.pw >> 8); state.sid_register[j + 4] = (char)((wave.waveform << 4) | ((wave.test != 0) ? 0x08 : 0) | ((wave.ring_mod != 0) ? 0x04 : 0) | ((wave.sync != 0) ? 0x02 : 0) | ((envelope.gate != 0) ? 0x01 : 0)); state.sid_register[j + 5] = (char)((envelope.attack << 4) | envelope.decay); state.sid_register[j + 6] = (char)((envelope.sustain << 4) | envelope.release); j++; wave = voice1.wave; envelope = voice1.envelope; state.sid_register[j + 0] = (char)(wave.freq & 0xff); state.sid_register[j + 1] = (char)(wave.freq >> 8); state.sid_register[j + 2] = (char)(wave.pw & 0xff); state.sid_register[j + 3] = (char)(wave.pw >> 8); state.sid_register[j + 4] = (char)((wave.waveform << 4) | ((wave.test != 0) ? 0x08 : 0) | ((wave.ring_mod != 0) ? 0x04 : 0) | ((wave.sync != 0) ? 0x02 : 0) | ((envelope.gate != 0) ? 0x01 : 0)); state.sid_register[j + 5] = (char)((envelope.attack << 4) | envelope.decay); state.sid_register[j + 6] = (char)((envelope.sustain << 4) | envelope.release); j++; wave = voice2.wave; envelope = voice2.envelope; state.sid_register[j + 0] = (char)(wave.freq & 0xff); state.sid_register[j + 1] = (char)(wave.freq >> 8); state.sid_register[j + 2] = (char)(wave.pw & 0xff); state.sid_register[j + 3] = (char)(wave.pw >> 8); state.sid_register[j + 4] = (char)((wave.waveform << 4) | ((wave.test != 0) ? 0x08 : 0) | ((wave.ring_mod != 0) ? 0x04 : 0) | ((wave.sync != 0) ? 0x02 : 0) | ((envelope.gate != 0) ? 0x01 : 0)); state.sid_register[j + 5] = (char)((envelope.attack << 4) | envelope.decay); state.sid_register[j + 6] = (char)((envelope.sustain << 4) | envelope.release); state.sid_register[j++] = (char)(filter.fc & 0x007); state.sid_register[j++] = (char)(filter.fc >> 3); state.sid_register[j++] = (char)((filter.res << 4) | filter.filt); state.sid_register[j++] = (char)(((filter.voice3off != 0) ? 0x80 : 0) | (filter.hp_bp_lp << 4) | filter.vol); // These registers are superfluous, but included for completeness. for (; j < 0x1d; j++) { state.sid_register[j] = (char)(read(j)); } for (; j < 0x20; j++) { state.sid_register[j] = (char)0; } state.bus_value = bus_value; state.bus_value_ttl = bus_value_ttl; state.accumulator0 = voice0.wave.accumulator; state.shift_register0 = voice0.wave.shift_register; state.rate_counter0 = voice0.envelope.rate_counter; state.rate_counter_period0 = voice0.envelope.rate_period; state.exponential_counter0 = voice0.envelope.exponential_counter; state.exponential_counter_period0 = voice0.envelope.exponential_counter_period; state.envelope_counter0 = voice0.envelope.envelope_counter; state.envelope_state0 = voice0.envelope.state; state.hold_zero0 = voice0.envelope.hold_zero; state.accumulator1 = voice1.wave.accumulator; state.shift_register1 = voice1.wave.shift_register; state.rate_counter1 = voice1.envelope.rate_counter; state.rate_counter_period1 = voice1.envelope.rate_period; state.exponential_counter1 = voice1.envelope.exponential_counter; state.exponential_counter_period1 = voice1.envelope.exponential_counter_period; state.envelope_counter1 = voice1.envelope.envelope_counter; state.envelope_state1 = voice1.envelope.state; state.hold_zero1 = voice1.envelope.hold_zero; state.accumulator2 = voice2.wave.accumulator; state.shift_register2 = voice2.wave.shift_register; state.rate_counter2 = voice2.envelope.rate_counter; state.rate_counter_period2 = voice2.envelope.rate_period; state.exponential_counter2 = voice2.envelope.exponential_counter; state.exponential_counter_period2 = voice2.envelope.exponential_counter_period; state.envelope_counter2 = voice2.envelope.envelope_counter; state.envelope_state2 = voice2.envelope.state; state.hold_zero2 = voice2.envelope.hold_zero; return(state); }
public void set_sync_source(WaveformGenerator source) { sync_source = source; source.sync_dest = this; }