1//! YM2612 FM synthesis sound chip, also known as the OPN2 2//! 3//! This implementation is mostly based on community research documented here: 4//! <http://gendev.spritesmind.net/forum/viewtopic.php?f=24&t=386> 5 6mod debug; 7mod envelope; 8mod lfo; 9mod phase; 10mod timer; 11 12use crate::ym2612::envelope::EnvelopeGenerator; 13use crate::ym2612::lfo::LowFrequencyOscillator; 14use crate::ym2612::phase::PhaseGenerator; 15use crate::ym2612::timer::{TimerA, TimerB, TimerControl, TimerTickEffect}; 16use bincode::{Decode, Encode}; 17use genesis_config::{GenesisEmulatorConfig, Opn2BusyBehavior}; 18use jgenesis_common::num::GetBit; 19use std::sync::LazyLock; 20use std::{array, mem}; 21 22pub use debug::{ 23 Channel3FrequencyMode, ChannelRegisters, GlobalRegisters, LfoState, OperatorRegisters, 24 TimerState, Ym2612DebugView, 25}; 26 27const FM_SAMPLE_DIVIDER: u8 = 24; 28 29// Phase is 10 bits 30const PHASE_MASK: u16 = 0x03FF; 31const HALF_PHASE_MASK: u16 = PHASE_MASK >> 1; 32 33// Operator output is signed 14-bit 34const OPERATOR_OUTPUT_MIN: i16 = -0x2000; 35const OPERATOR_OUTPUT_MAX: i16 = 0x1FFF; 36 37// Group 1 is channels 1-3 (idx 0-2), group 2 is channels 4-6 (idx 3-5) 38const GROUP_1_BASE_CHANNEL: usize = 0; 39const GROUP_2_BASE_CHANNEL: usize = 3; 40 41fn compute_key_code(f_number: u16, block: u8) -> u8 { 42 // Bits 4-2: Block 43 // Bit 1: F11 44 // Bit 0: (F11 & (F10 | F9 | F8)) | (!F11 & F10 & F9 & F8) 45 let f11 = f_number.bit(10); 46 let f10 = f_number.bit(9); 47 let f9 = f_number.bit(8); 48 let f8 = f_number.bit(7); 49 (block << 2) 50 | (u8::from(f11) << 1) 51 | u8::from((f11 && (f10 || f9 || f8)) || (!f11 && f10 && f9 && f8)) 52} 53 54#[derive(Debug, Clone, Default, Encode, Decode)] 55struct FmOperator { 56 phase: PhaseGenerator, 57 envelope: EnvelopeGenerator, 58 am_enabled: bool, 59 current_output: i16, 60 last_output: i16, 61 // Values used in output calculation that are copied here for convenience 62 lfo_counter: u8, 63 am_sensitivity: u8, 64} 65 66impl FmOperator { 67 fn update_frequency(&mut self, f_number: u16, block: u8) { 68 self.phase.f_number = f_number; 69 self.phase.block = block; 70 self.envelope.update_key_scale_rate(f_number, block); 71 } 72 73 fn update_key_scale(&mut self, key_scale: u8) { 74 self.envelope.key_scale = key_scale; 75 self.envelope.update_key_scale_rate(self.phase.f_number, self.phase.block); 76 } 77 78 fn key_on_or_off(&mut self, value: bool) { 79 if value { 80 if !self.envelope.is_key_on() { 81 self.phase.reset(); 82 self.envelope.key_on(); 83 } 84 } else { 85 self.envelope.key_off(); 86 } 87 } 88 89 fn sample_clock(&mut self, modulation_input: i16) -> i16 { 90 let phase = self.phase.current_phase().wrapping_add_signed(modulation_input); 91 92 // Phase is a 10-bit value that represents a number in the range 0 to 2*PI. 93 // Actual hardware splits this into a sign bit and a half-phase value from 0 to PI, computes 94 // the amplitude based on the half-phase, and then applies the sign bit at final output 95 let sign = phase.bit(9); 96 let sine_attenuation = phase_to_attenuation(phase); 97 98 let envelope_attenuation = self.envelope.current_attenuation(); 99 let envelope_am_attenuation = if self.am_enabled { 100 let am_attenuation = lfo::amplitude_modulation(self.lfo_counter, self.am_sensitivity); 101 (envelope_attenuation + am_attenuation).clamp(0, envelope::MAX_ATTENUATION) 102 } else { 103 envelope_attenuation 104 }; 105 106 // Add phase attenuation (4.8 fixed-point) and envelope/AM attenuation (4.6 fixed-point) 107 let total_attenuation = sine_attenuation + (envelope_am_attenuation << 2); 108 109 // Compute final output, adding the sign bit back in 110 let amplitude = attenuation_to_amplitude(total_attenuation); 111 let output = if sign { -(amplitude as i16) } else { amplitude as i16 }; 112 113 self.last_output = self.current_output; 114 self.current_output = output; 115 116 output 117 } 118} 119 120// Logic based on http://gendev.spritesmind.net/forum/viewtopic.php?p=6114#p6114 121#[inline] 122fn phase_to_attenuation(phase: u16) -> u16 { 123 // Actual hardware has a 256-entry quarter-sine table. This is emulated using a half-sine table 124 // for simplicity, but the values are calculated the same way 125 static LOG_SINE_TABLE: LazyLock<[u16; 512]> = LazyLock::new(|| { 126 array::from_fn(|mut i| { 127 use std::f64::consts::PI; 128 129 if i.bit(8) { 130 // Second quarter-phase 131 i = (!i) & 0xFF; 132 } 133 134 // The table indices represent numbers in the range 0 to PI/2, but slightly offset in order 135 // to avoid computing log2(0) 136 let n = ((i << 1) | 1) as f64; 137 let sine = (n / 512.0 * PI / 2.0).sin(); 138 139 // The table stores attenuation values, but on a log2 scale instead of log10 140 let attenuation = -sine.log2(); 141 142 // Table contains 12-bit values that represent 4.8 fixed-point 143 (attenuation * f64::from(1 << 8)).round() as u16 144 }) 145 }); 146 147 LOG_SINE_TABLE[(phase & HALF_PHASE_MASK) as usize] 148} 149 150// Logic based on http://gendev.spritesmind.net/forum/viewtopic.php?p=6114#p6114 151#[inline] 152fn attenuation_to_amplitude(attenuation: u16) -> u16 { 153 static POW2_TABLE: LazyLock<[u16; 256]> = LazyLock::new(|| { 154 array::from_fn(|i| { 155 // This is a lookup table for 2^(-n), where n is a value between 0 and 1 156 // Index i represents the number (i + 1)/256 157 let n = ((i + 1) as f64) / 256.0; 158 let inverse_pow2 = 2.0_f64.powf(-n); 159 160 // Table contains 11-bit values that represent 0.11 fixed-point 161 (inverse_pow2 * f64::from(1 << 11)).round() as u16 162 }) 163 }); 164 165 // Attenuation is interpreted as a 5.8 fixed-point number on a log2 scale 166 let int_part = (attenuation >> 8) & 0x1F; 167 if int_part >= 13 { 168 // Final result is guaranteed to shift down to 0 169 // Int part is applied as a right shift to 13-bit values 170 return 0; 171 } 172 173 let fract_part = attenuation & 0xFF; 174 let fract_pow2 = POW2_TABLE[fract_part as usize]; 175 (fract_pow2 << 2) >> int_part 176} 177 178#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Encode, Decode)] 179enum FrequencyMode { 180 #[default] 181 Single, 182 Multiple, 183} 184 185#[derive(Debug, Clone, Encode, Decode)] 186struct FmChannel { 187 operators: [FmOperator; 4], 188 mode: FrequencyMode, 189 pending_ch_f_number_high: u8, 190 channel_f_number: u16, 191 pending_ch_block: u8, 192 channel_block: u8, 193 pending_op_f_numbers_high: [u8; 3], 194 operator_f_numbers: [u16; 3], 195 pending_op_blocks: [u8; 3], 196 operator_blocks: [u8; 3], 197 algorithm: u8, 198 feedback_level: u8, 199 am_sensitivity: u8, 200 fm_sensitivity: u8, 201 l_output: bool, 202 r_output: bool, 203 current_output: i16, 204} 205 206impl FmChannel { 207 fn new() -> Self { 208 Self { 209 operators: array::from_fn(|_| FmOperator::default()), 210 mode: FrequencyMode::Single, 211 pending_ch_f_number_high: 0, 212 channel_f_number: 0, 213 pending_ch_block: 0, 214 channel_block: 0, 215 pending_op_f_numbers_high: [0; 3], 216 operator_f_numbers: [0; 3], 217 pending_op_blocks: [0; 3], 218 operator_blocks: [0; 3], 219 algorithm: 0, 220 feedback_level: 0, 221 am_sensitivity: 0, 222 fm_sensitivity: 0, 223 l_output: true, 224 r_output: true, 225 current_output: 0, 226 } 227 } 228 229 #[inline] 230 fn clock(&mut self, lfo_counter: u8, quantization_mask: i16) { 231 for operator in &mut self.operators { 232 operator.phase.clock(lfo_counter, self.fm_sensitivity); 233 operator.envelope.clock(&mut operator.phase); 234 235 operator.lfo_counter = lfo_counter; 236 operator.am_sensitivity = self.am_sensitivity; 237 } 238 239 self.generate_sample(quantization_mask); 240 } 241 242 fn generate_sample(&mut self, out_mask: i16) { 243 macro_rules! carrier_sum { 244 ($($carrier:expr),*) => { 245 { 246 let mut sum = 0; 247 $(sum += $carrier & out_mask;)* 248 sum.clamp(OPERATOR_OUTPUT_MIN & out_mask, OPERATOR_OUTPUT_MAX & out_mask) 249 } 250 } 251 } 252 253 let op1_feedback = match self.feedback_level { 254 0 => 0, 255 f => (self.operators[0].current_output + self.operators[0].last_output) >> (10 - f), 256 }; 257 258 // Operator order is 1 -> 3 -> 2 -> 4, per http://gendev.spritesmind.net/forum/viewtopic.php?p=30063#p30063 259 // Additionally, when two operators execute consecutively, if the first one modulates the 260 // second one, it will use the operator output from the previous cycle instead of the current 261 // cycle. This is due to how the chip pipelines operator evaluation internally. 262 let sample = match self.algorithm { 263 0 => { 264 // O1 -> O2 -> O3 -> O4 -> Output 265 let m1 = self.operators[0].sample_clock(op1_feedback); 266 267 let m2_old = self.operators[1].current_output; 268 self.operators[1].sample_clock(m1 >> 1); 269 270 let m3 = self.operators[2].sample_clock(m2_old >> 1); 271 let c4 = self.operators[3].sample_clock(m3 >> 1); 272 273 c4 & out_mask 274 } 275 1 => { 276 // O1 --| 277 // --> O3 -> O4 -> Output 278 // O2 --| 279 let m1_old = self.operators[0].current_output; 280 self.operators[0].sample_clock(op1_feedback); 281 282 let m2_old = self.operators[1].current_output; 283 self.operators[1].sample_clock(0); 284 285 let m3 = self.operators[2].sample_clock((m1_old + m2_old) >> 1); 286 let c4 = self.operators[3].sample_clock(m3 >> 1); 287 288 c4 & out_mask 289 } 290 2 => { 291 // O1 --| 292 // --> O4 -> Output 293 // O2 -> O3 --| 294 let m1 = self.operators[0].sample_clock(op1_feedback); 295 296 let m2_old = self.operators[1].current_output; 297 self.operators[1].sample_clock(0); 298 299 let m3 = self.operators[2].sample_clock(m2_old >> 1); 300 let c4 = self.operators[3].sample_clock((m1 + m3) >> 1); 301 302 c4 & out_mask 303 } 304 3 => { 305 // O1 -> O2 --| 306 // --> O4 -> Output 307 // O3 --| 308 let m1 = self.operators[0].sample_clock(op1_feedback); 309 310 let m2_old = self.operators[1].current_output; 311 self.operators[1].sample_clock(m1 >> 1); 312 313 let m3 = self.operators[2].sample_clock(0); 314 let c4 = self.operators[3].sample_clock((m2_old + m3) >> 1); 315 316 c4 & out_mask 317 } 318 4 => { 319 // O1 -> O2 --| 320 // --> Output 321 // O3 -> O4 --| 322 let m1 = self.operators[0].sample_clock(op1_feedback); 323 let c2 = self.operators[1].sample_clock(m1 >> 1); 324 let m3 = self.operators[2].sample_clock(0); 325 let c4 = self.operators[3].sample_clock(m3 >> 1); 326 327 carrier_sum!(c2, c4) 328 } 329 5 => { 330 // --> O2 --| 331 // | | 332 // O1 --|-> O3 ----> Output 333 // | | 334 // --> O4 --| 335 let m1_old = self.operators[0].current_output; 336 let m1 = self.operators[0].sample_clock(op1_feedback); 337 let c2 = self.operators[1].sample_clock(m1 >> 1); 338 let c3 = self.operators[2].sample_clock(m1_old >> 1); 339 let c4 = self.operators[3].sample_clock(m1 >> 1); 340 341 carrier_sum!(c2, c3, c4) 342 } 343 6 => { 344 // O1 --> O2 --| 345 // | 346 // O3 ----> Output 347 // | 348 // O4 --| 349 let m1 = self.operators[0].sample_clock(op1_feedback); 350 let c2 = self.operators[1].sample_clock(m1 >> 1); 351 let c3 = self.operators[2].sample_clock(0); 352 let c4 = self.operators[3].sample_clock(0); 353 354 carrier_sum!(c2, c3, c4) 355 } 356 7 => { 357 // O1 --| 358 // | 359 // O2 --| 360 // --> Output 361 // O3 --| 362 // | 363 // O4 --| 364 let c1 = self.operators[0].sample_clock(op1_feedback); 365 let c2 = self.operators[1].sample_clock(0); 366 let c3 = self.operators[2].sample_clock(0); 367 let c4 = self.operators[3].sample_clock(0); 368 369 carrier_sum!(c1, c2, c3, c4) 370 } 371 _ => panic!("invalid algorithm: {}", self.algorithm), 372 }; 373 374 self.current_output = sample; 375 } 376 377 // Update phase generator F-numbers & blocks after channel-level F-number, block, or frequency mode is updated 378 fn update_phase_generators(&mut self) { 379 match self.mode { 380 FrequencyMode::Single => { 381 let f_number = self.channel_f_number; 382 let block = self.channel_block; 383 for operator in &mut self.operators { 384 operator.update_frequency(f_number, block); 385 } 386 } 387 FrequencyMode::Multiple => { 388 for i in 0..3 { 389 let f_number = self.operator_f_numbers[i]; 390 let block = self.operator_blocks[i]; 391 392 self.operators[i].update_frequency(f_number, block); 393 } 394 395 let last_f_number = self.channel_f_number; 396 let last_block = self.channel_block; 397 398 self.operators[3].update_frequency(last_f_number, last_block); 399 } 400 } 401 } 402} 403 404impl Default for FmChannel { 405 fn default() -> Self { 406 Self::new() 407 } 408} 409 410// The YM2612 always raises the BUSY line for exactly 32 internal cycles after a register write 411const WRITE_BUSY_CYCLES: u8 = 32; 412 413#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Encode, Decode)] 414pub enum RegisterGroup { 415 // Channel 1-3 and global registers 416 #[default] 417 One, 418 // Channel 4-6 registers 419 Two, 420} 421 422trait GenesisConfigExt { 423 fn channels_muted(&self) -> [bool; 6]; 424} 425 426impl GenesisConfigExt for GenesisEmulatorConfig { 427 fn channels_muted(&self) -> [bool; 6] { 428 self.ym2612_channels_enabled.map(|enabled| !enabled) 429 } 430} 431 432#[derive(Debug, Clone, Encode, Decode)] 433pub struct Ym2612 { 434 channels: [FmChannel; 6], 435 channels_muted: [bool; 6], 436 dac_channel_enabled: bool, 437 dac_channel_sample: u8, 438 lfo: LowFrequencyOscillator, 439 selected_register: u8, 440 selected_register_group: RegisterGroup, 441 sample_divider: u8, 442 busy_cycles_remaining: u8, 443 timer_a: TimerA, 444 timer_b: TimerB, 445 csm_enabled: bool, 446 quantize_output: bool, 447 emulate_ladder_effect: bool, 448 busy_behavior: Opn2BusyBehavior, 449 last_status_read: u8, 450 status_decay_samples_remaining: u32, 451 output_samples: Vec<(f64, f64)>, 452} 453 454impl Ym2612 { 455 #[must_use] 456 pub fn new(config: &GenesisEmulatorConfig) -> Self { 457 Self::new_internal( 458 config.channels_muted(), 459 config.quantize_ym2612_output, 460 config.emulate_ym2612_ladder_effect, 461 config.opn2_busy_behavior, 462 FM_SAMPLE_DIVIDER, 463 Vec::with_capacity(500), 464 ) 465 } 466 467 fn new_internal( 468 channels_muted: [bool; 6], 469 quantize_output: bool, 470 emulate_ladder_effect: bool, 471 busy_behavior: Opn2BusyBehavior, 472 sample_divider: u8, 473 output_samples: Vec<(f64, f64)>, 474 ) -> Self { 475 Self { 476 channels: array::from_fn(|_| FmChannel::default()), 477 channels_muted, 478 dac_channel_enabled: false, 479 dac_channel_sample: 128, 480 lfo: LowFrequencyOscillator::new(), 481 selected_register: 0, 482 selected_register_group: RegisterGroup::default(), 483 sample_divider, 484 busy_cycles_remaining: 0, 485 timer_a: TimerA::new(), 486 timer_b: TimerB::new(), 487 csm_enabled: false, 488 quantize_output, 489 emulate_ladder_effect, 490 busy_behavior, 491 last_status_read: 0, 492 status_decay_samples_remaining: 0, 493 output_samples, 494 } 495 } 496 497 pub fn reset(&mut self) { 498 *self = Self::new_internal( 499 self.channels_muted, 500 self.quantize_output, 501 self.emulate_ladder_effect, 502 self.busy_behavior, 503 self.sample_divider, 504 mem::take(&mut self.output_samples), 505 ); 506 } 507 508 // Set the address register and set group to 1 (system registers + channels 1-3) 509 pub fn write_address_1(&mut self, value: u8) { 510 self.selected_register = value; 511 self.selected_register_group = RegisterGroup::One; 512 } 513 514 // Set the address register and set group to 2 (channels 4-6) 515 pub fn write_address_2(&mut self, value: u8) { 516 self.selected_register = value; 517 self.selected_register_group = RegisterGroup::Two; 518 } 519 520 // Write to the data port 521 // Whether this is a group 1 or 2 write depends solely on which address register was last written 522 pub fn write_data(&mut self, value: u8) { 523 match self.selected_register_group { 524 RegisterGroup::One => self.write_group_1_register(value), 525 RegisterGroup::Two => self.write_group_2_register(value), 526 } 527 } 528 529 // Write to the data port for group 1 (system registers + channels 1-3) 530 fn write_group_1_register(&mut self, value: u8) { 531 if self.selected_register != 0x2A { 532 log::trace!("G1: Wrote {value:02X} to {:02X}", self.selected_register); 533 } 534 535 self.busy_cycles_remaining = WRITE_BUSY_CYCLES; 536 537 let register = self.selected_register; 538 match register { 539 0x22 => { 540 // LFO configuration register 541 let lfo_enabled = value.bit(3); 542 self.lfo.set_enabled(lfo_enabled); 543 544 let lfo_frequency = value & 0x07; 545 self.lfo.set_frequency(lfo_frequency); 546 547 log::trace!("LFO enabled: {lfo_enabled}"); 548 log::trace!("LFO frequency: {lfo_frequency}"); 549 } 550 0x24 => { 551 // Timer A interval bits 9-2 552 self.timer_a.write_interval_high(value); 553 554 log::trace!("Timer A interval: {}", self.timer_a.interval()); 555 } 556 0x25 => { 557 // Timer A interval bits 1-0 558 self.timer_a.write_interval_low(value); 559 560 log::trace!("Timer A interval: {}", self.timer_a.interval()); 561 } 562 0x26 => { 563 // Timer B interval 564 self.timer_b.interval = value; 565 566 log::trace!("Timer B interval: {}", self.timer_b.interval); 567 } 568 0x27 => { 569 // Channel 3 mode + timer control 570 let mode = 571 if value & 0xC0 != 0 { FrequencyMode::Multiple } else { FrequencyMode::Single }; 572 self.csm_enabled = value & 0xC0 == 0x80; 573 574 // Mode applies only to channel 3 575 let channel = &mut self.channels[2]; 576 channel.mode = mode; 577 channel.update_phase_generators(); 578 579 self.timer_a.write_control(TimerControl { 580 enabled: value.bit(0), 581 overflow_flag_enabled: value.bit(2), 582 clear_overflow_flag: value.bit(4), 583 }); 584 585 self.timer_b.write_control(TimerControl { 586 enabled: value.bit(1), 587 overflow_flag_enabled: value.bit(3), 588 clear_overflow_flag: value.bit(5), 589 }); 590 591 log::trace!("Channel 3 frequency mode: {mode:?}"); 592 log::trace!("CSM enabled: {}", self.csm_enabled); 593 log::trace!("Timer A state: {:?}", self.timer_a); 594 log::trace!("Timer B state: {:?}", self.timer_b); 595 } 596 0x28 => { 597 let base_channel = 598 if value.bit(2) { GROUP_2_BASE_CHANNEL } else { GROUP_1_BASE_CHANNEL }; 599 let offset = value & 0x03; 600 if offset < 3 { 601 let channel_idx = base_channel + (value & 0x03) as usize; 602 let channel = &mut self.channels[channel_idx]; 603 channel.operators[0].key_on_or_off(value.bit(4)); 604 channel.operators[1].key_on_or_off(value.bit(5)); 605 channel.operators[2].key_on_or_off(value.bit(6)); 606 channel.operators[3].key_on_or_off(value.bit(7)); 607 608 log::trace!("Key on/off for channel {}: {:02X}", channel_idx + 1, value >> 4); 609 } 610 } 611 0x2A => { 612 self.dac_channel_sample = value; 613 } 614 0x2B => { 615 self.dac_channel_enabled = value.bit(7); 616 log::trace!("PCM enabled: {}", self.dac_channel_enabled); 617 } 618 0x30..=0x9F => { 619 self.write_operator_level_register(register, value, GROUP_1_BASE_CHANNEL); 620 } 621 0xA0..=0xBF => { 622 self.write_channel_level_register(register, value, GROUP_1_BASE_CHANNEL); 623 } 624 _ => {} 625 } 626 } 627 628 // Write to the data port for group 2 (channels 4-6) 629 fn write_group_2_register(&mut self, value: u8) { 630 log::trace!("G2: Wrote {value:02X} to {:02X}", self.selected_register); 631 632 self.busy_cycles_remaining = WRITE_BUSY_CYCLES; 633 634 let register = self.selected_register; 635 match register { 636 0x30..=0x9F => { 637 self.write_operator_level_register(register, value, GROUP_2_BASE_CHANNEL); 638 } 639 0xA0..=0xBF => { 640 self.write_channel_level_register(register, value, GROUP_2_BASE_CHANNEL); 641 } 642 _ => {} 643 } 644 } 645 646 #[allow(clippy::unused_self)] 647 #[must_use] 648 pub fn read_register(&mut self, address: u16) -> u8 { 649 if self.busy_behavior == Opn2BusyBehavior::Ym2612 && address & 3 != 0 { 650 // On YM2612, reads from $4001-$4003 return the last value read from $4000 651 // Status value decays to 0 after a certain amount of time has passed 652 return if self.status_decay_samples_remaining != 0 { 653 self.last_status_read 654 } else { 655 0 656 }; 657 } 658 659 let busy_flag = match self.busy_behavior { 660 Opn2BusyBehavior::AlwaysZero => false, 661 Opn2BusyBehavior::Ym2612 | Opn2BusyBehavior::Ym3438 => self.busy_cycles_remaining != 0, 662 }; 663 664 let status = (u8::from(busy_flag) << 7) 665 | (u8::from(self.timer_b.overflow_flag()) << 1) 666 | u8::from(self.timer_a.overflow_flag()); 667 668 // 12000 sample decay period produces a result similar to actual YM2612 hardware, though from 669 // limited testing the decay period can vary even on a single console 670 self.status_decay_samples_remaining = 12000; 671 self.last_status_read = status; 672 673 status 674 } 675 676 #[inline] 677 pub fn tick(&mut self, ticks: u32) { 678 for _ in 0..ticks { 679 self.busy_cycles_remaining = self.busy_cycles_remaining.saturating_sub(1); 680 681 self.sample_divider -= 1; 682 if self.sample_divider == 0 { 683 self.sample_divider = FM_SAMPLE_DIVIDER; 684 685 self.status_decay_samples_remaining = 686 self.status_decay_samples_remaining.saturating_sub(1); 687 688 self.lfo.tick(); 689 690 self.timer_b.tick(); 691 let timer_a_effect = self.timer_a.tick(); 692 693 if self.csm_enabled && timer_a_effect == TimerTickEffect::Overflowed { 694 // CSM: Whenever Timer A overflows, instantaneously key on & off all operators in 695 // channel 3 that are not already keyed on 696 for operator in &mut self.channels[2].operators { 697 if !operator.envelope.is_key_on() { 698 operator.key_on_or_off(true); 699 operator.key_on_or_off(false); 700 } 701 } 702 } 703 704 self.clock(); 705 self.output_samples.push(self.sample()); 706 } 707 } 708 } 709 710 #[must_use] 711 pub fn sample(&self) -> (f64, f64) { 712 let mut sum_l = 0; 713 let mut sum_r = 0; 714 for (i, channel) in self.channels.iter().enumerate() { 715 if self.channels_muted[i] { 716 continue; 717 } 718 719 let sample = if i == 5 && self.dac_channel_enabled { 720 // Channel 6 is in DAC mode; play PCM sample instead of FM output 721 // Convert unsigned 8-bit sample to a signed 14-bit sample 722 (i16::from(self.dac_channel_sample) - 128) << 6 723 } else { 724 channel.current_output 725 }; 726 727 let sample_l = self.apply_panning(sample, channel.l_output); 728 let sample_r = self.apply_panning(sample, channel.r_output); 729 730 sum_l += i32::from(sample_l); 731 sum_r += i32::from(sample_r); 732 } 733 734 // Each channel has a range of [-8192, 8191], so divide the sums by 6*8192 to convert to [-1.0, 1.0] 735 (f64::from(sum_l) / 49152.0, f64::from(sum_r) / 49152.0) 736 } 737 738 pub fn drain_output_samples(&mut self) -> impl Iterator<Item = (f64, f64)> { 739 self.output_samples.drain(..) 740 } 741 742 fn apply_panning(&self, sample: i16, pan_enabled: bool) -> i16 { 743 let pan_enabled: i16 = pan_enabled.into(); 744 745 if !self.emulate_ladder_effect { 746 return sample * pan_enabled; 747 } 748 749 // Ladder effect emulation 750 // If channel is not muted through panning, add +4 to non-negative samples and -3 to negative 751 // If muted, output a constant +4 for non-negative samples and -4 for negative 752 // See https://gendev.spritesmind.net/forum/viewtopic.php?p=32605#p32605 753 let adjustment = if sample >= 0 { 4 } else { -(4 - pan_enabled) }; 754 755 sample * pan_enabled + (adjustment << 5) 756 } 757 758 fn write_operator_level_register(&mut self, register: u8, value: u8, base_channel_idx: usize) { 759 assert!((0x30..=0x9F).contains(®ister)); 760 761 let channel_offset = register & 0x03; 762 if channel_offset == 3 { 763 // Invalid; only 3 channels per group 764 return; 765 } 766 767 let channel_idx = base_channel_idx + channel_offset as usize; 768 // Operator comes from bits 2 and 3 of register, except swapped (01=Operator 3, 10=Operator 2) 769 let operator_idx = (((register & 0x08) >> 3) | ((register & 0x04) >> 1)) as usize; 770 771 log::trace!( 772 "Writing to operator-level register for channel {} / operator {}", 773 channel_idx + 1, 774 operator_idx + 1 775 ); 776 777 let operator = &mut self.channels[channel_idx].operators[operator_idx]; 778 match register >> 4 { 779 0x03 => { 780 operator.phase.multiple = value & 0x0F; 781 operator.phase.detune = (value >> 4) & 0x07; 782 783 log::trace!( 784 "Multiple={}, detune={}", 785 operator.phase.multiple, 786 operator.phase.detune 787 ); 788 } 789 0x04 => { 790 operator.envelope.total_level = value & 0x7F; 791 792 log::trace!("Total level={:02X}", operator.envelope.total_level); 793 } 794 0x05 => { 795 operator.envelope.attack_rate = value & 0x1F; 796 operator.update_key_scale(value >> 6); 797 798 log::trace!( 799 "Attack rate={}, key scale={}, Rks={}", 800 operator.envelope.attack_rate, 801 operator.envelope.key_scale, 802 operator.envelope.key_scale_rate 803 ); 804 } 805 0x06 => { 806 operator.envelope.decay_rate = value & 0x1F; 807 operator.am_enabled = value.bit(7); 808 809 log::trace!( 810 "Decay rate={}, AM enabled={}", 811 operator.envelope.decay_rate, 812 operator.am_enabled 813 ); 814 } 815 0x07 => { 816 operator.envelope.sustain_rate = value & 0x1F; 817 818 log::trace!("Sustain rate={}", operator.envelope.sustain_rate); 819 } 820 0x08 => { 821 operator.envelope.release_rate = value & 0x0F; 822 operator.envelope.sustain_level = value >> 4; 823 824 log::trace!( 825 "Release rate={}, sustain level={}", 826 operator.envelope.release_rate, 827 operator.envelope.sustain_level 828 ); 829 } 830 0x09 => { 831 operator.envelope.write_ssg_register(value); 832 } 833 _ => unreachable!("register is in 0x30..=0x9F"), 834 } 835 } 836 837 fn write_channel_level_register(&mut self, register: u8, value: u8, base_channel_idx: usize) { 838 assert!((0xA0..=0xBF).contains(®ister)); 839 840 match register { 841 0xA0..=0xA2 => { 842 // F-number low bits 843 let channel_idx = base_channel_idx + (register & 0x03) as usize; 844 let channel = &mut self.channels[channel_idx]; 845 846 channel.channel_f_number = 847 u16::from_le_bytes([value, channel.pending_ch_f_number_high]); 848 channel.channel_block = channel.pending_ch_block; 849 850 channel.update_phase_generators(); 851 852 log::trace!("Channel {}: F-num={:04X}", channel_idx + 1, channel.channel_f_number); 853 } 854 0xA4..=0xA6 => { 855 // F-number high bits and block 856 // Writes to this register do not take effect until low bits are written 857 let channel_idx = base_channel_idx + (register & 0x03) as usize; 858 let channel = &mut self.channels[channel_idx]; 859 channel.pending_ch_f_number_high = value & 7; 860 channel.pending_ch_block = (value >> 3) & 7; 861 862 log::trace!( 863 "Channel {}: F-num high bits {}, block {}", 864 channel_idx + 1, 865 channel.pending_ch_f_number_high, 866 channel.pending_ch_block, 867 ); 868 } 869 0xA8..=0xAA => { 870 // Operator-level F-number low bits for channel 3 871 let channel_idx = base_channel_idx + 2; 872 let operator_idx = match register { 873 0xA8 => 2, 874 0xA9 => 0, 875 0xAA => 1, 876 _ => unreachable!("nested match expressions"), 877 }; 878 let channel = &mut self.channels[channel_idx]; 879 880 let f_num_high = channel.pending_op_f_numbers_high[operator_idx]; 881 channel.operator_f_numbers[operator_idx] = u16::from_le_bytes([value, f_num_high]); 882 channel.operator_blocks[operator_idx] = channel.pending_op_blocks[operator_idx]; 883 if channel.mode == FrequencyMode::Multiple { 884 channel.update_phase_generators(); 885 } 886 887 log::trace!( 888 "Set operator-level frequency for channel {} / operator {}: F-num={:04X}", 889 channel_idx + 1, 890 operator_idx + 1, 891 channel.operator_f_numbers[operator_idx] 892 ); 893 } 894 0xAC..=0xAE => { 895 // Operator-level F-number high bits and block for channel 3 896 // Writes to this register do not take effect until low bits are written 897 let channel_idx = base_channel_idx + 2; 898 let operator_idx = match register { 899 0xAC => 2, 900 0xAD => 0, 901 0xAE => 1, 902 _ => unreachable!("nested match expressions"), 903 }; 904 let channel = &mut self.channels[channel_idx]; 905 channel.pending_op_f_numbers_high[operator_idx] = value & 7; 906 channel.pending_op_blocks[operator_idx] = (value >> 3) & 7; 907 908 log::trace!( 909 "Set operator-level frequency / block for channel {} / operator {}: F-num high bits {}, block {}", 910 channel_idx + 1, 911 operator_idx + 1, 912 channel.pending_op_f_numbers_high[operator_idx], 913 channel.pending_op_blocks[operator_idx], 914 ); 915 } 916 0xB0..=0xB2 => { 917 // Algorithm and operator 1 feedback level 918 let channel_idx = base_channel_idx + (register & 0x03) as usize; 919 let channel = &mut self.channels[channel_idx]; 920 channel.algorithm = value & 0x07; 921 channel.feedback_level = (value >> 3) & 0x07; 922 923 log::trace!( 924 "Channel {}: Algorithm={}, feedback level={}", 925 channel_idx + 1, 926 channel.algorithm, 927 channel.feedback_level 928 ); 929 } 930 0xB4..=0xB6 => { 931 // Stereo control and LFO sensitivity 932 let channel_idx = base_channel_idx + (register & 0x03) as usize; 933 let channel = &mut self.channels[channel_idx]; 934 channel.l_output = value.bit(7); 935 channel.r_output = value.bit(6); 936 channel.am_sensitivity = (value >> 4) & 0x03; 937 channel.fm_sensitivity = value & 0x07; 938 939 log::trace!( 940 "Channel {}: L={}, R={}, AM sensitivity={}, FM sensitivity={}", 941 channel_idx + 1, 942 channel.l_output, 943 channel.r_output, 944 channel.am_sensitivity, 945 channel.fm_sensitivity 946 ); 947 } 948 _ => {} 949 } 950 } 951 952 #[inline] 953 fn clock(&mut self) { 954 let lfo_counter = self.lfo.counter(); 955 let quantization_mask = if self.quantize_output { 956 // Simulate a 9-bit DAC by masking out the lowest 5 bits of the 14-bit channel outputs 957 !((1 << 5) - 1) 958 } else { 959 !0 960 }; 961 962 for channel in &mut self.channels { 963 channel.clock(lfo_counter, quantization_mask); 964 } 965 } 966 967 pub fn reload_config(&mut self, config: &GenesisEmulatorConfig) { 968 self.channels_muted = config.channels_muted(); 969 self.quantize_output = config.quantize_ym2612_output; 970 self.emulate_ladder_effect = config.emulate_ym2612_ladder_effect; 971 self.busy_behavior = config.opn2_busy_behavior; 972 } 973} 974 975#[cfg(test)] 976mod tests { 977 use super::*; 978 979 #[test] 980 fn ladder_effect() { 981 let ym2612 = Ym2612::new(&GenesisEmulatorConfig { 982 emulate_ym2612_ladder_effect: true, 983 ..GenesisEmulatorConfig::default() 984 }); 985 986 // Zero; output +4 987 assert_eq!(4 << 5, ym2612.apply_panning(0, false)); 988 assert_eq!(4 << 5, ym2612.apply_panning(0, true)); 989 990 // Positive; output +4 when muted, add +4 when enabled 991 assert_eq!(4 << 5, ym2612.apply_panning(6 << 5, false)); 992 assert_eq!(10 << 5, ym2612.apply_panning(6 << 5, true)); 993 994 // Negative; output -4 when muted, add -3 when enabled 995 assert_eq!(-(4 << 5), ym2612.apply_panning(-(6 << 5), false)); 996 assert_eq!(-(9 << 5), ym2612.apply_panning(-(6 << 5), true)); 997 } 998 999 #[test] 1000 fn busy_flag_ym2612() { 1001 let mut ym2612 = Ym2612::new(&GenesisEmulatorConfig { 1002 opn2_busy_behavior: Opn2BusyBehavior::Ym2612, 1003 ..GenesisEmulatorConfig::default() 1004 }); 1005 1006 let check_4001_4003 = |ym2612: &mut Ym2612, value: u8| { 1007 for address in 0x4001..=0x4003 { 1008 assert_eq!(ym2612.read_register(address) & 0x80, value); 1009 } 1010 }; 1011 1012 // Write to a register 1013 ym2612.write_address_1(0x30); 1014 ym2612.write_data(0xFF); 1015 1016 // $4001-$4003 should read 0 1017 check_4001_4003(&mut ym2612, 0); 1018 1019 // Read from $4000 should have busy flag set 1020 assert_eq!(ym2612.read_register(0x4000) & 0x80, 0x80); 1021 1022 // $4001-$4003 should now read with the busy flag set 1023 check_4001_4003(&mut ym2612, 0x80); 1024 1025 // Tick for 40 internal cycles 1026 ym2612.tick(40); 1027 1028 // Busy flag should be clear by now, but $4001-$4003 should still read the old value 1029 check_4001_4003(&mut ym2612, 0x80); 1030 1031 // Read from $4000 should have busy flag clear 1032 assert_eq!(ym2612.read_register(0x4000) & 0x80, 0); 1033 1034 // $4001-$4003 should now have busy flag clear 1035 check_4001_4003(&mut ym2612, 0); 1036 1037 // Write to a register again 1038 ym2612.write_address_1(0x30); 1039 ym2612.write_data(0xFF); 1040 1041 // $4000 should now have busy flag set again 1042 assert_eq!(ym2612.read_register(0x4000) & 0x80, 0x80); 1043 check_4001_4003(&mut ym2612, 0x80); 1044 1045 // Tick for almost half a second's worth of cycles 1046 ym2612.tick(500000); 1047 1048 // Status value should have decayed to 0 by now 1049 check_4001_4003(&mut ym2612, 0); 1050 assert_eq!(ym2612.read_register(0x4000) & 0x80, 0); 1051 } 1052}