Last active
March 6, 2025 19:10
-
-
Save routevegetable/35b1ea3a3db81be014cb4d68cac185a7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::{process::Output, time}; | |
use timebase::{Event, Frame}; | |
use tinyaudio::prelude::*; | |
mod timebase; | |
const MSEC: i32 = 10; | |
const SEC: i32 = 10000; | |
const HNDRDUSEC: i32 = 10; | |
const fn period(khz: f32) -> i32 { | |
(MSEC as f32 / khz) as i32 | |
} | |
struct Piano<'a> { | |
frame: &'a Frame, | |
output: f32, | |
} | |
impl <'a> Piano<'a> { | |
fn new(frame: &'a Frame) -> Self { | |
Self { | |
frame, | |
output: 0.0, | |
} | |
} | |
fn key(&mut self, ev: Event, khz: f32) { | |
// Tremolo | |
let trem = self.frame.timebase(timebase::TimebaseMode::Repeat, period(khz / 30.0), ev).scale(-0.01,0.01); | |
// Fundamental | |
let tone = self.frame.timebase(timebase::TimebaseMode::Repeat, period(khz + trem), ev).circle().sin(); | |
// Harmonic | |
let tone2 = self.frame.timebase(timebase::TimebaseMode::Repeat, period(2.0* khz + trem), ev).circle().sin() / 2.0; | |
// Sustain | |
let ramp = self.frame.timebase(timebase::TimebaseMode::OneShot, SEC / 2, ev); | |
self.output += (tone + tone2) * ramp.scale(1.0, 0.0); | |
} | |
fn out(&self) -> f32 { | |
self.output | |
} | |
} | |
fn audio(f: &Frame) -> f32 { | |
let mut piano = Piano::new(f); | |
let tune = f.timebase(timebase::TimebaseMode::OneShot, 1*SEC, Event::zero()); | |
let evs = tune.seq::<5>(); | |
piano.key(evs[0], 0.440); | |
piano.key(evs[1], 0.540); | |
piano.key(evs[2], 0.240); | |
piano.key(evs[3], 0.740); | |
piano.key(evs[4], 0.840); | |
return piano.out(); | |
} | |
fn main() { | |
let _device = run_output_device(OutputDeviceParameters{ | |
sample_rate:10000, | |
channels_count:1, | |
channel_sample_count:1000 | |
}, { | |
let mut clock = 0i32; | |
move |data| { | |
for frame in data { | |
clock = clock + period(10.0); | |
*frame = audio(&Frame::new(clock)); | |
} | |
}}).unwrap(); | |
std::thread::sleep(std::time::Duration::from_secs(5)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment