Skip to content

Commit 26fe70c

Browse files
householder
1 parent 3e820cc commit 26fe70c

3 files changed

Lines changed: 61 additions & 0 deletions

File tree

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
use crate::{
2+
context::AudioContext,
3+
node::{Inputs, Node},
4+
ports::{PortBuilder, Ports},
5+
};
6+
7+
/// As suggested in https://signalsmith-audio.co.uk/writing/2021/lets-write-a-reverb/
8+
///
9+
/// Allegedly a bit lower density than saw a hadamard mixer
10+
#[derive(Clone)]
11+
pub struct HouseholderMixer {
12+
chans: usize,
13+
ports: Ports,
14+
}
15+
16+
impl HouseholderMixer {
17+
pub fn new(chans: usize) -> Self {
18+
Self {
19+
chans,
20+
ports: PortBuilder::default()
21+
.audio_in(chans)
22+
.audio_out(chans)
23+
.build(),
24+
}
25+
}
26+
}
27+
28+
impl Node for HouseholderMixer {
29+
fn process(&mut self, _ctx: &mut AudioContext, inputs: &Inputs, outputs: &mut [&mut [f32]]) {
30+
let block_size = outputs[0].len();
31+
let multiplier = 2.0 / self.chans as f32;
32+
33+
for i in 0..block_size {
34+
let sum: f32 = (0..self.chans)
35+
.map(|c| inputs.get(c).and_then(|x| *x).map_or(0.0, |buf| buf[i]))
36+
.sum();
37+
for c in 0..self.chans {
38+
let x = inputs.get(c).and_then(|x| *x).map_or(0.0, |buf| buf[i]);
39+
outputs[c][i] = x - multiplier * sum;
40+
}
41+
}
42+
}
43+
fn ports(&self) -> &Ports {
44+
&self.ports
45+
}
46+
}

crates/src/nodes/audio/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ pub mod allpass;
33
pub mod delay;
44
pub mod external;
55
pub mod fir;
6+
pub mod hadamard;
7+
pub mod householder;
68
pub mod mixer;
79
pub mod onepole;
810
pub mod ops;

crates/src/registry.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use crate::{
1414
delay::{DelayRead, DelayWrite},
1515
external::ExternalInput,
1616
hadamard::HadamardMixer,
17+
householder::HouseholderMixer,
1718
mixer::{MonoFanOut, TrackMixer},
1819
onepole::OnePole,
1920
ops::{ApplyOpKind, mult_node_factory},
@@ -382,6 +383,18 @@ pub fn audio_registry_factory() -> NodeRegistry {
382383
Ok(Box::new(HadamardMixer::new(chans)))
383384
}
384385
),
386+
node_spec!(
387+
"householder".into(),
388+
required = ["chans"],
389+
optional = [],
390+
build = |_, p| {
391+
let chans = p
392+
.get_usize("chans")
393+
.expect("Must provide chans to audio_input");
394+
395+
Ok(Box::new(HouseholderMixer::new(chans)))
396+
}
397+
),
385398
node_spec!(
386399
"external".into(),
387400
required = ["interface_name", "chans"],

0 commit comments

Comments
 (0)