bppt_wav/
structure.rs

1pub use self::de::Signal;
2use anyhow::{Ok, Result};
3use bppt::Notes;
4use derive_new::new;
5use serde::Deserialize;
6use std::fmt::Debug;
7use std::num::{NonZeroU16, NonZeroUsize};
8
9mod de;
10mod default;
11
12pub(crate) const SAMPLE_RATE: u32 = 48000;
13
14#[derive(new, PartialEq, Debug, Deserialize)]
15pub struct Track {
16    #[serde(rename = "BPM")]
17    pub bpm: NonZeroU16,
18    pub channels: Vec<Channel>,
19}
20
21impl Channel {
22    pub(crate) fn generator(&self) -> Result<impl Fn(NonZeroUsize, u8, u8, u8) -> Vec<f32>> {
23        let func = self.signal.clone().0.bind2("t", "f")?;
24        let notes = self.notes.set;
25        let tuning = self.tuning;
26        Ok(
27            move |len: NonZeroUsize, n: u8, octave: u8, volume: u8| -> Vec<f32> {
28                let f = (tuning as f64 / 16f64)
29                    * 2.0_f64.powf(((notes * octave + n) as f64) / (notes as f64));
30                (1..=usize::from(len))
31                    .map(|i| {
32                        let t = (i as f64) / (SAMPLE_RATE as f64);
33                        (func(t, f) * ((volume as f64) / 100f64)) as f32
34                    })
35                    .collect()
36            },
37        )
38    }
39}
40
41#[derive(PartialEq, Debug, new, Deserialize)]
42pub struct Channel {
43    pub signal: Signal,
44    #[serde(flatten)]
45    pub notes: Notes,
46    pub tuning: f32,
47}