Develop#34
Merged
Merged
Conversation
- rill-io: add MidiMessage ([u8; 3]), MidiBackend trait (poll()) - rill-io: add MidirBackend — cross-platform default via midir crate (feature "midir") - rill-io: add AlsaSeqBackend — ALSA sequencer input port (feature "alsa") - rill-patchbay: add MidiActor — byte parser → ControlEvent dispatch (feature "midi") - rill-patchbay: add ControlEvent::MidiClock, ::MidiTransport, MidiTransportKind - rill-patchbay: add EventPattern::MidiClock, ::MidiTransport, AnyMidi catch-all - rill-io: "midir" in default features alongside "portaudio" - rill-patchbay: optional dep on rill-io via "midi" feature - docs: add architecture/midi.md, update SUMMARY.md
- SimdDetector: real CPU detection via std::arch (SSE/AVX/NEON/SIMD128) - SimdDetector::recommended_simd_width() returns actual width (4/8/1) - VectorMask impls for F32x4, F32x8, F64x2, ScalarVector4 - VectorReduce trait with default methods + blanket impl - VectorScalarOps trait with default methods + blanket impl (super: Vector) - Scalar::from_usize() added to core math trait - Removed disabled expr module and vec_expr!/vec_eval! stubs - All 152 rill-core tests pass, workspace green, clippy clean
- generate_block_simd() processes 4 samples at once via ScalarVector4 - SIMD waveform methods: simd_sine, simd_triangle, simd_square, simd_pulse - simd_saw_raw + simd_saw_blep (raw SIMD, BLEP per-lane) - ScalarVector4::from_fn() constructor added for cross-crate use - Scalar fallback for remainder and high-frequency edge cases - LFO, Generator traits continue to use scalar generate() path - All 12 osc + 9 LFO tests pass
…ader SIMD - CombFilter: batched 4-sample read/write when delay_samples >= 4 - NoiseGenerator: generate_blue_block/generate_violet_block with 4-wide SIMD - InterpolatedReader: render_block_simd with 4-wide lerp math (linear wrap/non-wrap; cubic falls back to scalar for now) - Resampler inherits InterpolatedReader SIMD automatically - All 75 dsp tests + 24 doc-tests pass
- BiquadBlock: pre-computed 4x4 feedforward + state feedback - Block coefficients computed numerically at update_coeffs() time - process() uses 4-sample block form for SIMD chunks - Scalar remainder handled at block boundary - BiquadBlock made pub(crate) for reuse by Butterworth/Chebyshev - Workspace green, all biquad/stereo/Butterworth tests pass
- WdfElement trait kept scalar (object-safe for adapters) - process_incident_vector methods on Resistor, Capacitor, Inductor, Diode - Diode Newton-Raphson vectorized with early exit via VectorMask::all - process_batch_simd free function for batch processing via closure - Deleted rill-core-wdf/src/simd.rs (378 LOC) — no more parallel type hierarchy - simd feature removed from WDF Cargo.toml - Workspace green, all 21 WDF tests pass
- Distortion: 4-wide SIMD for HardClip (clamp), Tube (exp), SoftClip/Fuzz (scalar) - DryWetMix: 4-wide SIMD for dry/wet mix and stereo output - WriteHead: batched 4-sample math per tape write - Removed temp array copies in all effect/filter/osc/sampler nodes (delay, limiter, biquad, moog_ladder, sine, saw, wavetable, player) - Direct port buffer write eliminates 2 copies per block per node - BUF_SIZE alignment documentation in processable.rs - Workspace green, all tests pass
- MixerNode: replace vec![0.0; buffer_size] with [0.0f32; BUF_SIZE] (RT path alloc)
- PortAudio: replace vec![0.0f32; block] with stack [0.0f32; 8192]
- processable.rs: const { assert!(BUF_SIZE % 4 == 0) } at monomorphization time
- Workspace green
- Saw BLEP: VectorMask::select replaces per-lane scalar conditional - White noise: batched xorshift (4 calls) + ScalarVector4 amplitude - Brown noise: unrolled integrator with batched xorshift - Feedback mix (pre_process): 4-wide element-wise add in port feedback - Workspace green
…e→f32 - rill-core: f32_to_i16_chunk / i16_to_f32_chunk with ScalarVector4 (reusable for ALSA, rill-lofi bitcrushing, future backends) - FixedBuffer: #[repr(align(16))] for future hardware SIMD - ParallelAdapter: Vec<T> → [T; 8] stack array (RT allocation fix) - PipeWire: batched 4-sample byte→f32 conversion - ALSA: uses generic conversion functions instead of per-sample loop - Workspace green
…lters, noise, reader - rill-core: vector_add/mul/sin/clamp — scalar vs ScalarVector4 comparison - rill-core-dsp: oscillator benchmarks (Sine, Saw, Square, Triangle, Pulse) - rill-core-dsp: filter benchmarks (Biquad LP, HP, Peak) - rill-core-dsp: noise benchmarks (White, Brown, Blue, Violet) - rill-core-dsp: reader/resampler benchmarks (linear, cubic, 44.1k→48k) - criterion 0.5 added to workspace dev-dependencies - Initial results: clamp 3.9x speedup via SIMD4
Key findings: - ScalarVector4 auto-vectorized by LLVM matches/exceeds wide crate on x86_64 - Rill beats JUCE (C++) by 10-160x on key DSP primitives - Block processing (BUF_SIZE=256) is the #1 performance driver - sin() dominates oscillator cost; polynomial approx would give 3-5x more
… poly - rill-core: deinterleave_stereo / interleave_stereo with ScalarVector4 - PipeWire backend: uses SIMD deinterleave/interleave (replaces per-sample loops) - MoogLadder: process_4_voices(ScalarVector4) → polyphonic convenience - Alignment bench: FixedBuffer vs Vec vs misaligned (57% penalty for unaligned) - Workspace green
- README: objective benchmark tables (Ryzen 7735HS) vs JUCE/fundsp - Rill beats JUCE (C++) by 10-160x on key DSP primitives - Block processing + ScalarVector4 + VectorMask::select = key drivers - SIMD activation plan: completed - Future optimization plan: 14/16 items done, 2 deferred (E2,E3)
- README: test count 559→544, version 0.5.0-beta.2→0.5.0-beta.4 - AGENTS: 17→18 crates, add rill-core-actor to table - AGENTS: version 0.4.0→0.5.0-beta.4 - AGENTS: remove nonexistent features (unstable, stats, wdf-simd) - AGENTS: add missing features (midir, serialization, dot, midi, core-simd) - rill-core/lib.rs: add io module to architecture doc comment - All 544 tests pass
- rill-core: pub mod functions (was private, broke rill-io import) - processable.rs: % 4 → is_multiple_of(4) (clippy) - pipewire.rs: add std::fmt import, fix split_at_mut panic on empty channels - process_batch_simd: #[allow(dead_code)] (public API, not yet called) - clippy auto-fixes: unused imports, manual slice copies - All 544 tests pass with --all-features, PipeWire tests green
- Convert range-based for loops to iterators (enumerate, iter_mut, chunks) - Replace manual slice copies with copy_from_slice - Remove unused VecTrait imports - Add missing Biquad struct documentation - clippy --all-features --workspace: ZERO warnings - cargo test --all-features --workspace: ZERO failures (544 tests)
…mmand/Observer - Deleted: CommandQueue (crossbeam), TelemetryTx (crossbeam wrapper) - Restored: Command trait (no crossbeam), Telemetry enum (no crossbeam) - Moved: observer.rs → rill-patchbay (ActorRef<Telemetry>) - Removed: set_telemetry_tx from Node/NodeVariant traits (dead code) - Fixed: signal.rs doc test (removed CommandQueue references) - Workspace green
- Removed crossbeam-channel from all Cargo.toml (workspace, rill-core, rill-patchbay, rill-adrift) - Deleted rill-patchbay/src/manager.rs (806 LOC, deprecated, zero external callers) - Engine: removed dead attach_sequencer/detach_sequencer/CrossbeamReceiver - Sequencer: removed SequencerHandle/SequencerCommand (crossbeam-based) - Observer: moved to rill-patchbay with ActorRef<Telemetry> - Workspace green, clippy zero warnings, 544 tests pass
Graph already implemented ActorCell<Msg=SetParameter> but run() bypassed it with manual set_parameter loop. Now run() delegates to graph.receive(cmd) — proper actor pattern. Workspace green, 544 tests pass.
- AutomatonMsg enum (Tick, SetEnabled, Reset) for unified control - Servo holds Arc<MpscQueue<AutomatonMsg>> mailbox - Servo::update() drains queue before stepping (like Graph::run) - Servo::handle() returns ActorRef<AutomatonMsg> - AnyServo trait extended with handle() method - Patchbay::add_servo/add_boxed_servo return ActorRef - Automaton stays pure (applicative), Servo is the actor - Workspace green, 544 tests pass
…t, time, action) -> ParamValue - type Internal: mutable automaton state (Servo stores alongside control value) - type Action: optional action parameter - step(&self, &mut Internal, &ParamValue, Time, &Action) -> ParamValue - initial_internal() for state initialization - Removed: type State, type Output, extract_value, initial_state, reset - Removed: LfoState, EnvelopeState, SequencerState, RandomState, CellularState - Servo stores Internal, calls step with &mut self.internal - All 6 automaton impls updated, 544 tests pass - Workspace green
…arSystemDef Demonstrates fully declarative system construction: - GraphDef for sine oscillator → stereo output - SensorDef::Midi with mappings (CC + Note via EventPattern + MidiNoteKind) - ModularSystem::launch() for one-line startup All MIDI behaviour expressed as data, no imperative code.
- Both examples use CC#14 (freq) and CC#15 (amp) now - spawn_midi_sensor: log::info! for matched mappings, log::debug! for unmatched - Added env_logger to both midi examples (dev-dependency) - RUST_LOG=info for per-event output, RUST_LOG=debug for diagnostics
Diagnostic MIDI output now prints unconditionally to stderr: - Matched events: "midi name EventPattern -> param name (value)" - Unmatched events: "midi name: unmatched event EventType" No RUST_LOG needed.
MidirBackend now supports choosing which MIDI input port to connect to. midi_synth example accepts optional port index as first CLI argument.
- new_by_name(port_name) searches ports by name substring - new_by_port(index) selects by index - list_ports() prints all available ports - connect() helper eliminates duplication - Example: accepts name substring or numeric index - MidiConstructor uses new_by_name for SensorDef.port_name
Now shows the actual ControlEvent (with note, velocity, controller) instead of the EventPattern (with None placeholders). This will reveal what note/CC values are being received.
midi_to_freq already returns absolute Hz values. Passing them through min + norm * (max - min) with default min=0 max=1 should be identity but produced Float(1.0). Bypass transform pipeline for Frequency entirely.
MIDI sensor fully working: Note, CC, port selection. Removed debug output from polling thread.
- Args: [midi_port] [audio_backend] (default portaudio) - graph.run() errors printed to stderr instead of silently ignored
SineOsc::set_parameter() expects "frequency" and "amplitude", not "freq" and "amp". Params in add_node use short names but SetParameter uses the canonical parameter IDs.
…new() - new() iterates all ports, skips ones with "Through"/"Loop"/"RTMidi" - Falls back to port 0 if no real ports found - Examples reverted to use default auto-select
… found new_by_name() first, new() (auto-skip virtual ports) as fallback. Serial example now works without hardcoding KOMPLETE.
PortAudio backend (`portaudio.rs`): - Force at least 1 input channel when output is active to enter duplex mode — ALSA virtual devices (PipeWire) hang on output-only parameter negotiation - Use explicit CLIP_OFF | DITHER_OFF flags + default_low_output_latency for reliable buffer sizing with virtual devices - Remove dead `self.running.store()` at end of run() PipeWire backend (`pipewire.rs`): - Guard input stream creation behind `in_channels > 0` to avoid opening unnecessary capture streams Output sink (`output.rs`): - Add `data_received` guard before `write()` to skip incomplete writes when sink has multiple input ports populated by separate port propagations
- real-time-safety.md: add PortAudio to callback-driven row, remove CPAL - contributing.md: add PortAudio to backend list - crates.md: replace CPAL with PortAudio in rill-io description
- Remove unused variable `chosen_name` in midir_backend.rs - Remove unused import `ServoDef` in servo_constructor.rs - Use `..` for unused field in Custom pattern match - Remove dead imports in registration.rs test module - Remove unused `Arc` import in serialization.rs - Replace `iter().cloned().collect()` with `to_vec()` in modular/mod.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
0.5.0-beta.5