noise channel works!

This commit is contained in:
Alex Janka 2023-02-20 15:35:20 +11:00
parent 9f9cd006c0
commit 6676276706
3 changed files with 90 additions and 4 deletions

View file

@ -19,10 +19,12 @@ impl DacSample {
fn mixed(&self, mixer: &Mixer) -> Vec<f32> {
let left = (self.one * mixer.ch1.left.scale())
+ (self.two * mixer.ch2.left.scale())
+ (self.three * mixer.ch3.left.scale());
+ (self.three * mixer.ch3.left.scale())
+ (self.four * mixer.ch4.left.scale());
let right = (self.one * mixer.ch1.right.scale())
+ (self.two * mixer.ch2.right.scale())
+ (self.three * mixer.ch3.right.scale());
+ (self.three * mixer.ch3.right.scale())
+ (self.four * mixer.ch4.right.scale());
vec![
self.mix_channel(left, mixer.vol_left),
self.mix_channel(right, mixer.vol_right),
@ -133,6 +135,7 @@ impl Apu {
// envelope sweep
self.channels.one.envelope_tick();
self.channels.two.envelope_tick();
self.channels.four.envelope_tick();
}
if self.div_apu % 4 == 0 {
// ch1 frequency sweep
@ -143,6 +146,7 @@ impl Apu {
self.channels.one.length_tick();
self.channels.two.length_tick();
self.channels.three.length_tick();
self.channels.four.length_tick();
}
}
@ -151,9 +155,15 @@ impl Apu {
&mut izip!(
self.channels.one.tick(steps).into_iter(),
self.channels.two.tick(steps).into_iter(),
self.channels.three.tick(steps).into_iter()
self.channels.three.tick(steps).into_iter(),
self.channels.four.tick(steps).into_iter()
)
.map(|(one, two, three)| DacSample { one, two, three })
.map(|(one, two, three, four)| DacSample {
one,
two,
three,
four,
})
.collect(),
);
if self.buffer.len() >= CYCLES_PER_FRAME {

View file

@ -451,6 +451,43 @@ struct Lfsr {
clock_shift: u8,
width: LfsrWidth,
clock_divider: u8,
interval: u16,
timer: u16,
current_value: u8,
register: u16,
}
impl Lfsr {
fn update(&mut self) {
self.interval =
(1 << (self.clock_shift as u16)) * (1 + (2 * self.clock_divider as u16)) * 8;
}
fn tick(&mut self) {
self.timer += 1;
if self.timer > self.interval {
self.timer = 0;
self.next_value();
}
}
fn next_value(&mut self) {
let next = if (self.register & 0b1) == ((self.register >> 1) & 0b1) {
1
} else {
0
};
self.register = (self.register & !(0b1 << 15)) | (next << 15);
if self.width == LfsrWidth::SevenBit {
self.register = (self.register & !(0b1 << 7)) | (next << 7);
}
self.register >>= 1;
self.current_value = if (self.register & 0b1) == 0b1 {
0x1
} else {
0x0
};
}
}
impl Default for Lfsr {
@ -459,6 +496,10 @@ impl Default for Lfsr {
clock_shift: Default::default(),
width: LfsrWidth::FifteenBit,
clock_divider: Default::default(),
interval: 0,
timer: 0,
current_value: 0,
register: 0,
}
}
}
@ -489,6 +530,38 @@ impl NoiseChannel {
self.envelope = self.queued_envelope;
}
pub fn tick(&mut self, steps: usize) -> Vec<f32> {
if self.enabled {
(0..steps)
.map(|_| {
self.lfsr.tick();
self.dac(self.lfsr.current_value)
})
.collect()
} else {
vec![0.; steps]
}
}
fn dac(&self, digital: u8) -> f32 {
(((digital as f32) * (-2.)) + 1.) * ((self.envelope.current_volume as f32) / 15.)
}
pub(super) fn envelope_tick(&mut self) {
if self.enabled {
self.envelope.tick();
}
}
pub(super) fn length_tick(&mut self) {
if self.length_enable && self.enabled {
self.length_timer += 1;
if self.length_timer >= 64 {
self.enabled = false;
}
}
}
pub(super) fn update_length_timer(&mut self, data: u8) {
self.length_timer = data & 0b111111;
}
@ -522,6 +595,7 @@ impl NoiseChannel {
LfsrWidth::FifteenBit
};
self.lfsr.clock_divider = data & 0b111;
self.lfsr.update();
}
pub(super) fn get_frequency_and_randomness(&self) -> u8 {

View file

@ -94,6 +94,7 @@ pub(super) struct DacSample {
pub(super) one: f32,
pub(super) two: f32,
pub(super) three: f32,
pub(super) four: f32,
}
impl Default for DacSample {
@ -102,6 +103,7 @@ impl Default for DacSample {
one: 0.,
two: 0.,
three: 0.,
four: 0.,
}
}
}