fix: SDL3 Audio enabled again (poor sync)
This commit is contained in:
@@ -39,7 +39,6 @@ pub fn build(b: *std.Build) void {
|
|||||||
// Later on we'll use this module as the root module of a test executable
|
// Later on we'll use this module as the root module of a test executable
|
||||||
// which requires us to specify a target.
|
// which requires us to specify a target.
|
||||||
.target = target,
|
.target = target,
|
||||||
.link_libc = true,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Here we define an executable. An executable needs to have a root module
|
// Here we define an executable. An executable needs to have a root module
|
||||||
|
|||||||
@@ -247,7 +247,9 @@ pub const Apu = struct {
|
|||||||
|
|
||||||
sampling_cycle: u2,
|
sampling_cycle: u2,
|
||||||
|
|
||||||
stream: *c.SDL_AudioStream,
|
// NB: This AudioStream is owned by platform.zig
|
||||||
|
stream: ?*c.SDL_AudioStream = null,
|
||||||
|
|
||||||
sched: *Scheduler,
|
sched: *Scheduler,
|
||||||
|
|
||||||
fs: FrameSequencer,
|
fs: FrameSequencer,
|
||||||
@@ -273,7 +275,6 @@ pub const Apu = struct {
|
|||||||
|
|
||||||
.sampling_cycle = 0b00,
|
.sampling_cycle = 0b00,
|
||||||
.sched = sched,
|
.sched = sched,
|
||||||
.stream = undefined, // FIXME: bad practice
|
|
||||||
|
|
||||||
.capacitor = 0,
|
.capacitor = 0,
|
||||||
.fs = FrameSequencer.init(),
|
.fs = FrameSequencer.init(),
|
||||||
@@ -461,32 +462,23 @@ pub const Apu = struct {
|
|||||||
if (self.sampling_cycle != self.bias.sampling_cycle.read()) self.replaceSDLResampler();
|
if (self.sampling_cycle != self.bias.sampling_cycle.read()) self.replaceSDLResampler();
|
||||||
|
|
||||||
const ret = c.SDL_PutAudioStreamData(self.stream, &[2]i16{ @bitCast(ext_left ^ 0x8000), @bitCast(ext_right ^ 0x8000) }, 2 * @sizeOf(i16));
|
const ret = c.SDL_PutAudioStreamData(self.stream, &[2]i16{ @bitCast(ext_left ^ 0x8000), @bitCast(ext_right ^ 0x8000) }, 2 * @sizeOf(i16));
|
||||||
if (!ret) @panic("TODO: Failed to put i16s into SDL Audio Queue");
|
if (!ret) std.debug.panic("failed to append to sample queue. SDL Error: {s}", .{c.SDL_GetError()});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn replaceSDLResampler(self: *Self) void {
|
fn replaceSDLResampler(self: *Self) void {
|
||||||
@branchHint(.cold);
|
const sample_rate = Self.sampleRate(self.bias.sampling_cycle.read());
|
||||||
_ = self;
|
log.info("Sample Rate changed from {}Hz to {}Hz", .{ Self.sampleRate(self.sampling_cycle), sample_rate });
|
||||||
|
|
||||||
// @panic("TODO: Implement Multiple Sample Rates...");
|
self.sampling_cycle = self.bias.sampling_cycle.read();
|
||||||
|
|
||||||
// const sample_rate = Self.sampleRate(self.bias.sampling_cycle.read());
|
const desired: c.SDL_AudioSpec = .{
|
||||||
// log.info("Sample Rate changed from {}Hz to {}Hz", .{ Self.sampleRate(self.sampling_cycle), sample_rate });
|
.channels = 2,
|
||||||
|
.format = c.SDL_AUDIO_S16LE,
|
||||||
|
.freq = @intCast(Self.sampleRate(self.sampling_cycle)),
|
||||||
|
};
|
||||||
|
|
||||||
// // Sampling Cycle (Sample Rate) changed, Craete a new SDL Audio Resampler
|
const ret = c.SDL_SetAudioStreamFormat(self.stream, &desired, null);
|
||||||
// // FIXME: Replace SDL's Audio Resampler with either a custom or more reliable one
|
if (!ret) std.debug.panic("failed to change sample rate. SDL Error: {s}", .{c.SDL_GetError()});
|
||||||
// const old_stream = self.stream;
|
|
||||||
// defer c.SDL_DestroyAudioStream(old_stream);
|
|
||||||
|
|
||||||
// self.sampling_cycle = self.bias.sampling_cycle.read();
|
|
||||||
|
|
||||||
// var desired: c.SDL_AudioSpec = std.mem.zeroes(c.SDL_AudioSpec);
|
|
||||||
// desired.format = c.SDL_AUDIO_S16;
|
|
||||||
// desired.channels = 2;
|
|
||||||
// desired.freq = @intCast(sample_rate);
|
|
||||||
|
|
||||||
// const new_stream = c.SDL_OpenAudioDeviceStream(c.SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &desired, null, null) orelse @panic("TODO: Failed to replace SDL Audio Stream");
|
|
||||||
// self.stream = new_stream;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn interval(self: *const Self) u64 {
|
fn interval(self: *const Self) u64 {
|
||||||
|
|||||||
@@ -160,13 +160,13 @@ pub fn runFrame(sched: *Scheduler, cpu: *Arm7tdmi) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn audioSync(audio_sync: bool, stream: *c.SDL_AudioStream, is_buffer_full: *bool) void {
|
fn audioSync(audio_sync: bool, stream: ?*c.SDL_AudioStream, is_buffer_full: *bool) void {
|
||||||
// comptime std.debug.assert(@import("../platform.zig").sample_format == SDL.AUDIO_U16);
|
if (stream == null) return;
|
||||||
|
|
||||||
const sample_size = 2 * @sizeOf(u16);
|
const sample_size = 2 * @sizeOf(u16);
|
||||||
const max_buf_size: c_int = 0x400;
|
const max_buf_size: c_int = 0x400;
|
||||||
|
|
||||||
_ = audio_sync;
|
_ = audio_sync;
|
||||||
_ = stream;
|
|
||||||
_ = is_buffer_full;
|
_ = is_buffer_full;
|
||||||
|
|
||||||
_ = sample_size;
|
_ = sample_size;
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ pub const Gui = struct {
|
|||||||
allocator: Allocator,
|
allocator: Allocator,
|
||||||
|
|
||||||
pub fn init(allocator: Allocator, apu: *Apu, title_opt: ?*const [12]u8) !Self {
|
pub fn init(allocator: Allocator, apu: *Apu, title_opt: ?*const [12]u8) !Self {
|
||||||
|
errdefer |err| if (err == error.sdl_error) log.err("SDL Error: {s}", .{c.SDL_GetError()});
|
||||||
|
|
||||||
c.SDL_SetMainReady();
|
c.SDL_SetMainReady();
|
||||||
|
|
||||||
try errify(c.SDL_Init(c.SDL_INIT_VIDEO | c.SDL_INIT_AUDIO | c.SDL_INIT_EVENTS));
|
try errify(c.SDL_Init(c.SDL_INIT_VIDEO | c.SDL_INIT_AUDIO | c.SDL_INIT_EVENTS));
|
||||||
@@ -200,16 +202,16 @@ pub const Gui = struct {
|
|||||||
var zgui_redraw: bool = false;
|
var zgui_redraw: bool = false;
|
||||||
|
|
||||||
switch (self.state.emulation) {
|
switch (self.state.emulation) {
|
||||||
.Transition => |inner| switch (inner) {
|
.Transition => |target| switch (target) {
|
||||||
.Active => {
|
.Active => {
|
||||||
sync.paused.store(false, .monotonic);
|
sync.paused.store(false, .monotonic);
|
||||||
// if (!config.config().host.mute) try errify(c.SDL_PauseAudioDevice(c.SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK));
|
if (!config.config().host.mute) try errify(c.SDL_ResumeAudioStreamDevice(self.audio.stream));
|
||||||
|
|
||||||
self.state.emulation = .Active;
|
self.state.emulation = .Active;
|
||||||
},
|
},
|
||||||
.Inactive => {
|
.Inactive => {
|
||||||
// Assert that double pausing is impossible
|
// Assert that double pausing is impossible
|
||||||
// try errify(c.SDL_ResumeAudioDevice(c.SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK));
|
if (!config.config().host.mute) try errify(c.SDL_PauseAudioStreamDevice(self.audio.stream));
|
||||||
sync.paused.store(true, .monotonic);
|
sync.paused.store(true, .monotonic);
|
||||||
|
|
||||||
self.state.emulation = .Inactive;
|
self.state.emulation = .Inactive;
|
||||||
@@ -233,7 +235,7 @@ pub const Gui = struct {
|
|||||||
// spurious calls to SDL_LockAudioDevice?
|
// spurious calls to SDL_LockAudioDevice?
|
||||||
|
|
||||||
try errify(c.SDL_LockAudioStream(self.audio.stream));
|
try errify(c.SDL_LockAudioStream(self.audio.stream));
|
||||||
defer errify(c.SDL_UnlockAudioStream(self.audio.stream)) catch @panic("TODO: FIXME");
|
defer errify(c.SDL_UnlockAudioStream(self.audio.stream)) catch std.debug.panic("SDL Error: {s}", .{c.SDL_GetError()});
|
||||||
|
|
||||||
zgui_redraw = imgui.draw(&self.state, sync, win_dim, cpu, out_tex[0]);
|
zgui_redraw = imgui.draw(&self.state, sync, win_dim, cpu, out_tex[0]);
|
||||||
},
|
},
|
||||||
@@ -257,17 +259,17 @@ pub const Gui = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const Audio = struct {
|
pub const Audio = struct {
|
||||||
const Self = @This();
|
const log = std.log.scoped(.platform_audio);
|
||||||
const log = std.log.scoped(.PlatformAudio);
|
|
||||||
|
|
||||||
stream: *c.SDL_AudioStream,
|
stream: *c.SDL_AudioStream,
|
||||||
|
|
||||||
fn init(apu: *Apu) !Self {
|
fn init(apu: *Apu) !@This() {
|
||||||
var desired: c.SDL_AudioSpec = std.mem.zeroes(c.SDL_AudioSpec);
|
const desired: c.SDL_AudioSpec = .{
|
||||||
desired.freq = sample_rate;
|
.freq = sample_rate,
|
||||||
desired.format = c.SDL_AUDIO_S16LE;
|
.format = c.SDL_AUDIO_S16LE,
|
||||||
desired.channels = 2;
|
.channels = 2,
|
||||||
|
};
|
||||||
|
|
||||||
log.info("Host Sample Rate: {}Hz, Host Format: SDL_AUDIO_S16LE", .{sample_rate});
|
log.info("Host Sample Rate: {}Hz, Host Format: SDL_AUDIO_S16LE", .{sample_rate});
|
||||||
|
|
||||||
@@ -278,7 +280,7 @@ const Audio = struct {
|
|||||||
return .{ .stream = stream };
|
return .{ .stream = stream };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deinit(self: *Self) void {
|
fn deinit(self: *@This()) void {
|
||||||
c.SDL_DestroyAudioStream(self.stream);
|
c.SDL_DestroyAudioStream(self.stream);
|
||||||
self.* = undefined;
|
self.* = undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user