Compare commits
4 Commits
4b8ed3cebb
...
10aec67ee0
Author | SHA1 | Date |
---|---|---|
Rekai Nyangadzayi Musuka | 10aec67ee0 | |
Rekai Nyangadzayi Musuka | 4eb715a138 | |
Rekai Nyangadzayi Musuka | 14b24787ab | |
Rekai Nyangadzayi Musuka | eb7ffa29f4 |
|
@ -1,6 +1,5 @@
|
||||||
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,8 +3,6 @@ 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");
|
||||||
|
@ -20,7 +18,8 @@ const setLo = @import("../util.zig").setLo;
|
||||||
|
|
||||||
const log = std.log.scoped(.APU);
|
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 {
|
pub fn read(comptime T: type, apu: *const Apu, addr: u32) ?T {
|
||||||
const byte = @truncate(u8, addr);
|
const byte = @truncate(u8, addr);
|
||||||
|
@ -189,7 +188,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, SDL.AUDIO_U16, 2, host_sample_rate).?,
|
.stream = SDL.SDL_NewAudioStream(SDL.AUDIO_U16, 2, 1 << 15, host_format, 2, host_rate).?,
|
||||||
.sched = sched,
|
.sched = sched,
|
||||||
|
|
||||||
.capacitor = 0,
|
.capacitor = 0,
|
||||||
|
@ -356,7 +355,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), 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 {
|
fn interval(self: *const Self) u64 {
|
||||||
|
@ -456,8 +455,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,9 +1,7 @@
|
||||||
|
//! 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,7 +2,6 @@ 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,8 +2,6 @@ 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,10 +1,6 @@
|
||||||
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,6 +1,5 @@
|
||||||
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,5 +1,4 @@
|
||||||
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");
|
||||||
|
@ -8,8 +7,6 @@ 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,9 +2,7 @@ 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,11 +1,9 @@
|
||||||
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,5 +1,3 @@
|
||||||
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,5 +1,3 @@
|
||||||
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,5 +1,3 @@
|
||||||
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,6 +1,3 @@
|
||||||
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,5 +1,3 @@
|
||||||
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,5 +1,3 @@
|
||||||
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,5 +1,3 @@
|
||||||
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;
|
|
||||||
|
|
||||||
// 228 Lines which consist of 308 dots (which are 4 cycles long)
|
/// 4 Cycles in 1 dot
|
||||||
const cycles_per_frame: u64 = 228 * (308 * 4); //280896
|
const cycles_per_dot = 4;
|
||||||
const clock_rate: u64 = 1 << 24; // 16.78MHz
|
|
||||||
|
|
||||||
// TODO: Don't truncate this, be more accurate w/ timing
|
/// The GBA draws 228 Horizontal which each consist 308 dots
|
||||||
// 59.6046447754ns (truncated to just 59ns)
|
/// (note: not all lines are visible)
|
||||||
const clock_period: u64 = std.time.ns_per_s / clock_rate;
|
const cycles_per_frame = 228 * (308 * cycles_per_dot); //280896
|
||||||
const frame_period = (clock_period * cycles_per_frame);
|
|
||||||
|
|
||||||
// 59.7275005696Hz
|
/// The GBA ARM7TDMI runs at 2^24 Hz
|
||||||
pub const frame_rate = @intToFloat(f64, std.time.ns_per_s) /
|
const clock_rate = 1 << 24; // 16.78MHz
|
||||||
((@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;
|
const audio_sync = config.config().guest.audio_sync and !config.config().host.mute;
|
||||||
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,11 +132,10 @@ 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.
|
||||||
const ns_late = timestamp -| wake_time;
|
var 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
|
||||||
|
@ -144,15 +143,18 @@ 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;
|
||||||
|
|
||||||
// // Employ several sleep calls in periods of 10ms
|
const step = 2 * std.time.ns_per_ms; // Granularity of 2ms
|
||||||
// // By doing this the behaviour should average out to be
|
const times = sleep_for / step;
|
||||||
// // more consistent
|
var i: usize = 0;
|
||||||
// const loop_count = sleep_for / step; // How many groups of 10ms
|
|
||||||
|
|
||||||
// var i: usize = 0;
|
while (i < times) : (i += 1) {
|
||||||
// while (i < loop_count) : (i += 1) std.time.sleep(step);
|
std.time.sleep(step);
|
||||||
|
|
||||||
std.time.sleep(sleep_for);
|
// Upon wakeup, check to see if this particular sleep was longer than expected
|
||||||
|
// 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,7 +1,6 @@
|
||||||
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,6 +1,5 @@
|
||||||
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,10 +11,12 @@ 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 {
|
||||||
|
@ -253,7 +255,6 @@ 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,
|
||||||
|
|
||||||
|
@ -261,16 +262,22 @@ 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 = SDL.AUDIO_U16;
|
want.format = sample_format;
|
||||||
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 };
|
||||||
}
|
}
|
||||||
|
@ -281,18 +288,10 @@ 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 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);
|
_ = 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