Skip to content

Instantly share code, notes, and snippets.

@routevegetable
Last active March 6, 2025 19:10
Show Gist options
  • Save routevegetable/35b1ea3a3db81be014cb4d68cac185a7 to your computer and use it in GitHub Desktop.
Save routevegetable/35b1ea3a3db81be014cb4d68cac185a7 to your computer and use it in GitHub Desktop.
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