conformal_component/
synth.rs

1//! Abstractions for processors that generate audio.
2
3use crate::{
4    Processor,
5    audio::BufferMut,
6    events::{self, Event, Events},
7    parameters::{self, BufferStates, Flags, InfoRef, TypeSpecificInfoRef},
8};
9
10/// The parameter ID of the pitch bend parameter. See [`CONTROLLER_PARAMETERS`] for more.
11///
12/// This is the global version of the [`crate::events::NoteExpression::PitchBend`] note expression event.
13/// Notes should be shifted by the value of this controller plus the per-note pitch bend expression.
14pub const PITCH_BEND_PARAMETER: &str = "pitch_bend";
15
16/// The parameter ID of the mod wheel parameter. See [`CONTROLLER_PARAMETERS`] for more.
17pub const MOD_WHEEL_PARAMETER: &str = "mod_wheel";
18
19/// The parameter ID of the expression pedal parameter. See [`CONTROLLER_PARAMETERS`] for more.
20pub const EXPRESSION_PARAMETER: &str = "expression_pedal";
21
22/// The parameter ID of the sustain pedal parameter. See [`CONTROLLER_PARAMETERS`] for more.
23pub const SUSTAIN_PARAMETER: &str = "sustain_pedal";
24
25/// The parameter ID of the aftertouch parameter. See [`CONTROLLER_PARAMETERS`] for more.
26///
27/// Aftertouch is a pressure sensor sent by some controllers.
28///
29/// This is the global version of the [`crate::events::NoteExpression::Aftertouch`] note expression event.
30/// This controller parameter should affect all notes,
31/// while the note expression event affects a single note. Note that hosts are free
32/// to use a combination of this global controller with per-note controllers. This means
33/// plug-ins must combine this global controller with the per-note controller to get the total
34/// expression value.
35pub const AFTERTOUCH_PARAMETER: &str = "aftertouch";
36
37/// The parameter ID of the timbre parameter. See [`CONTROLLER_PARAMETERS`] for more.
38///
39/// Generally the timbre controller will be some sort of vertical motion, and
40/// is the global version of the [`crate::events::NoteExpression::Timbre`] note expression event.
41///
42/// This controller parameter should affect all notes,
43/// while the note expression event affects a single note. Note that hosts are free
44/// to use a combination of this global controller with per-note controllers. This means
45/// plug-ins must combine this global controller with the per-note controller to get the total
46/// expression value.
47pub const TIMBRE_PARAMETER: &str = "timbre";
48
49/// Parameter info for the pitch bend parameter. See [`CONTROLLER_PARAMETERS`] for more.
50pub const PITCH_BEND_INFO: InfoRef<'static, &'static str> = InfoRef {
51    title: "Pitch Bend",
52    short_title: "Bend",
53    unique_id: PITCH_BEND_PARAMETER,
54    flags: Flags { automatable: false },
55    type_specific: TypeSpecificInfoRef::Numeric {
56        default: 0.0,
57        valid_range: -1.0..=1.0,
58        units: None,
59    },
60};
61
62/// Parameter info for the mod wheel parameter. See [`CONTROLLER_PARAMETERS`] for more.
63pub const MOD_WHEEL_INFO: InfoRef<'static, &'static str> = InfoRef {
64    title: "Mod Wheel",
65    short_title: "Mod",
66    unique_id: MOD_WHEEL_PARAMETER,
67    flags: Flags { automatable: false },
68    type_specific: TypeSpecificInfoRef::Numeric {
69        default: 0.0,
70        valid_range: 0.0..=1.0,
71        units: None,
72    },
73};
74
75/// Parameter info for the expression pedal parameter. See [`CONTROLLER_PARAMETERS`] for more.
76pub const EXPRESSION_INFO: InfoRef<'static, &'static str> = InfoRef {
77    title: "Expression",
78    short_title: "Expr",
79    unique_id: EXPRESSION_PARAMETER,
80    flags: Flags { automatable: false },
81    type_specific: TypeSpecificInfoRef::Numeric {
82        default: 0.0,
83        valid_range: 0.0..=1.0,
84        units: None,
85    },
86};
87
88/// Parameter info for the sustain pedal parameter. See [`CONTROLLER_PARAMETERS`] for more.
89pub const SUSTAIN_INFO: InfoRef<'static, &'static str> = InfoRef {
90    title: "Sustain Pedal",
91    short_title: "Sus",
92    unique_id: SUSTAIN_PARAMETER,
93    flags: Flags { automatable: false },
94    type_specific: TypeSpecificInfoRef::Switch { default: false },
95};
96
97/// Parameter info for the aftertouch parameter. See [`CONTROLLER_PARAMETERS`] for more.
98pub const AFTERTOUCH_INFO: InfoRef<'static, &'static str> = InfoRef {
99    title: "Aftertouch",
100    short_title: "Aftertouch",
101    unique_id: AFTERTOUCH_PARAMETER,
102    flags: Flags { automatable: false },
103    type_specific: TypeSpecificInfoRef::Numeric {
104        default: 0.0,
105        valid_range: 0.0..=1.0,
106        units: None,
107    },
108};
109
110/// Parameter info for the timbre parameter. See [`CONTROLLER_PARAMETERS`] for more.
111pub const TIMBRE_INFO: InfoRef<'static, &'static str> = InfoRef {
112    title: "Timbre",
113    short_title: "Timbre",
114    unique_id: TIMBRE_PARAMETER,
115    flags: Flags { automatable: false },
116    type_specific: TypeSpecificInfoRef::Numeric {
117        default: 0.0,
118        valid_range: 0.0..=1.0,
119        units: None,
120    },
121};
122
123/// This represents a set of "controller parameters" that are common to
124/// all synths.
125///
126/// These parameters will not appear in audio software as
127/// automatable parameters, but they will be filled in with the current
128/// value of the corresponding controllers.
129///
130/// Note that synths will receive these regardless of what they returned
131/// from `crate::Component::parameter_infos`.
132pub const CONTROLLER_PARAMETERS: [InfoRef<'static, &'static str>; 6] = [
133    PITCH_BEND_INFO,
134    MOD_WHEEL_INFO,
135    EXPRESSION_INFO,
136    SUSTAIN_INFO,
137    AFTERTOUCH_INFO,
138    TIMBRE_INFO,
139];
140
141/// A trait for synthesizers
142///
143/// A synthesizer is a processor that creates audio from a series of _events_,
144/// such as Note On, or Note Off.
145pub trait Synth: Processor {
146    /// Handle parameter changes and events without processing any data.
147    /// Must not allocate or block.
148    ///
149    /// Note that `parameters` will include [`CONTROLLER_PARAMETERS`] related to controller state
150    /// (e.g. pitch bend, mod wheel, etc.) above, in addition to all the parameters
151    /// returned by `crate::Component::parameter_infos`.
152    fn handle_events<E: Iterator<Item = events::Data> + Clone, P: parameters::States>(
153        &mut self,
154        events: E,
155        parameters: P,
156    );
157
158    /// Process a buffer of events into a buffer of audio. Must not allocate or block.
159    ///
160    /// Note that `events` will be sorted by `sample_offset`
161    ///
162    /// `output` will be received in an undetermined state and must
163    /// be filled with audio by the processor during this call.
164    ///
165    /// Note that `parameters` will include [`CONTROLLER_PARAMETERS`] related to controller state
166    /// (e.g. pitch bend, mod wheel, etc.) above, in addition to all the parameters
167    /// returned by `crate::Component::parameter_infos`.
168    ///
169    /// In order to consume the parameters, you can use the [`crate::pzip`] macro
170    /// to convert the parameters into an iterator of tuples that represent
171    /// the state of the parameters at each sample.
172    ///
173    /// The sample rate of the audio was provided in `environment.sampling_rate`
174    /// in the call to `crate::Component::create_processor`.
175    ///
176    /// Note that it's guaranteed that `output` will be no longer than
177    /// `environment.max_samples_per_process_call` provided in the call to
178    /// `crate::Component::create_processor`.
179    fn process<E: Iterator<Item = Event> + Clone, P: BufferStates, O: BufferMut>(
180        &mut self,
181        events: Events<E>,
182        parameters: P,
183        output: &mut O,
184    );
185}