sonnum/zigsonnum/sonnum.zig

189 lines
No EOL
4.2 KiB
Zig

const std = @import("std");
const math = std.math;
const print = std.debug.print;
const ArrayList = std.ArrayList;
const Endian = std.builtin.Endian;
const SoundNode = @import("soundnode.zig").SoundNode;
const Activity = @import("activity.zig").Activity;
const SoundSettings = @import("settings.zig").SoundSettings;
pub fn singleSineTick(st: *SoundSettings, freq: f16, t: u32) f64 {
const ft: f64 = @floatFromInt(t);
return math.sin(st.sine_multiplier * @as(f64, freq) * ft);
}
pub fn main() !void {
//var gpa = std.heap.GeneralPurposeAllocator(.{}){};
//const allocator = gpa.allocator();
const allocator = std.heap.c_allocator;
var settings: SoundSettings = SoundSettings{};
const start_tick: u32 = 0;
const end_tick: u32 = 44100 * 10;
var left: SoundNode = try SoundNode.init(allocator, "left_sink");
defer left.deinit();
left.location.x = -0.15;
var right: SoundNode = try SoundNode.init(allocator, "right_sink");
defer right.deinit();
right.location.x = 0.15;
var sine: SoundNode = try SoundNode.init(allocator, "sine");
defer sine.deinit();
var a = Activity{
.start_tick = 0,
.end_tick = 0,
.opcode = 1,
.soundnode = &sine,
};
a.operands[0] = 410.0;
a.operands[1] = 0.8;
var sine2: SoundNode = try SoundNode.init(allocator, "sine2");
defer sine2.deinit();
var a4 = Activity{
.start_tick = 0,
.end_tick = end_tick,
.opcode = 3,
.soundnode = &sine2,
};
a4.operands[0] = 410.0;
a4.operands[1] = 820.0;
a4.operands[2] = 0.5;
try sine.activities.append(&a);
try sine2.activities.append(&a4);
var a2 = Activity{
.start_tick = 0,
.end_tick = end_tick,
.opcode = 2,
.soundnode = &left,
};
try left.activities.append(&a2);
var a3 = Activity{
.start_tick = 0,
.end_tick = end_tick,
.opcode = 2,
.soundnode = &right,
};
try right.activities.append(&a3);
var soundnodes = ArrayList(*SoundNode).init(allocator);
defer soundnodes.deinit();
//Preset sink nodes
try soundnodes.append(&sine);
try soundnodes.append(&sine2);
try soundnodes.append(&left);
try soundnodes.append(&right);
try left.wire_in.append(&sine2);
try right.wire_in.append(&sine2);
var tick: u32 = start_tick;
//STARTING WAV
const stdout_file = std.io.getStdOut().writer();
var bw = std.io.bufferedWriter(stdout_file);
const stdout = bw.writer();
//WRITING WAV HEADER
try stdout.writeAll("RIFF");
try stdout.writeInt(
u32,
36 + (end_tick * 2 * settings.sample_width),
Endian.little,
);
try stdout.writeAll("WAVE");
try stdout.writeAll("fmt ");
try stdout.writeInt(u32, 16, Endian.little);
try stdout.writeInt(u16, 1, Endian.little);
try stdout.writeInt(u16, 2, Endian.little);
try stdout.writeInt(u32, settings.sample_rate, Endian.little);
const block_align: u16 = @intCast(2 * settings.sample_width);
try stdout.writeInt(u32, @as(u32, block_align) * settings.sample_rate, Endian.little);
try stdout.writeInt(u16, block_align, Endian.little);
try stdout.writeInt(u16, settings.bit_depth, Endian.little);
try stdout.writeAll("data");
try stdout.writeInt(
u32,
end_tick * 2 * settings.sample_width,
Endian.little,
);
var sample: i24 = 0.0;
while (tick < end_tick) {
if (tick%44100 == 0) {
print("TICK {d}\n", .{tick});
}
for (soundnodes.items, 0..) |soundnode, i| {
for (soundnode.activities.items, 0..) |activity, j| {
if (tick <= activity.end_tick and tick >= activity.start_tick) {
try activity.do();
}
_ = j;
}
soundnode.freqamp.increment_tick();
_ = i;
}
var amp: f64 = 0;
const current_index = left.freqamp.current_index();
const clist_left = left.freqamp.freqamps[current_index];
for (clist_left.lst.items) |freqamp| {
amp += freqamp.r_amp * singleSineTick(&settings, freqamp.freq, tick);
}
sample = @intFromFloat(amp * @as(f64, @floatFromInt(settings.max_amp)));
try stdout.writeInt(i24, sample, Endian.little);
amp = 0;
const clist_right = right.freqamp.freqamps[current_index];
for (clist_right.lst.items) |freqamp| {
amp += freqamp.r_amp * singleSineTick(&settings, freqamp.freq, tick);
}
sample = @intFromFloat(amp * @as(f64, @floatFromInt(settings.max_amp)));
try stdout.writeInt(i24, sample, Endian.little);
tick += 1;
}
try bw.flush();
}