Skip to main content

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}