@@ -9,15 +9,23 @@ use crate::audio::pitch_shifter::PitchShifter;
99use crate :: audio:: recorder:: Recorder ;
1010use crate :: audio:: samplers:: Samplers ;
1111use crate :: ir:: cabinet:: IrCabinet ;
12+ use crate :: ir:: convolver:: Convolver ;
13+ use crate :: ir:: load_service:: ConvolverDropHandle ;
1214use crate :: metronome:: Metronome ;
1315use crate :: tuner:: Tuner ;
1416
17+ pub struct PreparedIr {
18+ pub name : String ,
19+ pub convolver : Convolver ,
20+ }
21+
1522pub enum EngineMessage {
1623 SetAmpChain ( Box < AmplifierChain > ) ,
1724 SetInputFilters ( Option < Box < dyn Stage > > , Option < Box < dyn Stage > > ) ,
1825 StartRecording ( Recorder ) ,
1926 StopRecording ,
20- SetIrCabinet ( Option < String > ) ,
27+ SwapIrConvolver ( Box < PreparedIr > ) ,
28+ ClearIr ,
2129 SetIrBypass ( bool ) ,
2230 SetIrGain ( f32 ) ,
2331 SetTunerEnabled ( bool ) ,
@@ -31,6 +39,8 @@ pub struct Engine {
3139 ir_cabinet : Option < IrCabinet > ,
3240 /// Channel for updating the amplifier chain.
3341 engine_receiver : Receiver < EngineMessage > ,
42+ /// Handle for sending old convolvers off the RT thread for deallocation.
43+ convolver_drop : ConvolverDropHandle ,
3444 samplers : Samplers ,
3545 tuner : Tuner ,
3646 recorder : Option < Recorder > ,
@@ -41,6 +51,7 @@ pub struct Engine {
4151 input_lowpass : Option < Box < dyn Stage > > ,
4252}
4353
54+ #[ derive( Clone ) ]
4455pub struct EngineHandle {
4556 engine_sender : Sender < EngineMessage > ,
4657}
@@ -52,6 +63,7 @@ impl Engine {
5263 ir_cabinet : Option < IrCabinet > ,
5364 peak_meter : PeakMeter ,
5465 metronome : Metronome ,
66+ convolver_drop : ConvolverDropHandle ,
5567 ) -> Result < ( Self , EngineHandle ) > {
5668 let ( engine_sender, engine_receiver) = bounded :: < EngineMessage > ( 10 ) ;
5769
@@ -60,6 +72,7 @@ impl Engine {
6072 chain : Box :: new ( AmplifierChain :: new ( ) ) ,
6173 ir_cabinet,
6274 engine_receiver,
75+ convolver_drop,
6376 samplers,
6477 tuner,
6578 recorder : None ,
@@ -173,7 +186,7 @@ impl Engine {
173186 }
174187
175188 pub fn handle_messages ( & mut self ) {
176- if let Ok ( message) = self . engine_receiver . try_recv ( ) {
189+ while let Ok ( message) = self . engine_receiver . try_recv ( ) {
177190 match message {
178191 EngineMessage :: SetAmpChain ( chain) => {
179192 self . chain = chain;
@@ -184,15 +197,17 @@ impl Engine {
184197 self . input_lowpass = lp;
185198 debug ! ( "Updated input filters" ) ;
186199 }
187- EngineMessage :: SetIrCabinet ( ir_name) => {
188- if let Some ( ref mut cab) = self . ir_cabinet
189- && let Some ( name) = ir_name
190- {
191- if let Err ( e) = cab. select_ir ( & name) {
192- error ! ( "Failed to set IR: {e}" ) ;
193- } else {
194- debug ! ( "IR Cabinet set to: {name}" ) ;
195- }
200+ EngineMessage :: SwapIrConvolver ( prepared) => {
201+ if let Some ( ref mut cab) = self . ir_cabinet {
202+ debug ! ( "IR convolver swapped: {}" , prepared. name) ;
203+ let old = cab. swap_convolver ( prepared. convolver ) ;
204+ self . convolver_drop . retire ( old) ;
205+ }
206+ }
207+ EngineMessage :: ClearIr => {
208+ if let Some ( ref mut cab) = self . ir_cabinet {
209+ cab. clear_convolver ( ) ;
210+ debug ! ( "IR cleared" ) ;
196211 }
197212 }
198213 EngineMessage :: SetIrBypass ( bypass) => {
@@ -211,44 +226,56 @@ impl Engine {
211226 self . tuner . set_enabled ( enabled) ;
212227 }
213228 EngineMessage :: StartRecording ( recorder) => {
214- if self . recorder . is_some ( ) {
215- debug ! ( "Recorder already active, ignoring start request" ) ;
216- return ;
217- }
218-
219- debug ! ( "Recorder updated" ) ;
220- self . recorder = Some ( recorder) ;
229+ self . handle_start_recording ( recorder) ;
221230 }
222231 EngineMessage :: StopRecording => {
223- if self . recorder . is_none ( ) {
224- debug ! ( "No active recorder to stop" ) ;
225- return ;
226- }
227-
228- debug ! ( "Stopping recorder" ) ;
229- if let Some ( recorder) = self . recorder . take ( )
230- && let Err ( e) = recorder. stop ( )
231- {
232- error ! ( "Failed to stop recorder: {e}" ) ;
233- }
234-
235- self . recorder = None ;
232+ self . handle_stop_recording ( ) ;
236233 }
237234 EngineMessage :: SetPitchShift ( semitones) => {
238- if semitones == 0 {
239- self . pitch_shifter = None ;
240- debug ! ( "Pitch shift disabled (bypass)" ) ;
241- } else if let Some ( ref mut shifter) = self . pitch_shifter {
242- shifter. set_semitones ( semitones as f32 ) ;
243- debug ! ( "Pitch shift set to {semitones} semitones" ) ;
244- } else {
245- self . pitch_shifter = Some ( PitchShifter :: new ( semitones as f32 ) ) ;
246- debug ! ( "Pitch shift set to {semitones} semitones" ) ;
247- }
235+ self . handle_pitch_shift ( semitones) ;
248236 }
249237 }
250238 }
251239 }
240+
241+ fn handle_start_recording ( & mut self , recorder : Recorder ) {
242+ if self . recorder . is_some ( ) {
243+ debug ! ( "Recorder already active, ignoring start request" ) ;
244+ return ;
245+ }
246+
247+ debug ! ( "Recorder updated" ) ;
248+ self . recorder = Some ( recorder) ;
249+ }
250+
251+ fn handle_stop_recording ( & mut self ) {
252+ if self . recorder . is_none ( ) {
253+ debug ! ( "No active recorder to stop" ) ;
254+ return ;
255+ }
256+
257+ debug ! ( "Stopping recorder" ) ;
258+ if let Some ( recorder) = self . recorder . take ( )
259+ && let Err ( e) = recorder. stop ( )
260+ {
261+ error ! ( "Failed to stop recorder: {e}" ) ;
262+ }
263+
264+ self . recorder = None ;
265+ }
266+
267+ fn handle_pitch_shift ( & mut self , semitones : i32 ) {
268+ if semitones == 0 {
269+ self . pitch_shifter = None ;
270+ debug ! ( "Pitch shift disabled (bypass)" ) ;
271+ } else if let Some ( ref mut shifter) = self . pitch_shifter {
272+ shifter. set_semitones ( semitones as f32 ) ;
273+ debug ! ( "Pitch shift set to {semitones} semitones" ) ;
274+ } else {
275+ self . pitch_shifter = Some ( PitchShifter :: new ( semitones as f32 ) ) ;
276+ debug ! ( "Pitch shift set to {semitones} semitones" ) ;
277+ }
278+ }
252279}
253280
254281impl Drop for Engine {
@@ -269,11 +296,15 @@ impl EngineHandle {
269296 } ) ;
270297 }
271298
272- pub fn set_ir_cabinet ( & self , ir_name : Option < String > ) {
273- let update = EngineMessage :: SetIrCabinet ( ir_name ) ;
299+ pub fn swap_ir_convolver ( & self , prepared : PreparedIr ) {
300+ let update = EngineMessage :: SwapIrConvolver ( Box :: new ( prepared ) ) ;
274301 self . send ( update) ;
275302 }
276303
304+ pub fn clear_ir ( & self ) {
305+ self . send ( EngineMessage :: ClearIr ) ;
306+ }
307+
277308 pub fn set_ir_bypass ( & self , bypass : bool ) {
278309 let update = EngineMessage :: SetIrBypass ( bypass) ;
279310 self . send ( update) ;
0 commit comments