Compare commits

...

6 Commits

Author SHA1 Message Date
Rekai Nyangadzayi Musuka 360a9a7b65 chore(apu): improve code organization
continuous-integration/drone/push Build is passing Details
2021-08-18 00:04:27 -05:00
Rekai Nyangadzayi Musuka 5d64e539a7 fix(apu): resolve off-by-one error 2021-08-17 23:14:56 -05:00
Rekai Nyangadzayi Musuka 22f96a10e7 fix(apu): increase accuracy of apu emulation
Reintroduce the Frame Sequencer and it's state enum (needed so that we
can reset the FS on NR52 enable)
2021-08-17 22:18:40 -05:00
Rekai Nyangadzayi Musuka 8fea8eb1ff fix(apu): better emulate behaviour of apu channel DACs 2021-08-17 21:26:22 -05:00
Rekai Nyangadzayi Musuka 9b2c91445a chore: enable audio by default
even if it sounds really bad right now
2021-08-17 21:25:55 -05:00
Rekai Nyangadzayi Musuka b9046bceba fix(apu): disable channel if DAC is disabled 2021-08-17 20:42:41 -05:00
4 changed files with 217 additions and 114 deletions

View File

@ -5,6 +5,7 @@ use types::ch1::{Sweep, SweepDirection};
use types::ch3::Volume as Ch3Volume; use types::ch3::Volume as Ch3Volume;
use types::ch4::{CounterWidth, Frequency as Ch4Frequency, PolynomialCounter}; use types::ch4::{CounterWidth, Frequency as Ch4Frequency, PolynomialCounter};
use types::common::{EnvelopeDirection, FrequencyHigh, SoundDuty, VolumeEnvelope}; use types::common::{EnvelopeDirection, FrequencyHigh, SoundDuty, VolumeEnvelope};
use types::fs::{FrameSequencer, State as FrameSequencerState};
use types::{ChannelControl, SoundOutput}; use types::{ChannelControl, SoundOutput};
pub mod gen; pub mod gen;
@ -25,7 +26,7 @@ pub struct Apu {
/// Noise /// Noise
ch4: Channel4, ch4: Channel4,
// Frame Sequencer sequencer: FrameSequencer,
div_prev: Option<u16>, div_prev: Option<u16>,
prod: Option<SampleProducer<f32>>, prod: Option<SampleProducer<f32>>,
@ -42,7 +43,7 @@ impl BusIo for Apu {
0x16 => self.ch2.duty(), 0x16 => self.ch2.duty(),
0x17 => self.ch2.envelope(), 0x17 => self.ch2.envelope(),
0x19 => self.ch2.freq_hi(), 0x19 => self.ch2.freq_hi(),
0x1A => self.ch3.enabled(), 0x1A => self.ch3.dac_enabled(),
0x1C => self.ch3.volume(), 0x1C => self.ch3.volume(),
0x1E => self.ch3.freq_hi(), 0x1E => self.ch3.freq_hi(),
0x21 => self.ch4.envelope(), 0x21 => self.ch4.envelope(),
@ -70,7 +71,7 @@ impl BusIo for Apu {
0x17 if self.ctrl.enabled => self.ch2.set_envelope(byte), 0x17 if self.ctrl.enabled => self.ch2.set_envelope(byte),
0x18 if self.ctrl.enabled => self.ch2.set_freq_lo(byte), 0x18 if self.ctrl.enabled => self.ch2.set_freq_lo(byte),
0x19 if self.ctrl.enabled => self.ch2.set_freq_hi(byte), 0x19 if self.ctrl.enabled => self.ch2.set_freq_hi(byte),
0x1A if self.ctrl.enabled => self.ch3.set_enabled(byte), 0x1A if self.ctrl.enabled => self.ch3.set_dac_enabled(byte),
0x1B if self.ctrl.enabled => self.ch3.set_len(byte), 0x1B if self.ctrl.enabled => self.ch3.set_len(byte),
0x1C if self.ctrl.enabled => self.ch3.set_volume(byte), 0x1C if self.ctrl.enabled => self.ch3.set_volume(byte),
0x1D if self.ctrl.enabled => self.ch3.set_freq_lo(byte), 0x1D if self.ctrl.enabled => self.ch3.set_freq_lo(byte),
@ -96,33 +97,35 @@ impl Apu {
pub(crate) fn tick(&mut self, div: u16) { pub(crate) fn tick(&mut self, div: u16) {
self.sample_counter += SAMPLE_INCREMENT; self.sample_counter += SAMPLE_INCREMENT;
// Length Control (256Hz) // Frame Sequencer (512Hz)
if self.falling_edge(13, div) { if self.is_falling_edge(12, div) {
self.handle_length(); use FrameSequencerState::*;
match self.sequencer.state() {
Length => self.clock_length(),
LengthAndSweep => {
self.clock_length();
self.clock_sweep();
}
Envelope => self.clock_envelope(),
Nothing => {}
} }
// Sweep (128Hz) self.sequencer.next();
if self.falling_edge(14, div) {
self.handle_sweep();
}
// Volume Envelope (64Hz)
if self.falling_edge(15, div) {
self.handle_volume();
} }
self.div_prev = Some(div); self.div_prev = Some(div);
self.ch1.clock(); self.ch1.tick();
self.ch2.clock(); self.ch2.tick();
self.ch3.clock(); self.ch3.tick();
self.ch4.clock(); self.ch4.tick();
if self.sample_counter >= SM83_CLOCK_SPEED { if self.sample_counter >= SM83_CLOCK_SPEED {
self.sample_counter %= SM83_CLOCK_SPEED; self.sample_counter %= SM83_CLOCK_SPEED;
if let Some(ref mut prod) = self.prod { if let Some(ref mut prod) = self.prod {
if prod.available_block() { if prod.available_blocking() {
// Sample the APU // Sample the APU
let ch1_amplitude = self.ch1.amplitude(); let ch1_amplitude = self.ch1.amplitude();
let ch1_left = self.ctrl.output.ch1_left() as u8 as f32 * ch1_amplitude; let ch1_left = self.ctrl.output.ch1_left() as u8 as f32 * ch1_amplitude;
@ -154,23 +157,20 @@ impl Apu {
} }
} }
pub fn set_producer(&mut self, prod: SampleProducer<f32>) {
self.prod = Some(prod);
}
/// 0xFF26 | NR52 - Sound On/Off /// 0xFF26 | NR52 - Sound On/Off
pub(crate) fn set_status(&mut self, byte: u8) { pub(crate) fn set_status(&mut self, byte: u8) {
self.ctrl.enabled = (byte >> 7) & 0x01 == 0x01; self.ctrl.enabled = (byte >> 7) & 0x01 == 0x01;
if self.ctrl.enabled { if self.ctrl.enabled {
// Frame Sequencer reset to Step 0 // Frame Sequencer reset to Step 0
// TODO: With the current implementation of the frame sequencer, what does this even mean? self.sequencer.reset();
// Square Duty units are reset to first step // Square Duty units are reset to first step
self.ch1.duty_pos = 0; self.ch1.duty_pos = 0;
self.ch2.duty_pos = 0; self.ch2.duty_pos = 0;
// Wave Channel's sample buffer reset to 0 // Wave Channel's sample buffer reset to 0
self.ch3.offset = 0;
} }
if !self.ctrl.enabled { if !self.ctrl.enabled {
@ -179,6 +179,10 @@ impl Apu {
} }
} }
pub fn attach_producer(&mut self, prod: SampleProducer<f32>) {
self.prod = Some(prod);
}
fn reset(&mut self) { fn reset(&mut self) {
self.ch1.sweep = Default::default(); self.ch1.sweep = Default::default();
self.ch1.duty = Default::default(); self.ch1.duty = Default::default();
@ -191,7 +195,7 @@ impl Apu {
self.ch2.freq_lo = Default::default(); self.ch2.freq_lo = Default::default();
self.ch2.freq_hi = Default::default(); self.ch2.freq_hi = Default::default();
self.ch3.enabled = Default::default(); self.ch3.dac_enabled = Default::default();
self.ch3.len = Default::default(); self.ch3.len = Default::default();
self.ch3.volume = Default::default(); self.ch3.volume = Default::default();
self.ch3.freq_lo = Default::default(); self.ch3.freq_lo = Default::default();
@ -205,13 +209,14 @@ impl Apu {
self.ctrl.channel = Default::default(); self.ctrl.channel = Default::default();
self.ctrl.output = Default::default(); self.ctrl.output = Default::default();
// Disable the rest of the channels // Disable the Channels
self.ch1.enabled = Default::default(); self.ch1.enabled = Default::default();
self.ch2.enabled = Default::default(); self.ch2.enabled = Default::default();
self.ch3.enabled = Default::default();
self.ch4.enabled = Default::default(); self.ch4.enabled = Default::default();
} }
fn clock_length(freq_hi: &FrequencyHigh, length_timer: &mut u16, enabled: &mut bool) { fn process_length(freq_hi: &FrequencyHigh, length_timer: &mut u16, enabled: &mut bool) {
if freq_hi.length_disable() && *length_timer > 0 { if freq_hi.length_disable() && *length_timer > 0 {
*length_timer -= 1; *length_timer -= 1;
@ -223,7 +228,7 @@ impl Apu {
} }
} }
fn clock_length_ch4(freq: &Ch4Frequency, length_timer: &mut u16, enabled: &mut bool) { fn ch4_process_length(freq: &Ch4Frequency, length_timer: &mut u16, enabled: &mut bool) {
if freq.length_disable() && *length_timer > 0 { if freq.length_disable() && *length_timer > 0 {
*length_timer -= 1; *length_timer -= 1;
@ -235,33 +240,33 @@ impl Apu {
} }
} }
fn handle_length(&mut self) { fn clock_length(&mut self) {
Self::clock_length( Self::process_length(
&self.ch1.freq_hi, &self.ch1.freq_hi,
&mut self.ch1.length_timer, &mut self.ch1.length_timer,
&mut self.ch1.enabled, &mut self.ch1.enabled,
); );
Self::clock_length( Self::process_length(
&self.ch2.freq_hi, &self.ch2.freq_hi,
&mut self.ch2.length_timer, &mut self.ch2.length_timer,
&mut self.ch2.enabled, &mut self.ch2.enabled,
); );
Self::clock_length( Self::process_length(
&self.ch3.freq_hi, &self.ch3.freq_hi,
&mut self.ch3.length_timer, &mut self.ch3.length_timer,
&mut self.ch3.enabled, &mut self.ch3.enabled,
); );
Self::clock_length_ch4( Self::ch4_process_length(
&self.ch4.freq, &self.ch4.freq,
&mut self.ch4.length_timer, &mut self.ch4.length_timer,
&mut self.ch4.enabled, &mut self.ch4.enabled,
); );
} }
fn handle_sweep(&mut self) { fn clock_sweep(&mut self) {
if self.ch1.sweep_timer != 0 { if self.ch1.sweep_timer != 0 {
self.ch1.sweep_timer -= 1; self.ch1.sweep_timer -= 1;
} }
@ -283,7 +288,7 @@ impl Apu {
} }
} }
fn clock_envelope(envelope: &VolumeEnvelope, period_timer: &mut u8, current_volume: &mut u8) { fn process_envelope(envelope: &VolumeEnvelope, period_timer: &mut u8, current_volume: &mut u8) {
use EnvelopeDirection::*; use EnvelopeDirection::*;
if envelope.period() != 0 { if envelope.period() != 0 {
@ -303,29 +308,29 @@ impl Apu {
} }
} }
fn handle_volume(&mut self) { fn clock_envelope(&mut self) {
// Channels 1, 2 and 4 have Volume Envelopes // Channels 1, 2 and 4 have Volume Envelopes
Self::clock_envelope( Self::process_envelope(
&self.ch1.envelope, &self.ch1.envelope,
&mut self.ch1.period_timer, &mut self.ch1.period_timer,
&mut self.ch1.current_volume, &mut self.ch1.current_volume,
); );
Self::clock_envelope( Self::process_envelope(
&self.ch2.envelope, &self.ch2.envelope,
&mut self.ch2.period_timer, &mut self.ch2.period_timer,
&mut self.ch2.current_volume, &mut self.ch2.current_volume,
); );
Self::clock_envelope( Self::process_envelope(
&self.ch4.envelope, &self.ch4.envelope,
&mut self.ch4.period_timer, &mut self.ch4.period_timer,
&mut self.ch4.current_volume, &mut self.ch4.current_volume,
); );
} }
fn falling_edge(&self, bit: u8, div: u16) -> bool { fn is_falling_edge(&self, bit: u8, div: u16) -> bool {
match self.div_prev { match self.div_prev {
Some(p) => (p >> bit & 0x01) == 0x01 && (div >> bit & 0x01) == 0x00, Some(p) => (p >> bit & 0x01) == 0x01 && (div >> bit & 0x01) == 0x00,
None => false, None => false,
@ -411,23 +416,6 @@ pub(crate) struct Channel1 {
} }
impl Channel1 { impl Channel1 {
fn amplitude(&self) -> f32 {
let dac_input = self.duty.wave_pattern().amplitude(self.duty_pos) * self.current_volume;
(dac_input as f32 / 7.5) - 1.0
}
fn clock(&mut self) {
if self.freq_timer != 0 {
self.freq_timer -= 1;
}
if self.freq_timer == 0 {
self.freq_timer = (2048 - self.frequency()) * 4;
self.duty_pos = (self.duty_pos + 1) % 8;
}
}
/// 0xFF10 | NR10 - Channel 1 Sweep Register /// 0xFF10 | NR10 - Channel 1 Sweep Register
pub(crate) fn sweep(&self) -> u8 { pub(crate) fn sweep(&self) -> u8 {
u8::from(self.sweep) | 0x80 u8::from(self.sweep) | 0x80
@ -456,7 +444,11 @@ impl Channel1 {
/// 0xFF12 | NR12 - Channel 1 Volume Envelope /// 0xFF12 | NR12 - Channel 1 Volume Envelope
pub(crate) fn set_envelope(&mut self, byte: u8) { pub(crate) fn set_envelope(&mut self, byte: u8) {
self.envelope = byte.into() self.envelope = byte.into();
if !self.is_dac_enabled() {
self.enabled = false;
}
} }
/// 0xFF13 | NR13 - Channel 1 Frequency low (lower 8 bits only) /// 0xFF13 | NR13 - Channel 1 Frequency low (lower 8 bits only)
@ -498,9 +490,31 @@ impl Channel1 {
self.length_timer = 64; self.length_timer = 64;
} }
if self.is_dac_enabled() {
self.enabled = true; self.enabled = true;
} }
} }
}
fn tick(&mut self) {
if self.freq_timer != 0 {
self.freq_timer -= 1;
}
if self.freq_timer == 0 {
self.freq_timer = (2048 - self.frequency()) * 4;
self.duty_pos = (self.duty_pos + 1) % 8;
}
}
fn amplitude(&self) -> f32 {
if self.is_dac_enabled() && self.enabled {
let input = self.duty.wave_pattern().amplitude(self.duty_pos) * self.current_volume;
(input as f32 / 7.5) - 1.0
} else {
0.0
}
}
fn calc_sweep_freq(&mut self) -> u16 { fn calc_sweep_freq(&mut self) -> u16 {
use SweepDirection::*; use SweepDirection::*;
@ -529,6 +543,10 @@ impl Channel1 {
fn frequency(&self) -> u16 { fn frequency(&self) -> u16 {
(self.freq_hi.freq_bits() as u16) << 8 | self.freq_lo as u16 (self.freq_hi.freq_bits() as u16) << 8 | self.freq_lo as u16
} }
fn is_dac_enabled(&self) -> bool {
self.envelope.0 & 0xF8 != 0x00
}
} }
#[derive(Debug, Default)] #[derive(Debug, Default)]
@ -556,23 +574,6 @@ pub(crate) struct Channel2 {
} }
impl Channel2 { impl Channel2 {
fn amplitude(&self) -> f32 {
let dac_input = self.duty.wave_pattern().amplitude(self.duty_pos) * self.current_volume;
(dac_input as f32 / 7.5) - 1.0
}
fn clock(&mut self) {
if self.freq_timer != 0 {
self.freq_timer -= 1;
}
if self.freq_timer == 0 {
self.freq_timer = (2048 - self.frequency()) * 4;
self.duty_pos = (self.duty_pos + 1) % 8;
}
}
/// 0xFF16 | NR21 - Channel 2 Sound length / Wave Pattern Duty /// 0xFF16 | NR21 - Channel 2 Sound length / Wave Pattern Duty
pub(crate) fn duty(&self) -> u8 { pub(crate) fn duty(&self) -> u8 {
u8::from(self.duty) | 0x3F u8::from(self.duty) | 0x3F
@ -591,7 +592,11 @@ impl Channel2 {
/// 0xFF17 | NR22 - Channel 2 Volume ENvelope /// 0xFF17 | NR22 - Channel 2 Volume ENvelope
pub(crate) fn set_envelope(&mut self, byte: u8) { pub(crate) fn set_envelope(&mut self, byte: u8) {
self.envelope = byte.into() self.envelope = byte.into();
if !self.is_dac_enabled() {
self.enabled = false;
}
} }
/// 0xFF18 | NR23 - Channel 2 Frequency low (lower 8 bits only) /// 0xFF18 | NR23 - Channel 2 Frequency low (lower 8 bits only)
@ -618,19 +623,45 @@ impl Channel2 {
self.length_timer = 64; self.length_timer = 64;
} }
if self.is_dac_enabled() {
self.enabled = true; self.enabled = true;
} }
} }
}
fn amplitude(&self) -> f32 {
if self.is_dac_enabled() && self.enabled {
let input = self.duty.wave_pattern().amplitude(self.duty_pos) * self.current_volume;
(input as f32 / 7.5) - 1.0
} else {
0.0
}
}
fn tick(&mut self) {
if self.freq_timer != 0 {
self.freq_timer -= 1;
}
if self.freq_timer == 0 {
self.freq_timer = (2048 - self.frequency()) * 4;
self.duty_pos = (self.duty_pos + 1) % 8;
}
}
fn frequency(&self) -> u16 { fn frequency(&self) -> u16 {
(self.freq_hi.freq_bits() as u16) << 8 | self.freq_lo as u16 (self.freq_hi.freq_bits() as u16) << 8 | self.freq_lo as u16
} }
fn is_dac_enabled(&self) -> bool {
self.envelope.0 & 0xF8 != 0x00
}
} }
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub(crate) struct Channel3 { pub(crate) struct Channel3 {
/// 0xFF1A | NR30 - Channel 3 Sound on/off /// 0xFF1A | NR30 - Channel 3 Sound on/off
enabled: bool, dac_enabled: bool,
/// 0xFF1B | NR31 - Sound Length /// 0xFF1B | NR31 - Sound Length
len: u8, len: u8,
/// 0xFF1C | NR32 - Channel 3 Volume /// 0xFF1C | NR32 - Channel 3 Volume
@ -647,6 +678,8 @@ pub(crate) struct Channel3 {
freq_timer: u16, freq_timer: u16,
offset: u8, offset: u8,
enabled: bool,
} }
impl BusIo for Channel3 { impl BusIo for Channel3 {
@ -671,13 +704,17 @@ impl Channel3 {
const WAVE_RAM_START_ADDR: u16 = 0xFF30; const WAVE_RAM_START_ADDR: u16 = 0xFF30;
/// 0xFF1A | NR30 - Channel 3 Sound on/off /// 0xFF1A | NR30 - Channel 3 Sound on/off
pub(crate) fn enabled(&self) -> u8 { pub(crate) fn dac_enabled(&self) -> u8 {
((self.enabled as u8) << 7) | 0x7F ((self.dac_enabled as u8) << 7) | 0x7F
} }
/// 0xFF1A | NR30 - Channel 3 Sound on/off /// 0xFF1A | NR30 - Channel 3 Sound on/off
pub(crate) fn set_enabled(&mut self, byte: u8) { pub(crate) fn set_dac_enabled(&mut self, byte: u8) {
self.enabled = (byte >> 7) & 0x01 == 0x01; self.dac_enabled = (byte >> 7) & 0x01 == 0x01;
if !self.dac_enabled {
self.enabled = false;
}
} }
/// 0xFF1B | NR31 - Sound Length /// 0xFF1B | NR31 - Sound Length
@ -724,18 +761,13 @@ impl Channel3 {
self.length_timer = 256; self.length_timer = 256;
} }
if self.dac_enabled {
self.enabled = true; self.enabled = true;
} }
} }
fn amplitude(&self) -> f32 {
let dac_input =
(self.read_sample(self.offset) >> self.volume.shift_count()) * self.enabled as u8;
(dac_input as f32 / 7.5) - 1.0
} }
fn clock(&mut self) { fn tick(&mut self) {
if self.freq_timer != 0 { if self.freq_timer != 0 {
self.freq_timer -= 1; self.freq_timer -= 1;
} }
@ -746,6 +778,15 @@ impl Channel3 {
} }
} }
fn amplitude(&self) -> f32 {
if self.dac_enabled && self.enabled {
let input = self.read_sample(self.offset) >> self.volume.shift_count();
(input as f32 / 7.5) - 1.0
} else {
0.0
}
}
fn read_sample(&self, index: u8) -> u8 { fn read_sample(&self, index: u8) -> u8 {
let i = (index / 2) as usize; let i = (index / 2) as usize;
@ -803,7 +844,11 @@ impl Channel4 {
/// 0xFF21 | NR42 - Channel 4 Volume Envelope /// 0xFF21 | NR42 - Channel 4 Volume Envelope
pub(crate) fn set_envelope(&mut self, byte: u8) { pub(crate) fn set_envelope(&mut self, byte: u8) {
self.envelope = byte.into() self.envelope = byte.into();
if !self.is_dac_enabled() {
self.enabled = false;
}
} }
/// 0xFF22 | NR43 - Chanel 4 Polynomial Counter /// 0xFF22 | NR43 - Chanel 4 Polynomial Counter
@ -838,17 +883,13 @@ impl Channel4 {
// LFSR behaviour during trigger event // LFSR behaviour during trigger event
self.lf_shift = 0x7FFF; self.lf_shift = 0x7FFF;
if self.is_dac_enabled() {
self.enabled = true; self.enabled = true;
} }
} }
fn amplitude(&self) -> f32 {
let dac_input = (!self.lf_shift & 0x01) as u8 * self.current_volume;
(dac_input as f32 / 7.5) - 1.0
} }
fn clock(&mut self) { fn tick(&mut self) {
if self.freq_timer != 0 { if self.freq_timer != 0 {
self.freq_timer -= 1; self.freq_timer -= 1;
} }
@ -866,6 +907,19 @@ impl Channel4 {
} }
} }
fn amplitude(&self) -> f32 {
if self.is_dac_enabled() && self.enabled {
let input = (!self.lf_shift & 0x01) as u8 * self.current_volume;
(input as f32 / 7.5) - 1.0
} else {
0.0
}
}
fn is_dac_enabled(&self) -> bool {
self.envelope.0 & 0xF8 != 0x00
}
fn divisor(code: u8) -> u8 { fn divisor(code: u8) -> u8 {
if code == 0 { if code == 0 {
return 8; return 8;

View File

@ -48,7 +48,7 @@ impl<T> SampleProducer<T> {
self.inner.slots() > 2 self.inner.slots() > 2
} }
pub(crate) fn available_block(&self) -> bool { pub(crate) fn available_blocking(&self) -> bool {
loop { loop {
if self.inner.slots() > 2 { if self.inner.slots() > 2 {
break true; break true;

View File

@ -73,7 +73,7 @@ pub(crate) mod ch1 {
} }
} }
pub(crate) mod ch3 { pub(super) mod ch3 {
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub(crate) enum Volume { pub(crate) enum Volume {
Mute = 0, Mute = 0,
@ -102,7 +102,7 @@ pub(crate) mod ch3 {
} }
} }
pub(crate) mod ch4 { pub(super) mod ch4 {
use super::bitfield; use super::bitfield;
bitfield! { bitfield! {
@ -217,7 +217,7 @@ pub(crate) mod ch4 {
} }
} }
pub(crate) mod common { pub(super) mod common {
use super::bitfield; use super::bitfield;
bitfield! { bitfield! {
@ -508,3 +508,52 @@ impl From<ChannelControl> for u8 {
ctrl.0 ctrl.0
} }
} }
pub(super) mod fs {
#[derive(Debug)]
pub(crate) struct FrameSequencer {
step: u8,
state: State,
}
impl Default for FrameSequencer {
fn default() -> Self {
Self {
step: Default::default(),
state: State::Length,
}
}
}
impl FrameSequencer {
pub(crate) fn next(&mut self) {
use State::*;
self.step = (self.step + 1) % 8;
self.state = match self.step {
1 | 3 | 5 => Nothing,
0 | 4 => Length,
2 | 6 => LengthAndSweep,
7 => Envelope,
_ => unreachable!("Step {} is invalid for the Frame Sequencer", self.step),
};
}
pub(crate) fn state(&self) -> State {
self.state
}
pub(crate) fn reset(&mut self) {
self.step = Default::default();
self.state = State::Length;
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) enum State {
Length,
Nothing,
LengthAndSweep,
Envelope,
}
}

View File

@ -63,16 +63,16 @@ fn main() -> Result<()> {
}; };
// Initialize Audio // Initialize Audio
// let spsc: AudioSPSC<f32> = Default::default(); let spsc: AudioSPSC<f32> = Default::default();
// let (prod, cons) = spsc.init(); let (prod, cons) = spsc.init();
// let (_stream, stream_handle) = OutputStream::try_default().expect("Initialized Audio"); let (_stream, stream_handle) = OutputStream::try_default().expect("Initialized Audio");
// let sink = Sink::try_new(&stream_handle)?; let sink = Sink::try_new(&stream_handle)?;
// sink.append(cons); sink.append(cons);
// game_boy.apu_mut().set_producer(prod); game_boy.apu_mut().attach_producer(prod);
// std::thread::spawn(move || { std::thread::spawn(move || {
// sink.sleep_until_end(); sink.sleep_until_end();
// }); });
let mut start = Instant::now(); let mut start = Instant::now();
let frame_time = Duration::from_secs_f64(1.0 / 59.73); // 59.73 Hz on Host let frame_time = Duration::from_secs_f64(1.0 / 59.73); // 59.73 Hz on Host