Added ym2612 total level and start of envelope implementation

This commit is contained in:
transistor 2023-04-09 13:11:45 -07:00
parent 4dc4b6ad22
commit 10ef61784a
7 changed files with 350 additions and 141 deletions

View File

@ -158,3 +158,8 @@ impl Iterator for SkewedSquareWave {
}
}
#[inline]
pub fn db_to_gain(db: f32) -> f32 {
(10.0_f32).powf(db / 20.0)
}

View File

@ -4,7 +4,6 @@ use crate::devices::TransmutableBox;
pub struct InterruptController {
target: Option<TransmutableBox>,
interrupts: Vec<(bool, u8)>,
highest: u8,
}
@ -12,7 +11,6 @@ pub struct InterruptController {
impl Default for InterruptController {
fn default() -> InterruptController {
InterruptController {
target: None,
interrupts: vec![(false, 0); 7],
highest: 0,
}
@ -20,15 +18,6 @@ impl Default for InterruptController {
}
impl InterruptController {
pub fn set_target(&mut self, dev: TransmutableBox) -> Result<(), Error> {
if self.target.is_some() {
return Err(Error::new("Interruptable device already set, and interrupt controller only supports one receiver"));
}
self.target = Some(dev);
Ok(())
}
pub fn set(&mut self, state: bool, priority: u8, number: u8) -> Result<(), Error> {
self.interrupts[priority as usize].0 = state;
self.interrupts[priority as usize].1 = number;

View File

@ -74,7 +74,6 @@ impl System {
}
pub fn add_interruptable_device(&mut self, name: &str, device: TransmutableBox) -> Result<(), Error> {
self.interrupt_controller.borrow_mut().set_target(device.clone())?;
self.try_queue_device(device.clone());
self.devices.insert(name.to_string(), device);
Ok(())

View File

@ -8,14 +8,14 @@ use moa_core::host::audio::{SquareWave};
const DEV_NAME: &str = "sn76489";
#[derive(Clone)]
pub struct ToneGenerator {
struct ToneGenerator {
on: bool,
attenuation: f32,
wave: SquareWave,
}
impl ToneGenerator {
pub fn new(sample_rate: usize) -> Self {
fn new(sample_rate: usize) -> Self {
Self {
on: false,
attenuation: 0.0,
@ -23,7 +23,7 @@ impl ToneGenerator {
}
}
pub fn set_attenuation(&mut self, attenuation: u8) {
fn set_attenuation(&mut self, attenuation: u8) {
if attenuation == 0x0F {
self.on = false;
} else {
@ -33,20 +33,20 @@ impl ToneGenerator {
info!("set attenuation to {} {}", self.attenuation, self.on);
}
pub fn set_counter(&mut self, count: usize) {
fn set_counter(&mut self, count: usize) {
let frequency = 3_579_545.0 / (count as f32 * 32.0);
self.wave.set_frequency(frequency);
info!("set frequency to {}", frequency);
}
pub fn get_sample(&mut self) -> f32 {
fn get_sample(&mut self) -> f32 {
self.wave.next().unwrap() / (self.attenuation + 1.0)
}
}
#[derive(Clone)]
pub struct NoiseGenerator {
struct NoiseGenerator {
on: bool,
attenuation: f32,
}
@ -61,7 +61,7 @@ impl Default for NoiseGenerator {
}
impl NoiseGenerator {
pub fn set_attenuation(&mut self, attenuation: u8) {
fn set_attenuation(&mut self, attenuation: u8) {
if attenuation == 0x0F {
self.on = false;
} else {
@ -71,13 +71,13 @@ impl NoiseGenerator {
info!("set attenuation to {} {}", self.attenuation, self.on);
}
pub fn set_control(&mut self, _bits: u8) {
fn set_control(&mut self, _bits: u8) {
//let frequency = 3_579_545.0 / (count as f32 * 32.0);
//self.wave.set_frequency(frequency);
//debug!("set frequency to {}", frequency);
}
pub fn get_sample(&mut self) -> f32 {
fn get_sample(&mut self) -> f32 {
// TODO this isn't implemented yet
0.0
}
@ -86,18 +86,20 @@ impl NoiseGenerator {
pub struct Sn76489 {
pub first_byte: Option<u8>,
pub source: Box<dyn Audio>,
pub tones: Vec<ToneGenerator>,
pub noise: NoiseGenerator,
clock_frequency: u32,
first_byte: Option<u8>,
source: Box<dyn Audio>,
tones: Vec<ToneGenerator>,
noise: NoiseGenerator,
}
impl Sn76489 {
pub fn create<H: Host>(host: &mut H) -> Result<Self, Error> {
pub fn create<H: Host>(host: &mut H, clock_frequency: u32) -> Result<Self, Error> {
let source = host.create_audio_source()?;
let sample_rate = source.samples_per_second();
Ok(Self {
clock_frequency,
first_byte: None,
source,
tones: vec![ToneGenerator::new(sample_rate); 3],

View File

@ -3,16 +3,24 @@ use std::num::NonZeroU8;
use std::collections::VecDeque;
use moa_core::{debug, warn};
use moa_core::{System, Error, ClockElapsed, Address, Addressable, Steppable, Transmutable};
use moa_core::{System, Error, Clock, ClockElapsed, Address, Addressable, Steppable, Transmutable};
use moa_core::host::{Host, Audio};
use moa_core::host::audio::{SineWave};
use moa_core::host::audio::{SineWave, db_to_gain};
const DEV_NAME: &str = "ym2612";
const CHANNELS: usize = 8;
#[derive(Copy, Clone, Debug)]
pub enum OperatorAlgorithm {
enum EnvelopeState {
Attack,
Decay1,
Decay2,
Release,
}
#[derive(Copy, Clone, Debug)]
enum OperatorAlgorithm {
A0,
A1,
A2,
@ -25,148 +33,283 @@ pub enum OperatorAlgorithm {
#[derive(Clone)]
pub struct Operator {
pub wave: SineWave,
pub frequency: f32,
pub multiplier: f32,
struct Operator {
wave: SineWave,
frequency: f32,
multiplier: f32,
total_level: f32,
attack_rate: usize,
first_decay_rate: usize,
first_decay_level: usize,
second_decay_rate: usize,
release_rate: usize,
envelope_state: EnvelopeState,
last_event: Clock,
envelope_gain: f32,
}
impl Operator {
pub fn new(sample_rate: usize) -> Self {
fn new(sample_rate: usize) -> Self {
Self {
wave: SineWave::new(400.0, sample_rate),
frequency: 400.0,
multiplier: 1.0,
total_level: 0.0,
attack_rate: 0,
first_decay_rate: 0,
first_decay_level: 0,
second_decay_rate: 0,
release_rate: 0,
envelope_state: EnvelopeState::Attack,
last_event: 0,
envelope_gain: 0.0,
}
}
pub fn set_frequency(&mut self, frequency: f32) {
fn set_frequency(&mut self, frequency: f32) {
self.frequency = frequency;
}
pub fn reset(&mut self) {
fn set_total_level(&mut self, db: f32) {
self.total_level = db_to_gain(db);
}
fn set_attack_rate(&mut self, rate: usize) {
self.attack_rate = rate;
}
fn set_first_decay_rate(&mut self, rate: usize) {
self.first_decay_rate = rate;
}
fn set_first_decay_level(&mut self, rate: usize) {
self.first_decay_level = rate;
}
fn set_second_decay_rate(&mut self, rate: usize) {
self.second_decay_rate = rate;
}
fn set_release_rate(&mut self, rate: usize) {
self.release_rate = rate;
}
fn notify_state_change(&mut self, state: bool, event_clock: Clock) {
self.last_event = event_clock;
if state {
self.envelope_state = EnvelopeState::Attack;
self.envelope_gain = 0.0;
} else {
self.envelope_state = EnvelopeState::Release;
}
}
fn reset(&mut self) {
self.wave.reset();
}
pub fn set_multiplier(&mut self, _frequency: f32, multiplier: f32) {
fn set_multiplier(&mut self, _frequency: f32, multiplier: f32) {
self.multiplier = multiplier;
}
pub fn get_sample(&mut self, modulator: f32) -> f32 {
// TODO this would need to take into account the volume and envelope
fn get_sample(&mut self, modulator: f32, event_clock: Clock) -> f32 {
self.wave.set_frequency((self.frequency * self.multiplier) + modulator);
self.wave.next().unwrap()
let sample = self.wave.next().unwrap();
/*
let time_since_last = event_clock - self.last_event;
match self.envelope_state {
EnvelopeState::Attack => {
let gain = rate_to_gain(self.attack_rate, time_since_last).min(self.total_level);
if gain == self.total_level {
self.envelope_state = EnvelopeState::Decay1;
}
sample / gain
},
EnvelopeState::Decay1 => {
let gain = (self.total_level - rate_to_gain(self.first_decay_rate, time_since_last)).max(self.total_level / 2.0);
if gain == self.total_level / 2.0 {
self.envelope_state = EnvelopeState::Decay2;
}
sample / gain
},
EnvelopeState::Decay2 => {
let gain = (self.total_level / 2.0 - rate_to_gain(self.second_decay_rate, time_since_last)).max(0.0);
sample / gain
},
EnvelopeState::Release => {
let gain = (self.total_level / 2.0 - rate_to_gain(self.release_rate, time_since_last)).max(0.0);
sample / gain
},
}
*/
sample
}
}
fn rate_to_gain(rate: usize, event_clock: Clock) -> f32 {
event_clock as f32 * rate as f32
}
#[derive(Clone)]
pub struct Channel {
pub operators: Vec<Operator>,
pub on: u8,
pub base_frequency: f32,
pub algorithm: OperatorAlgorithm,
struct Channel {
operators: Vec<Operator>,
on_state: u8,
next_on_state: u8,
base_frequency: f32,
algorithm: OperatorAlgorithm,
}
impl Channel {
pub fn new(sample_rate: usize) -> Self {
fn new(sample_rate: usize) -> Self {
Self {
operators: vec![Operator::new(sample_rate); 4],
on: 0,
on_state: 0,
next_on_state: 0,
base_frequency: 0.0,
algorithm: OperatorAlgorithm::A0,
}
}
pub fn set_frequency(&mut self, frequency: f32) {
fn set_frequency(&mut self, frequency: f32) {
self.base_frequency = frequency;
for operator in self.operators.iter_mut() {
operator.set_frequency(frequency);
}
}
pub fn reset(&mut self) {
fn reset(&mut self) {
for operator in self.operators.iter_mut() {
operator.reset();
}
}
pub fn get_sample(&mut self) -> f32 {
fn get_sample(&mut self, event_clock: Clock) -> f32 {
if self.on_state != self.next_on_state {
self.on_state = self.next_on_state;
for (i, operator) in self.operators.iter_mut().enumerate() {
operator.notify_state_change(((self.on_state >> i) & 0x01) != 0, event_clock);
}
}
if self.on_state != 0 {
self.get_algorithm_sample(event_clock)
} else {
0.0
}
}
fn get_algorithm_sample(&mut self, event_clock: Clock) -> f32 {
match self.algorithm {
OperatorAlgorithm::A0 => {
let modulator0 = self.operators[0].get_sample(0.0);
let modulator1 = self.operators[1].get_sample(modulator0);
let modulator2 = self.operators[2].get_sample(modulator1);
self.operators[3].get_sample(modulator2)
let modulator0 = self.operators[0].get_sample(0.0, event_clock);
let modulator1 = self.operators[1].get_sample(modulator0, event_clock);
let modulator2 = self.operators[2].get_sample(modulator1, event_clock);
self.operators[3].get_sample(modulator2, event_clock)
},
OperatorAlgorithm::A1 => {
let sample1 = self.operators[0].get_sample(0.0) + self.operators[1].get_sample(0.0);
let sample2 = self.operators[2].get_sample(sample1);
self.operators[3].get_sample(sample2)
let sample1 = self.operators[0].get_sample(0.0, event_clock) + self.operators[1].get_sample(0.0, event_clock);
let sample2 = self.operators[2].get_sample(sample1, event_clock);
self.operators[3].get_sample(sample2, event_clock)
},
OperatorAlgorithm::A2 => {
let sample1 = self.operators[1].get_sample(0.0);
let sample2 = self.operators[2].get_sample(sample1);
let sample3 = self.operators[0].get_sample(0.0) + sample2;
self.operators[3].get_sample(sample3)
let sample1 = self.operators[1].get_sample(0.0, event_clock);
let sample2 = self.operators[2].get_sample(sample1, event_clock);
let sample3 = self.operators[0].get_sample(0.0, event_clock) + sample2;
self.operators[3].get_sample(sample3, event_clock)
},
OperatorAlgorithm::A3 => {
let sample1 = self.operators[0].get_sample(0.0);
let sample2 = self.operators[1].get_sample(sample1);
let sample3 = self.operators[2].get_sample(0.0);
self.operators[3].get_sample(sample2 + sample3)
let sample1 = self.operators[0].get_sample(0.0, event_clock);
let sample2 = self.operators[1].get_sample(sample1, event_clock);
let sample3 = self.operators[2].get_sample(0.0, event_clock);
self.operators[3].get_sample(sample2 + sample3, event_clock)
},
OperatorAlgorithm::A4 => {
let sample1 = self.operators[0].get_sample(0.0);
let sample2 = self.operators[1].get_sample(sample1);
let sample3 = self.operators[2].get_sample(0.0);
let sample4 = self.operators[3].get_sample(sample3);
let sample1 = self.operators[0].get_sample(0.0, event_clock);
let sample2 = self.operators[1].get_sample(sample1, event_clock);
let sample3 = self.operators[2].get_sample(0.0, event_clock);
let sample4 = self.operators[3].get_sample(sample3, event_clock);
sample2 + sample4
},
OperatorAlgorithm::A5 => {
let sample1 = self.operators[0].get_sample(0.0);
self.operators[1].get_sample(sample1) + self.operators[2].get_sample(sample1) + self.operators[3].get_sample(sample1)
let sample1 = self.operators[0].get_sample(0.0, event_clock);
self.operators[1].get_sample(sample1, event_clock) + self.operators[2].get_sample(sample1, event_clock) + self.operators[3].get_sample(sample1, event_clock)
},
OperatorAlgorithm::A6 => {
let sample1 = self.operators[0].get_sample(0.0);
let sample2 = self.operators[1].get_sample(sample1);
sample2 + self.operators[2].get_sample(0.0) + self.operators[3].get_sample(0.0)
let sample1 = self.operators[0].get_sample(0.0, event_clock);
let sample2 = self.operators[1].get_sample(sample1, event_clock);
sample2 + self.operators[2].get_sample(0.0, event_clock) + self.operators[3].get_sample(0.0, event_clock)
},
OperatorAlgorithm::A7 => {
self.operators[0].get_sample(0.0)
+ self.operators[1].get_sample(0.0)
+ self.operators[2].get_sample(0.0)
+ self.operators[3].get_sample(0.0)
self.operators[0].get_sample(0.0, event_clock)
+ self.operators[1].get_sample(0.0, event_clock)
+ self.operators[2].get_sample(0.0, event_clock)
+ self.operators[3].get_sample(0.0, event_clock)
},
}
}
}
struct Dac {
enabled: bool,
samples: VecDeque<f32>,
}
impl Default for Dac {
fn default() -> Self {
Self {
enabled: false,
samples: VecDeque::with_capacity(100),
}
}
}
impl Dac {
fn add_sample(&mut self, sample: f32) {
self.samples.push_back(sample);
}
fn get_sample(&mut self) -> f32 {
if let Some(data) = self.samples.pop_front() {
data
} else {
0.0
}
}
}
pub struct Ym2612 {
pub source: Box<dyn Audio>,
pub selected_reg_0: Option<NonZeroU8>,
pub selected_reg_1: Option<NonZeroU8>,
source: Box<dyn Audio>,
selected_reg_0: Option<NonZeroU8>,
selected_reg_1: Option<NonZeroU8>,
pub channels: Vec<Channel>,
pub channel_frequencies: [(u8, u16); CHANNELS],
clock_frequency: u32,
event_clock_period: ClockElapsed,
channels: Vec<Channel>,
channel_frequencies: [(u8, u16); CHANNELS],
dac: Dac,
pub dac_enabled: bool,
pub dac: VecDeque<u8>,
timer_a_enable: bool,
timer_a: u16,
timer_a_current: u16,
timer_a_overflow: bool,
pub timer_a_enable: bool,
pub timer_a: u16,
pub timer_a_current: u16,
pub timer_a_overflow: bool,
timer_b_enable: bool,
timer_b: u8,
timer_b_current: u8,
timer_b_overflow: bool,
pub timer_b_enable: bool,
pub timer_b: u8,
pub timer_b_current: u8,
pub timer_b_overflow: bool,
registers: Vec<u8>,
}
impl Ym2612 {
pub fn create<H: Host>(host: &mut H) -> Result<Self, Error> {
pub fn create<H: Host>(host: &mut H, clock_frequency: u32) -> Result<Self, Error> {
let source = host.create_audio_source()?;
let sample_rate = source.samples_per_second();
Ok(Self {
@ -174,11 +317,12 @@ impl Ym2612 {
selected_reg_0: None,
selected_reg_1: None,
clock_frequency,
event_clock_period: 3 * 144 * 1_000_000_000 / clock_frequency as ClockElapsed,
channels: vec![Channel::new(sample_rate); 8],
channel_frequencies: [(0, 0); CHANNELS],
dac_enabled: false,
dac: VecDeque::with_capacity(100),
dac: Dac::default(),
timer_a_enable: false,
timer_a: 0,
@ -189,10 +333,15 @@ impl Ym2612 {
timer_b: 0,
timer_b_current: 0,
timer_b_overflow: false,
registers: vec![0; 512],
})
}
pub fn set_register(&mut self, bank: usize, reg: usize, data: u8) {
pub fn set_register(&mut self, bank: u8, reg: u8, data: u8) {
// Keep a copy for debugging purposes, and if the original values are needed
self.registers[bank as usize * 256 + reg as usize] = data;
//warn!("{}: set reg {}{:x} to {:x}", DEV_NAME, bank, reg, data);
match reg {
0x24 => {
@ -211,23 +360,23 @@ impl Ym2612 {
0x28 => {
let ch = (data as usize) & 0x07;
self.channels[ch].on = data >> 4;
self.channels[ch].next_on_state = data >> 4;
self.channels[ch].reset();
},
0x2a => {
if self.dac_enabled {
if self.dac.enabled {
for _ in 0..3 {
self.dac.push_back(data);
self.dac.add_sample(((data as f32 - 128.0) / 255.0) * 2.0);
}
}
},
0x2b => {
self.dac_enabled = data & 0x80 != 0;
self.dac.enabled = data & 0x80 != 0;
},
reg if (reg & 0xF0) == 0x30 => {
reg if is_reg_range(reg, 0x30) => {
let (ch, op) = get_ch_op(bank, reg);
let multiplier = if data == 0 { 0.5 } else { (data & 0x0F) as f32 };
let frequency = self.channels[ch].base_frequency;
@ -235,8 +384,24 @@ impl Ym2612 {
self.channels[ch].operators[op].set_multiplier(frequency, multiplier)
},
reg if is_reg_range(reg, 0x40) => {
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
self.channels[ch].operators[op].set_total_level((data & 0x7F) as f32 * 0.75);
},
reg if is_reg_range(reg, 0x50)
|| is_reg_range(reg, 0x60)
|| is_reg_range(reg, 0x70)
|| is_reg_range(reg, 0x80)
|| is_reg_range(reg, 0x90)
=> {
let (ch, op) = get_ch_op(bank, reg);
self.update_rates(ch, op);
},
reg if (0xA0..=0xA2).contains(&reg) => {
let ch = (reg & 0x07) + (bank * 3);
let ch = get_ch(bank, reg);
self.channel_frequencies[ch].1 = (self.channel_frequencies[ch].1 & 0xFF00) | data as u16;
let frequency = fnumber_to_frequency(self.channel_frequencies[ch]);
@ -245,13 +410,13 @@ impl Ym2612 {
},
reg if (0xA4..=0xA6).contains(&reg) => {
let ch = (reg & 0x07) - 4 + (bank * 3);
let ch = ((reg as usize) & 0x07) - 4 + ((bank as usize) * 3);
self.channel_frequencies[ch].1 = (self.channel_frequencies[ch].1 & 0xFF) | ((data as u16) & 0x07) << 8;
self.channel_frequencies[ch].0 = (data & 0x38) >> 3;
},
reg if (0xB0..=0xB2).contains(&reg) => {
let ch = (reg & 0x07) + (bank * 3);
let ch = get_ch(bank, reg);
self.channels[ch].algorithm = match data & 0x07 {
0 => OperatorAlgorithm::A0,
1 => OperatorAlgorithm::A1,
@ -270,59 +435,101 @@ impl Ym2612 {
},
}
}
fn update_rates(&mut self, ch: usize, op: usize) {
let index = get_index(ch, op);
let keycode = self.registers[0xA0 + get_ch_index(ch)] >> 1;
let rate_scaling = self.registers[0x50 + index] & 0xC0 >> 6;
let attack_rate = self.registers[0x50 + index] & 0x1F;
let first_decay_rate = self.registers[0x60 + index] & 0x1F;
let first_decay_level = (self.registers[0x80 + index] & 0x0F) >> 4;
let second_decay_rate = self.registers[0x70 + index] & 0x1F;
let release_rate = self.registers[0x80 + index] & 0x0F;
self.channels[ch].operators[op].set_attack_rate(calculate_rate(attack_rate, rate_scaling, keycode));
self.channels[ch].operators[op].set_first_decay_rate(calculate_rate(first_decay_rate, rate_scaling, keycode));
self.channels[ch].operators[op].set_first_decay_level(calculate_rate(first_decay_level, rate_scaling, keycode));
self.channels[ch].operators[op].set_second_decay_rate(calculate_rate(second_decay_rate, rate_scaling, keycode));
self.channels[ch].operators[op].set_release_rate(calculate_rate(release_rate, rate_scaling, keycode));
}
}
#[inline(always)]
pub fn fnumber_to_frequency(fnumber: (u8, u16)) -> f32 {
#[inline]
fn fnumber_to_frequency(fnumber: (u8, u16)) -> f32 {
(fnumber.1 as f32 * 0.0264) * 2_u32.pow(fnumber.0 as u32) as f32
}
#[inline(always)]
pub fn get_ch_op(bank: usize, reg: usize) -> (usize, usize) {
let ch = (reg & 0x03) + (bank * 3);
let op = (reg & 0xC0) >> 2;
#[inline]
fn calculate_rate(rate: u8, rate_scaling: u8, keycode: u8) -> usize {
let scale = match rate_scaling {
0 => 8,
1 => 4,
2 => 2,
3 => 1,
_ => 8, // this shouldn't be possible
};
(2 * rate as usize + (keycode as usize / scale)).min(64)
}
#[inline]
fn is_reg_range(reg: u8, base: u8) -> bool {
// There is no 4th channel in each of the groupings
reg >= base && reg <= base + 0x0F && (reg & 0x03) != 0x03
}
/// Get the channel and operator to target with a given register number
/// and bank number. Bank 0 refers to operators for channels 1-3, and
/// bank 1 refers to operators for channels 4-6.
#[inline]
fn get_ch_op(bank: u8, reg: u8) -> (usize, usize) {
let ch = ((reg as usize) & 0x03) + ((bank as usize) * 3);
let op = ((reg as usize) & 0x0C) >> 2;
(ch, op)
}
#[inline]
fn get_index(ch: usize, op: usize) -> usize {
let (bank, ch_l) = if ch < 3 { (0, ch) } else { (1, ch - 3) };
(bank << 8) | op << 2 | ch
}
#[inline]
fn get_ch(bank: u8, reg: u8) -> usize {
((reg as usize) & 0x07) + ((bank as usize) * 3)
}
#[inline]
fn get_ch_index(ch: usize) -> usize {
if ch < 3 {
ch
} else {
0x100 + ch - 3
}
}
impl Steppable for Ym2612 {
fn step(&mut self, system: &System) -> Result<ClockElapsed, Error> {
// TODO since you expect this step function to be called every 1ms of simulated time
// you could assume that you should produce (sample_rate / 1000) samples
//if self.sine.frequency < 2000.0 {
// self.sine.frequency += 1.0;
//}
//let rate = self.source.samples_per_second();
//self.source.write_samples(rate / 1000, &mut self.sine);
//println!("{}", self.sine.frequency);
//if self.on {
// let rate = self.source.samples_per_second();
// self.source.write_samples(rate / 1000, &mut self.sine);
//}
let rate = self.source.samples_per_second();
let available = self.source.space_available();
let samples = if available < rate / 1000 { available } else { rate / 1000 };
let nanos_per_sample = 1_000_000_000 / rate;
//if self.source.space_available() >= samples {
let mut buffer = vec![0.0; samples];
for buffered_sample in buffer.iter_mut().take(samples) {
for (i, buffered_sample) in buffer.iter_mut().enumerate().take(samples) {
let event_clock = (system.clock + (i * nanos_per_sample) as Clock) / self.event_clock_period;
let mut sample = 0.0;
for ch in 0..6 {
if self.channels[ch].on != 0 {
sample += self.channels[ch].get_sample();
}
sample += self.channels[ch].get_sample(event_clock);
}
if self.dac_enabled {
if let Some(data) = self.dac.pop_front() {
sample += ((data as f32 - 128.0) / 255.0) * 2.0;
}
} else if self.channels[6].on != 0 {
sample += self.channels[6].get_sample();
if self.dac.enabled {
sample += self.dac.get_sample();
} else {
sample += self.channels[6].get_sample(event_clock);
}
*buffered_sample = sample.clamp(-1.0, 1.0);
@ -361,7 +568,7 @@ impl Addressable for Ym2612 {
},
1 => {
if let Some(reg) = self.selected_reg_0 {
self.set_register(0, reg.get() as usize, data[0]);
self.set_register(0, reg.get(), data[0]);
}
},
2 => {
@ -369,7 +576,7 @@ impl Addressable for Ym2612 {
},
3 => {
if let Some(reg) = self.selected_reg_1 {
self.set_register(1, reg.get() as usize, data[0]);
self.set_register(1, reg.get(), data[0]);
}
},
_ => {

View File

@ -70,8 +70,8 @@ pub fn build_genesis<H: Host>(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(Ym2612::create(host)?);
let coproc_sn_sound = wrap_transmutable(Sn76489::create(host)?);
let coproc_ym_sound = wrap_transmutable(Ym2612::create(host, 7_670_454)?);
let coproc_sn_sound = wrap_transmutable(Sn76489::create(host, 3_579_545)?);
let coproc_register = wrap_transmutable(CoprocessorBankRegister::new(bank_register.clone()));
let coproc_area = wrap_transmutable(CoprocessorBankArea::new(bank_register, system.bus.clone()));

View File

@ -1,4 +1,11 @@
* the interrupt controller stuff is really not good. It should be more like busport, and connected to a device at startup (eg. create
interrupt controller, then create objects that use that controller and pass in values, maybe an option so that the controller doesn't
have to be hooked up, meaning hardware interrupts would not be used.
* along with the interrupt stuff, I'm kind of thinking of packaging things a bit differently, like using a tuple struct for the rc refcell
transmutable abstraction, so that you can avoid the need for explicit borrows
* improve performance
* should it be possible to reschedule multiple events at different intervals to reduce the times a given step function is called? Some have
multiple clocks, or multiple things at different clocks, and making them each an event would mean they could be smaller and faster, but at