From ac416cc72205af58f7aa5b494b00aa88dfca5e4e Mon Sep 17 00:00:00 2001 From: Theron Date: Tue, 26 Nov 2019 22:23:18 -0600 Subject: [PATCH] apu --- src/apu/mod.rs | 22 +++++++++++++++++++++ src/audio.rs | 34 ++++++++++++++++++++++++++++++++ src/{screen/mod.rs => screen.rs} | 0 3 files changed, 56 insertions(+) create mode 100644 src/audio.rs rename src/{screen/mod.rs => screen.rs} (100%) diff --git a/src/apu/mod.rs b/src/apu/mod.rs index 839d90a..3d21862 100644 --- a/src/apu/mod.rs +++ b/src/apu/mod.rs @@ -9,9 +9,13 @@ pub struct Apu { triangle: Triangle, noise: Noise, dmc: DMC, + + square_table: Vec, + tnd_table: Vec, } struct Square { + sample: u16, duty_cycle: usize, length_counter_halt: bool, // (this bit is also the envelope's loop flag) constant_volume_flag: bool, // (0: use volume from envelope; 1: use constant volume) @@ -24,6 +28,7 @@ struct Square { // $4008 Hlll.llll Triangle channel length counter halt and linear counter load (write) // bit 7 H--- ---- Halt length counter (this bit is also the linear counter's control flag) struct Triangle { + sample: u16, timer: usize, length_counter: usize, // (this bit is also the linear counter's control flag) linear_counter: usize, @@ -32,6 +37,7 @@ struct Triangle { // $400E M---.PPPP Mode and period (write) // bit 7 M--- ---- Mode flag struct Noise { + sample: u16, timer: usize, length_counter: usize, envelope: usize, @@ -45,12 +51,18 @@ struct DMC { impl Apu { fn new() -> Self { + let square_table = (0..31).map(|x| 95.52/(8128.0 / x as f32) + 100.0).collect(); + let tnd_table = (0..203).map(|x| 163.67/(24329.0 / x as f32) + 100.0).collect(); Apu { square1: Square::new(), square2: Square::new(), triangle: Triangle::new(), noise: Noise::new(), dmc: DMC::new(), + + square_table: square_table, + tnd_table: tnd_table, + } } @@ -81,4 +93,14 @@ impl Apu { 0x4017 => self.frame_counter(value), } } + + fn mix(&self) -> f32 { + let square_out = self.square_table[self.square1.sample + self.square2.sample as usize]; + let tnd_out = self.tnd_table[(3*self.triangle.sample)+(2*self.noise.sample)+self.dmc.sample as usize]; + square_out + tnd_out + } + + fn frame_counter(value: u8) { + + } } diff --git a/src/audio.rs b/src/audio.rs new file mode 100644 index 0000000..bc6b249 --- /dev/null +++ b/src/audio.rs @@ -0,0 +1,34 @@ +extern crate sdl2; + +use sdl2::audio::{AudioCallback, AudioSpecDesired}; + +pub struct Speaker { + buffer: [u8; 4096], +} + +impl AudioCallback for Speaker { + type Channel = f32; + fn callback(&mut self, out: &mut [f32]) { + for (i, x) in out.iter_mut().enumerate() { + *x = self.buffer[i]; // get data from apu + } + } +} + +pub fn initialize(context: &sdl2::Sdl) -> Result, String> { + let audio_subsystem = context.audio()?; + + let desired_spec = AudioSpecDesired { + freq: Some(44_100), + channels: Some(1), // mono + samples: 4096, // default sample size + }; + + audio_subsystem.open_playback(None, &desired_spec, |spec| { + // Show obtained AudioSpec + println!("{:?}", spec); + + // initialize the audio callback + Speaker{buffer: [0; 4096]} + }) +} \ No newline at end of file diff --git a/src/screen/mod.rs b/src/screen.rs similarity index 100% rename from src/screen/mod.rs rename to src/screen.rs