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}