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 (SignalNode, 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)

§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
  • SignalNode: Base trait for all nodes in the signal graph
  • Source: Active generators (oscillators, file readers)
  • Processor: Passive processors (filters, effects)
  • Sink: Active outputs (sound cards, 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> SignalNode<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::SignalNode;
pub use traits::ClockError;
pub use traits::ClockResult;
pub use traits::ConnectionError;
pub use traits::ConnectionResult;
pub use traits::NodeCategory;
pub use traits::NodeId;
pub use traits::NodeMetadata;
pub use traits::NodeParams;
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::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::SignalBuffer;
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
Ошибки конфигурации
control
Ошибки управления
executor
Graph executor for driving signal processing Graph executor for driving signal processing using the topology graph and active ports.
graph
Ошибки графа
interpolate
Fractional-index interpolation trait for slice-like types
io
Ошибки ввода-вывода
macros
Macros for node creation and boilerplate reduction
math
Mathematical abstractions for signal processing
prelude
Convenience prelude for importing common types
queue
Ошибки очередей
queues
Real-time safe command queues for automation
runtime
Ошибки времени выполнения
time
Time and clock abstractions for synchronization
traits
Core traits for the Rill ecosystem
utils
Utility functions for common operations

Macros§

audio_node
Общий макрос для создания любого типа узла
bail
Возврат ошибки с контекстом
context
Преобразование Result с добавлением контекста
error
Создать ошибку с кодом и сообщением
error_at
Создать ошибку с местом возникновения
mono_block
Macro for creating a mono block from a slice
processor_node
Создаёт пассивный процессор сигнала
sink_node
Создаёт активный приёмник сигнала
source_node
Создаёт активный источник сигнала
stereo_block
Macro for creating a stereo block from slices
vec_eval
Немедленно вычисляет векторное выражение (заглушка).
vec_expr
Создаёт ленивое векторное выражение (заглушка).
vec_map
with_parameters
Добавление параметров к существующему узлу

Structs§

Error
Основной тип ошибки для всей экосистемы Rill
ErrorLocation
Место возникновения ошибки
VersionInfo
Detailed version information

Enums§

ErrorCategory
Категория ошибки
ErrorCode
Код ошибки (для машинной обработки)

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
Результат операций в Rill Core