Improved documentation of MatrixCellChain
This commit is contained in:
parent
eff41e7ad5
commit
ed1ac581ce
5 changed files with 66 additions and 69 deletions
|
@ -1,6 +1,28 @@
|
|||
// Copyright (c) 2021-2022 Weird Constructor <weirdconstructor@gmail.com>
|
||||
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
|
||||
// See README.md and COPYING for details.
|
||||
/*! Defines an API for easy DSP chain building with the hexagonal [crate::Matrix].
|
||||
|
||||
The [crate::MatrixCellChain] abstractions allows very easy placement of DSP signal chains:
|
||||
|
||||
```
|
||||
use hexodsp::*;
|
||||
let mut chain = MatrixCellChain::new(CellDir::BR);
|
||||
chain.node_out("sin", "sig")
|
||||
.set_denorm("freq", 220.0)
|
||||
.node_io("amp", "inp", "sig")
|
||||
.set_denorm("att", 0.5)
|
||||
.node_inp("out", "ch1");
|
||||
|
||||
// use crate::nodes::new_node_engine;
|
||||
let (node_conf, _node_exec) = new_node_engine();
|
||||
let mut matrix = Matrix::new(node_conf, 7, 7);
|
||||
|
||||
chain.place(&mut matrix, 2, 2).expect("no error in this case");
|
||||
```
|
||||
*/
|
||||
|
||||
|
||||
use crate::{Cell, CellDir, Matrix, NodeId, ParamId, SAtom};
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
@ -12,16 +34,16 @@ struct MatrixChainLink {
|
|||
params: Vec<(ParamId, SAtom)>,
|
||||
}
|
||||
|
||||
/// A DSP chain builder for the [hexodsp::Matrix].
|
||||
/// A DSP chain builder for the [crate::Matrix].
|
||||
///
|
||||
/// This is an extremely easy API to create and place new DSP chains into the [hexodsp::Matrix].
|
||||
/// This is an extremely easy API to create and place new DSP chains into the [crate::Matrix].
|
||||
/// It can be used by frontends to place DSP chains on user request or it can be used
|
||||
/// by test cases to quickly fill the hexagonal Matrix.
|
||||
///
|
||||
///```
|
||||
/// use hexodsp::*;
|
||||
/// let mut chain = MatrixCellChain::new(CellDir::BR);
|
||||
/// chain.node_out("sin")
|
||||
/// chain.node_out("sin", "sig")
|
||||
/// .set_denorm("freq", 220.0)
|
||||
/// .node_io("amp", "inp", "sig")
|
||||
/// .set_denorm("att", 0.5)
|
||||
|
@ -42,6 +64,7 @@ pub struct MatrixCellChain {
|
|||
param_idx: usize,
|
||||
}
|
||||
|
||||
/// Error type for the [crate::MatrixCellChain].
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ChainError {
|
||||
UnknownOutput(NodeId, String),
|
||||
|
@ -122,14 +145,14 @@ impl MatrixCellChain {
|
|||
self
|
||||
}
|
||||
|
||||
/// Utility function for creating [hexodsp::Cell] for this chain.
|
||||
/// Utility function for creating [crate::Cell] for this chain.
|
||||
pub fn spawn_cell_from_node_id_name(&mut self, node_id: &str) -> Cell {
|
||||
let node_id = NodeId::from_str(node_id);
|
||||
|
||||
Cell::empty(node_id)
|
||||
}
|
||||
|
||||
/// Utility function to add a pre-built [hexodsp::Cell] as next link.
|
||||
/// Utility function to add a pre-built [crate::Cell] as next link.
|
||||
///
|
||||
/// This also sets the current parameter cell.
|
||||
pub fn add_link(&mut self, cell: Cell) {
|
||||
|
|
|
@ -366,12 +366,13 @@ The start of your `tests/node_*.rs` file usually should look like this:
|
|||
let (node_conf, mut node_exec) = new_node_engine();
|
||||
let mut matrix = Matrix::new(node_conf, 3, 3);
|
||||
|
||||
let ad = NodeId::Ad(0);
|
||||
let out = NodeId::Out(0);
|
||||
matrix.place(0, 0, Cell::empty(ad).out(None, None, ad.out("sig")));
|
||||
matrix.place(0, 1, Cell::empty(out).input(out.inp("ch1"), None, None));
|
||||
let mut chain = MatrixCellChain::new(CellDir::B);
|
||||
chain.node_out("ad", "sig")
|
||||
.node_inp("out", "ch1")
|
||||
.place(&mut matrix, 0, 0).unwrap();
|
||||
matrix.sync().unwrap();
|
||||
|
||||
let ad = NodeId::Ad(0);
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
@ -393,81 +394,50 @@ The two parameters to _new_ are the width and height of the hex grid.
|
|||
let mut matrix = Matrix::new(node_conf, 3, 3);
|
||||
```
|
||||
|
||||
Next step is to create a DSP chain of nodes and place that onto the hexagonal matrix.
|
||||
Luckily a simpler API has been created with the [crate::MatrixCellChain], that lets
|
||||
you build DSP chains on the fly using only names of the nodes and the corresponding
|
||||
input/output ports:
|
||||
|
||||
```ignore
|
||||
// Create a new cell chain that points in to the given direction (CellDir::B => to bottom).
|
||||
let mut chain = MatrixCellChain::new(CellDir::B);
|
||||
chain.node_out("ad", "sig") // Add a Node::Ad(0) cell, with the "sig" output set
|
||||
.node_inp("out", "ch1") // Add a Node::Out(0) cell, with the "ch1" input set
|
||||
.place(&mut matrix, 0, 0).unwrap();
|
||||
```
|
||||
|
||||
After placing the new cells, we need to synchronize it with the audio backend:
|
||||
|
||||
```ignore
|
||||
matrix.sync().unwrap();
|
||||
```
|
||||
|
||||
The `sync` is necessary to update the DSP graph.
|
||||
|
||||
Next you usually want to define short variable names for the [NodeId] that refer to the DSP
|
||||
node instances:
|
||||
|
||||
```ignore
|
||||
let ad = NodeId::Ad(0);
|
||||
let out = NodeId::Out(0);
|
||||
```
|
||||
|
||||
You can have multiple instances for a node. The number in the parenthesis are
|
||||
the instance index of that node.
|
||||
|
||||
Next you want to layout the nodes adjacent to each other on the hexagonal grid.
|
||||
This is a bit more tricky than with a rectangular grid.
|
||||
|
||||
```ignore
|
||||
matrix.place(0, 0, Cell::empty(ad).out(None, None, ad.out("sig")));
|
||||
matrix.place(0, 1, Cell::empty(out).input(out.inp("ch1"), None, None));
|
||||
matrix.sync().unwrap();
|
||||
```
|
||||
|
||||
The `sync` is necessary to update the DSP graph.
|
||||
When doing this, keep the following grid layout in mind:
|
||||
|
||||
```text
|
||||
_____ _____
|
||||
/ \ / \
|
||||
/ 0,0 \_____/ 2,0 \_____
|
||||
\ / \ / \
|
||||
\_____/ 1,0 \_____/ 3,0 \
|
||||
/ \ / \ /
|
||||
/ 0,1 \_____/ 2,1 \_____/
|
||||
\ / \ / \
|
||||
\_____/ 1,1 \_____/ 3,1 \
|
||||
/ \ / \ /
|
||||
/ 0,2 \_____/ 2,2 \_____/
|
||||
\ / \ /
|
||||
\_____/ 1,2 \_____/
|
||||
\ /
|
||||
\_____/
|
||||
```
|
||||
|
||||
Defining the outputs of a cell is done like this:
|
||||
|
||||
```ignore
|
||||
Cell::empty(ad).out(None, None, ad.out("sig"))
|
||||
```
|
||||
|
||||
[crate::Cell::empty] takes a [NodeId] as first argument. The [crate::Cell]
|
||||
structure then allows you to specify the output ports using the [crate::Cell::out]
|
||||
function. The 3 arguments of that function are for the 3 edges of that hex tile:
|
||||
|
||||
```ignore
|
||||
// TopRight BottomRight Bottom
|
||||
Cell::empty(ad).out(None, None, ad.out("sig"))
|
||||
```
|
||||
|
||||
[crate::Cell::input] works the same way, but the 3 arguments refer to the 3 input
|
||||
edges of a hex tile:
|
||||
|
||||
```ignore
|
||||
// Top TopLeft BottomLeft
|
||||
Cell::empty(out).input(out.inp("ch1"), None, None)
|
||||
```
|
||||
|
||||
The [NodeId] interface offers you functions to get the input parameter index from
|
||||
a name like `out.inp("ch1")` or the output port index from a name: `ad.out("sig")`.
|
||||
You can have multiple instances for a node. The number in the parenthesis are
|
||||
the instance index of that node.
|
||||
|
||||
After you have setup everything for the test, you usually want to modify a paramter
|
||||
and look at the values the graph returns.
|
||||
|
||||
|
||||
```ignore
|
||||
#[test]
|
||||
fn check_node_ad_1() {
|
||||
// ...
|
||||
// matrix setup code above
|
||||
// ...
|
||||
|
||||
let ad = NodeId::Ad(0);
|
||||
|
||||
// Fetch parameter id:
|
||||
let trig_p = ad.inp_param("trig").unwrap();
|
||||
|
|
|
@ -295,6 +295,7 @@ pub use matrix_repr::load_patch_from_file;
|
|||
pub use matrix_repr::save_patch_to_file;
|
||||
pub use nodes::{new_node_engine, NodeConfigurator, NodeExecutor};
|
||||
pub use sample_lib::{SampleLibrary, SampleLoadError};
|
||||
pub use chain_builder::MatrixCellChain;
|
||||
|
||||
pub struct Context<'a, 'b, 'c, 'd> {
|
||||
pub nframes: usize,
|
||||
|
|
|
@ -6,6 +6,7 @@ pub use hexodsp::dsp::*;
|
|||
pub use hexodsp::matrix::*;
|
||||
pub use hexodsp::nodes::new_node_engine;
|
||||
pub use hexodsp::NodeExecutor;
|
||||
pub use hexodsp::MatrixCellChain;
|
||||
|
||||
use hound;
|
||||
|
||||
|
|
|
@ -10,8 +10,10 @@ fn check_node_ad_1() {
|
|||
let (node_conf, mut node_exec) = new_node_engine();
|
||||
let mut matrix = Matrix::new(node_conf, 3, 3);
|
||||
|
||||
let mut chain = hexodsp::chain_builder::MatrixCellChain::new(CellDir::B);
|
||||
chain.node_out("ad", "sig").node_inp("out", "ch1").place(&mut matrix, 0, 0).unwrap();
|
||||
let mut chain = MatrixCellChain::new(CellDir::B);
|
||||
chain.node_out("ad", "sig")
|
||||
.node_inp("out", "ch1")
|
||||
.place(&mut matrix, 0, 0).unwrap();
|
||||
matrix.sync().unwrap();
|
||||
|
||||
let ad = NodeId::Ad(0);
|
||||
|
|
Loading…
Reference in a new issue