summaryrefslogtreecommitdiff
path: root/graphics/src/audio/program.rs
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/src/audio/program.rs')
-rw-r--r--graphics/src/audio/program.rs184
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;
- }
-}