diff --git a/src/platform/raylib.zig b/src/platform/raylib.zig index b455629..5b3dd98 100644 --- a/src/platform/raylib.zig +++ b/src/platform/raylib.zig @@ -12,6 +12,10 @@ pub const Driver = struct { rgba_buffer: [256 * 240]u32 = [_]u32{0xFF000000} ** (256 * 240), + audio_ring: [16384]i16 = [_]i16{0} ** 16384, + audio_ring_head: usize = 0, + audio_ring_tail: usize = 0, + event_queue: [16]platform.Event = undefined, event_head: usize = 0, event_tail: usize = 0, @@ -21,7 +25,7 @@ pub const Driver = struct { c.SetTargetFPS(60); c.InitAudioDevice(); - c.SetAudioStreamBufferSizeDefault(2048); + c.SetAudioStreamBufferSizeDefault(1024); const stream = c.LoadAudioStream(44100, 16, 1); c.PlayAudioStream(stream); @@ -116,8 +120,39 @@ pub const Driver = struct { pub fn queueAudio(self: *Driver, output: usize, buffer: contract.AudioBuffer) void { _ = output; - if (buffer.frames > 0) { - c.UpdateAudioStream(self.audio_stream, buffer.data.ptr, @intCast(buffer.frames)); + if (buffer.frames == 0) return; + + const samples = std.mem.bytesAsSlice(i16, buffer.data); + for (samples[0..@min(samples.len, buffer.frames)]) |s| { + const next = (self.audio_ring_head + 1) % self.audio_ring.len; + if (next != self.audio_ring_tail) { + self.audio_ring[self.audio_ring_head] = s; + self.audio_ring_head = next; + } + } + + self.flushAudio(); + } + + fn flushAudio(self: *Driver) void { + while (c.IsAudioStreamProcessed(self.audio_stream)) { + var chunk: [512]i16 = undefined; + var count: usize = 0; + + // Measure available samples in ring buffer + const available = if (self.audio_ring_head >= self.audio_ring_tail) + self.audio_ring_head - self.audio_ring_tail + else + self.audio_ring.len - self.audio_ring_tail + self.audio_ring_head; + + if (available < chunk.len) break; + + while (count < chunk.len) : (count += 1) { + chunk[count] = self.audio_ring[self.audio_ring_tail]; + self.audio_ring_tail = (self.audio_ring_tail + 1) % self.audio_ring.len; + } + + c.UpdateAudioStream(self.audio_stream, &chunk, @intCast(count)); } }