mod channel;
mod envelope;
mod noise_channel;
mod pulse_channel;
mod wave_channel;
use bitflags::bitflags;
use save_state::Savable;
use crate::GameBoyConfig;
use channel::{ApuChannel, Dac, LengthCountedChannel};
use noise_channel::NoiseChannel;
use pulse_channel::PulseChannel;
use wave_channel::WaveChannel;
pub struct AudioBuffers<'a> {
pulse1: &'a mut Vec<f32>,
pulse2: &'a mut Vec<f32>,
wave: &'a mut Vec<f32>,
noise: &'a mut Vec<f32>,
all: &'a mut Vec<f32>,
}
impl AudioBuffers<'_> {
pub fn pulse1(&self) -> &[f32] {
self.pulse1
}
pub fn pulse2(&self) -> &[f32] {
self.pulse2
}
pub fn wave(&self) -> &[f32] {
self.wave
}
pub fn noise(&self) -> &[f32] {
self.noise
}
pub fn all(&self) -> &[f32] {
self.all
}
}
impl Drop for AudioBuffers<'_> {
fn drop(&mut self) {
self.pulse1.clear();
self.pulse2.clear();
self.wave.clear();
self.noise.clear();
self.all.clear();
}
}
bitflags! {
#[derive(Savable)]
#[savable(bitflags)]
struct ChannelsControl: u8 {
const VIN_LEFT = 1 << 7;
const VOL_LEFT = 7 << 4;
const VIN_RIGHT = 1 << 3;
const VOL_RIGHT = 7;
}
}
impl ChannelsControl {
fn vol_left(&self) -> u8 {
(self.bits() >> 4) & 7
}
fn vol_right(&self) -> u8 {
self.bits() & 7
}
}
bitflags! {
#[derive(Savable)]
#[savable(bitflags)]
struct ChannelsSelection: u8 {
const NOISE_LEFT = 1 << 7;
const WAVE_LEFT = 1 << 6;
const PULSE2_LEFT = 1 << 5;
const PULSE1_LEFT = 1 << 4;
const NOISE_RIGHT = 1 << 3;
const WAVE_RIGHT = 1 << 2;
const PULSE2_RIGHT = 1 << 1;
const PULSE1_RIGHT = 1 << 0;
}
}
#[derive(Savable)]
pub struct Apu {
pulse1: Dac<LengthCountedChannel<PulseChannel>>,
pulse2: Dac<LengthCountedChannel<PulseChannel>>,
wave: Dac<LengthCountedChannel<WaveChannel>>,
noise: Dac<LengthCountedChannel<NoiseChannel>>,
channels_control: ChannelsControl,
channels_selection: ChannelsSelection,
power: bool,
sample_counter: f64,
#[savable(skip)]
buffer: Vec<f32>,
#[savable(skip)]
pulse1_buffers: Vec<f32>,
#[savable(skip)]
pulse2_buffers: Vec<f32>,
#[savable(skip)]
wave_buffers: Vec<f32>,
#[savable(skip)]
noise_buffers: Vec<f32>,
divider_sequencer_clock_bit: bool,
sequencer_position: i8,
clocks_counter: u8,
config: GameBoyConfig,
}
impl Apu {
pub fn new(config: GameBoyConfig) -> Self {
Self {
channels_control: ChannelsControl::from_bits_truncate(0),
channels_selection: ChannelsSelection::from_bits_truncate(0),
power: false,
buffer: Vec::new(),
pulse1_buffers: Vec::new(),
pulse2_buffers: Vec::new(),
wave_buffers: Vec::new(),
noise_buffers: Vec::new(),
sample_counter: 0.,
pulse1: Dac::new(LengthCountedChannel::new(PulseChannel::default(), 64)),
pulse2: Dac::new(LengthCountedChannel::new(PulseChannel::default(), 64)),
wave: Dac::new(LengthCountedChannel::new(WaveChannel::new(config), 256)),
noise: Dac::new(LengthCountedChannel::new(NoiseChannel::default(), 64)),
divider_sequencer_clock_bit: false,
sequencer_position: 0,
clocks_counter: 0,
config,
}
}
pub fn new_skip_boot_rom(config: GameBoyConfig) -> Self {
let mut apu = Self::new(config);
apu.pulse1.channel_mut().write_pattern_duty(2);
apu.pulse1
.channel_mut()
.envelope_mut()
.write_envelope_register(0xF3);
apu.noise.write_sound_length(0x3F);
apu.channels_control = ChannelsControl::from_bits_truncate(0x77);
apu.channels_selection = ChannelsSelection::from_bits_truncate(0xF3);
apu.pulse1.set_enable(true);
apu.wave.set_dac_enable(false);
apu.power = true;
apu
}
pub fn read_register(&mut self, addr: u16) -> u8 {
match addr {
0xFF10 => 0x80 | self.pulse1.channel_mut().read_sweep_register(),
0xFF11 => 0x3F | (self.pulse1.channel_mut().read_pattern_duty() << 6),
0xFF12 => self.pulse1.channel().envelope().read_envelope_register(),
0xFF13 => 0xFF,
0xFF14 => 0xBF | ((self.pulse1.read_length_enable() as u8) << 6),
0xFF15 => 0xFF,
0xFF16 => 0x3F | (self.pulse2.channel_mut().read_pattern_duty() << 6),
0xFF17 => self.pulse2.channel().envelope().read_envelope_register(),
0xFF18 => 0xFF,
0xFF19 => 0xBF | ((self.pulse2.read_length_enable() as u8) << 6),
0xFF1A => 0x7F | ((self.wave.dac_enabled() as u8) << 7),
0xFF1B => 0xFF,
0xFF1C => 0x9F | ((self.wave.channel().read_volume()) << 5),
0xFF1D => 0xFF,
0xFF1E => 0xBF | ((self.wave.read_length_enable() as u8) << 6),
0xFF1F => 0xFF,
0xFF20 => 0xFF,
0xFF21 => self.noise.channel().envelope().read_envelope_register(),
0xFF22 => self.noise.channel().read_noise_register(),
0xFF23 => 0xBF | ((self.noise.read_length_enable() as u8) << 6),
0xFF24 => self.channels_control.bits(),
0xFF25 => self.channels_selection.bits(),
0xFF26 => {
0x70 | ((self.power as u8) << 7)
| ((self.noise.enabled() as u8) << 3)
| ((self.wave.enabled() as u8) << 2)
| ((self.pulse2.enabled() as u8) << 1)
| self.pulse1.enabled() as u8
}
0xFF27..=0xFF2F => 0xFF,
0xFF30..=0xFF3F => self.wave.channel().read_buffer((addr & 0xF) as u8),
_ => unreachable!(),
}
}
pub fn write_register(&mut self, addr: u16, data: u8) {
if !self.power && addr <= 0xFF25 && (addr % 5 != 2 || addr == 0xFF25) {
return;
}
let is_length_clock_next = self.is_length_clock_next();
match addr {
0xFF10 => self.pulse1.channel_mut().write_sweep_register(data),
0xFF11 => {
if self.power {
self.pulse1.channel_mut().write_pattern_duty(data >> 6);
}
self.pulse1.write_sound_length(data & 0x3F);
}
0xFF12 => {
self.pulse1
.channel_mut()
.envelope_mut()
.write_envelope_register(data);
self.pulse1.set_dac_enable(data & 0xF8 != 0);
}
0xFF13 => {
let freq = (self.pulse1.channel().frequency() & 0xFF00) | data as u16;
self.pulse1.channel_mut().write_frequency(freq);
}
0xFF14 => {
let freq =
(self.pulse1.channel().frequency() & 0xFF) | (((data as u16) & 0x7) << 8);
self.pulse1.channel_mut().write_frequency(freq);
Self::write_channel_length_enable_and_trigger(
&mut *self.pulse1,
is_length_clock_next,
data,
);
}
0xFF15 => {}
0xFF16 => {
if self.power {
self.pulse2.channel_mut().write_pattern_duty(data >> 6);
}
self.pulse2.write_sound_length(data & 0x3F);
}
0xFF17 => {
self.pulse2
.channel_mut()
.envelope_mut()
.write_envelope_register(data);
self.pulse2.set_dac_enable(data & 0xF8 != 0);
}
0xFF18 => {
let freq = (self.pulse2.channel().frequency() & 0xFF00) | data as u16;
self.pulse2.channel_mut().write_frequency(freq);
}
0xFF19 => {
let freq =
(self.pulse2.channel().frequency() & 0xFF) | (((data as u16) & 0x7) << 8);
self.pulse2.channel_mut().write_frequency(freq);
Self::write_channel_length_enable_and_trigger(
&mut *self.pulse2,
is_length_clock_next,
data,
);
}
0xFF1A => {
self.wave.set_dac_enable(data & 0x80 != 0);
}
0xFF1B => {
self.wave.write_sound_length(data);
}
0xFF1C => self.wave.channel_mut().write_volume((data >> 5) & 3),
0xFF1D => {
let freq = (self.wave.channel().frequency() & 0xFF00) | data as u16;
self.wave.channel_mut().write_frequency(freq);
}
0xFF1E => {
let freq = (self.wave.channel().frequency() & 0xFF) | (((data as u16) & 0x7) << 8);
self.wave.channel_mut().write_frequency(freq);
Self::write_channel_length_enable_and_trigger(
&mut *self.wave,
is_length_clock_next,
data,
);
}
0xFF1F => {}
0xFF20 => self.noise.write_sound_length(data & 0x3F),
0xFF21 => {
self.noise
.channel_mut()
.envelope_mut()
.write_envelope_register(data);
self.noise.set_dac_enable(data & 0xF8 != 0);
}
0xFF22 => self.noise.channel_mut().write_noise_register(data),
0xFF23 => {
Self::write_channel_length_enable_and_trigger(
&mut *self.noise,
is_length_clock_next,
data,
);
}
0xFF24 => self.channels_control = ChannelsControl::from_bits_truncate(data),
0xFF25 => self.channels_selection = ChannelsSelection::from_bits_truncate(data),
0xFF26 => {
let new_power = data & 0x80 != 0;
if self.power && !new_power {
self.power_off();
} else if !self.power && new_power {
self.power_on();
}
self.power = new_power;
}
0xFF27..=0xFF2F => {
}
0xFF30..=0xFF3F => {
self.wave
.channel_mut()
.write_buffer((addr & 0xF) as u8, data);
}
_ => unreachable!(),
}
}
pub fn read_pcm12(&self) -> u8 {
let p1 = self.pulse1.output() & 0xF;
let p2 = self.pulse2.output() & 0xF;
(p2 << 4) | p1
}
pub fn read_pcm34(&self) -> u8 {
let p1 = self.wave.output() & 0xF;
let p2 = self.noise.output() & 0xF;
(p2 << 4) | p1
}
pub fn get_buffers(&mut self) -> AudioBuffers<'_> {
AudioBuffers {
pulse1: &mut self.pulse1_buffers,
pulse2: &mut self.pulse2_buffers,
wave: &mut self.wave_buffers,
noise: &mut self.noise_buffers,
all: &mut self.buffer,
}
}
pub fn clock(&mut self, double_speed: bool, divider: u8) {
let clocks = (!double_speed) as u8 + 1;
self.clocks_counter += clocks;
if self.clocks_counter >= 2 {
self.clocks_counter -= 2;
} else {
return;
}
const SAMPLE_RATE: f64 = 44100.;
const SAMPLE_EVERY_N_CLOCKS: f64 = (((16384 * 256) / 4) as f64) / SAMPLE_RATE;
self.sample_counter += 1.;
if self.sample_counter >= SAMPLE_EVERY_N_CLOCKS {
self.push_output();
self.sample_counter -= SAMPLE_EVERY_N_CLOCKS;
}
if !self.power {
return;
}
self.pulse1.channel_mut().clock();
self.pulse2.channel_mut().clock();
self.wave.channel_mut().clock();
self.noise.channel_mut().clock();
let old_div_sequencer_bit = self.divider_sequencer_clock_bit;
let bit = if double_speed { 5 } else { 4 };
let new_div_sequencer_bit = (divider >> bit) & 1 == 1;
self.divider_sequencer_clock_bit = new_div_sequencer_bit;
if old_div_sequencer_bit && !new_div_sequencer_bit {
self.sequencer_position += 1;
match self.sequencer_position {
1 | 5 => {
self.pulse1.clock_length_counter();
self.pulse2.clock_length_counter();
self.wave.clock_length_counter();
self.noise.clock_length_counter();
}
3 | 7 => {
self.pulse1.channel_mut().clock_sweeper();
self.pulse1.clock_length_counter();
self.pulse2.clock_length_counter();
self.wave.clock_length_counter();
self.noise.clock_length_counter();
}
8 => {
self.pulse1.channel_mut().envelope_mut().clock();
self.pulse2.channel_mut().envelope_mut().clock();
self.noise.channel_mut().envelope_mut().clock();
self.sequencer_position = 0;
}
0 | 2 | 4 | 6 => {}
_ => unreachable!(),
}
}
}
}
impl Apu {
fn push_output(&mut self) {
let right_vol = self.channels_control.vol_right() as f32 + 1.;
let left_vol = self.channels_control.vol_left() as f32 + 1.;
let pulse1 = self.pulse1.dac_output() / 8.;
let pulse2 = self.pulse2.dac_output() / 8.;
let wave = self.wave.dac_output() / 8.;
let noise = self.noise.dac_output() / 8.;
let right_pulse1 = if self
.channels_selection
.contains(ChannelsSelection::PULSE1_RIGHT)
{
pulse1 * right_vol
} else {
0.
};
let right_pulse2 = if self
.channels_selection
.contains(ChannelsSelection::PULSE2_RIGHT)
{
pulse2 * right_vol
} else {
0.
};
let right_wave = if self
.channels_selection
.contains(ChannelsSelection::WAVE_RIGHT)
{
wave * right_vol
} else {
0.
};
let right_noise = if self
.channels_selection
.contains(ChannelsSelection::NOISE_RIGHT)
{
noise * right_vol
} else {
0.
};
let left_pulse1 = if self
.channels_selection
.contains(ChannelsSelection::PULSE1_LEFT)
{
pulse1 * left_vol
} else {
0.
};
let left_pulse2 = if self
.channels_selection
.contains(ChannelsSelection::PULSE2_LEFT)
{
pulse2 * left_vol
} else {
0.
};
let left_wave = if self
.channels_selection
.contains(ChannelsSelection::WAVE_LEFT)
{
wave * left_vol
} else {
0.
};
let left_noise = if self
.channels_selection
.contains(ChannelsSelection::NOISE_LEFT)
{
noise * left_vol
} else {
0.
};
let right_pulse1 = right_pulse1 / 5.0;
let left_pulse1 = left_pulse1 / 5.0;
let right_pulse2 = right_pulse2 / 5.0;
let left_pulse2 = left_pulse2 / 5.0;
let right_wave = right_wave / 5.0;
let left_wave = left_wave / 5.0;
let right_noise = right_noise / 5.0;
let left_noise = left_noise / 5.0;
self.pulse1_buffers.push(right_pulse1);
self.pulse1_buffers.push(left_pulse1);
self.pulse2_buffers.push(right_pulse2);
self.pulse2_buffers.push(left_pulse2);
self.wave_buffers.push(right_wave);
self.wave_buffers.push(left_wave);
self.noise_buffers.push(right_noise);
self.noise_buffers.push(left_noise);
let right_sample = right_pulse1 + right_pulse2 + right_wave + right_noise;
let left_sample = left_pulse1 + left_pulse2 + left_wave + left_noise;
self.buffer.push(right_sample);
self.buffer.push(left_sample);
}
fn power_off(&mut self) {
for i in 0xFF10..=0xFF25 {
self.write_register(i, 0);
}
self.pulse1.set_enable(false);
self.pulse2.set_enable(false);
self.wave.set_enable(false);
self.noise.set_enable(false);
}
fn power_on(&mut self) {
self.sequencer_position = 0;
if self.divider_sequencer_clock_bit {
self.sequencer_position = -1;
}
self.pulse1.channel_mut().reset_sequencer();
self.pulse2.channel_mut().reset_sequencer();
self.wave.channel_mut().reset_buffer_index();
if !self.config.is_dmg {
self.pulse1.reset_length_counter();
self.pulse2.reset_length_counter();
self.wave.reset_length_counter();
self.noise.reset_length_counter();
}
}
fn is_length_clock_next(&self) -> bool {
(self.sequencer_position + 1) % 2 != 0
}
fn write_channel_length_enable_and_trigger<C: ApuChannel>(
channel: &mut LengthCountedChannel<C>,
is_length_clock_next: bool,
data: u8,
) {
let old_length_enable = channel.read_length_enable();
let new_length_enable = (data >> 6) & 1 == 1;
channel.write_length_enable(new_length_enable);
if !is_length_clock_next && !old_length_enable && new_length_enable {
channel.clock_length_counter();
}
if data & 0x80 != 0 {
channel.trigger_length(!is_length_clock_next);
}
}
}