77 lines
2.3 KiB
Rust
77 lines
2.3 KiB
Rust
use core::fmt;
|
|
use std::fmt::Formatter;
|
|
use crate::note::Note;
|
|
|
|
pub enum PulseWidth {
|
|
/// 50% duty cycle
|
|
Half,
|
|
/// 25% duty cycle
|
|
Quarter,
|
|
/// 12.5% duty cycle
|
|
Eighth,
|
|
}
|
|
|
|
impl PulseWidth {
|
|
fn from(str: &str) -> Result<PulseWidth, crate::Error> {
|
|
match str {
|
|
"P2" => Ok(PulseWidth::Half),
|
|
"P4" => Ok(PulseWidth::Quarter),
|
|
"P8" => Ok(PulseWidth::Eighth),
|
|
_ => Err(crate::Error::PulseWidth),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for PulseWidth {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "SQR {}", match self {
|
|
PulseWidth::Half => "P2",
|
|
PulseWidth::Quarter => "P4",
|
|
PulseWidth::Eighth => "P8",
|
|
})
|
|
}
|
|
}
|
|
|
|
/// thanks to Rumple_Frumpkins from Bitsy Talk for his help in figuring out the blip format.
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub struct Blip {
|
|
id: String,
|
|
notes: Vec<Note>,
|
|
name: Option<String>,
|
|
/// Attack (ms), Decay (ms), Sustain (level: 1-15), Hold (sustain duration, ms), Release (ms)
|
|
envelope: [u8; 5],
|
|
/// first value is milliseconds per note;
|
|
/// second value is a modifier to the first note (add or subtract milliseconds)
|
|
beat: [i16; 2],
|
|
/// potential values are P2, P4 and P8.
|
|
pulse_width: PulseWidth,
|
|
/// Notes can sound repeatedly, or just once as the blip fades out.
|
|
repeat: bool,
|
|
}
|
|
|
|
impl From<&str> for Blip {
|
|
fn from(str: &str) -> Self {
|
|
let mut id = String::new();
|
|
let mut notes = vec![];
|
|
let mut name = None;
|
|
let mut envelope = [0; 5];
|
|
let mut beat = [0; 2];
|
|
let mut pulse_width = PulseWidth::Half;
|
|
let mut repeat = false;
|
|
|
|
for line in str.lines() {
|
|
if line.starts_with("BLIP ") {
|
|
id = line.replace("BLIP ", "");
|
|
} else if line.starts_with("NAME ") {
|
|
name = Some(line.replace("NAME ", ""));
|
|
} else if line.starts_with("ENV ") {
|
|
let envelope_temp: Vec<u8> = line.replace("ENV ", "").split(' ').map(|v| v.parse().unwrap()).collect();
|
|
} else {
|
|
// notes = line.split(',').map(|n| Note::from(n)).collect().unwrap();
|
|
}
|
|
}
|
|
|
|
Self { id, notes, name, envelope, beat, pulse_width, repeat }
|
|
}
|
|
}
|