@@ -73,28 +73,41 @@ fn test_sinc() {
7373}
7474
7575#[ test]
76- fn test_sinc_downsampling_antialiasing ( ) {
76+ fn test_sinc_antialiasing ( ) {
7777 const SOURCE_HZ : f64 = 2000.0 ;
7878 const TARGET_HZ : f64 = 1500.0 ;
7979 const SIGNAL_FREQ : f64 = 900.0 ;
80+ const TAPS : usize = 100 ;
8081
8182 let source_signal = signal:: rate ( SOURCE_HZ ) . const_hz ( SIGNAL_FREQ ) . sine ( ) ;
82-
83- let ring_buffer = ring_buffer:: Fixed :: from ( vec ! [ 0.0 ; 100 ] ) ;
83+ let ring_buffer = ring_buffer:: Fixed :: from ( vec ! [ 0.0 ; TAPS ] ) ;
8484 let sinc = Sinc :: new ( ring_buffer) ;
8585 let mut downsampled = source_signal. from_hz_to_hz ( sinc, SOURCE_HZ , TARGET_HZ ) ;
8686
87- for _ in 0 ..50 {
87+ // Warm up the filter to reach steady state
88+ for _ in 0 ..TAPS / 2 {
8889 downsampled. next ( ) ;
8990 }
9091
92+ // Measure peak amplitude in steady state
9193 let samples: Vec < f64 > = downsampled. take ( 1500 ) . collect ( ) ;
92-
93- let rms = ( samples. iter ( ) . map ( |& s| s * s) . sum :: < f64 > ( ) / samples. len ( ) as f64 ) . sqrt ( ) ;
94+ let peak_amplitude = samples
95+ . iter ( )
96+ . map ( |& s| s. abs ( ) )
97+ . max_by ( |a, b| a. partial_cmp ( b) . unwrap ( ) )
98+ . unwrap ( ) ;
99+
100+ // With Hann-windowed sinc, With 50 taps and 900 Hz being relatively close to the 750 Hz
101+ // cutoff, we're in the early stopband region where attenuation is less than -44 dB.
102+ // Empirical measurement shows ~41 dB for this configuration.
103+ const EXPECTED_ATTENUATION_DB : f64 = 41.0 ;
104+ let max_peak_amplitude = 10.0_f64 . powf ( -EXPECTED_ATTENUATION_DB / 20.0 ) ;
94105
95106 assert ! (
96- rms < 0.1 ,
97- "Expected RMS < 0.1 (well-filtered), got {:.3}. Aliasing occurred." ,
98- rms
107+ peak_amplitude < max_peak_amplitude,
108+ "Expected ≥{:.0} dB attenuation (peak < {:.4}), got peak {:.4}" ,
109+ EXPECTED_ATTENUATION_DB ,
110+ max_peak_amplitude,
111+ peak_amplitude
99112 ) ;
100113}
0 commit comments