//! Example: render a simple melody (pulse lead + triangle bass + noise hihat) to WAV. use soundgen_core::{ voice::{DutyCycle, NoiseChannel, NoiseMode, PulseChannel, TriangleChannel}, ChannelRenderer, Envelope, VoiceKind, }; use soundgen_io::write_wav; fn note_freq(n: &str) -> f32 { // Note name to frequency: e.g., "A4" = 440 Hz let notes = [ "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B", ]; let note = &n[..n.len() - 1]; let octave: i32 = n[n.len() - 1..].parse().unwrap(); let semitone = notes.iter().position(|&x| x == note).unwrap() as i32; let midi = 12 * (octave + 1) + semitone; 440.0 * 2.0f32.powf((midi - 69) as f32 / 12.0) } fn main() { let sr = 44100u32; let bpm = 120.0; let beat = 60.0 / bpm; // seconds per beat let total_beats = 8.0; let total_samples = (beat * total_beats * sr as f32) as usize; // Melody: C4 E4 G4 C5 G4 E4 C4 G3 let melody = ["C4", "E4", "G4", "C5", "G4", "E4", "C4", "G3"]; // Bass: C3 C3 G3 G3 A2 A2 F2 F2 let bass = ["C3", "C3", "G3", "G3", "A2", "A2", "F2", "F2"]; let samples_per_note = (beat * sr as f32) as usize; let mut stereo = Vec::with_capacity(total_samples * 2); for i in 0..8 { // Lead: pulse wave let mut lead = ChannelRenderer::new( VoiceKind::Pulse(PulseChannel::new(sr as f32, DutyCycle::D50)), sr as f32, ) .with_envelope(Envelope::adsr(sr as f32, 0.01, 0.05, 0.6, 0.08)) .with_volume(0.3) .with_pan(-0.3); lead.trigger(); lead.set_frequency(note_freq(melody[i])); // Bass: triangle let mut bass_ch = ChannelRenderer::new( VoiceKind::Triangle(TriangleChannel::new(sr as f32)), sr as f32, ) .with_envelope(Envelope::adsr(sr as f32, 0.02, 0.1, 0.5, 0.1)) .with_volume(0.35) .with_pan(0.3); bass_ch.trigger(); bass_ch.set_frequency(note_freq(bass[i])); // Hihat: noise on offbeats let has_hihat = i % 2 == 1; let mut hihat = ChannelRenderer::new( VoiceKind::Noise(NoiseChannel::new(sr as f32, NoiseMode::White)), sr as f32, ) .with_envelope(Envelope::adsr(sr as f32, 0.0, 0.02, 0.0, 0.03)) .with_volume(0.15) .with_pan(0.0); if has_hihat { hihat.trigger(); hihat.set_frequency(10000.0); } for _ in 0..samples_per_note { let (ll, lr) = lead.tick(); let (bl, br) = bass_ch.tick(); let (hl, hr) = hihat.tick(); let l = (ll + bl + hl).tanh(); let r = (lr + br + hr).tanh(); stereo.push(l); stereo.push(r); } } let out = std::path::Path::new("play_melody.wav"); write_wav(out, &stereo, sr).expect("failed to write WAV"); eprintln!("Wrote {} ({} notes, {:.1}s)", out.display(), 8, beat * 8.0); }