Skip to content

Commit b3739dd

Browse files
committed
IIRFilterNode: transpose (channels x coeffs) values matrix
For improved cache locality and readability
1 parent f7879c2 commit b3739dd

File tree

1 file changed

+18
-10
lines changed

1 file changed

+18
-10
lines changed

src/node/iir_filter.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! The IIR filter control and renderer parts
2+
use arrayvec::ArrayVec;
23
use num_complex::Complex;
4+
35
use std::f64::consts::PI;
46

57
use crate::context::{AudioContextRegistration, BaseAudioContext};
@@ -254,7 +256,7 @@ struct IirFilterRenderer {
254256
/// Normalized filter's coeffs -- `(b[n], a[n])`
255257
norm_coeffs: Vec<(f64, f64)>,
256258
/// filter's states
257-
states: Vec<Vec<f64>>,
259+
states: ArrayVec<Vec<f64>, MAX_CHANNELS>,
258260
}
259261

260262
impl IirFilterRenderer {
@@ -292,7 +294,11 @@ impl IirFilterRenderer {
292294
});
293295

294296
let coeffs_len = norm_coeffs.len();
295-
let states = vec![Vec::<f64>::with_capacity(MAX_CHANNELS); coeffs_len];
297+
298+
// eagerly assume stereo input, will adjust during rendering if needed
299+
let mut states = ArrayVec::new();
300+
states.push(vec![0.; coeffs_len]);
301+
states.push(vec![0.; coeffs_len]);
296302

297303
Self {
298304
norm_coeffs,
@@ -340,15 +346,16 @@ impl AudioProcessor for IirFilterRenderer {
340346
// see https://webaudio.github.io/web-audio-api/#channels-tail-time
341347
let num_channels = input.number_of_channels();
342348

343-
if num_channels != self.states[0].len() {
344-
self.states
345-
.iter_mut()
346-
.for_each(|state| state.resize(num_channels, 0.));
349+
if num_channels != self.states.len() {
350+
self.states.truncate(num_channels);
351+
for _ in self.states.len()..num_channels {
352+
self.states.push(vec![0.; self.norm_coeffs.len()]);
353+
}
347354
}
348355

349356
output.set_number_of_channels(num_channels);
350357
} else {
351-
let num_channels = self.states[0].len();
358+
let num_channels = self.states.len();
352359
output.set_number_of_channels(num_channels);
353360
}
354361

@@ -359,17 +366,18 @@ impl AudioProcessor for IirFilterRenderer {
359366
} else {
360367
input.channel_data(channel_number)
361368
};
369+
let channel_state = &mut self.states[channel_number];
362370

363371
for (&i, o) in input_channel.iter().zip(output_channel.iter_mut()) {
364372
let input = f64::from(i);
365373
let b0 = self.norm_coeffs[0].0;
366-
let last_state = self.states[0][channel_number];
374+
let last_state = channel_state[0];
367375
let output = b0.mul_add(input, last_state);
368376

369377
// update states for next call
370378
for (i, (b, a)) in self.norm_coeffs.iter().skip(1).enumerate() {
371-
let state = self.states[i + 1][channel_number];
372-
self.states[i][channel_number] = b * input - a * output + state;
379+
let state = channel_state[i + 1];
380+
channel_state[i] = b * input - a * output + state;
373381
}
374382

375383
#[cfg(debug_assertions)]

0 commit comments

Comments
 (0)