diff --git a/src/core/apu.zig b/src/core/apu.zig index af56ef8..afa7d6b 100644 --- a/src/core/apu.zig +++ b/src/core/apu.zig @@ -20,7 +20,8 @@ const setLo = @import("../util.zig").setLo; const log = std.log.scoped(.APU); -pub const host_sample_rate = 1 << 15; +pub const host_rate = @import("../platform.zig").sample_rate; +pub const host_format = @import("../platform.zig").sample_format; pub fn read(comptime T: type, apu: *const Apu, addr: u32) ?T { const byte = @truncate(u8, addr); @@ -189,7 +190,7 @@ pub const Apu = struct { .bias = .{ .raw = 0x0200 }, .sampling_cycle = 0b00, - .stream = SDL.SDL_NewAudioStream(SDL.AUDIO_U16, 2, 1 << 15, SDL.AUDIO_U16, 2, host_sample_rate).?, + .stream = SDL.SDL_NewAudioStream(SDL.AUDIO_U16, 2, 1 << 15, host_format, 2, host_rate).?, .sched = sched, .capacitor = 0, @@ -356,7 +357,7 @@ pub const Apu = struct { defer SDL.SDL_FreeAudioStream(old_stream); self.sampling_cycle = self.bias.sampling_cycle.read(); - self.stream = SDL.SDL_NewAudioStream(SDL.AUDIO_U16, 2, @intCast(c_int, sample_rate), SDL.AUDIO_U16, 2, host_sample_rate).?; + self.stream = SDL.SDL_NewAudioStream(SDL.AUDIO_U16, 2, @intCast(c_int, sample_rate), host_format, 2, host_rate).?; } fn interval(self: *const Self) u64 { diff --git a/src/core/emu.zig b/src/core/emu.zig index a070dc3..5c77f20 100644 --- a/src/core/emu.zig +++ b/src/core/emu.zig @@ -36,7 +36,7 @@ const RunKind = enum { }; pub fn run(quit: *Atomic(bool), scheduler: *Scheduler, cpu: *Arm7tdmi, tracker: *FpsTracker) void { - const audio_sync = config.config().guest.audio_sync; + const audio_sync = config.config().guest.audio_sync and !config.config().host.mute; if (audio_sync) log.info("Audio sync enabled", .{}); if (config.config().guest.video_sync) { diff --git a/src/platform.zig b/src/platform.zig index 35752a0..e8c2a2b 100644 --- a/src/platform.zig +++ b/src/platform.zig @@ -15,6 +15,9 @@ const pitch = @import("core/ppu.zig").framebuf_pitch; const gba_width = @import("core/ppu.zig").width; const gba_height = @import("core/ppu.zig").height; +pub const sample_rate = 44100; +pub const sample_format = SDL.AUDIO_F32; + const default_title: []const u8 = "ZBA"; pub const Gui = struct { @@ -253,7 +256,6 @@ pub const Gui = struct { const Audio = struct { const Self = @This(); const log = std.log.scoped(.PlatformAudio); - const sample_rate = @import("core/apu.zig").host_sample_rate; device: SDL.SDL_AudioDeviceID, @@ -261,7 +263,7 @@ const Audio = struct { var have: SDL.SDL_AudioSpec = undefined; var want: SDL.SDL_AudioSpec = std.mem.zeroes(SDL.SDL_AudioSpec); want.freq = sample_rate; - want.format = SDL.AUDIO_U16; + want.format = sample_format; want.channels = 2; want.samples = 0x100; want.callback = Self.callback; @@ -270,7 +272,8 @@ const Audio = struct { const device = SDL.SDL_OpenAudioDevice(null, 0, &want, &have, 0); if (device == 0) panic(); - SDL.SDL_PauseAudioDevice(device, 0); // Unpause Audio + if (!config.config().host.mute) + SDL.SDL_PauseAudioDevice(device, 0); // Unpause Audio return .{ .device = device }; } @@ -281,18 +284,10 @@ const Audio = struct { } export fn callback(userdata: ?*anyopaque, stream: [*c]u8, len: c_int) void { - const apu = @ptrCast(*Apu, @alignCast(@alignOf(*Apu), userdata)); + const T = *Apu; + const apu = @ptrCast(T, @alignCast(@alignOf(T), userdata)); - // TODO: Find a better way to mute this - if (!config.config().host.mute) { - _ = SDL.SDL_AudioStreamGet(apu.stream, stream, len); - } else { - // FIXME: I don't think this hack to remove DC Offset is acceptable :thinking: - std.mem.set(u8, stream[0..@intCast(usize, len)], 0x40); - } - - // If we don't write anything, play silence otherwise garbage will be played - // if (written == 0) std.mem.set(u8, stream[0..@intCast(usize, len)], 0x40); + _ = SDL.SDL_AudioStreamGet(apu.stream, stream, len); } };