Skip to content

Commit

Permalink
Added Dac to smooth audio signals and remove unneeded code
Browse files Browse the repository at this point in the history
Signed-off-by: Amjad Alsharafi <[email protected]>
  • Loading branch information
Amjad50 committed Dec 21, 2024
1 parent 5b99b87 commit 19cb6c5
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 129 deletions.
73 changes: 73 additions & 0 deletions plastic_core/src/apu2a03/channel.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use serde::{Deserialize, Serialize};
use std::{
collections::VecDeque,
ops::{Deref, DerefMut},
};

pub trait APUChannel: Serialize + for<'de> Deserialize<'de> {
fn get_output(&mut self) -> f32;
}

pub trait TimedAPUChannel: APUChannel {
fn timer_clock(&mut self);
}

#[derive(Serialize, Deserialize)]
pub struct BufferedChannel {
buffer: VecDeque<f32>,
}

impl BufferedChannel {
pub fn new() -> Self {
Self {
buffer: VecDeque::new(),
}
}

pub fn recored_sample(&mut self, sample: f32) {
self.buffer.push_back(sample);
}

pub fn take_buffer(&mut self) -> Vec<f32> {
self.buffer.drain(..).collect()
}
}

#[derive(Serialize, Deserialize)]
#[serde(bound = "C: APUChannel")]
pub struct Dac<C: APUChannel> {
capacitor: f32,
channel: C,
}

impl<C: APUChannel> Dac<C> {
pub fn new(channel: C) -> Self {
Self {
capacitor: 0.,
channel,
}
}

pub fn dac_output(&mut self) -> f32 {
let dac_in = self.channel.get_output() / 2.2;
let dac_out = dac_in - self.capacitor;

self.capacitor = dac_in - dac_out * 0.996;

dac_out
}
}

impl<C: APUChannel> Deref for Dac<C> {
type Target = C;

fn deref(&self) -> &Self::Target {
&self.channel
}
}

impl<C: APUChannel> DerefMut for Dac<C> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.channel
}
}
2 changes: 1 addition & 1 deletion plastic_core/src/apu2a03/channels/dmc.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::super::tone_source::{APUChannel, TimedAPUChannel};
use super::super::channel::{APUChannel, TimedAPUChannel};
use serde::{Deserialize, Serialize};

const DMC_PERIOD_RATES_NTSC: [u16; 0x10] = [
Expand Down
2 changes: 1 addition & 1 deletion plastic_core/src/apu2a03/channels/noise.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::super::channel::{APUChannel, TimedAPUChannel};
use super::super::envelope::{EnvelopeGenerator, EnvelopedChannel};
use super::super::tone_source::{APUChannel, TimedAPUChannel};
use serde::{Deserialize, Serialize};

/// Table for NTSC only
Expand Down
2 changes: 1 addition & 1 deletion plastic_core/src/apu2a03/channels/square.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::super::channel::{APUChannel, TimedAPUChannel};
use super::super::envelope::{EnvelopeGenerator, EnvelopedChannel};
use super::super::sequencer::Sequencer;
use super::super::tone_source::{APUChannel, TimedAPUChannel};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
Expand Down
2 changes: 1 addition & 1 deletion plastic_core/src/apu2a03/channels/triangle.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::super::channel::{APUChannel, TimedAPUChannel};
use super::super::sequencer::Sequencer;
use super::super::tone_source::{APUChannel, TimedAPUChannel};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
Expand Down
2 changes: 1 addition & 1 deletion plastic_core/src/apu2a03/envelope.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::tone_source::APUChannel;
use super::channel::APUChannel;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
Expand Down
3 changes: 2 additions & 1 deletion plastic_core/src/apu2a03/length_counter.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::channel::{APUChannel, TimedAPUChannel};
use super::envelope::{EnvelopeGenerator, EnvelopedChannel};
use super::tone_source::{APUChannel, TimedAPUChannel};
use serde::{Deserialize, Serialize};

const LEGNTH_COUNTER_TABLE: [u8; 0x20] = [
Expand Down Expand Up @@ -67,6 +67,7 @@ impl LengthCounter {
}

#[derive(Serialize, Deserialize)]
#[serde(bound = "C: APUChannel")]
pub struct LengthCountedChannel<C>
where
C: APUChannel,
Expand Down
55 changes: 20 additions & 35 deletions plastic_core/src/apu2a03/mod.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
mod apu2a03_registers;
mod channel;
mod channels;
mod envelope;
mod length_counter;
mod sequencer;
mod tone_source;

use crate::common::{
interconnection::{APUCPUConnection, CPUIrqProvider},
save_state::{Savable, SaveError},
CPU_FREQ,
};
use apu2a03_registers::Register;
use channel::{APUChannel, BufferedChannel, Dac, TimedAPUChannel};
use channels::{Dmc, NoiseWave, SquarePulse, TriangleWave};
use envelope::EnvelopedChannel;
use length_counter::LengthCountedChannel;
use serde::{Deserialize, Serialize};
use std::cell::Cell;
use tone_source::{APUChannel, BufferedChannel, TimedAPUChannel};

// for performance
/// The sample rate expected to get from [`NES::audio_buffer`](crate::NES::audio_buffer)
Expand All @@ -29,11 +29,11 @@ const SAMPLES_EVERY_N_APU_CLOCK: f64 = CPU_FREQ / (SAMPLE_RATE as f64);

#[derive(Serialize, Deserialize)]
pub struct APU2A03 {
square_pulse_1: LengthCountedChannel<SquarePulse>,
square_pulse_2: LengthCountedChannel<SquarePulse>,
triangle: LengthCountedChannel<TriangleWave>,
noise: LengthCountedChannel<NoiseWave>,
dmc: Dmc,
square_pulse_1: Dac<LengthCountedChannel<SquarePulse>>,
square_pulse_2: Dac<LengthCountedChannel<SquarePulse>>,
triangle: Dac<LengthCountedChannel<TriangleWave>>,
noise: Dac<LengthCountedChannel<NoiseWave>>,
dmc: Dac<Dmc>,

buffered_channel: BufferedChannel,

Expand All @@ -58,14 +58,14 @@ impl APU2A03 {
let buffered_channel = BufferedChannel::new();

Self {
square_pulse_1: LengthCountedChannel::new(SquarePulse::new(true)),
square_pulse_2: LengthCountedChannel::new(SquarePulse::new(false)),
square_pulse_1: Dac::new(LengthCountedChannel::new(SquarePulse::new(true))),
square_pulse_2: Dac::new(LengthCountedChannel::new(SquarePulse::new(false))),

triangle: LengthCountedChannel::new(TriangleWave::new()),
triangle: Dac::new(LengthCountedChannel::new(TriangleWave::new())),

noise: LengthCountedChannel::new(NoiseWave::new()),
noise: Dac::new(LengthCountedChannel::new(NoiseWave::new())),

dmc: Dmc::new(),
dmc: Dac::new(Dmc::new()),

buffered_channel,

Expand Down Expand Up @@ -385,11 +385,11 @@ impl APU2A03 {
}

fn get_mixer_output(&mut self) -> f32 {
let square_pulse_1 = self.square_pulse_1.get_output();
let square_pulse_2 = self.square_pulse_2.get_output();
let triangle = self.triangle.get_output();
let noise = self.noise.get_output();
let dmc = self.dmc.get_output();
let square_pulse_1 = self.square_pulse_1.dac_output();
let square_pulse_2 = self.square_pulse_2.dac_output();
let triangle = self.triangle.dac_output();
let noise = self.noise.dac_output();
let dmc = self.dmc.dac_output();

let pulse_out = if square_pulse_1 == 0. && square_pulse_2 == 0. {
0.
Expand Down Expand Up @@ -425,28 +425,13 @@ impl APU2A03 {
std::cmp::Ordering::Greater => self.wait_reset -= 1,
}

// after how many apu clocks a sample should be recorded
let samples_every_n_apu_clock = SAMPLES_EVERY_N_APU_CLOCK + self.offset;

self.sample_counter += 1.;
if self.sample_counter >= samples_every_n_apu_clock {
if self.sample_counter >= SAMPLES_EVERY_N_APU_CLOCK {
let output = self.get_mixer_output();

self.buffered_channel.recored_sample(output);

// check for needed change in offset
let change = if self.buffered_channel.get_is_overusing() {
-0.001
} else if self.buffered_channel.get_is_underusing() {
0.001
} else {
0.
};

self.offset += change;
self.buffered_channel.clear_using_flags();

self.sample_counter -= samples_every_n_apu_clock;
self.sample_counter -= SAMPLES_EVERY_N_APU_CLOCK;
}

// clocked on every CPU cycle
Expand All @@ -463,7 +448,7 @@ impl APU2A03 {

// this is clocked in every CPU cycle, so the numbers are multiplied by 2
match self.cycle {
7455 => {
7457 => {
self.generate_quarter_frame_clock();
}
14913 => {
Expand Down
88 changes: 0 additions & 88 deletions plastic_core/src/apu2a03/tone_source.rs

This file was deleted.

0 comments on commit 19cb6c5

Please sign in to comment.