From a9d51fb919fb1b940dafbb66890abb9b98848f08 Mon Sep 17 00:00:00 2001 From: transistor Date: Sun, 2 Oct 2022 10:29:34 -0700 Subject: [PATCH] Added DAC to ym2612 and changed mixing method --- emulator/core/src/error.rs | 2 +- emulator/frontends/common/src/audio.rs | 2 +- emulator/peripherals/yamaha/src/sn76489.rs | 9 ++----- emulator/peripherals/yamaha/src/ym2612.rs | 28 ++++++++++++++++++---- emulator/systems/genesis/src/system.rs | 2 +- todo.txt | 5 ++++ 6 files changed, 33 insertions(+), 15 deletions(-) diff --git a/emulator/core/src/error.rs b/emulator/core/src/error.rs index 28e25ed..845151a 100644 --- a/emulator/core/src/error.rs +++ b/emulator/core/src/error.rs @@ -57,7 +57,7 @@ pub enum LogLevel { Debug, } -static mut LOG_LEVEL: LogLevel = LogLevel::Info; +static mut LOG_LEVEL: LogLevel = LogLevel::Warning; pub fn log_level() -> LogLevel { unsafe { LOG_LEVEL } diff --git a/emulator/frontends/common/src/audio.rs b/emulator/frontends/common/src/audio.rs index cbdfc6f..b03d6ae 100644 --- a/emulator/frontends/common/src/audio.rs +++ b/emulator/frontends/common/src/audio.rs @@ -58,7 +58,7 @@ impl AudioSource { self.sequence_num = mixer_sequence_num; for i in 0..locked_mixer.buffer.len() { - locked_mixer.buffer[i] += self.buffer.next().unwrap_or(0.0); + locked_mixer.buffer[i] = (locked_mixer.buffer[i] + self.buffer.next().unwrap_or(0.0)).clamp(-1.0, 1.0); } self.frame_size = locked_mixer.frame_size(); diff --git a/emulator/peripherals/yamaha/src/sn76489.rs b/emulator/peripherals/yamaha/src/sn76489.rs index 8c6117d..c4b0d99 100644 --- a/emulator/peripherals/yamaha/src/sn76489.rs +++ b/emulator/peripherals/yamaha/src/sn76489.rs @@ -40,7 +40,7 @@ impl ToneGenerator { } pub fn get_sample(&mut self) -> f32 { - self.wave.next().unwrap() / self.attenuation + self.wave.next().unwrap() / (self.attenuation + 1.0) } } @@ -115,23 +115,18 @@ impl Steppable for Sn76489 { let mut buffer = vec![0.0; samples]; for i in 0..samples { let mut sample = 0.0; - let mut count = 0; for ch in 0..3 { if self.tones[ch].on { sample += self.tones[ch].get_sample(); - count += 1; } } if self.noise.on { sample += self.noise.get_sample(); - count += 1; } - if count > 0 { - buffer[i] = sample / count as f32; - } + buffer[i] = sample.clamp(-1.0, 1.0); } self.source.write_samples(&buffer); } else { diff --git a/emulator/peripherals/yamaha/src/ym2612.rs b/emulator/peripherals/yamaha/src/ym2612.rs index 14cfb93..f75a319 100644 --- a/emulator/peripherals/yamaha/src/ym2612.rs +++ b/emulator/peripherals/yamaha/src/ym2612.rs @@ -1,5 +1,6 @@ use std::num::NonZeroU8; +use std::collections::VecDeque; use moa_core::{debug, warning}; use moa_core::{System, Error, ClockElapsed, Address, Addressable, Steppable, Transmutable}; @@ -154,6 +155,9 @@ pub struct Ym2612 { pub channels: Vec, pub channel_frequencies: [(u8, u16); CHANNELS], + + pub dac_enabled: bool, + pub dac: VecDeque, } impl Ym2612 { @@ -166,6 +170,8 @@ impl Ym2612 { selected_reg_1: None, channels: vec![Channel::new(sample_rate); 8], channel_frequencies: [(0, 0); CHANNELS], + dac_enabled: false, + dac: VecDeque::with_capacity(100), }) } @@ -175,6 +181,14 @@ impl Ym2612 { self.channels[ch].on = data >> 4; self.channels[ch].reset(); println!("Note: {}: {:x}", ch, self.channels[ch].on); + } else if reg == 0x2a { + if self.dac_enabled { + for _ in 0..3 { + self.dac.push_back(data); + } + } + } else if reg == 0x2b { + self.dac_enabled = data & 0x80 != 0; } else if (reg & 0xF0) == 0x30 { let (ch, op) = get_ch_op(bank, reg); let multiplier = if data == 0 { 0.5 } else { (data & 0x0F) as f32 }; @@ -249,18 +263,22 @@ impl Steppable for Ym2612 { let mut buffer = vec![0.0; samples]; for i in 0..samples { let mut sample = 0.0; - let mut count = 0; - for ch in 0..7 { + for ch in 0..6 { if self.channels[ch].on != 0 { sample += self.channels[ch].get_sample(); - count += 1; } } - if count > 0 { - buffer[i] = sample / count as f32; + if self.dac_enabled { + if let Some(data) = self.dac.pop_front() { + sample += data as f32 / 255.0; + } + } else if self.channels[6].on != 0 { + sample += self.channels[6].get_sample(); } + + buffer[i] = sample.clamp(-1.0, 1.0); } self.source.write_samples(&buffer); //} diff --git a/emulator/systems/genesis/src/system.rs b/emulator/systems/genesis/src/system.rs index 66d646b..85de013 100644 --- a/emulator/systems/genesis/src/system.rs +++ b/emulator/systems/genesis/src/system.rs @@ -70,7 +70,7 @@ pub fn build_genesis(host: &mut H, mut options: SegaGenesisOptions) -> // Build the Coprocessor's Bus let bank_register = Signal::new(0); let coproc_ram = wrap_transmutable(MemoryBlock::new(vec![0; 0x00002000])); - let coproc_ym_sound = wrap_transmutable(AddressRepeater::new(wrap_transmutable(Ym2612::create(host)?), 0x2000)); + let coproc_ym_sound = wrap_transmutable(Ym2612::create(host)?); let coproc_sn_sound = wrap_transmutable(Sn76489::create(host)?); let coproc_register = wrap_transmutable(CoprocessorBankRegister::new(bank_register.clone())); let coproc_area = wrap_transmutable(CoprocessorBankArea::new(bank_register, system.bus.clone())); diff --git a/todo.txt b/todo.txt index bfdcb94..e5cf939 100644 --- a/todo.txt +++ b/todo.txt @@ -1,4 +1,8 @@ +* test the Z80 more, add tests +* double check the functioning of the banked areas and register settings for Z80 coprocessor +* address repeater on ym2612 doesn't seem to work the same, when it's on the 68000 device. The Z80 device doesn't have an affect, but maybe it's not being used + * make the keys easier to config... * add log crate to core @@ -17,6 +21,7 @@ Web Assembly: * fix audio, and/or make it possible to disable audio processing/simulation for one or both sound chips (might be nice to have sn76489 but not ym2612) +* should you have a separate attenuation value for each input in the mixer so that you can make one chip quieter (the sn76489 is pretty loud, and I added a fixed offset to the attenuation for now) Harte Tests: