From 5e2b4bbbc602344ff43e4499cc80c866a2b934c2 Mon Sep 17 00:00:00 2001 From: zenith391 <39484230+zenith391@users.noreply.github.com> Date: Thu, 21 Dec 2023 22:41:35 +0100 Subject: [PATCH] wasm: fix audio --- examples/media-player.zig | 10 +++++++--- src/audio.zig | 2 +- src/backends/macos/backend.zig | 2 +- src/backends/wasm/backend.zig | 6 +++--- src/backends/wasm/capy.js | 18 ++++++++++-------- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/examples/media-player.zig b/examples/media-player.zig index 61200713..d4ac4374 100644 --- a/examples/media-player.zig +++ b/examples/media-player.zig @@ -14,9 +14,13 @@ fn sine(generator: *const capy.audio.AudioGenerator, time: u64, n_frames: u32) v var i: u32 = 0; const frequency = pitch.get(); + const seconds_per_frame = 1.0 / 44100.0; + + const time_seconds: f64 = @as(f64, @floatFromInt(time)) / 44100.0; + while (i < n_frames) : (i += 1) { - const inner_time = @as(f32, @floatFromInt((time + i) % 44100)) / 44100 * frequency * 2 * std.math.pi; - const value = @sin(inner_time); + const inner_time = (time_seconds + @as(f64, @floatFromInt(i)) * seconds_per_frame) * 2 * std.math.pi * frequency; + const value: f32 = @floatCast(@sin(inner_time)); left[i] = value; right[i] = value; } @@ -36,7 +40,7 @@ pub fn main() !void { capy.alignment(.{}, capy.column(.{}, .{ rotatingDisc(), // TODO capy.label(.{ .text = "Audio Name", .alignment = .Center }), - capy.slider(.{ .min = 20, .max = 2000, .step = 1 }) + capy.slider(.{ .min = 40, .max = 2000, .step = 1 }) .bind("value", &pitch), })), ); diff --git a/src/audio.zig b/src/audio.zig index c55b5f62..7c300710 100644 --- a/src/audio.zig +++ b/src/audio.zig @@ -83,7 +83,7 @@ pub fn backendUpdate() void { generatorsMutex.lock(); defer generatorsMutex.unlock(); for (generators.items) |generator| { - generator.onWriteRequested(44100); + generator.onWriteRequested(4410); } } diff --git a/src/backends/macos/backend.zig b/src/backends/macos/backend.zig index 36a03669..1ce5e7d3 100644 --- a/src/backends/macos/backend.zig +++ b/src/backends/macos/backend.zig @@ -13,7 +13,7 @@ const MouseButton = shared.MouseButton; // pub const PeerType = *opaque {}; pub const PeerType = objc.id; -const atomicValue = if (@hasDecl(std.atomic,"Value")) std.atomic.Value else std.atomic.Atomic; // support zig 0.11 as well as current master +const atomicValue = if (@hasDecl(std.atomic, "Value")) std.atomic.Value else std.atomic.Atomic; // support zig 0.11 as well as current master var activeWindows = atomicValue(usize).init(0); var hasInit: bool = false; diff --git a/src/backends/wasm/backend.zig b/src/backends/wasm/backend.zig index 70353e43..bc59653c 100644 --- a/src/backends/wasm/backend.zig +++ b/src/backends/wasm/backend.zig @@ -566,11 +566,11 @@ pub const AudioGenerator = struct { const channels = 2; const channelDatas = try allocator.alloc([]f32, channels); for (channelDatas) |*buffer| { - buffer.* = try allocator.alloc(f32, 44100); // 1 second of buffer + buffer.* = try allocator.alloc(f32, 4410); // 0.1 seconds of buffer @memset(buffer.*, 0); } return AudioGenerator{ - .source = js.createSource(sampleRate, 500.0), + .source = js.createSource(sampleRate, 0.1), .buffers = channelDatas, }; } @@ -583,7 +583,7 @@ pub const AudioGenerator = struct { js.audioCopyToChannel( self.source, self.buffers[channel].ptr, - self.buffers[channel].len, + self.buffers[channel].len * @sizeOf(f32), channel, ); } diff --git a/src/backends/wasm/capy.js b/src/backends/wasm/capy.js index 6aab46b5..01197963 100644 --- a/src/backends/wasm/capy.js +++ b/src/backends/wasm/capy.js @@ -478,7 +478,7 @@ let env = { source: source, frameCount: frameCount, nextUpdate: audioContext.currentTime, - soundBuffer: new SoundBuffer(audioContext, 44100, 6, false), + soundBuffer: new SoundBuffer(audioContext, 44100, 6, true), }; return audioSources.push(audioSource) - 1; }, @@ -585,22 +585,24 @@ async function loadExtras() { } drawCommands = []; + requestAnimationFrame(update); + } + //setInterval(update, 32); + requestAnimationFrame(update); + + function audioUpdate() { // Audio const latency = 0.1; // The latency we want, in seconds. - if (audioContext.currentTime > lastAudioUpdateTime - latency) { + if (audioContext.currentTime > lastAudioUpdateTime + latency) { // Trigger an event so the audio buffer is refilled pushEvent({ type: 6, args: [], }); - lastAudioUpdateTime += latency; + lastAudioUpdateTime = audioContext.currentTime - 0.01; } - - - requestAnimationFrame(update); } - //setInterval(update, 32); - requestAnimationFrame(update); + setInterval(audioUpdate, 50); window.onresize = function() { pushEvent({ type: 0, target: rootElementId });