diff options
Diffstat (limited to 'graphics/src/audio/program.rs')
| -rw-r--r-- | graphics/src/audio/program.rs | 184 |
1 files changed, 0 insertions, 184 deletions
diff --git a/graphics/src/audio/program.rs b/graphics/src/audio/program.rs deleted file mode 100644 index f5decd6..0000000 --- a/graphics/src/audio/program.rs +++ /dev/null @@ -1,184 +0,0 @@ -use crate::audio::{ - Channels, - channel::{Channel, DutyCycle}, - parse, -}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum ChanSpec { - PulseA, - PulseB, - Triangle, - Noise, -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum Instruction { - Pause, - PauseLen(u32), - Jump(usize), - SetVolume(ChanSpec, u8), - SetPitch(ChanSpec, u8), - SetPulseDutyA(DutyCycle), - SetPulseDutyB(DutyCycle), - SetNoiseMode(bool), -} - -fn map_pitch(pitch: u8) -> f32 { - const HALF_STEP: f32 = 1.059_463_1; - HALF_STEP.powf(pitch as f32 - 128.0) -} - -const fn map_volume(volume: u8) -> f32 { - if volume > 100 { - 1.0 - } else { - (volume as f32) / 100.0 - } -} - -#[derive(Debug, Clone)] -pub struct Program { - ins: Vec<Instruction>, - pc: usize, - looping: bool, - pause_cnt: u32, - pause_len: u32, -} -impl Program { - pub const fn new(ins: Vec<Instruction>, looping: bool) -> Self { - let pc = ins.len(); - Self { - ins, - pc, - looping, - pause_cnt: 0, - pause_len: 4, - } - } - - pub fn parse(src: &str, looping: bool) -> parse::Result<Self> { - let ins = parse::parse(src)?; - Ok(Self::new(ins, looping)) - } - - pub fn merge(self, other: Self) -> Self { - let mut res = vec![]; - - let mut l = 0; - let mut r = 0; - let l_ins = self.ins; - let r_ins = other.ins; - - loop { - if l >= l_ins.len() && r >= r_ins.len() { - // were done here - break; - } - - let mut has_pause = false; - while l < l_ins.len() { - let ins = l_ins[l]; - l += 1; - if matches!(ins, Instruction::Pause) { - has_pause = true; - break; - } - res.push(ins); - } - while r < r_ins.len() { - let ins = r_ins[r]; - r += 1; - if matches!(ins, Instruction::Pause) { - has_pause = true; - break; - } - res.push(ins); - } - if has_pause { - res.push(Instruction::Pause); - } - } - - Self::new(res, self.looping) - } - - fn exec_ins(&mut self, channels: &mut Channels, ins: Instruction) { - use Instruction as I; - match ins { - I::Pause => { - self.pause_cnt = self.pause_len; - } - I::PauseLen(pause_len) => { - self.pause_len = pause_len; - } - I::Jump(pc) => { - self.pc = pc; - } - I::SetVolume(chan_spec, volume) => { - // set the volume (amplitude) on a given channel - use ChanSpec as C; - let v = map_volume(volume); - match chan_spec { - C::PulseA => channels.pulse_a.set_volume(v), - C::PulseB => channels.pulse_b.set_volume(v), - C::Triangle => channels.triangle.set_volume(v), - C::Noise => channels.noise.set_volume(v), - } - } - I::SetPitch(chan_spec, pitch) => { - // set the pitch (freq) on a given channel - use ChanSpec as C; - let p = map_pitch(pitch); - match chan_spec { - C::PulseA => channels.pulse_a.set_pitch(p), - C::PulseB => channels.pulse_b.set_pitch(p), - C::Triangle => channels.triangle.set_pitch(p), - C::Noise => channels.noise.set_pitch(p), - } - } - I::SetPulseDutyA(duty_cycle) => { - channels.pulse_a.set_duty(duty_cycle); - } - I::SetPulseDutyB(duty_cycle) => { - channels.pulse_b.set_duty(duty_cycle); - } - I::SetNoiseMode(mode) => { - channels.noise.set_mode(mode); - } - } - } - - pub fn exec(&mut self, channels: &mut Channels) { - if self.pause_cnt > 0 { - self.pause_cnt -= 1; - } - loop { - if self.pause_cnt > 0 { - break; - } - if self.finished() { - if self.looping { - self.pc = 0; - } else { - break; - } - } - let ins = self.ins[self.pc]; - self.exec_ins(channels, ins); - self.pc += 1; - } - } - - pub const fn finished(&self) -> bool { - self.pc >= self.ins.len() - } - - pub const fn play(&mut self) { - self.pc = 0; - } - - pub const fn set_looping(&mut self, looping: bool) { - self.looping = looping; - } -} |