Open_file & SecretSound
Open_file Open_file
Hey, I’ve been playing around with a tiny audio synth in Rust and thinking it could be fun to merge code and sound—what do you think about exploring how a little algorithm can shape a whole sonic texture?
SecretSound SecretSound
That sounds like a quiet dance between code and waves, I’m curious what textures you’ll let the algorithm paint.
Open_file Open_file
I’m thinking of a noise‑driven wavetable that morphs over time, maybe a simple LFO that tweaks filter resonance and a tiny random seed for each cycle—so the texture feels alive, not just static. Want to dive into a quick demo?
SecretSound SecretSound
A gentle pulse already hums in my mind. Send me the code and let the quiet speak.
Open_file Open_file
use std::f32::consts::PI; use std::time::Instant; use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; fn main() { // setup audio host and default output device let host = cpal::default_host(); let device = host.default_output_device().expect("No output device"); let config = device.default_output_config().expect("No default config"); // choose sample rate and channels let sample_rate = config.sample_rate().0 as f32; let channels = config.channels() as usize; // synth state let mut phase = 0.0f32; let mut lfo_phase = 0.0f32; let freq = 220.0f32; // base tone let lfo_rate = 0.1f32; // slow pulse let lfo_amp = 0.5f32; // depth of resonance change let mut last_instant = Instant::now(); // build stream let err_fn = |err| eprintln!("stream error: {}", err); let stream = match config.sample_format() { cpal::SampleFormat::F32 => device.build_output_stream( &config.into(), move |data: &mut [f32], _: &cpal::OutputCallbackInfo| { write_data(data, channels, sample_rate, &mut phase, &mut lfo_phase, freq, lfo_rate, lfo_amp, last_instant); }, err_fn, ), cpal::SampleFormat::I16 => device.build_output_stream( &config.into(), move |data: &mut [i16], _: &cpal::OutputCallbackInfo| { write_data_i16(data, channels, sample_rate, &mut phase, &mut lfo_phase, freq, lfo_rate, lfo_amp, last_instant); }, err_fn, ), cpal::SampleFormat::U16 => device.build_output_stream( &config.into(), move |data: &mut [u16], _: &cpal::OutputCallbackInfo| { write_data_u16(data, channels, sample_rate, &mut phase, &mut lfo_phase, freq, lfo_rate, lfo_amp, last_instant); }, err_fn, ), }.expect("Failed to build stream"); stream.play().expect("Failed to play stream"); // keep the program running std::thread::sleep(std::time::Duration::from_secs(30)); } fn write_data( output: &mut [f32], channels: usize, sample_rate: f32, phase: &mut f32, lfo_phase: &mut f32, freq: f32, lfo_rate: f32, lfo_amp: f32, last_instant: Instant, ) { let dt = (last_instant.elapsed().as_secs_f32()) / output.len() as f32; for frame in output.chunks_mut(channels) { // LFO modulates filter resonance (here just a simple detune) let lfo = (2.0 * PI * lfo_rate * (*lfo_phase)).sin() * lfo_amp; let current_freq = freq + lfo * 50.0; // tweak frequency by up to ±50Hz // generate a sine wave let sample = (2.0 * PI * current_freq * *phase).sin() * 0.2; for out in frame.iter_mut() { *out = sample; } *phase += dt * current_freq; if *phase > 1.0 { *phase -= 1.0; } *lfo_phase += dt * lfo_rate; if *lfo_phase > 1.0 { *lfo_phase -= 1.0; } } } fn write_data_i16( output: &mut [i16], channels: usize, sample_rate: f32, phase: &mut f32, lfo_phase: &mut f32, freq: f32, lfo_rate: f32, lfo_amp: f32, last_instant: Instant, ) { let mut float_buf = vec![0.0f32; output.len()]; write_data(&mut float_buf, channels, sample_rate, phase, lfo_phase, freq, lfo_rate, lfo_amp, last_instant); for (i, sample) in output.iter_mut().enumerate() { *sample = (float_buf[i] * i16::MAX as f32) as i16; } } fn write_data_u16( output: &mut [u16], channels: usize, sample_rate: f32, phase: &mut f32, lfo_phase: &mut f32, freq: f32, lfo_rate: f32, lfo_amp: f32, last_instant: Instant, ) { let mut float_buf = vec![0.0f32; output.len()]; write_data(&mut float_buf, channels, sample_rate, phase, lfo_phase, freq, lfo_rate, lfo_amp, last_instant); for (i, sample) in output.iter_mut().enumerate() { *sample = ((float_buf[i] + 1.0) * 0.5 * u16::MAX as f32) as u16; } }