channel 3 audio
This commit is contained in:
parent
62b7bced99
commit
83080ed806
16
Cargo.lock
generated
16
Cargo.lock
generated
|
@ -279,6 +279,12 @@ version = "1.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.2.8"
|
||||
|
@ -413,6 +419,7 @@ dependencies = [
|
|||
"cpal",
|
||||
"futures",
|
||||
"gilrs",
|
||||
"itertools",
|
||||
"minifb",
|
||||
"once_cell",
|
||||
"rand",
|
||||
|
@ -546,6 +553,15 @@ dependencies = [
|
|||
"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]]
|
||||
name = "jni"
|
||||
version = "0.19.0"
|
||||
|
|
|
@ -17,3 +17,4 @@ ringbuf = "0.3.2"
|
|||
async-ringbuf = "0.1.2"
|
||||
futures = "0.3.26"
|
||||
once_cell = "1.17.1"
|
||||
itertools = "0.10.5"
|
||||
|
|
|
@ -13,6 +13,7 @@ use cpal::{
|
|||
Device, Stream, StreamConfig,
|
||||
};
|
||||
use futures::executor;
|
||||
use itertools::izip;
|
||||
use samplerate::{ConverterType, Samplerate};
|
||||
|
||||
mod channels;
|
||||
|
@ -27,8 +28,12 @@ const fn reg(a: Address) -> usize {
|
|||
|
||||
impl DacSample {
|
||||
fn mixed(&self, mixer: &Mixer) -> Vec<f32> {
|
||||
let left = (self.one * mixer.ch1.left.scale()) + (self.two * mixer.ch2.left.scale());
|
||||
let right = (self.one * mixer.ch1.right.scale()) + (self.two * mixer.ch2.right.scale());
|
||||
let left = (self.one * mixer.ch1.left.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![
|
||||
self.mix_channel(left, mixer.vol_left),
|
||||
self.mix_channel(right, mixer.vol_right),
|
||||
|
@ -150,18 +155,18 @@ impl Apu {
|
|||
// tick sound length timers
|
||||
self.channels.one.length_tick();
|
||||
self.channels.two.length_tick();
|
||||
self.channels.three.length_tick();
|
||||
}
|
||||
}
|
||||
|
||||
fn tick(&mut self, steps: usize) {
|
||||
self.buffer.append(
|
||||
&mut self
|
||||
.channels
|
||||
.one
|
||||
.tick(steps)
|
||||
.into_iter()
|
||||
.zip(self.channels.two.tick(steps).into_iter())
|
||||
.map(|(one, two)| DacSample { one, two })
|
||||
&mut izip!(
|
||||
self.channels.one.tick(steps).into_iter(),
|
||||
self.channels.two.tick(steps).into_iter(),
|
||||
self.channels.three.tick(steps).into_iter()
|
||||
)
|
||||
.map(|(one, two, three)| DacSample { one, two, three })
|
||||
.collect(),
|
||||
);
|
||||
if self.buffer.len() >= CYCLES_PER_FRAME {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
processor::memory::Address,
|
||||
util::{get_bit, set_or_clear_bit},
|
||||
util::{get_bit, set_or_clear_bit, Nibbles},
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
|
@ -180,7 +180,7 @@ impl PwmChannel {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
self.sweep.counter += 1;
|
||||
|
@ -279,6 +279,7 @@ impl PwmChannel {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum ShiftVolumePercent {
|
||||
Zero,
|
||||
TwentyFive,
|
||||
|
@ -286,6 +287,30 @@ enum ShiftVolumePercent {
|
|||
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) enabled: bool,
|
||||
dac_enabled: bool,
|
||||
|
@ -295,7 +320,7 @@ pub(super) struct WaveChannel {
|
|||
wavelength: u16,
|
||||
wave_timer: u16,
|
||||
wave_position: usize,
|
||||
wave_ram: [u8; 16],
|
||||
wave_ram: WaveRam,
|
||||
}
|
||||
|
||||
impl WaveChannel {
|
||||
|
@ -308,9 +333,9 @@ impl WaveChannel {
|
|||
length_timer: 0xFF,
|
||||
volume: ShiftVolumePercent::Zero,
|
||||
wavelength,
|
||||
wave_timer: (2048 - wavelength) * 4,
|
||||
wave_timer: (2048 - wavelength) * 2,
|
||||
wave_position: 1,
|
||||
wave_ram: [0; 16],
|
||||
wave_ram: WaveRam { data: [0; 16] },
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -318,6 +343,41 @@ impl WaveChannel {
|
|||
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) {
|
||||
self.dac_enabled = get_bit(data, 7);
|
||||
}
|
||||
|
@ -337,7 +397,7 @@ impl WaveChannel {
|
|||
0b10 => ShiftVolumePercent::Fifty,
|
||||
0b11 => ShiftVolumePercent::TwentyFive,
|
||||
_ => panic!("should be unreachable"),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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) {
|
||||
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");
|
||||
}
|
||||
self.wave_ram[real_addr] = data;
|
||||
self.wave_ram.data[real_addr] = data;
|
||||
}
|
||||
|
||||
fn set_wave_timer(&mut self) {
|
||||
self.wave_timer = (2048 - self.wavelength) * 4;
|
||||
self.wave_timer = (2048 - self.wavelength) * 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -93,10 +93,15 @@ impl Default for Mixer {
|
|||
pub(super) struct DacSample {
|
||||
pub(super) one: f32,
|
||||
pub(super) two: f32,
|
||||
pub(super) three: f32,
|
||||
}
|
||||
|
||||
impl Default for DacSample {
|
||||
fn default() -> Self {
|
||||
Self { one: 0., two: 0. }
|
||||
Self {
|
||||
one: 0.,
|
||||
two: 0.,
|
||||
three: 0.,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue