feat(snd): implement ch1 & envelopes for ch1 and ch2

This commit is contained in:
Rekai Nyangadzayi Musuka 2021-07-10 18:56:54 -05:00
parent 3c28dd7a6b
commit 7ab6e120f9
1 changed files with 57 additions and 20 deletions

View File

@ -59,6 +59,7 @@ impl Sound {
} }
} }
self.ch1.clock();
self.ch2.clock(); self.ch2.clock();
self.div_prev = Some(bit_5); self.div_prev = Some(bit_5);
@ -68,12 +69,19 @@ impl Sound {
// Sample the APU // Sample the APU
self.cycle %= SAMPLE_RATE_IN_CYCLES; self.cycle %= SAMPLE_RATE_IN_CYCLES;
let left_sample = self.ch2.amplitude(); let ch1_amplitude = self.ch1.amplitude();
let right_sample = left_sample; let ch1_left = self.ctrl.output.ch1_left() as u8 as f32 * ch1_amplitude;
let ch1_right = self.ctrl.output.ch1_right() as u8 as f32 * ch1_amplitude;
let ch2_amplitude = self.ch2.amplitude();
let ch2_left = self.ctrl.output.ch2_left() as u8 as f32 * ch2_amplitude;
let ch2_right = self.ctrl.output.ch2_right() as u8 as f32 * ch2_amplitude;
let left_sample = (ch1_left + ch2_left) / 2.0;
let right_sample = (ch1_right + ch2_right) / 2.0;
if let Some(send) = self.sender.as_ref() { if let Some(send) = self.sender.as_ref() {
send.add_sample(left_sample); send.add_sample(left_sample, right_sample);
send.add_sample(right_sample);
} }
} }
} }
@ -360,10 +368,31 @@ pub(crate) struct Channel1 {
// Length Functionality // Length Functionality
length_timer: u16, length_timer: u16,
freq_timer: u16,
duty_pos: u8,
enabled: bool, enabled: bool,
} }
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 {
// TODO: Why is this 2048?
self.freq_timer = (2048 - self.frequency()) * 4;
self.duty_pos = (self.duty_pos + 1) % 8;
}
}
/// 0xFF11 | NR11 - Channel 1 Sound length / Wave pattern duty /// 0xFF11 | NR11 - Channel 1 Sound length / Wave pattern duty
pub(crate) fn duty(&self) -> u8 { pub(crate) fn duty(&self) -> u8 {
u8::from(self.duty) & 0xC0 // Only bits 7 and 6 can be read u8::from(self.duty) & 0xC0 // Only bits 7 and 6 can be read
@ -527,12 +556,16 @@ pub(crate) struct Channel2 {
} }
impl Channel2 { impl Channel2 {
fn amplitude(&self) -> u8 { fn amplitude(&self) -> f32 {
self.duty.wave_pattern().amplitude(self.duty_pos) 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) { fn clock(&mut self) {
if self.freq_timer != 0 {
self.freq_timer -= 1; self.freq_timer -= 1;
}
if self.freq_timer == 0 { if self.freq_timer == 0 {
// TODO: Why is this 2048? // TODO: Why is this 2048?
@ -977,14 +1010,14 @@ impl From<Channel4Frequency> for u8 {
bitfield! { bitfield! {
pub struct SoundOutput(u8); pub struct SoundOutput(u8);
impl Debug; impl Debug;
pub snd4_so2, set_snd4_so2: 7; pub ch4_left, set_ch4_left: 7;
pub snd3_so2, set_snd3_so2: 6; pub ch3_left, set_ch3_left: 6;
pub snd2_so2, set_snd2_so2: 5; pub ch2_left, set_ch2_left: 5;
pub snd1_so2, set_snd1_so2: 4; pub ch1_left, set_ch1_left: 4;
pub snd4_so1, set_snd4_so1: 3; pub ch4_right, set_ch4_right: 3;
pub snd3_so1, set_snd3_so1: 2; pub ch3_right, set_ch3_right: 2;
pub snd2_so1, set_snd2_so1: 1; pub ch2_right, set_ch2_right: 1;
pub snd1_so1, set_snd1_so1: 0; pub ch1_right, set_ch1_right: 0;
} }
impl Copy for SoundOutput {} impl Copy for SoundOutput {}
@ -1058,19 +1091,23 @@ impl AudioSenderReceiver {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct SampleSender { pub struct SampleSender {
send: Sender<u8>, send: Sender<f32>,
} }
impl SampleSender { impl SampleSender {
fn add_sample(&self, sample: u8) { fn add_sample(&self, left: f32, right: f32) {
self.send self.send
.send(sample) .send(left)
.expect("Send audio sample across threads");
self.send
.send(right)
.expect("Send audio sample across threads"); .expect("Send audio sample across threads");
} }
} }
pub struct SampleReceiver { pub struct SampleReceiver {
recv: Receiver<u8>, recv: Receiver<f32>,
} }
impl Iterator for SampleReceiver { impl Iterator for SampleReceiver {
@ -1078,7 +1115,7 @@ impl Iterator for SampleReceiver {
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
// TODO: Should this never return none? // TODO: Should this never return none?
self.recv.recv().ok().map(|num| num as f32) self.recv.recv().ok()
} }
} }