Game Boy APU (audio processing unit)
8use crate::HardwareMode; 9use crate::api::GameBoyEmulatorConfig; 10use crate::apu::noise::NoiseChannel; 11use crate::apu::pulse::PulseChannel; 12use crate::apu::wavetable::WavetableChannel; 13use crate::audio::{GB_APU_FREQUENCY, GameBoyResampler}; 14use crate::cgb::CpuSpeed; 15use crate::timer::GbTimer; 16use bincode::{Decode, Encode}; 17use jgenesis_common::frontend::AudioOutput; 18use jgenesis_common::num::GetBit; 19use std::array; 20 21#[derive(Debug, Clone, Copy, Encode, Decode)] 22pub struct StereoControl { 23 pub left_volume: u8, 24 pub right_volume: u8, 25 pub left_channels: [bool; 4], 26 pub right_channels: [bool; 4], 27 // Vin functionality is not emulated but some test ROMs depend on these bits being R/W 28 vin_bits: u8, 29} 30 31impl Default for StereoControl { 32 fn default() -> Self { 33 Self::new() 34 } 35} 36 37impl StereoControl { 38 #[must_use] 39 pub fn new() -> Self { 40 // Initial state from https://gbdev.io/pandocs/Power_Up_Sequence.html#hardware-registers 41 Self { 42 left_volume: 7, 43 right_volume: 7, 44 vin_bits: 0, 45 left_channels: [true; 4], 46 right_channels: [true, true, false, false], 47 } 48 } 49 50 #[must_use] 51 pub fn zero() -> Self { 52 Self { 53 left_volume: 0, 54 right_volume: 0, 55 vin_bits: 0, 56 left_channels: [false; 4], 57 right_channels: [false; 4], 58 } 59 } 60 61 #[must_use] 62 pub fn read_volume(&self) -> u8 { 63 (self.left_volume << 4) | self.right_volume | self.vin_bits 64 } 65 66 pub fn write_volume(&mut self, value: u8) { 67 // NR50: Stereo volume controls 68 self.left_volume = (value >> 4) & 0x07; 69 self.right_volume = value & 0x07; 70 self.vin_bits = value & 0x88; 71 72 log::trace!("NR50 write"); 73 log::trace!(" L volume: {}", self.left_volume); 74 log::trace!(" R volume: {}", self.right_volume); 75 } 76 77 #[must_use] 78 pub fn read_enabled(&self) -> u8 { 79 let high_nibble = stereo_channels_to_nibble(self.left_channels); 80 let low_nibble = stereo_channels_to_nibble(self.right_channels); 81 (high_nibble << 4) | low_nibble 82 } 83 84 pub fn write_enabled(&mut self, value: u8) { 85 // NR51: Stereo panning controls 86 self.left_channels = array::from_fn(|i| value.bit(4 + i as u8)); 87 self.right_channels = array::from_fn(|i| value.bit(i as u8)); 88 89 log::trace!("NR51 write"); 90 log::trace!(" L enabled: {:?}", self.left_channels); 91 log::trace!(" R enabled: {:?}", self.right_channels); 92 } 93} 94 95fn stereo_channels_to_nibble(channels: [bool; 4]) -> u8 { 96 channels.into_iter().enumerate().map(|(i, b)| u8::from(b) << i).reduce(|a, b| a | b).unwrap() 97} 98 99#[derive(Debug, Clone, Encode, Decode)] 100struct Dac { 101 analog_sample: f64, 102 output_level: f64, 103} 104 105impl Dac { 106 fn new() -> Self { 107 Self { analog_sample: 0.0, output_level: 0.0 } 108 } 109 110 fn digital_to_analog(&mut self, sample: Option<u8>) -> f64 { 111 // When the DAC is enabled or disabled, gradually fade in/out over a very short period. 112 // Some games depend on this to avoid buzzing due to how they use the wavetable channel, e.g. Cannon Fodder 113 // 1/20000th of a second period is based on what SameBoy does; I think in actual hardware this can vary 114 // because it's an emergent property of the hardware, not an intentional audio effect 115 const FADE_DELTA: f64 = 20000.0 / GB_APU_FREQUENCY; 116 117 match sample { 118 Some(sample) => { 119 // Convert from digital [0, 15] to analog [-1, +1] but inverted 120 // Digital 0 -> Analog +1 121 // Digital 15 -> Analog -1 122 self.analog_sample = (f64::from(15 - sample) - 7.5) / 7.5; 123 124 // Gradually fade in if DAC was just enabled 125 self.output_level = (self.output_level + FADE_DELTA).clamp(0.0, 1.0); 126 } 127 None => { 128 // DAC is disabled; gradually fade out, keep current analog sample output 129 self.output_level = (self.output_level - FADE_DELTA).clamp(0.0, 1.0); 130 } 131 } 132 133 self.analog_sample * self.output_level 134 } 135} 136 137#[derive(Debug, Clone, Encode, Decode)] 138pub(crate) struct Apu { 139 hardware_mode: HardwareMode, 140 enabled: bool, 141 pulse_1: PulseChannel, 142 pulse_2: PulseChannel, 143 wavetable: WavetableChannel, 144 noise: NoiseChannel, 145 stereo_control: StereoControl, 146 dacs: [Dac; 4], 147 frame_sequencer_step: u8, 148 previous_div_bit: bool, 149 resampler: GameBoyResampler, 150} 151 152impl Apu { 153 pub fn new(config: GameBoyEmulatorConfig, hardware_mode: HardwareMode) -> Self { 154 Self { 155 hardware_mode, 156 enabled: true, 157 pulse_1: PulseChannel::new(), 158 pulse_2: PulseChannel::new(), 159 wavetable: WavetableChannel::new(hardware_mode), 160 noise: NoiseChannel::new(), 161 stereo_control: StereoControl::new(), 162 dacs: array::from_fn(|_| Dac::new()), 163 frame_sequencer_step: 0, 164 previous_div_bit: false, 165 resampler: GameBoyResampler::new(&config), 166 } 167 } 168 169 pub fn tick_m_cycle(&mut self, timer: &GbTimer, cpu_speed: CpuSpeed) { 170 // In CGB double speed mode, the DIV-APU counter reads DIV bit 5 instead of 4 so that it 171 // continues to tick at 512 Hz instead of running twice as fast 172 let div_bit_index = match cpu_speed { 173 CpuSpeed::Normal => 4, 174 CpuSpeed::Double => 5, 175 }; 176 177 let div_bit = timer.read_div().bit(div_bit_index); 178 if self.previous_div_bit && !div_bit { 179 // Clock frame sequencer 180 self.frame_sequencer_step = (self.frame_sequencer_step + 1) & 7; 181 182 if self.enabled { 183 if !self.frame_sequencer_step.bit(0) { 184 self.clock_length_counters(); 185 } 186 187 if self.frame_sequencer_step == 7 { 188 self.clock_envelopes(); 189 } 190 191 if self.frame_sequencer_step == 2 || self.frame_sequencer_step == 6 { 192 self.pulse_1.clock_sweep(); 193 } 194 } 195 } 196 self.previous_div_bit = div_bit; 197 198 if !self.enabled { 199 // If APU is disabled, output constant 0s 200 self.resampler.collect_sample(0.0, 0.0); 201 return; 202 } 203 204 self.pulse_1.tick_m_cycle(); 205 self.pulse_2.tick_m_cycle(); 206 self.noise.tick_m_cycle(); 207 208 for _ in 0..2 { 209 self.wavetable.tick_2mhz(); 210 self.generate_sample(); 211 } 212 } 213 214 fn generate_sample(&mut self) { 215 // Analog samples in range [-1, +1] 216 let channel_samples = [ 217 self.dacs[0].digital_to_analog(self.pulse_1.sample()), 218 self.dacs[1].digital_to_analog(self.pulse_2.sample()), 219 self.dacs[2].digital_to_analog(self.wavetable.sample()), 220 self.dacs[3].digital_to_analog(self.noise.sample()), 221 ]; 222 223 // Sum channel samples; now in range [-4, +4] 224 let mut sample_l = (0..4) 225 .map(|i| channel_samples[i] * f64::from(self.stereo_control.left_channels[i])) 226 .sum::<f64>(); 227 let mut sample_r = (0..4) 228 .map(|i| channel_samples[i] * f64::from(self.stereo_control.right_channels[i])) 229 .sum::<f64>(); 230 231 // Apply volume multiplier (1-8); now in range [-32, +32] 232 sample_l *= f64::from(self.stereo_control.left_volume + 1); 233 sample_r *= f64::from(self.stereo_control.right_volume + 1); 234 235 // Normalize back from [-32, +32] to [-1, +1] range 236 // Additionally multiply by 0.5 because otherwise sound is way too loud 237 sample_l /= 64.0; 238 sample_r /= 64.0; 239 240 self.resampler.collect_sample(sample_l, sample_r); 241 } 242 243 fn clock_length_counters(&mut self) { 244 self.pulse_1.clock_length_counter(); 245 self.pulse_2.clock_length_counter(); 246 self.wavetable.clock_length_counter(); 247 self.noise.clock_length_counter(); 248 } 249 250 fn clock_envelopes(&mut self) { 251 self.pulse_1.clock_envelope(); 252 self.pulse_2.clock_envelope(); 253 self.noise.clock_envelope(); 254 } 255 256 pub fn read_register(&self, address: u16) -> u8 { 257 log::trace!("APU read register {address:04X}"); 258 259 match address & 0x7F { 260 0x10 => self.pulse_1.read_register_0(), 261 0x11 => self.pulse_1.read_register_1(), 262 0x12 => self.pulse_1.read_register_2(), 263 0x14 => self.pulse_1.read_register_4(), 264 0x16 => self.pulse_2.read_register_1(), 265 0x17 => self.pulse_2.read_register_2(), 266 0x19 => self.pulse_2.read_register_4(), 267 0x1A => self.wavetable.read_register_0(), 268 0x1C => self.wavetable.read_register_2(), 269 0x1E => self.wavetable.read_register_4(), 270 0x21 => self.noise.read_register_2(), 271 0x22 => self.noise.read_register_3(), 272 0x23 => self.noise.read_register_4(), 273 0x24 => self.stereo_control.read_volume(), 274 0x25 => self.stereo_control.read_enabled(), 275 0x26 => self.read_nr52(), 276 0x30..=0x3F => self.wavetable.read_ram(address), 277 _ => 0xFF, 278 } 279 } 280 281 fn read_nr52(&self) -> u8 { 282 0x70 | (u8::from(self.enabled) << 7) 283 | (u8::from(self.noise.enabled()) << 3) 284 | (u8::from(self.wavetable.enabled()) << 2) 285 | (u8::from(self.pulse_2.enabled()) << 1) 286 | u8::from(self.pulse_1.enabled()) 287 } 288 289 pub fn read_pcm12(&self) -> u8 { 290 let ch1_sample = self.pulse_1.sample().unwrap_or(0); 291 let ch2_sample = self.pulse_2.sample().unwrap_or(0); 292 ch1_sample | (ch2_sample << 4) 293 } 294 295 pub fn read_pcm34(&self) -> u8 { 296 let ch3_sample = self.wavetable.sample().unwrap_or(0); 297 let ch4_sample = self.noise.sample().unwrap_or(0); 298 ch3_sample | (ch4_sample << 4) 299 } 300 301 pub fn write_register(&mut self, address: u16, value: u8) { 302 log::trace!("APU write register {address:04X} {value:02X}"); 303 304 if !self.enabled && address != 0xFF26 && !(0xFF30..0xFF40).contains(&address) { 305 // When APU is disabled, writes are only allowed to NR52 and wavetable RAM 306 // On DMG, writes to length counters are allowed while the APU is disabled 307 if self.hardware_mode == HardwareMode::Dmg { 308 match address & 0x7F { 309 0x11 => self.pulse_1.write_register_1(value, false), 310 0x16 => self.pulse_2.write_register_1(value, false), 311 0x1B => self.wavetable.write_register_1(value), 312 0x20 => self.noise.write_register_1(value), 313 _ => {} 314 } 315 } 316 317 return; 318 } 319 320 match address & 0x7F { 321 0x10 => self.pulse_1.write_register_0(value), 322 0x11 => self.pulse_1.write_register_1(value, self.enabled), 323 0x12 => self.pulse_1.write_register_2(value), 324 0x13 => self.pulse_1.write_register_3(value), 325 0x14 => self.pulse_1.write_register_4(value, self.frame_sequencer_step), 326 0x16 => self.pulse_2.write_register_1(value, self.enabled), 327 0x17 => self.pulse_2.write_register_2(value), 328 0x18 => self.pulse_2.write_register_3(value), 329 0x19 => self.pulse_2.write_register_4(value, self.frame_sequencer_step), 330 0x1A => self.wavetable.write_register_0(value), 331 0x1B => self.wavetable.write_register_1(value), 332 0x1C => self.wavetable.write_register_2(value), 333 0x1D => self.wavetable.write_register_3(value), 334 0x1E => self.wavetable.write_register_4(value, self.frame_sequencer_step), 335 0x20 => self.noise.write_register_1(value), 336 0x21 => self.noise.write_register_2(value), 337 0x22 => self.noise.write_register_3(value), 338 0x23 => self.noise.write_register_4(value, self.frame_sequencer_step), 339 0x24 => self.stereo_control.write_volume(value), 340 0x25 => self.stereo_control.write_enabled(value), 341 0x26 => self.write_nr52(value), 342 0x30..=0x3F => self.wavetable.write_ram(address, value), 343 _ => {} 344 } 345 } 346 347 fn write_nr52(&mut self, value: u8) { 348 // NR52: APU control 349 let prev_enabled = self.enabled; 350 self.enabled = value.bit(7); 351 352 if prev_enabled && !self.enabled { 353 // Reset all channel and register state 354 self.pulse_1 = PulseChannel::new(); 355 self.pulse_2 = PulseChannel::new(); 356 self.wavetable.reset(self.hardware_mode); 357 self.noise = NoiseChannel::new(); 358 self.stereo_control = StereoControl::zero(); 359 } else if !prev_enabled && self.enabled { 360 // Reset frame sequencer step when APU is re-enabled 361 self.frame_sequencer_step = 7; 362 } 363 364 log::trace!("NR52 write, APU enabled: {}", self.enabled); 365 } 366 367 pub fn drain_samples_into<A: AudioOutput>( 368 &mut self, 369 audio_output: &mut A, 370 ) -> Result<(), A::Err> { 371 self.resampler.output_samples(audio_output) 372 } 373 374 pub fn reload_config(&mut self, config: GameBoyEmulatorConfig) { 375 self.resampler.reload_config(&config); 376 } 377 378 pub fn update_output_frequency(&mut self, output_frequency: u64) { 379 self.resampler.update_output_frequency(output_frequency); 380 } 381}