diff options
author | alaric <alaric@netmythos.org> | 2024-04-18 05:43:45 -0700 |
---|---|---|
committer | alaric <alaric@netmythos.org> | 2024-04-18 05:43:45 -0700 |
commit | 37e8f04af45812a987a0668e81300e39460ccf70 (patch) | |
tree | a4aa87208018901ef9b2836345dfc9452d33bf0f | |
parent | fd2c21fe088654c5df56ca7275e7602246a56c4a (diff) | |
download | tiny-synth-37e8f04af45812a987a0668e81300e39460ccf70.tar.gz tiny-synth-37e8f04af45812a987a0668e81300e39460ccf70.zip |
feat: it works more or less
m--------- | engine | 0 | ||||
-rw-r--r-- | src/main.zig | 109 |
2 files changed, 94 insertions, 15 deletions
diff --git a/engine b/engine -Subproject 4bc2379da46d12143ec79230b6ee815d09605bd +Subproject 20ebeac9a56c70ffa57356ce8403caf101ee4ba diff --git a/src/main.zig b/src/main.zig index e8c7d8c..d7d3ee7 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,14 +1,91 @@ const engine = @import("engine"); +const matrix = engine.matrix; +const Mat3 = matrix.Matrix(f32, 3, 3); +const webgl = engine.webgl; const input = engine.input; +const Color = engine.Color; + +var prog: webgl.General2DSolidProgram = undefined; +var vao: webgl.VertexArrayObject = undefined; +var buf: webgl.Buffer = undefined; pub fn init() void { engine.print("Hello Synth!", .{}); + + prog = webgl.createGeneral2DSolidProgram() catch unreachable; + buf = webgl.Buffer.init(); + vao = webgl.VertexArrayObject.init(); + prog.setVertexAttribPointer(.pos, vao, buf); + const r_points: [4][2]f32 = .{ .{ 0, 0 }, .{ 1, 0 }, .{ 0, 1 }, .{ 1, 1 } }; + buf.bindAndFill(.array_buffer, .vec2, &r_points, .static_draw); + prog.use(); + vao.bind(); + prog.setUniform(.view, Mat3.identity); } +fn drawRectangle(x: f32, y: f32, width: f32, height: f32, col: engine.Color) void { + const model = Mat3.translation(.{ x, y }).scaled(.{ width, height }); + prog.setUniform(.model, model); + prog.setUniform(.color, .{ col.r, col.g, col.b }); + webgl.drawArrays(.triangle_strip, 0, 4); +} + +const key_is_black = [_]bool{ + false, + true, + false, + true, + false, + false, + true, + false, + true, + false, + true, + false, +}; + +var click_location: [2]f32 = undefined; +var is_mouse_down: bool = false; +var was_mouse_down: bool = false; + pub fn update(dt: f32) void { _ = dt; + const dims = webgl.getScreenSize(); engine.webgl.viewportToScreen(); - engine.webgl.clear(engine.Color.blue); + engine.webgl.clear(Color.rgbFromScalar(0.4)); + prog.setUniform(.projection, matrix.projectionMatrix2D(dims[0], dims[1])); + + const gap = 8.0; + const key_width = 60.0; + const key_height = 100.0; + + const total_width = @as(f32, @floatFromInt(key_is_black.len)) * (key_width + gap); + const base_y = dims[1] * 0.5 - key_height * 0.5; + + var x: f32 = dims[0] * 0.5 - total_width * 0.5; + for (0.., key_is_black) |i, is_black| { + const col: Color = if (is_black) Color.black else Color.white; + const y: f32 = if (is_black) base_y + key_height * 0.5 else base_y; + const w: f32 = key_width; + + drawRectangle(x, y, w, key_height, col); + + const click = is_mouse_down and !was_mouse_down; + const release = !is_mouse_down and was_mouse_down; + if (click or release) { + const in_rect_x = click_location[0] >= x and click_location[0] <= x + key_width; + const my = dims[1] - click_location[1]; + const in_rect_y = my >= y and my <= y + key_height; + if (in_rect_x and in_rect_y) { + sine_counters[i][0] = is_mouse_down; + } + } + + x += w + gap; + } + + was_mouse_down = is_mouse_down; } pub fn handleInput(ev: input.InputEvent) void { @@ -17,13 +94,15 @@ pub fn handleInput(ev: input.InputEvent) void { 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 => {}, + .mouse => |m| { + is_mouse_down = m.buttons.left; + if (is_mouse_down and !was_mouse_down) { + click_location = m.pos; + } + }, } } @@ -58,33 +137,33 @@ const asharp4_hz = 466.1638; const b4_hz = 493.8833; const c5_hz = 523.251; -const loudness = 0.5; +const loudness = 1.0; +const loudness_per_tone: f32 = 1.0 / @as(f32, @floatFromInt(mappings.len)); -pub fn audioCallback(info: engine.wasm.AudioInfo) void { +pub fn audioCallback(info: *const engine.wasm.AudioInfo) void { const math = engine.math; + var incr: f32 = 0.0; + var v: f32 = 0.0; 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]); + incr = mapping[1] / @as(f32, @floatFromInt(info.sample_rate)); + v = @sin(2 * math.pi * counter[1]); + s.* += v * counter[2] * loudness_per_tone; if (counter[0]) { - s.* += v; + counter[2] = math.interpolateRange(math.easeInSine, counter[2], 1.0, 0.01); } else { - s.* += v * counter[2]; - counter[2] *= 0.999; + counter[2] = math.interpolateRange(math.easeInSine, counter[2], 0.0, 0.01); } counter[1] += incr; if (counter[1] > 1.0) counter[1] -= 1.0; - tone_count += 1; } - s.* /= tone_count; s.* *= loudness; } } else { |