elemaudio_rs/authoring/
mc.rs

1use crate::graph::Node;
2use crate::{create_node, unpack, ElemNode};
3
4fn channels_and_props(mut props: serde_json::Value) -> (usize, serde_json::Value) {
5    let channels = props
6        .get("channels")
7        .and_then(|value| value.as_u64())
8        .expect("mc helpers require a positive `channels` prop") as usize;
9
10    if let serde_json::Value::Object(map) = &mut props {
11        map.remove("channels");
12    }
13
14    (channels, props)
15}
16
17fn unpack_mc(
18    kind: &str,
19    props: serde_json::Value,
20    children: impl IntoIterator<Item = ElemNode>,
21) -> Vec<Node> {
22    let (channels, props) = channels_and_props(props);
23    unpack(create_node(kind, props, children), channels)
24}
25
26/// Loads a sample from the virtual file system and triggers its playback
27/// on the rising edge of an incoming pulse train. Expects a props arg and
28/// then one child, `t`, the pulse train to trigger playback.
29///
30/// This node is nearly identical to `el.sample`, except that `mc.sample`
31/// supports multi-channel buffers through the virtual file system and
32/// produces multi-channel output. The return value is an array containing
33/// the individual channel signals you want to address.
34pub fn sample(props: serde_json::Value, gate: impl Into<ElemNode>) -> Vec<Node> {
35    unpack_mc("mc.sample", props, [gate.into()])
36}
37
38/// The multichannel variant of `sampleseq`.
39///
40/// Loads a sequence-driven sample from the virtual file system and
41/// produces multi-channel output. Expects a props arg and then one child,
42/// `t`, the current time or trigger signal.
43pub fn sampleseq(props: serde_json::Value, time: impl Into<ElemNode>) -> Vec<Node> {
44    unpack_mc("mc.sampleseq", props, [time.into()])
45}
46
47/// The multichannel variant of `sampleseq2`.
48///
49/// Equivalent to `mc.sampleseq`, except that it adds pitch shifting and
50/// time stretching support for the source sample.
51pub fn sampleseq2(props: serde_json::Value, time: impl Into<ElemNode>) -> Vec<Node> {
52    unpack_mc("mc.sampleseq2", props, [time.into()])
53}
54
55/// Multichannel table lookup.
56pub fn table(props: serde_json::Value, t: impl Into<ElemNode>) -> Vec<Node> {
57    unpack_mc("mc.table", props, [t.into()])
58}
59
60/// Multichannel capture node.
61pub fn capture(
62    props: serde_json::Value,
63    g: impl Into<ElemNode>,
64    args: impl IntoIterator<Item = ElemNode>,
65) -> Vec<Node> {
66    let children = std::iter::once(g.into()).chain(args);
67    unpack_mc("mc.capture", props, children)
68}