Skip to content

Commit

Permalink
Fixes.
Browse files Browse the repository at this point in the history
  • Loading branch information
SamiPerttu committed Jun 10, 2024
1 parent 3c04914 commit 2f041c3
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 29 deletions.
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ FunDSP supports `no_std` environments. To enable `no_std`, disable
the feature `std`, which is enabled by default. The `alloc` crate
is still needed for components that allocate memory.

In a `no_std` environment,
audio file reading and writing is not available.
Audio file reading and writing is not available in `no_std`.

```rust
[dependencies]
Expand Down Expand Up @@ -330,7 +329,7 @@ Arithmetic operators are applied to outputs channelwise.

Arithmetic between two components never broadcasts channels: channel arities have to match always.

Direct arithmetic with `f32` and `f64` values, however, broadcasts to an arbitrary number of channels.
Direct arithmetic with `f32` values, however, broadcasts to an arbitrary number of channels.

The negation operator broadcasts also: `-A` is equivalent with `(0.0 - A)`.

Expand Down Expand Up @@ -944,13 +943,13 @@ a setting listener.
let (sender, equalizer) = listen(equalizer);
```

Then, we can send settings of the form (band, (center, Q, gain)).
Then, we can send settings to change center frequency, Q and gain.
The settings are available because we constructed the filter using
the `bell_hz` form.
Set band 1 to amplify by 3 dB at 1000 Hz with Q set to 2.0:

```rust
sender.try_send((1, (1000.0, 2.0, db_amp(3.0)))).expect("Cannot send setting.");
sender.try_send(Setting::center_q_gain(1000.0, 2.0, db_amp(3.0)).index(1)).expect("Cannot send setting.");
```

## evcxr
Expand Down
56 changes: 32 additions & 24 deletions src/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ struct Vertex {
pub tick_output: Vec<f32>,
/// Stable, globally unique ID for this vertex.
pub id: NodeId,
/// This is set if all vertex inputs are sourced from matching outputs of the indicated node.
/// We can then omit copying and use the node outputs directly.
pub source_vertex: Option<NodeIndex>,
/// This is set if all vertex inputs are sourced from successive outputs of the indicated node.
/// We can then omit copying and use the source node outputs directly.
pub source_vertex: Option<(NodeIndex, usize)>,
/// Network revision in which this vertex was changed last.
pub changed: u64,
}
Expand Down Expand Up @@ -117,36 +117,35 @@ impl Vertex {
self.tick_output.len()
}

/// Update source vertex shortcut.
pub fn update_source_vertex(&mut self) {
self.source_vertex = None;
/// Preallocate everything.
pub fn allocate(&mut self) {
self.unit.allocate();
}

/// Calculate source vertex and source port.
pub fn get_source_vertex(&self) -> Option<(NodeIndex, usize)> {
if self.inputs() == 0 {
return;
return None;
}
let mut source_node = 0;
let mut source_port = 0;
for i in 0..self.inputs() {
match self.source[i].source {
let source = self.source[i].source;
match source {
Port::Local(node, port) => {
if port != i {
return;
}
if i == 0 {
source_node = node;
} else if source_node != node {
return;
source_port = port;
} else if source_node != node || source_port + i != port {
return None;
}
}
_ => {
return;
return None;
}
}
}
self.source_vertex = Some(source_node);
}

/// Preallocate everything.
pub fn allocate(&mut self) {
self.unit.allocate();
Some((source_node, source_port))
}
}

Expand Down Expand Up @@ -667,8 +666,9 @@ impl Net {

/// Compute and store node order for this network.
fn determine_order(&mut self) {
for vertex in self.vertex.iter_mut() {
vertex.update_source_vertex();
// Update source vertex shortcut.
for j in 0..self.vertex.len() {
self.vertex[j].source_vertex = self.vertex[j].get_source_vertex();
}
let mut order = Vec::new();
if !self.determine_order_in(&mut order) {
Expand Down Expand Up @@ -826,6 +826,7 @@ impl Net {
match self.vertex[index].source[channel].source {
Port::Local(node, port) => {
assert!(node < self.size());
// Self connections are prohibited.
assert!(node != index);
assert!(port < self.vertex[node].outputs());
}
Expand All @@ -835,6 +836,13 @@ impl Net {
_ => (),
}
}
if let Some((source_node, source_port)) = self.vertex[index].source_vertex {
assert!(source_node < self.size());
assert!(source_node != index);
assert!(
source_port + self.vertex[index].inputs() <= self.vertex[source_node].outputs()
);
}
}
}

Expand Down Expand Up @@ -1031,15 +1039,15 @@ impl AudioUnit for Net {
let simd_size = simd_items(size);
// Iterate units in network order.
for &node_index in self.order.as_ref().unwrap().iter() {
if let Some(source_node) = self.vertex[node_index].source_vertex {
if let Some((source_node, source_port)) = self.vertex[node_index].source_vertex {
// We can source inputs directly from a source vertex.
let ptr = &mut self.vertex[source_node].output as *mut BufferVec;
let vertex = &mut self.vertex[node_index];
// Safety: we know there is no aliasing, as self connections are prohibited.
unsafe {
vertex.unit.process(
size,
&(*ptr).buffer_ref(),
&(*ptr).buffer_ref().subset(source_port, vertex.inputs()),
&mut vertex.output.buffer_mut(),
);
}
Expand Down
9 changes: 9 additions & 0 deletions tests/test_basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,15 @@ fn test_basic() {
check_wave((noise() | envelope(|t| spline_noise(1, t * 10.0))) >> panner());
check_wave(impulse::<U2>());

let dc42 = Net::wrap(Box::new(dc(42.)));
let dcs = dc42.clone() | dc42;
let reverb = Net::wrap(Box::new(reverb_stereo(40., 5., 1.)));
let filter = Net::wrap(Box::new(lowpass_hz(1729., 1.)));
let filters = filter.clone() | filter;
let net = dcs >> reverb >> filters;
net.check();
check_wave(net);

// Wave filtering, tick vs. process rendering, node reseting.
let input = Wave::render(44100.0, 1.0, &mut (noise() | noise()));
check_wave_filter(&input, butterpass_hz(1000.0) | lowpole_hz(100.0));
Expand Down

0 comments on commit 2f041c3

Please sign in to comment.