More fixes for the ym2612, even though it's still no were near right

This commit is contained in:
transistor 2023-04-23 12:22:20 -07:00
parent 5740550c95
commit 1447ca1048

View File

@ -115,9 +115,9 @@ const RATE_TABLE: &[u16] = &[
const DEV_NAME: &str = "ym2612"; const DEV_NAME: &str = "ym2612";
const CHANNELS: usize = 8; const CHANNELS: usize = 6;
const OPERATORS: usize = 4;
const MAX_ENVELOPE: u16 = 0xFFC; const MAX_ENVELOPE: u16 = 0xFFC;
const SSG_CENTER: u16 = 0x800;
#[repr(usize)] #[repr(usize)]
@ -132,7 +132,7 @@ enum EnvelopeState {
#[derive(Clone)] #[derive(Clone)]
struct EnvelopeGenerator { struct EnvelopeGenerator {
debug_name: String, debug_name: String,
total_level: f32, total_level: u16,
sustain_level: u16, sustain_level: u16,
rates: [usize; 4], rates: [usize; 4],
@ -146,7 +146,7 @@ impl EnvelopeGenerator {
fn new(debug_name: String) -> Self { fn new(debug_name: String) -> Self {
Self { Self {
debug_name, debug_name,
total_level: 0.0, total_level: 0,
sustain_level: 0, sustain_level: 0,
rates: [0; 4], rates: [0; 4],
@ -157,8 +157,8 @@ impl EnvelopeGenerator {
} }
} }
fn set_total_level(&mut self, db: f32) { fn set_total_level(&mut self, level: u16) {
self.total_level = db_to_gain(db); self.total_level = level;
} }
fn set_sustain_level(&mut self, level: u16) { fn set_sustain_level(&mut self, level: u16) {
@ -172,6 +172,7 @@ impl EnvelopeGenerator {
fn notify_state_change(&mut self, state: bool, envelope_clock: Clock) { fn notify_state_change(&mut self, state: bool, envelope_clock: Clock) {
self.last_state_change = envelope_clock; self.last_state_change = envelope_clock;
if state { if state {
self.last_envelope_clock = envelope_clock;
self.envelope_state = EnvelopeState::Attack; self.envelope_state = EnvelopeState::Attack;
self.envelope = 0; self.envelope = 0;
} else { } else {
@ -180,7 +181,7 @@ impl EnvelopeGenerator {
} }
fn update_envelope(&mut self, envelope_clock: Clock) { fn update_envelope(&mut self, envelope_clock: Clock) {
for clock in self.last_envelope_clock..=envelope_clock { for clock in (self.last_envelope_clock + 1)..=envelope_clock {
self.do_cycle(clock); self.do_cycle(clock);
} }
self.last_envelope_clock = envelope_clock; self.last_envelope_clock = envelope_clock;
@ -218,10 +219,11 @@ impl EnvelopeGenerator {
fn get_db_at(&mut self) -> f32 { fn get_db_at(&mut self) -> f32 {
let envelope = if self.envelope_state == EnvelopeState::Attack { let envelope = if self.envelope_state == EnvelopeState::Attack {
!self.envelope !self.envelope & 0x3FF
} else { } else {
self.envelope self.envelope
}; };
let attenuation_10bit = (envelope + self.total_level).min(MAX_ENVELOPE);
envelope as f32 * 0.09375 envelope as f32 * 0.09375
} }
} }
@ -271,8 +273,8 @@ impl Operator {
self.multiplier = multiplier; self.multiplier = multiplier;
} }
fn set_total_level(&mut self, db: f32) { fn set_total_level(&mut self, level: u16) {
self.envelope.set_total_level(db) self.envelope.set_total_level(level)
} }
fn set_sustain_level(&mut self, level: u16) { fn set_sustain_level(&mut self, level: u16) {
@ -284,7 +286,7 @@ impl Operator {
} }
fn notify_state_change(&mut self, state: bool, envelope_clock: Clock) { fn notify_state_change(&mut self, state: bool, envelope_clock: Clock) {
self.envelope.notify_state_change(state, envelope_clock) self.envelope.notify_state_change(state, envelope_clock);
} }
fn get_sample(&mut self, modulator: f32, envelope_clock: Clock) -> f32 { fn get_sample(&mut self, modulator: f32, envelope_clock: Clock) -> f32 {
@ -293,7 +295,6 @@ impl Operator {
self.envelope.update_envelope(envelope_clock); self.envelope.update_envelope(envelope_clock);
let gain = db_to_gain(self.envelope.get_db_at()); let gain = db_to_gain(self.envelope.get_db_at());
//let gain = self.envelope.total_level;
sample / gain sample / gain
} }
@ -317,7 +318,7 @@ impl Channel {
fn new(debug_name: String, sample_rate: usize) -> Self { fn new(debug_name: String, sample_rate: usize) -> Self {
Self { Self {
debug_name: debug_name.clone(), debug_name: debug_name.clone(),
operators: (0..4).map(|i| Operator::new(format!("{}, op {}", debug_name, i), sample_rate)).collect(), operators: (0..OPERATORS).map(|i| Operator::new(format!("{}, op {}", debug_name, i), sample_rate)).collect(),
on_state: 0, on_state: 0,
next_on_state: 0, next_on_state: 0,
base_frequency: 0.0, base_frequency: 0.0,
@ -343,6 +344,7 @@ impl Channel {
self.on_state = self.next_on_state; self.on_state = self.next_on_state;
for (i, operator) in self.operators.iter_mut().enumerate() { for (i, operator) in self.operators.iter_mut().enumerate() {
operator.notify_state_change(((self.on_state >> i) & 0x01) != 0, envelope_clock); operator.notify_state_change(((self.on_state >> i) & 0x01) != 0, envelope_clock);
println!("notified at {}", envelope_clock);
} }
} }
@ -469,7 +471,7 @@ impl Ym2612 {
clock_frequency, clock_frequency,
envelope_clock_period: 351 * 1_000_000_000 / clock_frequency as ClockElapsed, //3 * 144 * 1_000_000_000 / clock_frequency as ClockElapsed, envelope_clock_period: 351 * 1_000_000_000 / clock_frequency as ClockElapsed, //3 * 144 * 1_000_000_000 / clock_frequency as ClockElapsed,
channels: (0..6).map(|i| Channel::new(format!("ch {}", i), sample_rate)).collect(), channels: (0..CHANNELS).map(|i| Channel::new(format!("ch {}", i), sample_rate)).collect(),
channel_frequencies: [(0, 0); CHANNELS], channel_frequencies: [(0, 0); CHANNELS],
dac: Dac::default(), dac: Dac::default(),
@ -502,14 +504,14 @@ impl Steppable for Ym2612 {
let envelope_clock = (system.clock + (i * nanos_per_sample) as Clock) / self.envelope_clock_period; let envelope_clock = (system.clock + (i * nanos_per_sample) as Clock) / self.envelope_clock_period;
let mut sample = 0.0; let mut sample = 0.0;
for ch in 0..5 { for ch in 0..(CHANNELS - 1) {
sample += self.channels[ch].get_sample(envelope_clock); sample += self.channels[ch].get_sample(envelope_clock);
} }
if self.dac.enabled { if self.dac.enabled {
sample += self.dac.get_sample(); sample += self.dac.get_sample();
} else { } else {
sample += self.channels[5].get_sample(envelope_clock); sample += self.channels[CHANNELS - 1].get_sample(envelope_clock);
} }
*buffered_sample = sample.clamp(-1.0, 1.0); *buffered_sample = sample.clamp(-1.0, 1.0);
@ -552,8 +554,8 @@ impl Ym2612 {
return; return;
}, },
}; };
println!("ch {} is {}", ch, if data >> 4 != 0 { "on" } else { "off" });
self.channels[ch].next_on_state = data >> 4; self.channels[ch].next_on_state = data >> 4;
self.channels[ch].reset();
}, },
0x2a => { 0x2a => {
@ -578,8 +580,11 @@ impl Ym2612 {
reg if is_reg_range(reg, 0x40) => { reg if is_reg_range(reg, 0x40) => {
let (ch, op) = get_ch_op(bank, reg); let (ch, op) = get_ch_op(bank, reg);
// 0-127 is the attenuation, where 0 is the highest volume and 127 is the lowest, in 0.75 dB intervals // The total level (attenuation) is 0-127, where 0 is the highest volume and 127
self.channels[ch].operators[op].set_total_level((data & 0x7F) as f32 * 0.75); // is the lowest, in 0.75 dB intervals. The 7-bit value is multiplied by 8 to
// convert it to a 10-bit attenuation for the envelope generator, which is an
// attenuation value in 0.09375 dB intervals
self.channels[ch].operators[op].set_total_level((data & 0x7F) as u16 * 8);
}, },
reg if is_reg_range(reg, 0x50) reg if is_reg_range(reg, 0x50)