Skip to main content

resonant_stream/
lib.rs

1#![warn(missing_docs)]
2
3//! `resonant-stream` — streaming DSP pipeline.
4//!
5//! This crate provides a pull-based, synchronous processing pipeline for audio
6//! DSP. Chunks of sample data flow through a chain of [`DspNode`]s, each
7//! transforming the audio in place where possible to minimise allocations.
8//!
9//! # Architecture
10//!
11//! ```text
12//! ┌───────────┐    ┌───────────┐    ┌───────────┐
13//! │  Source    │───▶│  Node A   │───▶│  Node B   │───▶ output
14//! │ (Chunk)   │    │ (filter)  │    │ (gain)    │
15//! └───────────┘    └───────────┘    └───────────┘
16//! ```
17//!
18//! - [`Chunk`] carries interleaved samples plus metadata (sample rate, channels).
19//! - [`DspNode`] is the core trait — implement it to create custom processors.
20//! - [`StreamError`] covers format mismatches and processing failures.
21//!
22//! # Quick start
23//!
24//! ```
25//! use resonant_stream::{Chunk, DspNode, StreamError};
26//!
27//! // A simple gain node that scales all samples.
28//! struct Gain(f32);
29//!
30//! impl DspNode for Gain {
31//!     fn process(&mut self, mut input: Chunk) -> Result<Chunk, StreamError> {
32//!         for s in input.data_mut() {
33//!             *s *= self.0;
34//!         }
35//!         Ok(input)
36//!     }
37//!     fn reset(&mut self) {}
38//! }
39//!
40//! let mut gain = Gain(0.5);
41//! let chunk = Chunk::new(vec![1.0, -1.0, 0.5, -0.5], 44100, 1);
42//! let out = gain.process(chunk).unwrap();
43//! assert_eq!(out.data(), &[0.5, -0.5, 0.25, -0.25]);
44//! ```
45
46mod chunk;
47mod error;
48/// Operator-overloaded graph combinators for pipeline composition.
49pub mod graph;
50#[cfg(feature = "io")]
51/// Hardware audio I/O nodes backed by [`cpal`](https://docs.rs/cpal).
52pub mod io;
53mod node;
54/// Built-in processing nodes.
55pub mod nodes;
56mod pipeline;
57
58pub use chunk::Chunk;
59pub use error::StreamError;
60pub use graph::{GraphExt, Parallel, Serial, Stack};
61pub use node::DspNode;
62pub use pipeline::{Pipeline, PipelineBuilder};