this repo has no description
at main 58 lines 1.8 kB view raw
1//! example: generate a filtered sine wave with tremolo 2//! 3//! writes output.wav - no ffmpeg needed. 4 5const std = @import("std"); 6const noise = @import("noise"); 7 8pub fn main() !void { 9 const sample_rate: u32 = 48000; 10 const duration: f32 = 5.0; 11 const num_samples: u32 = @intFromFloat(@as(f32, @floatFromInt(sample_rate)) * duration); 12 13 // oscillator frequency (A4 = 440 Hz) 14 const freq: f32 = 440.0; 15 16 // lowpass at 2kHz to soften the tone 17 const lpf = noise.biquad.lowpass(2000, 0.707, @floatFromInt(sample_rate)); 18 var lpf_state: noise.State = .{}; 19 20 // tremolo at 4 Hz 21 var tremolo = noise.Lfo.init(4.0, @floatFromInt(sample_rate)); 22 23 // create output file 24 const file = try std.fs.cwd().createFile("output.wav", .{}); 25 defer file.close(); 26 27 // write WAV header 28 const header = noise.WavHeader.init(num_samples, sample_rate, 1); 29 try file.writeAll(header.asBytes()); 30 31 // write samples 32 for (0..num_samples) |i| { 33 const t: f32 = @floatFromInt(i); 34 const sr: f32 = @floatFromInt(sample_rate); 35 36 // generate sine wave 37 const phase = t * 2.0 * std.math.pi * freq / sr; 38 var sample = @sin(phase); 39 40 // apply lowpass filter 41 sample = noise.biquad.step(lpf, &lpf_state, sample); 42 43 // apply tremolo (amplitude modulation) 44 const mod = (tremolo.step(.sine) + 1.0) / 2.0; // 0 to 1 45 sample *= 0.3 + 0.7 * mod; // depth of 70% 46 47 // fade in/out 48 const fade_samples: f32 = 0.1 * sr; 49 if (t < fade_samples) { 50 sample *= t / fade_samples; 51 } else if (t > @as(f32, @floatFromInt(num_samples)) - fade_samples) { 52 sample *= (@as(f32, @floatFromInt(num_samples)) - t) / fade_samples; 53 } 54 55 // write sample 56 try file.writeAll(std.mem.asBytes(&sample)); 57 } 58}