this repo has no description
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}