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};