working sine gen in zig

This commit is contained in:
aprilnightk 2025-08-17 20:54:42 +03:00
parent 2a66715202
commit 7061a92caf
6 changed files with 243 additions and 53 deletions

3
.gitignore vendored
View file

@ -18,6 +18,9 @@ t*.html
.kdev4/
HTML/
PDF/
.zig-cache/
*/src/soundnode
*.o
JSON/
JSON_HIST/
testrun*/

15
test.py
View file

@ -18,15 +18,12 @@ class TestProgram(Program):
self.reset()
sn = SineNode(440, self.room)
sn2 = SawtoothNode(440, self.room)
sn.air_to(self.room.left_sink)
sn.air_to(self.room.right_sink)
sn2.air_to(self.room.left_sink)
sn2.air_to(self.room.right_sink)
sn.wire_to(self.room.left_sink)
sn.wire_to(self.room.right_sink)
sn.start_location = (4,0,0)
sn2.start_location = (-4,0,0)
#sn.start_location = (49,0,0)
#sn2.start_location = (-4,0,0)
"""
NoteAction('A4', self.st(0), self.st(0.5), [sn, tn], self)
@ -34,8 +31,8 @@ class TestProgram(Program):
NoteAction('F4', self.st(2), self.st(0.5), [sn, tn], self)
NoteAction('E4', self.st(3), self.st(0.5), [sn, tn], self)
"""
LinearPitchTransition('A4', 'E4', self.st(0), self.st(5), [sn], self)
LinearPitchTransition('E4', 'A4', self.st(0), self.st(5), [sn2], self)
#LinearPitchTransition('A4', 'E4', self.st(0), self.st(5), [sn], self)
#LinearPitchTransition('E4', 'A4', self.st(0), self.st(5), [sn2], self)
#LinearSpatialTransition((-8,0,0),(8,0,0), self.st(0), self.st(5), [sn], self)

View file

View file

@ -0,0 +1,46 @@
//! By convention, main.zig is where your main function lives in the case that
//! you are building an executable. If you are making a library, the convention
//! is to delete this file and start with root.zig instead.
pub fn main() !void {
// Prints to stderr (it's a shortcut based on `std.io.getStdErr()`)
std.debug.print("All your {s} are belong to us.\n", .{"codebase"});
// stdout is for the actual output of your application, for example if you
// are implementing gzip, then only the compressed bytes should be sent to
// stdout, not any debugging messages.
const stdout_file = std.io.getStdOut().writer();
var bw = std.io.bufferedWriter(stdout_file);
const stdout = bw.writer();
try stdout.print("Run `zig build test` to run the tests.\n", .{});
try bw.flush(); // Don't forget to flush!
}
test "simple test" {
var list = std.ArrayList(i32).init(std.testing.allocator);
defer list.deinit(); // Try commenting this out and see if zig detects the memory leak!
try list.append(42);
try std.testing.expectEqual(@as(i32, 42), list.pop());
}
test "use other module" {
try std.testing.expectEqual(@as(i32, 150), lib.add(100, 50));
}
test "fuzz example" {
const Context = struct {
fn testOne(context: @This(), input: []const u8) anyerror!void {
_ = context;
// Try passing `--fuzz` to `zig build test` and see if it manages to fail this test case!
try std.testing.expect(!std.mem.eql(u8, "canyoufindme", input));
}
};
try std.testing.fuzz(Context{}, Context.testOne, .{});
}
const std = @import("std");
/// This imports the separate module containing `root.zig`. Take a look in `build.zig` for details.
const lib = @import("zigsonnum_lib");

View file

@ -1,46 +1,67 @@
//! By convention, main.zig is where your main function lives in the case that
//! you are building an executable. If you are making a library, the convention
//! is to delete this file and start with root.zig instead.
pub fn main() !void {
// Prints to stderr (it's a shortcut based on `std.io.getStdErr()`)
std.debug.print("All your {s} are belong to us.\n", .{"codebase"});
// stdout is for the actual output of your application, for example if you
// are implementing gzip, then only the compressed bytes should be sent to
// stdout, not any debugging messages.
const stdout_file = std.io.getStdOut().writer();
var bw = std.io.bufferedWriter(stdout_file);
const stdout = bw.writer();
try stdout.print("Run `zig build test` to run the tests.\n", .{});
try bw.flush(); // Don't forget to flush!
}
test "simple test" {
var list = std.ArrayList(i32).init(std.testing.allocator);
defer list.deinit(); // Try commenting this out and see if zig detects the memory leak!
try list.append(42);
try std.testing.expectEqual(@as(i32, 42), list.pop());
}
test "use other module" {
try std.testing.expectEqual(@as(i32, 150), lib.add(100, 50));
}
test "fuzz example" {
const Context = struct {
fn testOne(context: @This(), input: []const u8) anyerror!void {
_ = context;
// Try passing `--fuzz` to `zig build test` and see if it manages to fail this test case!
try std.testing.expect(!std.mem.eql(u8, "canyoufindme", input));
}
};
try std.testing.fuzz(Context{}, Context.testOne, .{});
}
const std = @import("std");
const soundnode = @import("soundnode.zig");
const expect = std.testing.expect;
const print = std.debug.print;
const math = std.math;
/// This imports the separate module containing `root.zig`. Take a look in `build.zig` for details.
const lib = @import("zigsonnum_lib");
const TestError = error {
IsFive,
IsSix
};
pub fn prnt(s: []const u8) void {
print("{s}\n", .{s});
}
pub fn prntNum(i: anytype) void {
print("{d}\n", .{i});
}
pub fn testValue(a: u8) TestError!u8 {
if (a == 5) {
return TestError.IsFive;
}
else {
if (a == 6) {
return TestError.IsSix;
}
else {
return a;
}
}
}
pub fn distanceBetweenPoints(pt1: *const Pnt, pt2: *const Pnt) f32 {
if ((pt1.x == pt2.x) and (pt1.y == pt2.y) and (pt1.z == pt2.z)) {
return 0;
}
const dx: f32 = pt1.x - pt2.x;
const dy: f32 = pt1.y - pt2.y;
const dz: f32 = pt1.z - pt2.z;
return math.sqrt(dx*dx + dy*dy + dz*dz);
}
pub fn main() void {
const p1: Pnt = Pnt{.x = 0, .y = 0};
const p2: Pnt = Pnt{.x = 1, .y = 1};
const p3: Pnt = Pnt{.x = 1, .y = 9751.767};
var dst: f32 = distanceBetweenPoints(&p1, &p2);
prntNum(dst);
dst = distanceBetweenPoints(&p1, &p3);
prntNum(dst);
}

123
zigsonnum/src/soundnode.zig Normal file
View file

@ -0,0 +1,123 @@
const std = @import("std");
const print = std.debug.print;
const math = std.math;
const Endian = std.builtin.Endian;
pub const tau: f64 = 2 * 3.1415926535897932384626433832795028841971;
pub fn prnt(s: []const u8) void {
print("{s}\n", .{s});
}
const SoundSettings = struct {
const default_sample_rate: u16 = 44100;
const default_bit_depth: u8 = 24;
sample_rate: u16 = default_sample_rate,
speed_of_sound: f32 = 343.0 / @as(f32, default_sample_rate),
bit_depth: u8 = default_bit_depth,
max_amp: i64 = math.pow(i64, 2, default_bit_depth-1) - 1,
min_amp: i64 = - math.pow(i64, 2, default_bit_depth-1),
sample_width: u8 = @intFromFloat(@as(f32, default_bit_depth) / 8.0),
sine_multiplier: f64 = tau / default_sample_rate,
fn printSettings(self: *const SoundSettings) void {
print("Sample rate : {d}\n", .{self.sample_rate});
print("Bit depth : {d}\n", .{self.bit_depth});
print("Max amp : {d}\n", .{self.max_amp});
print("Min amp : {d}\n", .{self.min_amp});
print("Sample width: {d}\n", .{self.sample_width});
print("Sine mult : {d}\n", .{self.sine_multiplier});
}
};
const Pnt = struct {
x: f32 = 0,
y: f32 = 0,
z: f32 = 0,
fn printPnt(self: *const Pnt) void {
print("{d} {d} {d}\n", .{self.x, self.y, self.z});
}
};
const SoundNode = struct {
name: []const u8 = "soundnode",
air_in: []*SoundNode = undefined,
wire_in: []*SoundNode = undefined,
location: Pnt = Pnt{.x = 0, .y = 0, .z = 0}
};
pub fn singleSineTick(st: *SoundSettings, freq: f16, t: u64) f64 {
const ft: f64 = @floatFromInt(t);
return math.sin(st.sine_multiplier * @as(f64, freq) * ft);
}
pub fn main() !void {
var sn1: SoundNode = SoundNode{ .name="left_sink" };
sn1.location.x = 4;
var st = SoundSettings{};
st.printSettings();
const duration_in_sec: u32 = 5*60;
prnt("start");
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 + ((duration_in_sec * st.sample_rate) * 2 * st.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, st.sample_rate, Endian.little);
const block_align: u16 = @intCast(2 * st.sample_width);
try stdout.writeInt(u32, @as(u32, block_align) * st.sample_rate, Endian.little);
try stdout.writeInt(u16, block_align, Endian.little);
try stdout.writeInt(u16, st.bit_depth, Endian.little);
try stdout.writeAll("data");
try stdout.writeInt(
u32,
(duration_in_sec * st.sample_rate) * 2 * st.sample_width,
Endian.little,
);
var sample: i24 = 0.0;
var amp: f64 = undefined;
for (0 .. st.sample_rate * duration_in_sec) |t| {
amp = singleSineTick(&st, 440, t);
sample = @intFromFloat(amp * @as(f64, @floatFromInt(st.max_amp)));
try stdout.writeInt(i24, sample, Endian.little);
try stdout.writeInt(i24, sample, Endian.little);
}
prnt("done");
try bw.flush();
}