feat(snd): implement channel 4
This commit is contained in:
parent
3dbf026d33
commit
d145ae44f3
51
src/sound.rs
51
src/sound.rs
|
@ -62,6 +62,7 @@ impl Sound {
|
||||||
|
|
||||||
self.ch1.clock();
|
self.ch1.clock();
|
||||||
self.ch2.clock();
|
self.ch2.clock();
|
||||||
|
self.ch4.clock();
|
||||||
|
|
||||||
self.div_prev = Some(bit_5);
|
self.div_prev = Some(bit_5);
|
||||||
|
|
||||||
|
@ -77,8 +78,12 @@ impl Sound {
|
||||||
let ch2_left = self.ctrl.output.ch2_left() as u8 as f32 * 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 ch2_right = self.ctrl.output.ch2_right() as u8 as f32 * ch2_amplitude;
|
||||||
|
|
||||||
let left_sample = (ch1_left + ch2_left) / 2.0;
|
let ch4_amplitude = self.ch4.amplitude();
|
||||||
let right_sample = (ch1_right + ch2_right) / 2.0;
|
let ch4_left = self.ctrl.output.ch4_left() as u8 as f32 * ch4_amplitude;
|
||||||
|
let ch4_right = self.ctrl.output.ch4_right() as u8 as f32 * ch4_amplitude;
|
||||||
|
|
||||||
|
let left_sample = (ch1_left + ch2_left + ch4_left) / 3.0;
|
||||||
|
let right_sample = (ch1_right + ch2_right + ch4_right) / 3.0;
|
||||||
|
|
||||||
if let Some(send) = self.sender.as_ref() {
|
if let Some(send) = self.sender.as_ref() {
|
||||||
send.add_sample(left_sample, right_sample);
|
send.add_sample(left_sample, right_sample);
|
||||||
|
@ -878,7 +883,9 @@ pub(crate) struct Channel4 {
|
||||||
length_timer: u16,
|
length_timer: u16,
|
||||||
|
|
||||||
/// Linear Feedback Shift Register (15-bit)
|
/// Linear Feedback Shift Register (15-bit)
|
||||||
shift_register: u16,
|
lf_shift: u16,
|
||||||
|
|
||||||
|
freq_timer: u16,
|
||||||
|
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
}
|
}
|
||||||
|
@ -915,17 +922,49 @@ impl Channel4 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// LFSR behaviour during trigger event
|
// LFSR behaviour during trigger event
|
||||||
self.shift_register = 0x7FFF;
|
self.lf_shift = 0x7FFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
if self.freq_timer != 0 {
|
||||||
|
self.freq_timer -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.freq_timer == 0 {
|
||||||
|
let divisor = Self::divisor(self.poly.divisor_code()) as u16;
|
||||||
|
self.freq_timer = divisor << self.poly.shift_count();
|
||||||
|
|
||||||
|
let xor_result = (self.lf_shift & 0x01) ^ ((self.lf_shift & 0x02) >> 1);
|
||||||
|
self.lf_shift = (self.lf_shift >> 1) | xor_result << 14;
|
||||||
|
|
||||||
|
if let CounterWidth::Long = self.poly.counter_width() {
|
||||||
|
self.lf_shift = (self.lf_shift & !(0x01 << 6)) | xor_result << 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn divisor(code: u8) -> u8 {
|
||||||
|
if code == 0 {
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
code << 4
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bitfield! {
|
bitfield! {
|
||||||
pub struct PolynomialCounter(u8);
|
pub struct PolynomialCounter(u8);
|
||||||
impl Debug;
|
impl Debug;
|
||||||
freq, set_freq: 7, 4;
|
shift_count, set_shift_count: 7, 4;
|
||||||
from into CounterWidth, counter_width, set_counter_width: 3, 3;
|
from into CounterWidth, counter_width, set_counter_width: 3, 3;
|
||||||
div_ratio, set_div_ratio: 2, 0;
|
divisor_code, set_divisor_code: 2, 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Copy for PolynomialCounter {}
|
impl Copy for PolynomialCounter {}
|
||||||
|
|
Loading…
Reference in New Issue