@@ -2,9 +2,8 @@ use std::collections::VecDeque;
22
33const CPU_HZ : f64 = 4_194_304.0 ;
44const FRAME_CYCLES : u32 = 70_224 ;
5- pub ( crate ) const OUTPUT_SAMPLE_RATE_HZ : f64 = 48_000.0 ;
6- const CYCLES_PER_SAMPLE : f64 = CPU_HZ / OUTPUT_SAMPLE_RATE_HZ ;
7- const MAX_SAMPLE_QUEUE : usize = 8_192 ;
5+ pub ( crate ) const DEFAULT_OUTPUT_SAMPLE_RATE_HZ : f64 = 48_000.0 ;
6+ const MAX_SAMPLE_QUEUE : usize = 2_048 ;
87
98const REG_NR10 : u16 = 0xFF10 ;
109const REG_NR11 : u16 = 0xFF11 ;
@@ -35,7 +34,6 @@ const REG_NR51: u16 = 0xFF25;
3534const REG_NR52 : u16 = 0xFF26 ;
3635
3736const FREQ_DIVISOR : u32 = 131072 ;
38- const NOISE_CLOCK_BASE : u32 = 524288 ;
3937const FRAME_SEQUENCER_CYCLES : u32 = 8192 ;
4038
4139const DUTY_CYCLES : [ [ u8 ; 8 ] ; 4 ] = [
@@ -611,7 +609,7 @@ impl NoiseChannel {
611609
612610 let divisor = Self :: divisor_value ( self . divisor_code ) ;
613611 let shift = self . shift_clock_frequency ;
614- let threshold = ( NOISE_CLOCK_BASE / ( divisor << shift) ) / 2 ;
612+ let threshold = divisor << ( shift + 4 ) ;
615613
616614 self . timer = self . timer . wrapping_add ( cycles) ;
617615
@@ -732,6 +730,8 @@ pub struct Apu {
732730 wave_channel : WaveChannel ,
733731 noise_channel : NoiseChannel ,
734732 sample_cycle_accumulator : f64 ,
733+ sample_rate_hz : f64 ,
734+ cycles_per_sample : f64 ,
735735 samples : VecDeque < [ i32 ; 2 ] > ,
736736 current_sample : i32 ,
737737 current_sample_left : i32 ,
@@ -752,6 +752,8 @@ impl Apu {
752752 wave_channel : WaveChannel :: new ( ) ,
753753 noise_channel : NoiseChannel :: new ( ) ,
754754 sample_cycle_accumulator : 0.0 ,
755+ sample_rate_hz : DEFAULT_OUTPUT_SAMPLE_RATE_HZ ,
756+ cycles_per_sample : CPU_HZ / DEFAULT_OUTPUT_SAMPLE_RATE_HZ ,
755757 samples : VecDeque :: new ( ) ,
756758 current_sample : 0 ,
757759 current_sample_left : 0 ,
@@ -776,8 +778,8 @@ impl Apu {
776778 self . noise_channel . step ( cycles) ;
777779
778780 self . sample_cycle_accumulator += cycles as f64 ;
779- while self . sample_cycle_accumulator >= CYCLES_PER_SAMPLE {
780- self . sample_cycle_accumulator -= CYCLES_PER_SAMPLE ;
781+ while self . sample_cycle_accumulator >= self . cycles_per_sample {
782+ self . sample_cycle_accumulator -= self . cycles_per_sample ;
781783 self . mix_sample ( ) ;
782784 if self . samples . len ( ) >= MAX_SAMPLE_QUEUE {
783785 self . samples . pop_front ( ) ;
@@ -797,41 +799,14 @@ impl Apu {
797799 self . wave_channel . tick_length ( ) ;
798800 self . noise_channel . tick_length ( ) ;
799801 }
800- 1 => {
801- self . pulse_channel . tick_sweep ( ) ;
802- self . pulse_channel . tick_length ( ) ;
803- self . pulse_channel2 . tick_length ( ) ;
804- self . wave_channel . tick_length ( ) ;
805- self . noise_channel . tick_length ( ) ;
806- }
807- 2 => {
808- self . pulse_channel . tick_length ( ) ;
809- self . pulse_channel2 . tick_length ( ) ;
810- self . wave_channel . tick_length ( ) ;
811- self . noise_channel . tick_length ( ) ;
812- }
813- 3 => {
814- self . pulse_channel . tick_envelope ( ) ;
815- self . pulse_channel2 . tick_envelope ( ) ;
816- self . pulse_channel . tick_length ( ) ;
817- self . pulse_channel2 . tick_length ( ) ;
818- self . wave_channel . tick_length ( ) ;
819- self . noise_channel . tick_length ( ) ;
820- }
821- 4 => {
802+ 2 | 6 => {
822803 self . pulse_channel . tick_length ( ) ;
823804 self . pulse_channel2 . tick_length ( ) ;
824805 self . wave_channel . tick_length ( ) ;
825806 self . noise_channel . tick_length ( ) ;
826- }
827- 5 => {
828807 self . pulse_channel . tick_sweep ( ) ;
829- self . pulse_channel . tick_length ( ) ;
830- self . pulse_channel2 . tick_length ( ) ;
831- self . wave_channel . tick_length ( ) ;
832- self . noise_channel . tick_length ( ) ;
833808 }
834- 6 => {
809+ 4 => {
835810 self . pulse_channel . tick_length ( ) ;
836811 self . pulse_channel2 . tick_length ( ) ;
837812 self . wave_channel . tick_length ( ) ;
@@ -840,10 +815,7 @@ impl Apu {
840815 7 => {
841816 self . pulse_channel . tick_envelope ( ) ;
842817 self . pulse_channel2 . tick_envelope ( ) ;
843- self . pulse_channel . tick_length ( ) ;
844- self . pulse_channel2 . tick_length ( ) ;
845- self . wave_channel . tick_length ( ) ;
846- self . noise_channel . tick_length ( ) ;
818+ self . noise_channel . tick_envelope ( ) ;
847819 }
848820 _ => { }
849821 }
@@ -903,7 +875,7 @@ impl Apu {
903875
904876 pub fn samples_per_frame ( & self ) -> u32 {
905877 let frame_rate = CPU_HZ / FRAME_CYCLES as f64 ;
906- ( OUTPUT_SAMPLE_RATE_HZ / frame_rate) . round ( ) as u32
878+ ( self . sample_rate_hz / frame_rate) . round ( ) as u32
907879 }
908880
909881 fn reset_state ( & mut self ) {
@@ -1095,7 +1067,23 @@ impl Apu {
10951067 }
10961068
10971069 pub fn sample_rate_hz ( & self ) -> f64 {
1098- OUTPUT_SAMPLE_RATE_HZ
1070+ self . sample_rate_hz
1071+ }
1072+
1073+ pub fn set_sample_rate_hz ( & mut self , sample_rate_hz : f64 ) {
1074+ if !sample_rate_hz. is_finite ( ) || sample_rate_hz <= 0.0 {
1075+ return ;
1076+ }
1077+ if ( self . sample_rate_hz - sample_rate_hz) . abs ( ) < f64:: EPSILON {
1078+ return ;
1079+ }
1080+ self . sample_rate_hz = sample_rate_hz;
1081+ self . cycles_per_sample = CPU_HZ / sample_rate_hz;
1082+ self . sample_cycle_accumulator = 0.0 ;
1083+ self . samples . clear ( ) ;
1084+ self . current_sample = 0 ;
1085+ self . current_sample_left = 0 ;
1086+ self . current_sample_right = 0 ;
10991087 }
11001088
11011089 pub fn has_sample ( & self ) -> bool {
@@ -1126,8 +1114,8 @@ impl Apu {
11261114#[ cfg( test) ]
11271115mod tests {
11281116 use super :: {
1129- Apu , CPU_HZ , CYCLES_PER_SAMPLE , FRAME_CYCLES , NoiseChannel , OUTPUT_SAMPLE_RATE_HZ ,
1130- PulseChannel , WaveChannel ,
1117+ Apu , CPU_HZ , DEFAULT_OUTPUT_SAMPLE_RATE_HZ , FRAME_CYCLES , NoiseChannel , PulseChannel ,
1118+ WaveChannel ,
11311119 } ;
11321120
11331121 #[ test]
@@ -1569,7 +1557,7 @@ mod tests {
15691557 let apu = Apu :: new ( ) ;
15701558 let rate = apu. sample_rate_hz ( ) ;
15711559 assert ! (
1572- ( rate - OUTPUT_SAMPLE_RATE_HZ ) . abs( ) < 0.1 ,
1560+ ( rate - DEFAULT_OUTPUT_SAMPLE_RATE_HZ ) . abs( ) < 0.1 ,
15731561 "Sample rate should be ~48kHz, got {}" ,
15741562 rate
15751563 ) ;
@@ -1580,7 +1568,7 @@ mod tests {
15801568 let mut apu = Apu :: new ( ) ;
15811569 assert ! ( !apu. has_sample( ) ) ;
15821570 assert_eq ! ( apu. sample( ) , 0 ) ;
1583- let cycles_per_sample = CYCLES_PER_SAMPLE . ceil ( ) as u32 ;
1571+ let cycles_per_sample = ( CPU_HZ / apu . sample_rate_hz ( ) ) . ceil ( ) as u32 ;
15841572 let _ = apu. step ( cycles_per_sample) ;
15851573 assert ! ( apu. has_sample( ) ) ;
15861574 let sample = apu. take_sample ( ) ;
@@ -1591,7 +1579,7 @@ mod tests {
15911579 #[ test]
15921580 fn apu_sample_is_clamped ( ) {
15931581 let mut apu = Apu :: new ( ) ;
1594- let cycles_per_sample = CYCLES_PER_SAMPLE . ceil ( ) as u32 ;
1582+ let cycles_per_sample = ( CPU_HZ / apu . sample_rate_hz ( ) ) . ceil ( ) as u32 ;
15951583 for _ in 0 ..10 {
15961584 let _ = apu. step ( cycles_per_sample) ;
15971585 if apu. has_sample ( ) {
0 commit comments