Skip to main content

Crate rill_core

Crate rill_core 

Source
Expand description

§Rill Core

The core of the Rill ecosystem. Provides fundamental traits, types, and utilities for building real-time signal processing applications.

§Architecture Overview

rill-core/
├── traits/           # Core traits (Node, Source, Processor, Sink, etc.)
├── math/             # Mathematical abstractions (Scalar, Transcendental, Vector)
│   └── vector/       # Vector types, SIMD abstractions, slice operations
├── buffer/           # Lock-free signal buffers with AtomicCell safety
├── queues/           # Real-time safe command queues
├── time/             # Time and clock abstractions (ClockTick, SystemClock)
├── io/               # Generic I/O backend trait (IoBackend)
├── macros/           # Node creation macros (source_node!, processor_node!, etc.)
├── prelude           # Convenience prelude for common imports
├── interpolate       # Fractional-index interpolation trait
└── executor/         # Graph executor for driving signal processing

§Key Concepts

  • Scalar: Base numeric trait for any type (floats and integers)
  • Transcendental: Float numeric abstraction with sin/cos/sqrt
  • AtomicCell: Safe atomic wrapper for lock-free data structures
  • Node: Base trait for all nodes in the signal graph
  • Source: Active generators (oscillators, file readers)
  • Processor: Passive processors (filters, effects)
  • Sink: Active outputs (I/O devices, file writers)
  • PipeBuffer: Zero-copy connections between nodes
  • CommandQueue: Real-time safe parameter automation
  • ClockTick: Sample-accurate timing for synchronization

§Example

use rill_core::prelude::*;
use rill_core::Port;
use rill_core::traits::node;

// Create a simple sine source
struct MySine<T: Transcendental, const BUF_SIZE: usize> {
    frequency: T,
    amplitude: T,
    phase: T,
    sample_rate: T,
}

impl<T: Transcendental, const BUF_SIZE: usize> Node<T, BUF_SIZE> for MySine<T, BUF_SIZE> {
    fn metadata(&self) -> NodeMetadata {
        NodeMetadata {
            name: "Sine".to_string(),
            type_name: None,
            category: NodeCategory::Source,
            description: "Sine wave oscillator".to_string(),
            author: "Rill".to_string(),
            version: env!("CARGO_PKG_VERSION").to_string(),
            signal_inputs: 0,
            signal_outputs: 1,
            control_inputs: 0,
            control_outputs: 0,
            clock_inputs: 1,
            clock_outputs: 0,
            feedback_ports: 0,
            parameters: vec![],
        }
    }
     
    fn init(&mut self, sample_rate: f32) {
        self.sample_rate = T::from_f32(sample_rate);
    }
     
    fn reset(&mut self) {
        self.phase = T::ZERO;
    }
     
    fn get_parameter(&self, _id: &ParameterId) -> Option<ParamValue> {
        None
    }
     
    fn set_parameter(&mut self, _id: &ParameterId, _value: ParamValue) -> ProcessResult<()> {
        Ok(())
    }
     
    fn id(&self) -> NodeId { NodeId(0) }
    fn set_id(&mut self, _id: NodeId) {}
     
    fn input_port(&self, _index: usize) -> Option<&Port<T, BUF_SIZE>> { None }
    fn input_port_mut(&mut self, _index: usize) -> Option<&mut Port<T, BUF_SIZE>> { None }
    fn output_port(&self, _index: usize) -> Option<&Port<T, BUF_SIZE>> { None }
    fn output_port_mut(&mut self, _index: usize) -> Option<&mut Port<T, BUF_SIZE>> { None }
    fn control_port(&self, _index: usize) -> Option<&Port<T, BUF_SIZE>> { None }
    fn control_port_mut(&mut self, _index: usize) -> Option<&mut Port<T, BUF_SIZE>> { None }
     
    fn state(&self) -> &node::NodeState<T,BUF_SIZE> {
        unimplemented!()
    }
     
    fn state_mut(&mut self) -> &mut node::NodeState<T,BUF_SIZE> {
        unimplemented!()
    }
}

impl<T: Transcendental, const BUF_SIZE: usize> Source<T, BUF_SIZE> for MySine<T, BUF_SIZE> {
    fn generate(
        &mut self,
        clock: &ClockTick,
        _control_inputs: &[T],
        _clock_inputs: &[ClockTick],
    ) -> ProcessResult<()> {
        let two_pi = T::from_f32(2.0 * std::f32::consts::PI);
        let phase_inc = self.frequency / T::from_f32(clock.sample_rate);
        let amp = self.amplitude;
         
        let mut temp = [T::ZERO; BUF_SIZE];
        for i in 0..BUF_SIZE {
            let phase_rad = self.phase * two_pi;
            temp[i] = phase_rad.sin() * amp;
            self.phase = self.phase + phase_inc;
            if self.phase >= T::from_f32(1.0) {
                self.phase = self.phase - T::from_f32(1.0);
            }
        }
        *self.output_port_mut(0).unwrap().buffer.as_mut_array() = temp;
        Ok(())
    }
     
    fn num_signal_outputs(&self) -> usize { 1 }
    fn num_control_inputs(&self) -> usize { 0 }
    fn num_clock_inputs(&self) -> usize { 1 }
}

Re-exports§

pub use traits::ClockError;
pub use traits::ClockResult;
pub use traits::ConnectionError;
pub use traits::ConnectionResult;
pub use traits::Eurorack;
pub use traits::Node;
pub use traits::NodeCategory;
pub use traits::NodeId;
pub use traits::NodeMetadata;
pub use traits::NodeState;
pub use traits::NodeTypeId;
pub use traits::ParamMetadata;
pub use traits::ParamRange;
pub use traits::ParamType;
pub use traits::ParamValue;
pub use traits::ParameterError;
pub use traits::ParameterId;
pub use traits::Params;
pub use traits::Port;
pub use traits::PortDirection;
pub use traits::PortError;
pub use traits::PortId;
pub use traits::PortResult;
pub use traits::PortType;
pub use traits::ProcessError;
pub use traits::ProcessResult;
pub use traits::Processor;
pub use traits::Sink;
pub use traits::Source;
pub use math::Scalar;
pub use math::Transcendental;
pub use buffer::AtomicCell;
pub use buffer::AtomicCellError;
pub use buffer::AtomicStats;
pub use buffer::Buffer;
pub use buffer::BufferError;
pub use buffer::BufferResult;
pub use buffer::BufferStats;
pub use buffer::DelayLine;
pub use buffer::FanInBuffer;
pub use buffer::FanOutBuffer;
pub use buffer::PipeBuffer;
pub use buffer::RingBuffer;
pub use queues::QueueError;
pub use queues::QueueResult;
pub use time::ClockSource;
pub use time::ClockTick;
pub use time::SystemClock;

Modules§

buffer
Lock-free, real-time safe signal buffers
config
Configuration error constructors.
control
Control error constructors (OSC, automation).
executor
Graph executor for driving signal processing Graph executor for driving signal processing using the topology graph and active ports.
interpolate
Fractional-index interpolation trait for slice-like types
io
Generic multi-channel signal I/O abstraction
macros
Macros for node creation and boilerplate reduction
math
Mathematical abstractions for signal processing
prelude
Convenience prelude for importing common types
queues
Real-time safe command queues for automation
runtime
Runtime error constructors (thread priority, critical violations).
time
Time and clock abstractions for synchronization
traits
Core traits for the Rill ecosystem
utils
Utility functions for common operations

Macros§

bail
Return early with an error (convenience for return Err(...)).
context
Transform a Result by mapping the error with additional context.
error
Create an error with a code and message.
error_at
Create an error with source location attached.
mono_block
Macro for creating a mono block from a slice
node
General macro for creating any type of node
processor_node
Creates a passive signal processor
sink_node
Creates an active signal receiver
source_node
Creates an active signal source
stereo_block
Macro for creating a stereo block from slices
vec_map
Map over SIMD vector chunks of size 4, applying a closure to each chunk.
with_parameters
Adding parameters to an existing node

Structs§

Error
Primary error type for the entire Rill ecosystem.
ErrorLocation
Source location where an error originated.
VersionInfo
Detailed version information for the rill-core crate.

Enums§

ErrorCategory
Error category for grouping related error codes.
ErrorCode
Machine-processable error code.

Constants§

CACHE_LINE_SIZE
Cache line size for alignment (64 bytes on x86_64)
DEFAULT_BLOCK_SIZE
Default block size for signal processing
DEFAULT_BUFFER_SIZE
Default buffer size for most use cases
DEFAULT_SAMPLE_RATE
Default sample rate (44.1 kHz)
MAX_BLOCK_SIZE
Maximum block size
MAX_BUFFER_SIZE
Maximum buffer size (2^16 = 65536 samples)
MAX_SAMPLE_RATE
Maximum supported sample rate
MIN_BLOCK_SIZE
Minimum block size
MIN_BUFFER_SIZE
Minimum buffer size
MIN_SAMPLE_RATE
Minimum supported sample rate
VERSION
Current version of rill-core

Functions§

version_info
Get detailed version information

Type Aliases§

Result
Result type alias for Rill Core operations.