summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralaric <alaric@netmythos.org>2024-04-18 04:00:17 -0700
committeralaric <alaric@netmythos.org>2024-04-18 04:00:17 -0700
commit2f1cc050e56333eaf5efe83d4bbf1fe3e8ee254f (patch)
treeb38bfa46d5eb4f25bff23696942ae6185661e3d6
parent7180e5b0907f9125b3f45c9efa75fb03e400c98b (diff)
downloadtiny-synth-2f1cc050e56333eaf5efe83d4bbf1fe3e8ee254f.tar.gz
tiny-synth-2f1cc050e56333eaf5efe83d4bbf1fe3e8ee254f.zip
feat:scuffed piano keys
-rw-r--r--build.zig13
-rw-r--r--cors_server.py26
m---------engine0
-rw-r--r--src/main.zig88
4 files changed, 125 insertions, 2 deletions
diff --git a/build.zig b/build.zig
index e0567c3..1cc921b 100644
--- a/build.zig
+++ b/build.zig
@@ -6,6 +6,8 @@ pub fn build(b: *std.Build) void {
const wasm_target: std.Target.Query = .{
.cpu_arch = .wasm32,
.os_tag = .freestanding,
+ // Features needed for multithreading
+ .cpu_features_add = std.Target.wasm.featureSet(&.{ .atomics, .bulk_memory }),
};
const target = b.standardTargetOptions(.{
.whitelist = &.{wasm_target},
@@ -28,6 +30,17 @@ pub fn build(b: *std.Build) void {
// WASM doesn't use a normal entry point. The HTML/JS shell code is going
// to handle calling our functions.
exe.entry = .disabled;
+ // Enabling shared memory is required for multithreading
+ exe.shared_memory = true;
+ exe.import_memory = true;
+
+ // TODO(Alaric): Pass these params down to the engine to support into the
+ // JS shell or something Idk. If they change when I change the code then that
+ // would be bad.
+ const init_pages = (1049972 / 65536) + 1;
+ const max_pages = (91553792 / 65536) + 1;
+ exe.initial_memory = init_pages * 65536;
+ exe.max_memory = max_pages * 65536;
exe.root_module.addImport("engine", engine.module("engine"));
// Here we install a pre-written HTML/JS shell. After building, if you
diff --git a/cors_server.py b/cors_server.py
new file mode 100644
index 0000000..0221711
--- /dev/null
+++ b/cors_server.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python3
+
+# It's python3 -m http.server PORT for a CORS world
+
+from http.server import HTTPServer, SimpleHTTPRequestHandler
+import sys
+
+
+class CORSRequestHandler(SimpleHTTPRequestHandler):
+
+ def end_headers(self):
+ self.send_header('Cross-Origin-Opener-Policy', 'same-origin')
+ self.send_header('Cross-Origin-Embedder-Policy', 'require-corp')
+ self.send_header('Cache-Control', 'no-store, no-cache, must-revalidate')
+ return super(CORSRequestHandler, self).end_headers()
+
+ def do_OPTIONS(self):
+ self.send_response(200)
+ self.end_headers()
+
+host = sys.argv[1] if len(sys.argv) > 2 else '0.0.0.0'
+port = int(sys.argv[len(sys.argv)-1]) if len(sys.argv) > 1 else 8080
+
+print("Listening on {}:{}".format(host, port))
+httpd = HTTPServer((host, port), CORSRequestHandler)
+httpd.serve_forever()
diff --git a/engine b/engine
-Subproject 89ed3b75abde2bc08eb1638d5c0becc8606e6a9
+Subproject e9b2f8b62f21ee3f8887304ebdcd625753e11b0
diff --git a/src/main.zig b/src/main.zig
index 11ee946..e8c7d8c 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -1,12 +1,96 @@
const engine = @import("engine");
const input = engine.input;
-pub fn init() void {}
+pub fn init() void {
+ engine.print("Hello Synth!", .{});
+}
+
pub fn update(dt: f32) void {
_ = dt;
+ engine.webgl.viewportToScreen();
+ engine.webgl.clear(engine.Color.blue);
}
+
pub fn handleInput(ev: input.InputEvent) void {
- _ = ev;
+ switch (ev) {
+ .key => |k| {
+ for (mappings, 0..) |map, i| {
+ if (k.codepoint == map[0] and !k.is_repeat) {
+ sine_counters[i][0] = k.is_down;
+ if (k.is_down) {
+ sine_counters[i][2] = 1.0;
+ }
+ }
+ }
+ },
+ else => {},
+ }
+}
+
+var sine_counters = [1]struct { bool, f32, f32 }{.{ false, 0, 0 }} ** mappings.len;
+
+const mappings = [_]struct { u32, f32 }{
+ .{ 'a', c4_hz },
+ .{ 'w', csharp4_hz },
+ .{ 's', d4_hz },
+ .{ 'e', dsharp4_hz },
+ .{ 'd', e4_hz },
+ .{ 'f', f4_hz },
+ .{ 't', fsharp4_hz },
+ .{ 'g', g4_hz },
+ .{ 'y', gsharp4_hz },
+ .{ 'h', a4_hz },
+ .{ 'u', asharp4_hz },
+ .{ 'j', b4_hz },
+};
+
+const c4_hz = 261.626;
+const csharp4_hz = 277.1826;
+const d4_hz = 293.6648;
+const dsharp4_hz = 311.1270;
+const e4_hz = 329.6276;
+const f4_hz = 349.2282;
+const fsharp4_hz = 369.9944;
+const g4_hz = 391.9954;
+const gsharp4_hz = 415.3047;
+const a4_hz = 440.0000;
+const asharp4_hz = 466.1638;
+const b4_hz = 493.8833;
+
+const c5_hz = 523.251;
+const loudness = 0.5;
+
+pub fn audioCallback(info: engine.wasm.AudioInfo) void {
+ const math = engine.math;
+
+ for (info.write_area, 0..) |channel, channel_i| {
+ if (channel_i == 0) {
+ for (channel) |*s| {
+ s.* = 0;
+ var tone_count: f32 = 0;
+ for (&sine_counters, mappings) |*counter, mapping| {
+ if (!counter[0] and counter[2] < 0.0001) continue;
+ const incr = mapping[1] / @as(f32, @floatFromInt(info.sample_rate));
+ const v = @sin(2 * math.pi * counter[1]);
+
+ if (counter[0]) {
+ s.* += v;
+ } else {
+ s.* += v * counter[2];
+ counter[2] *= 0.999;
+ }
+
+ counter[1] += incr;
+ if (counter[1] > 1.0) counter[1] -= 1.0;
+ tone_count += 1;
+ }
+ s.* /= tone_count;
+ s.* *= loudness;
+ }
+ } else {
+ @memcpy(channel, info.write_area[channel_i - 1]);
+ }
+ }
}
comptime {