1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//! # Dhwani — Node-Based Audio DAW Engine
//!
//!
//! **Dhwani** is an audio engine for Digital Audio Workstations (DAWs).
//! It focuses on safety, performance, and modular, extensible DSP building
//! blocks for audio applications. The engine is designed to power
//! synthesizers, mixers, effects chains, and complete DAW backends while
//! leveraging Rust's safety and concurrency guarantees.
//!
//! ## Core architecture
//!
//! Processing is built around four core concepts: [`Processor`],
//! [`track::Track`], [`node::Node`], and connections.
//!
//! A project may contain multiple tracks, and each track may contain multiple
//! nodes. A node inherits its active [`time::TimeRange`] from its parent
//! track.
//!
//! Every node exposes one or more [`port::Port`]s, which may be either inputs
//! or outputs and carry [`signal::Signals`] or [`event::Events`]. Ports can be
//! connected to compatible ports on other nodes. Each node also owns internal
//! buffers corresponding to its output ports.
//!
//! Nodes are processed in topological order. This guarantees that when a node
//! with input connections is executed, the output buffers of all upstream
//! nodes have already been produced.
//!
//! ### Nodes
//!
//! Every processing unit is represented by a `dyn` trait object implementing
//! [`node::NodeTrait`]. Nodes are created through the builder pattern via
//! [`node::NodeBuilderTrait`], allowing declarative configuration before being
//! inserted into the processing graph.
//!
//! Example nodes include oscillators, filters, piano rolls, mixers, and
//! effects.
//!
//! ### Ports & Connections
//!
//! Nodes communicate through [`port::Port`]s. Three kinds of ports are
//! available:
//!
//! - **[`signal::Signals`]** — continuous audio-rate or control-rate
//! floating-point streams (e.g. audio buffers or LFO outputs) for each
//! channel.
//! - **[`event::Events`]** — discrete, timestamped events within a processing
//! frame (e.g. MIDI note on/off messages).
//! - **[`port::PortProxy`]** — proxy ports that forward another port,
//! primarily used by parent nodes to expose child node interfaces.
//!
//! An output port may be connected to one or more compatible input ports.
//!
//! ### Processor
//!
//! The [`Processor`] owns the node graph and is driven by the audio thread.
//! On each callback it advances the graph by one frame, walking nodes in
//! topological order and propagating data through connected ports.
//!
//! The order of nodes are updated when a node is inserted or replaced. Replacing
//! may remove all previous connections to and from the nodes. If no connections
//! require removal or change, then the previous connections persists.
//!
//! ### Controller
//!
//! The optional `controller` feature exposes a [`controller::start_controller`] handle
//! that can be sent to a UI thread or any non-audio thread. It communicates with the
//! [`Processor`] via a lock-free SPSC ring buffer (`rb`) consumer and a MPSC queue.
//! allowing safe parameter automation, node graph mutations, and transport control
//! without blocking the audio thread.
//!
//! ## Feature Flags
//!
//! | Flag | Description |
//! |------|-------------|
//! | `controller` | Enables the [`controller::start_controller`] type for cross-thread communication |
//!
//! ## Example (minimal skeleton)
//!
//! see `examples/gui.rs` and `examples/simple.rs`
//! Can run the example using `./dhwani.sh gui` or `./dhwani.sh simple`
// Private
// Public
/// Built-in node implementations (oscillators, filters, mixers, etc.).
/// Each sub-module exposes a builder that implements [`node::NodeBuilderTrait`].
// ─── Re-exports ───────────────────────────────────────────────────────────────
/// Dhwani error type
pub use Error;
/// Owns the node graph and drives per-frame processing on the audio thread.
/// Constructed once; thereafter only mutated via [`controller::start_controller`] messages.
pub use Processor;
// ─── Optional: Controller (cross-thread communication) ────────────────────────
/// Cross-thread controller bridge.
///
/// The [`controller::start_controller`] is the only safe way to mutate the [`Processor`] from
/// outside the audio thread. Internally it uses a lock-free ring buffer (`rb`)
/// to queue commands (parameter changes, node graph edits, transport control)
/// that the audio thread drains at the start of each frame.
///
/// # Usage
///
/// ```text
/// #[cfg(feature = "controller")]
/// let (controller: Arc<controller>, rb: RingBufReceiver) = Controller::new(config);
/// ```