3 个版本

0.1.2 2020年12月29日
0.1.1 2020年12月29日
0.1.0 2020年12月28日

#1786 in 数据结构

MIT 许可证

57KB
1K SLoC

siraph 库是一个基于节点的数字信号处理库。

功能

  • 节点: 添加了包含一些基本有用节点的 nodes 模块,如 MapConst。此功能默认启用。

  • 数学: 添加了包含与数学相关的有用节点的 nodes::math 模块,如 AddOscillator。此功能依赖于 num-traits 库和 nodes 功能。

  • 随机: 添加了包含与随机数生成器相关的有用节点的 nodes::random 模块,如 SampleAndHold。此功能依赖于 rand 库和 nodes 功能。

示例

// Using the `nodes` feature

use siraph::Graph;
use siraph::nodes::{Hold, Pulse, FromIter, Map};

let mut graph = Graph::new();

// First, we can insert nodes into the graph.

// This node just takes the values given by an iterator
// and send them into its output.
let from_iter = graph.insert(FromIter::new(std::iter::successors(Some(0u32), |&i| Some(i + 1))));

// This node infinitly outputs 4 `false` then 1 `true`.
let pulse = graph.insert(Pulse::new(4));

// This one wait for a pulse and holds the value its has in its input
// until a new pulse.
let hold = graph.insert(Hold::<u32>::new());

// Simply uses the given function to maps its input to its output.
let map = graph.insert(Map::new(|val: u32| val * val));

// Then, we can plug them together.
graph.plug(from_iter, "output", hold, "input").unwrap();
graph.plug(pulse, "output", hold, "resample").unwrap();
graph.plug(hold, "output", map, "input").unwrap();

// Once our graph is done, we can retreive values from it using a sink.
let mut sink = graph.sink(map, "output").unwrap();

// Here is a simple schem of what we have so far
/*
+------------------------+
| from_iter   output i32 >----+   +------------------------------+
+------------------------+    +---> input                        |  +----------------------+
                                  |            hold   output i32 >--> input   map   output > sink
                              +---> resample                     |  +----------------------+
+---------------------+       |   +------------------------------+
| pulse   output bool >-------+
+---------------------+
*/

// Values can be retreived with the `next` function on the sink
// Once again, the `()` is the context provided to the nodes.
assert_eq!(sink.next(), Some(0));
assert_eq!(sink.next(), Some(0));
assert_eq!(sink.next(), Some(0));
assert_eq!(sink.next(), Some(0));
assert_eq!(sink.next(), Some(0));
assert_eq!(sink.next(), Some(25));
assert_eq!(sink.next(), Some(25));
assert_eq!(sink.next(), Some(25));
assert_eq!(sink.next(), Some(25));
assert_eq!(sink.next(), Some(25));

// The sink is an iterator
for (i, val) in sink.take(1000).enumerate() {
    let i = ((i/5)*5) as u32 + 10;
    assert_eq!(val, i*i)
}

创建自己的节点

您可以使用 Node 特性创建自己的节点。

use siraph::{Node, Register, Input, Output};

// Our node will take an input and smooth it using a basic interpolation function.
#[derive(Default)]
pub struct Smooth {
    input: Input<f64>,
    output: Output<f64>,

    last_value: Option<f64>,
}

impl Node for Smooth {
    fn register(&self, r: &mut Register) {
        // This function will register the inputs and outputs of this node.
        r.input("input", &self.input);
        r.output("output", &self.output);
    }

    fn process(&mut self) {
        // It is in this function that all the processing will be done.
        const X: f64 = 1.0/3.0;

        // In our case, our computation is not very expensive but
        // in other cases, things can get complicated.
        // We can skip certain part of the processing by
        // checking if our outputs are used.
        if self.output.is_used() {
            if let Some(cur) = self.input.get() {
                if let Some(last) = self.last_value {
                    self.last_value = Some(last * X + (1.0 - X) * cur);
                    self.output.set(self.last_value);
                } else {
                    self.output.set(cur);
                    self.last_value = Some(cur);
                }
            } else {
                self.output.set(None);
            }
        }
    }

    fn reset(&mut self) {
        // In this function, the inputs of the node should not be used even
        // if they may return valid values.
        self.last_value = None;
    }
}

待办事项列表

  • 将 VSTs 作为节点加载

依赖项

~145KB