feat(snd): implement ch1 & envelopes for ch1 and ch2
This commit is contained in:
parent
3c28dd7a6b
commit
7ab6e120f9
77
src/sound.rs
77
src/sound.rs
|
@ -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) {
|
||||||
self.freq_timer -= 1;
|
if self.freq_timer != 0 {
|
||||||
|
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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue