@@ -233,24 +233,34 @@ impl IIRFilterNode {
233233 let nquist = sample_rate / 2. ;
234234
235235 for ( i, & f) in frequency_hz. iter ( ) . enumerate ( ) {
236- let freq = f64:: from ( f) . clamp ( 0. , nquist) ;
237- let z = -2.0 * PI * freq / sample_rate;
238- let mut num: Complex < f64 > = Complex :: new ( 0. , 0. ) ;
239- let mut denom: Complex < f64 > = Complex :: new ( 0. , 0. ) ;
236+ let freq = f64:: from ( f) ;
237+ // <https://webaudio.github.io/web-audio-api/#dom-iirfilternode-getfrequencyresponse>
238+ // > If a value in the frequencyHz parameter is not within [0, sampleRate/2],
239+ // > where sampleRate is the value of the sampleRate property of the AudioContext,
240+ // > the corresponding value at the same index of the magResponse/phaseResponse
241+ // > array MUST be NaN.
242+ if freq < 0. || freq > nquist {
243+ mag_response[ i] = f32:: NAN ;
244+ phase_response[ i] = f32:: NAN ;
245+ } else {
246+ let z = -2.0 * PI * freq / sample_rate;
247+ let mut num: Complex < f64 > = Complex :: new ( 0. , 0. ) ;
248+ let mut denom: Complex < f64 > = Complex :: new ( 0. , 0. ) ;
240249
241- for ( idx, & b) in self . feedforward . iter ( ) . enumerate ( ) {
242- num += Complex :: from_polar ( b, idx as f64 * z) ;
243- }
250+ for ( idx, & b) in self . feedforward . iter ( ) . enumerate ( ) {
251+ num += Complex :: from_polar ( b, idx as f64 * z) ;
252+ }
244253
245- for ( idx, & a) in self . feedback . iter ( ) . enumerate ( ) {
246- denom += Complex :: from_polar ( a, idx as f64 * z) ;
247- }
254+ for ( idx, & a) in self . feedback . iter ( ) . enumerate ( ) {
255+ denom += Complex :: from_polar ( a, idx as f64 * z) ;
256+ }
248257
249- let response = num / denom;
258+ let response = num / denom;
250259
251- let ( mag, phase) = response. to_polar ( ) ;
252- mag_response[ i] = mag as f32 ;
253- phase_response[ i] = phase as f32 ;
260+ let ( mag, phase) = response. to_polar ( ) ;
261+ mag_response[ i] = mag as f32 ;
262+ phase_response[ i] = phase as f32 ;
263+ }
254264 }
255265 }
256266}
@@ -897,4 +907,23 @@ mod tests {
897907 let feedforward = vec ! [ b0, b1, b2] ;
898908 compare_frequency_response ( BiquadFilterType :: Highshelf , feedback, feedforward) ;
899909 }
910+
911+ #[ test]
912+ fn test_frequency_response_invalid_frequencies ( ) {
913+ let context = OfflineAudioContext :: new ( 2 , 555 , 44_100. ) ;
914+ let options = IIRFilterOptions {
915+ feedback : vec ! [ 1. ; 10 ] ,
916+ feedforward : vec ! [ 1. ; 10 ] ,
917+ audio_node_options : AudioNodeOptions :: default ( ) ,
918+ } ;
919+ let iir = IIRFilterNode :: new ( & context, options) ;
920+
921+ let frequency_hz = [ -1. , 22_051. ] ;
922+ let mut mags = [ 0. ; 2 ] ;
923+ let mut phases = [ 0. ; 2 ] ;
924+
925+ iir. get_frequency_response ( & frequency_hz, & mut mags, & mut phases) ;
926+ mags. iter ( ) . for_each ( |v| assert ! ( v. is_nan( ) ) ) ;
927+ phases. iter ( ) . for_each ( |v| assert ! ( v. is_nan( ) ) ) ;
928+ }
900929}
0 commit comments