rill_core/lib.rs
1//! # Rill Core
2//!
3//! The core of the Rill ecosystem. Provides fundamental traits, types,
4//! and utilities for building real-time signal processing applications.
5//!
6//! ## Architecture Overview
7//!
8//! ```text
9//! rill-core/
10//! ├── traits/ # Core traits (Algorithm, Parameter, ProcessError)
11//! ├── math/ # Mathematical abstractions (Scalar, Transcendental, Vector)
12//! │ └── vector/ # Vector types, SIMD abstractions, slice operations
13//! ├── buffer/ # Lock-free signal buffers with AtomicCell safety
14//! ├── queues/ # Real-time safe command queues
15//! ├── time/ # Time and clock abstractions (ClockTick, SystemClock)
16//! ├── io/ # Generic I/O backend trait (IoBackend)
17//! ├── macros/ # Node creation macros (source_node!, processor_node!, etc.)
18//! ├── prelude # Convenience prelude for common imports
19//! └── interpolate # Fractional-index interpolation trait
20//! ```
21//!
22//! ## Key Concepts
23//!
24//! - **Scalar**: Base numeric trait for any type (floats and integers)
25//! - **Transcendental**: Float numeric abstraction with sin/cos/sqrt
26//! - **AtomicCell**: Safe atomic wrapper for lock-free data structures
27//! - **Algorithm**: Core processing trait for signal nodes
28//! - **PipeBuffer**: Zero-copy connections between nodes
29//! - **CommandQueue**: Real-time safe parameter automation
30//! - **ClockTick**: Sample-accurate timing for synchronization
31//!
32//! ## Getting Started
33//!
34//! See crate-level documentation and module docs for usage examples.
35//! ```text
36
37#![warn(missing_docs)]
38#![allow(clippy::doc_lazy_continuation)]
39#![deny(unsafe_code)]
40#![cfg_attr(not(test), deny(unused))]
41#![cfg_attr(docsrs, feature(doc_cfg))]
42
43// ============================================================================
44// Core Modules
45// ============================================================================
46
47/// Core traits for the Rill ecosystem
48pub mod traits;
49
50/// Mathematical abstractions for signal processing
51pub mod math;
52
53/// Lock-free, real-time safe signal buffers
54pub mod buffer;
55
56/// Real-time safe command queues for automation
57pub mod queues;
58
59/// Time and clock abstractions for synchronization
60pub mod time;
61
62#[doc(hidden)]
63pub use math::vector;
64
65/// Macros for node creation and boilerplate reduction
66#[macro_use]
67pub mod macros;
68
69/// Convenience prelude for importing common types
70pub mod prelude;
71
72/// Fractional-index interpolation trait for slice-like types
73pub mod interpolate;
74
75/// Generic multi-channel signal I/O abstraction
76pub mod io;
77
78/// Built-in function registry for signal processing DSLs
79pub mod builtin;
80
81// ============================================================================
82// Error Types
83// ============================================================================
84
85/// Core error types for the Rill ecosystem
86mod error;
87pub use error::*;
88
89// ============================================================================
90// Re-exports for Convenience
91// ============================================================================
92
93// Re-export core traits
94pub use traits::{
95 Algorithm, AsAny, IntoParamValue, MultichannelAlgorithm, ParamMetadata, ParamRange, ParamType,
96 ParamValue, ParameterError, ParameterId, Params, ProcessError, ProcessResult, SisoAdapter,
97};
98
99pub use builtin::MultichannelBlockBuiltin;
100
101// Re-export math abstractions
102pub use math::{Scalar, Transcendental};
103
104/// Re-export `glam` for real-valued matrix and vector operations.
105pub use glam;
106
107// Re-export buffer types with AtomicCell safety
108pub use buffer::{
109 AtomicCell, AtomicCellError, AtomicStats, Buffer, BufferError, BufferResult, BufferStats,
110 DelayLine, FanInBuffer, FanOutBuffer, PipeBuffer, RingBuffer,
111};
112
113// Re-export queue types (from rill-patchbay integration)
114pub use queues::{QueueError, QueueResult};
115
116// Re-export time abstractions
117pub use time::{ClockSource, ClockTick, RenderContext, SystemClock};
118
119// ============================================================================
120// Constants
121// ============================================================================
122
123/// Current version of rill-core
124pub const VERSION: &str = env!("CARGO_PKG_VERSION");
125
126/// Maximum supported sample rate
127pub const MAX_SAMPLE_RATE: f32 = 384_000.0;
128
129/// Minimum supported sample rate
130pub const MIN_SAMPLE_RATE: f32 = 8_000.0;
131
132/// Default sample rate (44.1 kHz)
133pub const DEFAULT_SAMPLE_RATE: f32 = 44_100.0;
134
135/// Default block size for signal processing
136pub const DEFAULT_BLOCK_SIZE: usize = 64;
137
138/// Maximum block size
139pub const MAX_BLOCK_SIZE: usize = 8192;
140
141/// Minimum block size
142pub const MIN_BLOCK_SIZE: usize = 16;
143
144/// Default buffer size for most use cases
145pub const DEFAULT_BUFFER_SIZE: usize = 1024;
146
147/// Maximum buffer size (2^16 = 65536 samples)
148pub const MAX_BUFFER_SIZE: usize = 65536;
149
150/// Minimum buffer size
151pub const MIN_BUFFER_SIZE: usize = 16;
152
153/// Cache line size for alignment (64 bytes on x86_64)
154pub const CACHE_LINE_SIZE: usize = 64;
155
156// ============================================================================
157// Utility Functions
158// ============================================================================
159
160/// Utility functions for common operations
161pub mod utils {
162 use crate::math::Transcendental;
163
164 /// Convert seconds to samples
165 #[inline(always)]
166 pub fn seconds_to_samples(seconds: f32, sample_rate: f32) -> usize {
167 (seconds * sample_rate) as usize
168 }
169
170 /// Convert samples to seconds
171 #[inline(always)]
172 pub fn samples_to_seconds(samples: usize, sample_rate: f32) -> f32 {
173 samples as f32 / sample_rate
174 }
175
176 /// Convert dB to linear gain
177 #[inline(always)]
178 pub fn db_to_linear<T: Transcendental>(db: T) -> T {
179 T::from_f32(10.0_f32.powf(db.to_f32() / 20.0))
180 }
181
182 /// Convert linear gain to dB
183 #[inline(always)]
184 pub fn linear_to_db<T: Transcendental>(linear: T) -> T {
185 T::from_f32(20.0 * linear.to_f32().log10())
186 }
187
188 /// Check if a value is a power of two
189 #[inline(always)]
190 pub const fn is_power_of_two(x: usize) -> bool {
191 x != 0 && (x & (x - 1)) == 0
192 }
193
194 /// Round up to the next power of two
195 #[inline(always)]
196 pub const fn next_power_of_two(x: usize) -> usize {
197 let mut n = x - 1;
198 n |= n >> 1;
199 n |= n >> 2;
200 n |= n >> 4;
201 n |= n >> 8;
202 n |= n >> 16;
203 n + 1
204 }
205}
206
207// ============================================================================
208// Version Information
209// ============================================================================
210
211/// Get detailed version information
212pub fn version_info() -> VersionInfo {
213 VersionInfo {
214 version: VERSION,
215 crate_name: env!("CARGO_PKG_NAME"),
216 authors: env!("CARGO_PKG_AUTHORS"),
217 description: env!("CARGO_PKG_DESCRIPTION"),
218 repository: env!("CARGO_PKG_REPOSITORY"),
219 }
220}
221
222/// Detailed version information for the rill-core crate.
223#[derive(Debug, Clone)]
224pub struct VersionInfo {
225 /// Crate version string (from `CARGO_PKG_VERSION`).
226 pub version: &'static str,
227 /// Crate name (from `CARGO_PKG_NAME`).
228 pub crate_name: &'static str,
229 /// Author list (from `CARGO_PKG_AUTHORS`).
230 pub authors: &'static str,
231 /// Crate description (from `CARGO_PKG_DESCRIPTION`).
232 pub description: &'static str,
233 /// Repository URL (from `CARGO_PKG_REPOSITORY`).
234 pub repository: &'static str,
235}
236
237// ============================================================================
238// Tests
239// ============================================================================
240
241#[cfg(test)]
242mod tests {
243 use super::prelude::*;
244 use super::utils;
245
246 #[test]
247 fn test_constants() {
248 assert!(!VERSION.is_empty());
249 const {
250 assert!(MAX_SAMPLE_RATE > MIN_SAMPLE_RATE);
251 assert!(MAX_BLOCK_SIZE > MIN_BLOCK_SIZE);
252 }
253 assert_eq!(DEFAULT_BLOCK_SIZE, 64);
254 assert_eq!(DEFAULT_SAMPLE_RATE, 44100.0);
255 assert_eq!(CACHE_LINE_SIZE, 64);
256 }
257
258 #[test]
259 fn test_utils() {
260 assert_eq!(utils::seconds_to_samples(1.0, 44100.0), 44100);
261 assert!((utils::samples_to_seconds(44100, 44100.0) - 1.0).abs() < 1e-6);
262
263 let linear = utils::db_to_linear(0.0f32);
264 assert!((linear - 1.0).abs() < 1e-6);
265
266 let db = utils::linear_to_db(1.0f32);
267 assert!((db - 0.0).abs() < 1e-6);
268
269 assert!(utils::is_power_of_two(64));
270 assert!(!utils::is_power_of_two(63));
271 assert_eq!(utils::next_power_of_two(63), 64);
272 }
273
274 #[test]
275 fn test_atomic_cell() {
276 let cell = AtomicCell::new(42);
277 assert_eq!(cell.load(), 42);
278 cell.store(100);
279 assert_eq!(cell.load(), 100);
280 }
281}
282
283// ============================================================================
284// Documentation Tests
285// ============================================================================
286
287#[cfg(doctest)]
288mod doctests {
289 //! This module exists only to host documentation tests
290}