mara2/src/sh0rk/music.rs

130 lines
3.4 KiB
Rust

use super::sys::{tone, TONE_PULSE1, TONE_PULSE2};
pub struct Note {
pub freq: u32,
pub dur: u32,
pub volume: u32,
pub flags: u32,
}
impl Note {
pub fn play(&self) {
tone(self.freq, self.dur, self.volume, self.flags);
}
}
impl From<(u32, u32, u32, u32)> for Note {
fn from((freq, dur, volume, flags): (u32, u32, u32, u32)) -> Self {
Note {freq, dur, volume, flags}
}
}
pub enum Quantum {
Rest(u8),
Notes([(u32, u32, u32, u32); 2]),
}
pub use Quantum::*;
pub const CHOPSTICKS: [Quantum; 48] = [
// G7
Notes([(196, 14, 25, TONE_PULSE1), (175, 14, 25, TONE_PULSE2)]),
Rest(15),
Notes([(196, 14, 25, TONE_PULSE1), (175, 14, 25, TONE_PULSE2)]),
Rest(15),
Notes([(196, 14, 25, TONE_PULSE1), (175, 14, 25, TONE_PULSE2)]),
Rest(15),
// G7
Notes([(196, 15, 25, TONE_PULSE1), (175, 15, 25, TONE_PULSE2)]),
Rest(15),
Notes([(196, 15, 25, TONE_PULSE1), (175, 15, 25, TONE_PULSE2)]),
Rest(15),
Notes([(196, 15, 25, TONE_PULSE1), (175, 15, 25, TONE_PULSE2)]),
Rest(15),
// C
Notes([(196, 15, 25, TONE_PULSE1), (164, 15, 25, TONE_PULSE2)]),
Rest(15),
Notes([(196, 15, 25, TONE_PULSE1), (175, 15, 25, TONE_PULSE2)]),
Rest(15),
Notes([(196, 15, 25, TONE_PULSE1), (175, 15, 25, TONE_PULSE2)]),
Rest(15),
// C
Notes([(196, 15, 25, TONE_PULSE1), (164, 15, 25, TONE_PULSE2)]),
Rest(15),
Notes([(246, 15, 25, TONE_PULSE1), (164, 15, 25, TONE_PULSE2)]),
Rest(15),
Notes([(246, 15, 25, TONE_PULSE1), (164, 15, 25, TONE_PULSE2)]),
Rest(15),
// G7
Notes([(246, 15, 25, TONE_PULSE1), (164, 15, 25, TONE_PULSE2)]),
Rest(15),
Notes([(246, 15, 25, TONE_PULSE1), (164, 15, 25, TONE_PULSE2)]),
Rest(15),
Notes([(246, 15, 25, TONE_PULSE1), (164, 15, 25, TONE_PULSE2)]),
Rest(15),
// G7
Notes([(246, 15, 25, TONE_PULSE1), (164, 15, 25, TONE_PULSE2)]),
Rest(15),
Notes([(261, 15, 25, TONE_PULSE1), (130, 15, 25, TONE_PULSE2)]),
Rest(15),
Notes([(261, 15, 25, TONE_PULSE1), (130, 15, 25, TONE_PULSE2)]),
Rest(15),
// C
Notes([(261, 15, 25, TONE_PULSE1), (130, 15, 25, TONE_PULSE2)]),
Rest(15),
Notes([(261, 15, 25, TONE_PULSE1), (130, 15, 25, TONE_PULSE2)]),
Rest(15),
Notes([(261, 15, 25, TONE_PULSE1), (130, 15, 25, TONE_PULSE2)]),
Rest(15),
// C
Notes([(261, 15, 25, TONE_PULSE1), (130, 15, 25, TONE_PULSE2)]),
Rest(15),
Notes([(246, 15, 25, TONE_PULSE1), (146, 15, 25, TONE_PULSE2)]),
Rest(15),
Notes([(220, 15, 25, TONE_PULSE1), (164, 15, 25, TONE_PULSE2)]),
Rest(15),
];
pub struct Song<const N: usize> {
position: usize,
sleep_timer: u8,
song: [Quantum; N],
paused: bool,
}
impl<const N: usize> Song<N> {
pub const fn new(song: [Quantum;N]) -> Self {
Self{
position: 0,
sleep_timer: 0,
song,
paused: false,
}
}
pub fn pause(&mut self) {
self.paused = !self.paused;
}
pub fn update(&mut self) {
if self.paused {
return;
}
if self.sleep_timer != 0 {
self.sleep_timer -= 1;
return;
}
match self.song[self.position % self.song.len()] {
Rest(n) => self.sleep_timer = n,
Notes(notes) => {
for note in notes {
Note::from(note).play();
}
},
}
self.position += 1;
}
}