Compare commits
No commits in common. "10aec67ee0c5a84b6f4e7f430a77f01ecaa5ed16" and "4b8ed3cebbd43fb6af13e5cead3c5d5fbb29ec32" have entirely different histories.
10aec67ee0
...
4b8ed3cebb
|
@ -1,5 +1,6 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
const AudioDeviceId = @import("sdl2").SDL_AudioDeviceID;
|
||||||
const Arm7tdmi = @import("cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("cpu.zig").Arm7tdmi;
|
||||||
const Bios = @import("bus/Bios.zig");
|
const Bios = @import("bus/Bios.zig");
|
||||||
const Ewram = @import("bus/Ewram.zig");
|
const Ewram = @import("bus/Ewram.zig");
|
||||||
|
|
|
@ -3,6 +3,8 @@ const SDL = @import("sdl2");
|
||||||
const io = @import("bus/io.zig");
|
const io = @import("bus/io.zig");
|
||||||
const util = @import("../util.zig");
|
const util = @import("../util.zig");
|
||||||
|
|
||||||
|
const AudioDeviceId = SDL.SDL_AudioDeviceID;
|
||||||
|
|
||||||
const Arm7tdmi = @import("cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("cpu.zig").Arm7tdmi;
|
||||||
const Scheduler = @import("scheduler.zig").Scheduler;
|
const Scheduler = @import("scheduler.zig").Scheduler;
|
||||||
const ToneSweep = @import("apu/ToneSweep.zig");
|
const ToneSweep = @import("apu/ToneSweep.zig");
|
||||||
|
@ -18,8 +20,7 @@ const setLo = @import("../util.zig").setLo;
|
||||||
|
|
||||||
const log = std.log.scoped(.APU);
|
const log = std.log.scoped(.APU);
|
||||||
|
|
||||||
pub const host_rate = @import("../platform.zig").sample_rate;
|
pub const host_sample_rate = 1 << 15;
|
||||||
pub const host_format = @import("../platform.zig").sample_format;
|
|
||||||
|
|
||||||
pub fn read(comptime T: type, apu: *const Apu, addr: u32) ?T {
|
pub fn read(comptime T: type, apu: *const Apu, addr: u32) ?T {
|
||||||
const byte = @truncate(u8, addr);
|
const byte = @truncate(u8, addr);
|
||||||
|
@ -188,7 +189,7 @@ pub const Apu = struct {
|
||||||
.bias = .{ .raw = 0x0200 },
|
.bias = .{ .raw = 0x0200 },
|
||||||
|
|
||||||
.sampling_cycle = 0b00,
|
.sampling_cycle = 0b00,
|
||||||
.stream = SDL.SDL_NewAudioStream(SDL.AUDIO_U16, 2, 1 << 15, host_format, 2, host_rate).?,
|
.stream = SDL.SDL_NewAudioStream(SDL.AUDIO_U16, 2, 1 << 15, SDL.AUDIO_U16, 2, host_sample_rate).?,
|
||||||
.sched = sched,
|
.sched = sched,
|
||||||
|
|
||||||
.capacitor = 0,
|
.capacitor = 0,
|
||||||
|
@ -355,7 +356,7 @@ pub const Apu = struct {
|
||||||
defer SDL.SDL_FreeAudioStream(old_stream);
|
defer SDL.SDL_FreeAudioStream(old_stream);
|
||||||
|
|
||||||
self.sampling_cycle = self.bias.sampling_cycle.read();
|
self.sampling_cycle = self.bias.sampling_cycle.read();
|
||||||
self.stream = SDL.SDL_NewAudioStream(SDL.AUDIO_U16, 2, @intCast(c_int, sample_rate), host_format, 2, host_rate).?;
|
self.stream = SDL.SDL_NewAudioStream(SDL.AUDIO_U16, 2, @intCast(c_int, sample_rate), SDL.AUDIO_U16, 2, host_sample_rate).?;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn interval(self: *const Self) u64 {
|
fn interval(self: *const Self) u64 {
|
||||||
|
@ -455,8 +456,8 @@ const DmaSoundKind = enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const FrameSequencer = struct {
|
pub const FrameSequencer = struct {
|
||||||
|
const interval = (1 << 24) / 512;
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
pub const interval = (1 << 24) / 512;
|
|
||||||
|
|
||||||
step: u3,
|
step: u3,
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
//! Linear Feedback Shift Register
|
|
||||||
const io = @import("../../bus/io.zig");
|
const io = @import("../../bus/io.zig");
|
||||||
|
|
||||||
|
/// Linear Feedback Shift Register
|
||||||
const Scheduler = @import("../../scheduler.zig").Scheduler;
|
const Scheduler = @import("../../scheduler.zig").Scheduler;
|
||||||
|
const FrameSequencer = @import("../../apu.zig").FrameSequencer;
|
||||||
|
const Noise = @import("../Noise.zig");
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
pub const interval: u64 = (1 << 24) / (1 << 22);
|
pub const interval: u64 = (1 << 24) / (1 << 22);
|
||||||
|
|
|
@ -2,6 +2,7 @@ const std = @import("std");
|
||||||
const io = @import("../../bus/io.zig");
|
const io = @import("../../bus/io.zig");
|
||||||
|
|
||||||
const Scheduler = @import("../../scheduler.zig").Scheduler;
|
const Scheduler = @import("../../scheduler.zig").Scheduler;
|
||||||
|
const FrameSequencer = @import("../../apu.zig").FrameSequencer;
|
||||||
const ToneSweep = @import("../ToneSweep.zig");
|
const ToneSweep = @import("../ToneSweep.zig");
|
||||||
const Tone = @import("../Tone.zig");
|
const Tone = @import("../Tone.zig");
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@ const std = @import("std");
|
||||||
const io = @import("../../bus/io.zig");
|
const io = @import("../../bus/io.zig");
|
||||||
|
|
||||||
const Scheduler = @import("../../scheduler.zig").Scheduler;
|
const Scheduler = @import("../../scheduler.zig").Scheduler;
|
||||||
|
const FrameSequencer = @import("../../apu.zig").FrameSequencer;
|
||||||
|
const Wave = @import("../Wave.zig");
|
||||||
|
|
||||||
const buf_len = 0x20;
|
const buf_len = 0x20;
|
||||||
pub const interval: u64 = (1 << 24) / (1 << 22);
|
pub const interval: u64 = (1 << 24) / (1 << 22);
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const config = @import("../../config.zig");
|
const config = @import("../../config.zig");
|
||||||
|
|
||||||
|
const Bit = @import("bitfield").Bit;
|
||||||
|
const Bitfield = @import("bitfield").Bitfield;
|
||||||
|
const DateTime = @import("datetime").datetime.Datetime;
|
||||||
|
|
||||||
const Arm7tdmi = @import("../cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("../cpu.zig").Arm7tdmi;
|
||||||
const Backup = @import("backup.zig").Backup;
|
const Backup = @import("backup.zig").Backup;
|
||||||
const Gpio = @import("gpio.zig").Gpio;
|
const Gpio = @import("gpio.zig").Gpio;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Bit = @import("bitfield").Bit;
|
const Bit = @import("bitfield").Bit;
|
||||||
|
const Bitfield = @import("bitfield").Bitfield;
|
||||||
const DateTime = @import("datetime").datetime.Datetime;
|
const DateTime = @import("datetime").datetime.Datetime;
|
||||||
|
|
||||||
const Arm7tdmi = @import("../cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("../cpu.zig").Arm7tdmi;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const builtin = @import("builtin");
|
||||||
const timer = @import("timer.zig");
|
const timer = @import("timer.zig");
|
||||||
const dma = @import("dma.zig");
|
const dma = @import("dma.zig");
|
||||||
const apu = @import("../apu.zig");
|
const apu = @import("../apu.zig");
|
||||||
|
@ -7,6 +8,8 @@ const util = @import("../../util.zig");
|
||||||
const Bit = @import("bitfield").Bit;
|
const Bit = @import("bitfield").Bit;
|
||||||
const Bitfield = @import("bitfield").Bitfield;
|
const Bitfield = @import("bitfield").Bitfield;
|
||||||
const Bus = @import("../Bus.zig");
|
const Bus = @import("../Bus.zig");
|
||||||
|
const DmaController = @import("dma.zig").DmaController;
|
||||||
|
const Scheduler = @import("../scheduler.zig").Scheduler;
|
||||||
|
|
||||||
const setHi = util.setHi;
|
const setHi = util.setHi;
|
||||||
const setLo = util.setLo;
|
const setLo = util.setLo;
|
||||||
|
|
|
@ -2,7 +2,9 @@ const std = @import("std");
|
||||||
const util = @import("../../util.zig");
|
const util = @import("../../util.zig");
|
||||||
|
|
||||||
const TimerControl = @import("io.zig").TimerControl;
|
const TimerControl = @import("io.zig").TimerControl;
|
||||||
|
const Io = @import("io.zig").Io;
|
||||||
const Scheduler = @import("../scheduler.zig").Scheduler;
|
const Scheduler = @import("../scheduler.zig").Scheduler;
|
||||||
|
const Event = @import("../scheduler.zig").Event;
|
||||||
const Arm7tdmi = @import("../cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("../cpu.zig").Arm7tdmi;
|
||||||
|
|
||||||
pub const TimerTuple = std.meta.Tuple(&[_]type{ Timer(0), Timer(1), Timer(2), Timer(3) });
|
pub const TimerTuple = std.meta.Tuple(&[_]type{ Timer(0), Timer(1), Timer(2), Timer(3) });
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const util = @import("../util.zig");
|
||||||
|
|
||||||
const Bus = @import("Bus.zig");
|
const Bus = @import("Bus.zig");
|
||||||
const Bit = @import("bitfield").Bit;
|
const Bit = @import("bitfield").Bit;
|
||||||
const Bitfield = @import("bitfield").Bitfield;
|
const Bitfield = @import("bitfield").Bitfield;
|
||||||
const Scheduler = @import("scheduler.zig").Scheduler;
|
const Scheduler = @import("scheduler.zig").Scheduler;
|
||||||
|
const FilePaths = @import("../util.zig").FilePaths;
|
||||||
const Logger = @import("../util.zig").Logger;
|
const Logger = @import("../util.zig").Logger;
|
||||||
|
|
||||||
const File = std.fs.File;
|
const File = std.fs.File;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
const Bus = @import("../../Bus.zig");
|
const Bus = @import("../../Bus.zig");
|
||||||
const Arm7tdmi = @import("../../cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("../../cpu.zig").Arm7tdmi;
|
||||||
const InstrFn = @import("../../cpu.zig").arm.InstrFn;
|
const InstrFn = @import("../../cpu.zig").arm.InstrFn;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
const Bus = @import("../../Bus.zig");
|
const Bus = @import("../../Bus.zig");
|
||||||
const Arm7tdmi = @import("../../cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("../../cpu.zig").Arm7tdmi;
|
||||||
const InstrFn = @import("../../cpu.zig").arm.InstrFn;
|
const InstrFn = @import("../../cpu.zig").arm.InstrFn;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
const Bus = @import("../../Bus.zig");
|
const Bus = @import("../../Bus.zig");
|
||||||
const Arm7tdmi = @import("../../cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("../../cpu.zig").Arm7tdmi;
|
||||||
const InstrFn = @import("../../cpu.zig").arm.InstrFn;
|
const InstrFn = @import("../../cpu.zig").arm.InstrFn;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const util = @import("../../../util.zig");
|
||||||
|
|
||||||
const shifter = @import("../barrel_shifter.zig");
|
const shifter = @import("../barrel_shifter.zig");
|
||||||
const Bus = @import("../../Bus.zig");
|
const Bus = @import("../../Bus.zig");
|
||||||
const Arm7tdmi = @import("../../cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("../../cpu.zig").Arm7tdmi;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
const Arm7tdmi = @import("../cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("../cpu.zig").Arm7tdmi;
|
||||||
const CPSR = @import("../cpu.zig").PSR;
|
const CPSR = @import("../cpu.zig").PSR;
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
const Bus = @import("../../Bus.zig");
|
const Bus = @import("../../Bus.zig");
|
||||||
const Arm7tdmi = @import("../../cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("../../cpu.zig").Arm7tdmi;
|
||||||
const InstrFn = @import("../../cpu.zig").thumb.InstrFn;
|
const InstrFn = @import("../../cpu.zig").thumb.InstrFn;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
const Bus = @import("../../Bus.zig");
|
const Bus = @import("../../Bus.zig");
|
||||||
const Arm7tdmi = @import("../../cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("../../cpu.zig").Arm7tdmi;
|
||||||
const InstrFn = @import("../../cpu.zig").thumb.InstrFn;
|
const InstrFn = @import("../../cpu.zig").thumb.InstrFn;
|
||||||
|
|
|
@ -2,29 +2,29 @@ const std = @import("std");
|
||||||
const SDL = @import("sdl2");
|
const SDL = @import("sdl2");
|
||||||
const config = @import("../config.zig");
|
const config = @import("../config.zig");
|
||||||
|
|
||||||
|
const Bus = @import("Bus.zig");
|
||||||
const Scheduler = @import("scheduler.zig").Scheduler;
|
const Scheduler = @import("scheduler.zig").Scheduler;
|
||||||
const Arm7tdmi = @import("cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("cpu.zig").Arm7tdmi;
|
||||||
const FpsTracker = @import("../util.zig").FpsTracker;
|
const FpsTracker = @import("../util.zig").FpsTracker;
|
||||||
|
const FilePaths = @import("../util.zig").FilePaths;
|
||||||
|
|
||||||
const Timer = std.time.Timer;
|
const Timer = std.time.Timer;
|
||||||
|
const Thread = std.Thread;
|
||||||
const Atomic = std.atomic.Atomic;
|
const Atomic = std.atomic.Atomic;
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
/// 4 Cycles in 1 dot
|
// 228 Lines which consist of 308 dots (which are 4 cycles long)
|
||||||
const cycles_per_dot = 4;
|
const cycles_per_frame: u64 = 228 * (308 * 4); //280896
|
||||||
|
const clock_rate: u64 = 1 << 24; // 16.78MHz
|
||||||
|
|
||||||
/// The GBA draws 228 Horizontal which each consist 308 dots
|
// TODO: Don't truncate this, be more accurate w/ timing
|
||||||
/// (note: not all lines are visible)
|
// 59.6046447754ns (truncated to just 59ns)
|
||||||
const cycles_per_frame = 228 * (308 * cycles_per_dot); //280896
|
const clock_period: u64 = std.time.ns_per_s / clock_rate;
|
||||||
|
const frame_period = (clock_period * cycles_per_frame);
|
||||||
|
|
||||||
/// The GBA ARM7TDMI runs at 2^24 Hz
|
// 59.7275005696Hz
|
||||||
const clock_rate = 1 << 24; // 16.78MHz
|
pub const frame_rate = @intToFloat(f64, std.time.ns_per_s) /
|
||||||
|
((@intToFloat(f64, std.time.ns_per_s) / @intToFloat(f64, clock_rate)) * @intToFloat(f64, cycles_per_frame));
|
||||||
/// The # of nanoseconds a frame should take
|
|
||||||
const frame_period = (std.time.ns_per_s * cycles_per_frame) / clock_rate;
|
|
||||||
|
|
||||||
/// Exact Value: 59.7275005696Hz
|
|
||||||
/// The inverse of the frame period
|
|
||||||
pub const frame_rate: f64 = @intToFloat(f64, clock_rate) / cycles_per_frame;
|
|
||||||
|
|
||||||
const log = std.log.scoped(.Emulation);
|
const log = std.log.scoped(.Emulation);
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ const RunKind = enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn run(quit: *Atomic(bool), scheduler: *Scheduler, cpu: *Arm7tdmi, tracker: *FpsTracker) void {
|
pub fn run(quit: *Atomic(bool), scheduler: *Scheduler, cpu: *Arm7tdmi, tracker: *FpsTracker) void {
|
||||||
const audio_sync = config.config().guest.audio_sync and !config.config().host.mute;
|
const audio_sync = config.config().guest.audio_sync;
|
||||||
if (audio_sync) log.info("Audio sync enabled", .{});
|
if (audio_sync) log.info("Audio sync enabled", .{});
|
||||||
|
|
||||||
if (config.config().guest.video_sync) {
|
if (config.config().guest.video_sync) {
|
||||||
|
@ -132,10 +132,11 @@ fn videoSync(timer: *Timer, wake_time: u64) u64 {
|
||||||
|
|
||||||
// TODO: Better sleep impl?
|
// TODO: Better sleep impl?
|
||||||
fn sleep(timer: *Timer, wake_time: u64) ?u64 {
|
fn sleep(timer: *Timer, wake_time: u64) ?u64 {
|
||||||
|
// const step = std.time.ns_per_ms * 10; // 10ms
|
||||||
const timestamp = timer.read();
|
const timestamp = timer.read();
|
||||||
|
|
||||||
// ns_late is non zero if we are late.
|
// ns_late is non zero if we are late.
|
||||||
var ns_late = timestamp -| wake_time;
|
const ns_late = timestamp -| wake_time;
|
||||||
|
|
||||||
// If we're more than a frame late, skip the rest of this loop
|
// If we're more than a frame late, skip the rest of this loop
|
||||||
// Recalculate what our new wake time should be so that we can
|
// Recalculate what our new wake time should be so that we can
|
||||||
|
@ -143,18 +144,15 @@ fn sleep(timer: *Timer, wake_time: u64) ?u64 {
|
||||||
if (ns_late > frame_period) return timestamp + frame_period;
|
if (ns_late > frame_period) return timestamp + frame_period;
|
||||||
const sleep_for = frame_period - ns_late;
|
const sleep_for = frame_period - ns_late;
|
||||||
|
|
||||||
const step = 2 * std.time.ns_per_ms; // Granularity of 2ms
|
// // Employ several sleep calls in periods of 10ms
|
||||||
const times = sleep_for / step;
|
// // By doing this the behaviour should average out to be
|
||||||
var i: usize = 0;
|
// // more consistent
|
||||||
|
// const loop_count = sleep_for / step; // How many groups of 10ms
|
||||||
|
|
||||||
while (i < times) : (i += 1) {
|
// var i: usize = 0;
|
||||||
std.time.sleep(step);
|
// while (i < loop_count) : (i += 1) std.time.sleep(step);
|
||||||
|
|
||||||
// Upon wakeup, check to see if this particular sleep was longer than expected
|
std.time.sleep(sleep_for);
|
||||||
// if so we should exit early, but probably not skip a whole frame period
|
|
||||||
ns_late = timer.read() -| wake_time;
|
|
||||||
if (ns_late > frame_period) return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const io = @import("bus/io.zig");
|
const io = @import("bus/io.zig");
|
||||||
|
|
||||||
|
const EventKind = @import("scheduler.zig").EventKind;
|
||||||
const Scheduler = @import("scheduler.zig").Scheduler;
|
const Scheduler = @import("scheduler.zig").Scheduler;
|
||||||
const Arm7tdmi = @import("cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("cpu.zig").Arm7tdmi;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
const Bus = @import("Bus.zig");
|
||||||
const Arm7tdmi = @import("cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("cpu.zig").Arm7tdmi;
|
||||||
const Clock = @import("bus/gpio.zig").Clock;
|
const Clock = @import("bus/gpio.zig").Clock;
|
||||||
|
|
||||||
|
|
|
@ -11,12 +11,10 @@ const FpsTracker = @import("util.zig").FpsTracker;
|
||||||
|
|
||||||
const span = @import("util.zig").span;
|
const span = @import("util.zig").span;
|
||||||
|
|
||||||
|
const pitch = @import("core/ppu.zig").framebuf_pitch;
|
||||||
const gba_width = @import("core/ppu.zig").width;
|
const gba_width = @import("core/ppu.zig").width;
|
||||||
const gba_height = @import("core/ppu.zig").height;
|
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";
|
const default_title: []const u8 = "ZBA";
|
||||||
|
|
||||||
pub const Gui = struct {
|
pub const Gui = struct {
|
||||||
|
@ -255,6 +253,7 @@ pub const Gui = struct {
|
||||||
const Audio = struct {
|
const Audio = struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
const log = std.log.scoped(.PlatformAudio);
|
const log = std.log.scoped(.PlatformAudio);
|
||||||
|
const sample_rate = @import("core/apu.zig").host_sample_rate;
|
||||||
|
|
||||||
device: SDL.SDL_AudioDeviceID,
|
device: SDL.SDL_AudioDeviceID,
|
||||||
|
|
||||||
|
@ -262,22 +261,16 @@ const Audio = struct {
|
||||||
var have: SDL.SDL_AudioSpec = undefined;
|
var have: SDL.SDL_AudioSpec = undefined;
|
||||||
var want: SDL.SDL_AudioSpec = std.mem.zeroes(SDL.SDL_AudioSpec);
|
var want: SDL.SDL_AudioSpec = std.mem.zeroes(SDL.SDL_AudioSpec);
|
||||||
want.freq = sample_rate;
|
want.freq = sample_rate;
|
||||||
want.format = sample_format;
|
want.format = SDL.AUDIO_U16;
|
||||||
want.channels = 2;
|
want.channels = 2;
|
||||||
want.samples = 0x100;
|
want.samples = 0x100;
|
||||||
want.callback = Self.callback;
|
want.callback = Self.callback;
|
||||||
want.userdata = apu;
|
want.userdata = apu;
|
||||||
|
|
||||||
std.debug.assert(sample_format == SDL.AUDIO_F32);
|
|
||||||
log.info("Host Sample Rate: {}Hz, Host Format: SDL.AUDIO_F32", .{sample_rate});
|
|
||||||
|
|
||||||
const device = SDL.SDL_OpenAudioDevice(null, 0, &want, &have, 0);
|
const device = SDL.SDL_OpenAudioDevice(null, 0, &want, &have, 0);
|
||||||
if (device == 0) panic();
|
if (device == 0) panic();
|
||||||
|
|
||||||
if (!config.config().host.mute) {
|
SDL.SDL_PauseAudioDevice(device, 0); // Unpause Audio
|
||||||
SDL.SDL_PauseAudioDevice(device, 0); // Unpause Audio
|
|
||||||
log.info("Unpaused Device", .{});
|
|
||||||
}
|
|
||||||
|
|
||||||
return .{ .device = device };
|
return .{ .device = device };
|
||||||
}
|
}
|
||||||
|
@ -288,10 +281,18 @@ const Audio = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
export fn callback(userdata: ?*anyopaque, stream: [*c]u8, len: c_int) void {
|
export fn callback(userdata: ?*anyopaque, stream: [*c]u8, len: c_int) void {
|
||||||
const T = *Apu;
|
const apu = @ptrCast(*Apu, @alignCast(@alignOf(*Apu), userdata));
|
||||||
const apu = @ptrCast(T, @alignCast(@alignOf(T), userdata));
|
|
||||||
|
|
||||||
_ = SDL.SDL_AudioStreamGet(apu.stream, stream, len);
|
// 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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue