Initial commit of a toy analogue audio generator

Key components:
- no_std core so it can be used bare metal on embedded systems
- default implementation for RPi 2350, with midi input and I2s output using PIO
- Visualiser for the web to play with on a dev system
This commit is contained in:
2026-03-23 15:06:31 +00:00
commit 496b6bdc71
34 changed files with 3662 additions and 0 deletions

View File

@@ -0,0 +1,52 @@
//! Synthesiser parameter model — mirrors synth-core state.
//! Serialised as JSON for postMessage() across the AudioWorklet MessagePort.
use wasm_bindgen::prelude::*;
use serde::{Serialize, Deserialize};
#[wasm_bindgen]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SynthParams {
pub osc_freq: f32, // Hz
pub osc_wave: u8, // 0=Sine 1=Saw 2=Square 3=Triangle
pub filter_cutoff: f32, // Hz
pub filter_res: f32, // 0.01.0
pub env_attack: f32, // seconds
pub env_decay: f32,
pub env_sustain: f32, // 0.01.0
pub env_release: f32,
pub lfo_rate: f32, // Hz
pub lfo_depth: f32, // 0.01.0
pub master_gain: f32, // 0.01.0
}
#[wasm_bindgen]
impl SynthParams {
#[wasm_bindgen(constructor)]
pub fn new() -> Self {
Self {
osc_freq: 440.0,
osc_wave: 1,
filter_cutoff: 2000.0,
filter_res: 0.3,
env_attack: 0.01,
env_decay: 0.1,
env_sustain: 0.7,
env_release: 0.3,
lfo_rate: 2.0,
lfo_depth: 0.0,
master_gain: 0.8,
}
}
pub fn to_json(&self) -> String {
// serde_json would pull in std; for WASM we use the js glue instead.
// This is a simple manual serialisation for the scaffold.
format!(
r#"{{"osc_freq":{:.2},"osc_wave":{},"filter_cutoff":{:.2},"filter_res":{:.3},"env_attack":{:.4},"env_decay":{:.4},"env_sustain":{:.3},"env_release":{:.4},"lfo_rate":{:.3},"lfo_depth":{:.3},"master_gain":{:.3}}}"#,
self.osc_freq, self.osc_wave, self.filter_cutoff, self.filter_res,
self.env_attack, self.env_decay, self.env_sustain, self.env_release,
self.lfo_rate, self.lfo_depth, self.master_gain
)
}
}