Skip to content
Snippets Groups Projects
Verified Commit 9d52f679 authored by João Magalhães's avatar João Magalhães :rocket:
Browse files

feat: initial APU and continuous audio

parent 01c26760
No related branches found
No related tags found
1 merge request!19Initial tentative audio support 🔉
Pipeline #2245 failed
use sdl2::{
audio::{AudioCallback, AudioSpecDesired},
audio::{AudioCallback, AudioDevice, AudioSpecDesired},
AudioSubsystem, Sdl,
};
use std::time::Duration;
struct SquareWave {
pub struct AudioWave {
phase_inc: f32,
phase: f32,
volume: f32,
/// The relative amount of time (as a percentage decimal) the low level
/// is going to be present during a period (cycle).
/// From [Wikipedia](https://en.wikipedia.org/wiki/Duty_cycle).
duty_cycle: f32,
}
impl AudioCallback for SquareWave {
impl AudioCallback for AudioWave {
type Channel = f32;
fn callback(&mut self, out: &mut [f32]) {
for x in out.iter_mut() {
// this is a square wave with 50% of down
// and 50% of up values
*x = if self.phase <= 0.5 {
*x = if self.phase < (1.0 - self.duty_cycle) {
self.volume
} else {
-self.volume
......@@ -28,6 +32,7 @@ impl AudioCallback for SquareWave {
}
pub struct Audio {
pub device: AudioDevice<AudioWave>,
pub audio_subsystem: AudioSubsystem,
}
......@@ -42,10 +47,11 @@ impl Audio {
};
let device = audio_subsystem
.open_playback(None, &desired_spec, |spec| SquareWave {
.open_playback(None, &desired_spec, |spec| AudioWave {
phase_inc: 440.0 / spec.freq as f32,
phase: 0.0,
volume: 0.25,
duty_cycle: 0.5,
})
.unwrap();
......@@ -53,8 +59,9 @@ impl Audio {
// device's activity
device.resume();
std::thread::sleep(Duration::from_millis(2000));
Self { audio_subsystem }
Self {
device,
audio_subsystem,
}
}
}
pub struct Apu {
}
impl Apu {
pub fn new() -> Self {
Self {}
}
pub fn read(&mut self, addr: u16) -> u8 {
match addr {
0xff26 => 1 as u8, // todo implement this
_ => 0x00
}
}
pub fn write(&mut self, addr: u16, value: u8) {
match addr {
0xff26 => {
// @todo implement the logic here
},
_ => {}
}
}
}
......@@ -7,7 +7,7 @@ use crate::{
ppu::{Ppu, PpuMode, Tile, FRAME_BUFFER_SIZE},
rom::Cartridge,
timer::Timer,
util::read_file,
util::read_file, apu::Apu,
};
#[cfg(feature = "wasm")]
......@@ -57,9 +57,10 @@ impl GameBoy {
#[cfg_attr(feature = "wasm", wasm_bindgen(constructor))]
pub fn new() -> Self {
let ppu = Ppu::new();
let apu = Apu::new();
let pad = Pad::new();
let timer = Timer::new();
let mmu = Mmu::new(ppu, pad, timer);
let mmu = Mmu::new(ppu, apu, pad, timer);
let cpu = Cpu::new(mmu);
Self { cpu }
}
......
#![allow(clippy::uninlined_format_args)]
pub mod apu;
pub mod cpu;
pub mod data;
pub mod gb;
......
use crate::{debugln, pad::Pad, ppu::Ppu, rom::Cartridge, timer::Timer};
use crate::{debugln, pad::Pad, ppu::Ppu, rom::Cartridge, timer::Timer, apu::Apu};
pub const BOOT_SIZE: usize = 2304;
pub const RAM_SIZE: usize = 8192;
......@@ -13,6 +13,11 @@ pub struct Mmu {
/// some of the access operations.
ppu: Ppu,
/// Reference to the APU (Audio Processing Unit) that is going
/// to be used both for register reading/writing and to forward
/// some of the access operations.
apu: Apu,
/// Reference to the Gamepad structure that is going to control
/// the I/O access to this device.
pad: Pad,
......@@ -44,9 +49,10 @@ pub struct Mmu {
}
impl Mmu {
pub fn new(ppu: Ppu, pad: Pad, timer: Timer) -> Self {
pub fn new(ppu: Ppu, apu: Apu, pad: Pad, timer: Timer) -> Self {
Self {
ppu,
apu,
pad,
timer,
rom: Cartridge::new(),
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment