bbx_dsp/
plugin.rs

1//! Plugin DSP trait for FFI integration.
2//!
3//! This module defines the `PluginDsp` trait that consumers implement
4//! to define their plugin's DSP processing chain.
5
6use bbx_midi::MidiEvent;
7
8use crate::context::DspContext;
9
10/// Trait for plugin-specific DSP implementations.
11///
12/// Consumers implement this trait to define their audio processing chain.
13/// The FFI layer uses this trait to manage the DSP lifecycle.
14///
15/// # Example
16///
17/// ```ignore
18/// use bbx_dsp::{PluginDsp, context::DspContext};
19/// use bbx_dsp::blocks::effectors::gain::GainBlock;
20///
21/// pub struct PluginGraph {
22///     pub gain: GainBlock<f32>,
23/// }
24///
25/// impl PluginDsp for PluginGraph {
26///     fn new() -> Self {
27///         Self { gain: GainBlock::new(0.0) }
28///     }
29///
30///     fn prepare(&mut self, context: &DspContext) {
31///         // Initialize blocks for the given sample rate/buffer size
32///     }
33///
34///     fn reset(&mut self) {
35///         // Clear filter states, etc.
36///     }
37///
38///     fn apply_parameters(&mut self, params: &[f32]) {
39///         // Map parameter array to block fields
40///     }
41///
42///     fn process(&mut self, inputs: &[&[f32]], outputs: &mut [&mut [f32]], midi_events: &[MidiEvent], context: &DspContext) {
43///         // Process audio and MIDI through the chain
44///     }
45/// }
46/// ```
47pub trait PluginDsp: Default + Send + 'static {
48    /// Create a new instance with default configuration.
49    fn new() -> Self;
50
51    /// Prepare the DSP chain for playback.
52    ///
53    /// Called when audio specs change (sample rate, buffer size, channels).
54    fn prepare(&mut self, context: &DspContext);
55
56    /// Reset all DSP state.
57    ///
58    /// Called to clear filter histories, oscillator phases, etc.
59    fn reset(&mut self);
60
61    /// Apply parameter values from a flat array.
62    ///
63    /// The parameter indices are plugin-specific, typically defined
64    /// via generated constants from `parameters.json`.
65    fn apply_parameters(&mut self, params: &[f32]);
66
67    /// Process a block of audio with MIDI events.
68    ///
69    /// - `inputs`: Array of input channel buffers
70    /// - `outputs`: Array of output channel buffers
71    /// - `midi_events`: MIDI events with sample-accurate timing (sorted by sample_offset)
72    /// - `context`: DSP context with sample rate, buffer size, etc.
73    fn process(
74        &mut self,
75        inputs: &[&[f32]],
76        outputs: &mut [&mut [f32]],
77        midi_events: &[MidiEvent],
78        context: &DspContext,
79    );
80
81    /// Called when a note-on event is received.
82    ///
83    /// Default implementation does nothing (suitable for effect plugins).
84    #[allow(unused_variables)]
85    fn note_on(&mut self, note: u8, velocity: u8, sample_offset: u32) {}
86
87    /// Called when a note-off event is received.
88    ///
89    /// Default implementation does nothing (suitable for effect plugins).
90    #[allow(unused_variables)]
91    fn note_off(&mut self, note: u8, sample_offset: u32) {}
92
93    /// Called when a control change event is received.
94    ///
95    /// Default implementation does nothing.
96    #[allow(unused_variables)]
97    fn control_change(&mut self, cc: u8, value: u8, sample_offset: u32) {}
98
99    /// Called when a pitch bend event is received.
100    ///
101    /// Default implementation does nothing.
102    #[allow(unused_variables)]
103    fn pitch_bend(&mut self, value: i16, sample_offset: u32) {}
104}