channel 3 audio

This commit is contained in:
Alex Janka 2023-02-20 14:26:30 +11:00
parent 62b7bced99
commit 83080ed806
5 changed files with 107 additions and 20 deletions

16
Cargo.lock generated
View file

@ -279,6 +279,12 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
[[package]]
name = "either"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]] [[package]]
name = "errno" name = "errno"
version = "0.2.8" version = "0.2.8"
@ -413,6 +419,7 @@ dependencies = [
"cpal", "cpal",
"futures", "futures",
"gilrs", "gilrs",
"itertools",
"minifb", "minifb",
"once_cell", "once_cell",
"rand", "rand",
@ -546,6 +553,15 @@ dependencies = [
"windows-sys 0.42.0", "windows-sys 0.42.0",
] ]
[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]] [[package]]
name = "jni" name = "jni"
version = "0.19.0" version = "0.19.0"

View file

@ -17,3 +17,4 @@ ringbuf = "0.3.2"
async-ringbuf = "0.1.2" async-ringbuf = "0.1.2"
futures = "0.3.26" futures = "0.3.26"
once_cell = "1.17.1" once_cell = "1.17.1"
itertools = "0.10.5"

View file

@ -13,6 +13,7 @@ use cpal::{
Device, Stream, StreamConfig, Device, Stream, StreamConfig,
}; };
use futures::executor; use futures::executor;
use itertools::izip;
use samplerate::{ConverterType, Samplerate}; use samplerate::{ConverterType, Samplerate};
mod channels; mod channels;
@ -27,8 +28,12 @@ const fn reg(a: Address) -> usize {
impl DacSample { impl DacSample {
fn mixed(&self, mixer: &Mixer) -> Vec<f32> { fn mixed(&self, mixer: &Mixer) -> Vec<f32> {
let left = (self.one * mixer.ch1.left.scale()) + (self.two * mixer.ch2.left.scale()); let left = (self.one * mixer.ch1.left.scale())
let right = (self.one * mixer.ch1.right.scale()) + (self.two * mixer.ch2.right.scale()); + (self.two * mixer.ch2.left.scale())
+ (self.three * mixer.ch3.left.scale());
let right = (self.one * mixer.ch1.right.scale())
+ (self.two * mixer.ch2.right.scale())
+ (self.three * mixer.ch3.right.scale());
vec![ vec![
self.mix_channel(left, mixer.vol_left), self.mix_channel(left, mixer.vol_left),
self.mix_channel(right, mixer.vol_right), self.mix_channel(right, mixer.vol_right),
@ -150,18 +155,18 @@ impl Apu {
// tick sound length timers // tick sound length timers
self.channels.one.length_tick(); self.channels.one.length_tick();
self.channels.two.length_tick(); self.channels.two.length_tick();
self.channels.three.length_tick();
} }
} }
fn tick(&mut self, steps: usize) { fn tick(&mut self, steps: usize) {
self.buffer.append( self.buffer.append(
&mut self &mut izip!(
.channels self.channels.one.tick(steps).into_iter(),
.one self.channels.two.tick(steps).into_iter(),
.tick(steps) self.channels.three.tick(steps).into_iter()
.into_iter() )
.zip(self.channels.two.tick(steps).into_iter()) .map(|(one, two, three)| DacSample { one, two, three })
.map(|(one, two)| DacSample { one, two })
.collect(), .collect(),
); );
if self.buffer.len() >= CYCLES_PER_FRAME { if self.buffer.len() >= CYCLES_PER_FRAME {

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
processor::memory::Address, processor::memory::Address,
util::{get_bit, set_or_clear_bit}, util::{get_bit, set_or_clear_bit, Nibbles},
}; };
#[derive(Clone, Copy, PartialEq)] #[derive(Clone, Copy, PartialEq)]
@ -180,7 +180,7 @@ impl PwmChannel {
} }
pub(super) fn frequency_tick(&mut self) { pub(super) fn frequency_tick(&mut self) {
if self.sweep.slope == 0 || !self.enabled { if self.sweep.slope == 0 || self.sweep.pace == 0 || !self.enabled {
return; return;
} }
self.sweep.counter += 1; self.sweep.counter += 1;
@ -279,6 +279,7 @@ impl PwmChannel {
} }
} }
#[derive(Debug, PartialEq)]
enum ShiftVolumePercent { enum ShiftVolumePercent {
Zero, Zero,
TwentyFive, TwentyFive,
@ -286,6 +287,30 @@ enum ShiftVolumePercent {
OneHundred, OneHundred,
} }
impl ShiftVolumePercent {
fn as_shift_amount(&self) -> u8 {
match self {
ShiftVolumePercent::Zero => 8,
ShiftVolumePercent::TwentyFive => 2,
ShiftVolumePercent::Fifty => 1,
ShiftVolumePercent::OneHundred => 0,
}
}
}
struct WaveRam {
data: [u8; 16],
}
impl WaveRam {
fn as_samples(&self) -> Vec<u8> {
self.data
.into_iter()
.flat_map(|v| [v.get_high_nibble(), v.get_low_nibble()])
.collect()
}
}
pub(super) struct WaveChannel { pub(super) struct WaveChannel {
pub(super) enabled: bool, pub(super) enabled: bool,
dac_enabled: bool, dac_enabled: bool,
@ -295,7 +320,7 @@ pub(super) struct WaveChannel {
wavelength: u16, wavelength: u16,
wave_timer: u16, wave_timer: u16,
wave_position: usize, wave_position: usize,
wave_ram: [u8; 16], wave_ram: WaveRam,
} }
impl WaveChannel { impl WaveChannel {
@ -308,9 +333,9 @@ impl WaveChannel {
length_timer: 0xFF, length_timer: 0xFF,
volume: ShiftVolumePercent::Zero, volume: ShiftVolumePercent::Zero,
wavelength, wavelength,
wave_timer: (2048 - wavelength) * 4, wave_timer: (2048 - wavelength) * 2,
wave_position: 1, wave_position: 1,
wave_ram: [0; 16], wave_ram: WaveRam { data: [0; 16] },
} }
} }
@ -318,6 +343,41 @@ impl WaveChannel {
self.enabled = true; self.enabled = true;
} }
pub fn tick(&mut self, steps: usize) -> Vec<f32> {
if self.enabled {
(0..steps)
.map(|_| {
let b;
(self.wave_timer, b) = self.wave_timer.overflowing_sub(1);
if b {
self.wave_position = (self.wave_position + 1) % 32;
self.set_wave_timer();
}
self.dac(self.wave_ram.as_samples()[self.wave_position])
})
.collect()
} else {
vec![0.; steps]
}
}
fn dac(&self, digital: u8) -> f32 {
if self.dac_enabled && self.volume != ShiftVolumePercent::Zero {
((((digital >> self.volume.as_shift_amount()) as f32) * (-2.)) + 1.) / 15.
} else {
0.
}
}
pub(super) fn length_tick(&mut self) {
if self.length_enable && self.enabled {
self.length_timer += 1;
if self.length_timer >= 64 {
self.enabled = false;
}
}
}
pub(super) fn update_dac(&mut self, data: u8) { pub(super) fn update_dac(&mut self, data: u8) {
self.dac_enabled = get_bit(data, 7); self.dac_enabled = get_bit(data, 7);
} }
@ -337,7 +397,7 @@ impl WaveChannel {
0b10 => ShiftVolumePercent::Fifty, 0b10 => ShiftVolumePercent::Fifty,
0b11 => ShiftVolumePercent::TwentyFive, 0b11 => ShiftVolumePercent::TwentyFive,
_ => panic!("should be unreachable"), _ => panic!("should be unreachable"),
} };
} }
pub(super) fn get_volume(&self) -> u8 { pub(super) fn get_volume(&self) -> u8 {
@ -370,14 +430,14 @@ impl WaveChannel {
pub(super) fn update_wave_ram(&mut self, addr: Address, data: u8) { pub(super) fn update_wave_ram(&mut self, addr: Address, data: u8) {
let real_addr = (addr - 0xFF30) as usize; let real_addr = (addr - 0xFF30) as usize;
if real_addr >= self.wave_ram.len() { if real_addr >= self.wave_ram.data.len() {
panic!("sent the wrong address to update_wave_ram"); panic!("sent the wrong address to update_wave_ram");
} }
self.wave_ram[real_addr] = data; self.wave_ram.data[real_addr] = data;
} }
fn set_wave_timer(&mut self) { fn set_wave_timer(&mut self) {
self.wave_timer = (2048 - self.wavelength) * 4; self.wave_timer = (2048 - self.wavelength) * 2;
} }
} }

View file

@ -93,10 +93,15 @@ impl Default for Mixer {
pub(super) struct DacSample { pub(super) struct DacSample {
pub(super) one: f32, pub(super) one: f32,
pub(super) two: f32, pub(super) two: f32,
pub(super) three: f32,
} }
impl Default for DacSample { impl Default for DacSample {
fn default() -> Self { fn default() -> Self {
Self { one: 0., two: 0. } Self {
one: 0.,
two: 0.,
three: 0.,
}
} }
} }