summaryrefslogtreecommitdiff
path: root/audio/src/channel.rs
diff options
context:
space:
mode:
Diffstat (limited to 'audio/src/channel.rs')
-rw-r--r--audio/src/channel.rs46
1 files changed, 28 insertions, 18 deletions
diff --git a/audio/src/channel.rs b/audio/src/channel.rs
index b74792e..2b4be02 100644
--- a/audio/src/channel.rs
+++ b/audio/src/channel.rs
@@ -44,7 +44,21 @@ impl ChannelKind {
Self::Noise { mode: false }
}
- fn sample(self, phase: f32, lsr_ptr: &mut i16) -> i16 {
+ const fn on_phase(self, lsr_ptr: &mut i16) {
+ if let Self::Noise { mode } = self {
+ let mut lsr = *lsr_ptr;
+ let feedback = if mode {
+ (lsr & 1) ^ ((lsr >> 1) & 1)
+ } else {
+ (lsr & 1) ^ ((lsr >> 6) & 1)
+ };
+ lsr >>= 1;
+ lsr |= feedback << 14;
+ *lsr_ptr = lsr;
+ }
+ }
+
+ fn sample(self, phase: f32, lsr: i16) -> i16 {
match self {
Self::Pulse { duty_cycle } => {
let duty = duty_cycle as f32 / 100.0;
@@ -57,17 +71,12 @@ impl ChannelKind {
let value = ((step as f32 / (steps - 1) as f32) * 4.0) - 1.0;
(value * i16::MAX as f32) as i16
}
- Self::Noise { mode } => {
- let mut lsr = *lsr_ptr;
- let feedback = if mode {
- (lsr & 1) ^ ((lsr >> 1) & 1)
+ Self::Noise { .. } => {
+ if (lsr & 0x1) == 1 {
+ i16::MAX
} else {
- (lsr & 1) ^ ((lsr >> 6) & 1)
- };
- lsr >>= 1;
- lsr |= feedback << 14;
- *lsr_ptr = lsr;
- lsr
+ i16::MIN
+ }
}
}
}
@@ -98,8 +107,9 @@ impl Channel {
phase += step;
if phase >= 1.0 {
phase -= 1.0;
+ self.kind.on_phase(lsr_ptr);
}
- let real_note = self.kind.sample(phase, lsr_ptr);
+ let real_note = self.kind.sample(phase, *lsr_ptr);
let note = (real_note as f32 * volume) as i16;
*sample += note / 4;
}
@@ -113,7 +123,7 @@ struct RuntimeState {
pulse_b_phase: f32,
triangle_phase: f32,
noise_phase: f32,
- noise_lsfr: i16,
+ noise_lsr: i16,
}
impl RuntimeState {
const fn new() -> Self {
@@ -122,7 +132,7 @@ impl RuntimeState {
pulse_b_phase: 0.0,
triangle_phase: 0.0,
noise_phase: 0.0,
- noise_lsfr: 1,
+ noise_lsr: 1,
}
}
}
@@ -170,13 +180,13 @@ impl<'s> Device<'s> {
set_audio_stream_callback(&stream, move |buffer| {
let chan = cb_data.load(Ordering::Relaxed);
chan.pulse_a
- .sample(buffer, &mut state.pulse_a_phase, &mut state.noise_lsfr);
+ .sample(buffer, &mut state.pulse_a_phase, &mut state.noise_lsr);
chan.pulse_b
- .sample(buffer, &mut state.pulse_b_phase, &mut state.noise_lsfr);
+ .sample(buffer, &mut state.pulse_b_phase, &mut state.noise_lsr);
chan.triangle
- .sample(buffer, &mut state.triangle_phase, &mut state.noise_lsfr);
+ .sample(buffer, &mut state.triangle_phase, &mut state.noise_lsr);
chan.noise
- .sample(buffer, &mut state.noise_phase, &mut state.noise_lsfr);
+ .sample(buffer, &mut state.noise_phase, &mut state.noise_lsr);
})?;
stream.set_volume(1.0);
stream.set_pitch(1.0);