11use crate :: io:: recorder:: { AudioBlock , BLOCK_FRAMES } ;
22use crate :: sim:: chain:: AmplifierChain ;
3+ use anyhow:: { Context , Result } ;
34use crossbeam:: channel:: { Receiver , Sender } ;
4- use jack:: { AudioIn , AudioOut , Client , Control , Port , ProcessScope } ;
5- use log:: { error , info } ;
5+ use jack:: { AudioIn , AudioOut , Client , Control , Frames , Port , ProcessHandler , ProcessScope } ;
6+ use log:: { debug , error } ;
67use rubato:: {
78 Resampler , SincFixedIn , SincInterpolationParameters , SincInterpolationType , WindowFunction ,
89} ;
910
10- pub type ProcessHandler = Box < dyn FnMut ( & Client , & ProcessScope ) -> Control + Send + ' static > ;
11+ const CHANNELS : usize = 1 ;
12+ const OVERSAMPLE_FACTOR : f64 = 4.0 ;
13+ const MAX_BLOCK_SIZE : usize = 4096 ;
1114
1215pub struct Processor {
13- /// Amplifier.
16+ /// Amplifier chain, used for processing amp simulations on the input .
1417 chain : Box < AmplifierChain > ,
18+ /// Channel for updating the amplifier chain.
1519 rx_chain : Receiver < Box < AmplifierChain > > ,
16- /// Optional recorder.
20+ /// Optional recorder channel .
1721 tx_audio : Option < Sender < AudioBlock > > ,
1822 in_port : Port < AudioIn > ,
19- out_l : Port < AudioOut > ,
20- out_r : Port < AudioOut > ,
23+ out_port_left : Port < AudioOut > ,
24+ out_port_right : Port < AudioOut > ,
2125 upsampler : SincFixedIn < f32 > ,
2226 downsampler : SincFixedIn < f32 > ,
2327 /// Reusable buffer for input frames.
24- input_frames : Vec < Vec < f32 > > ,
28+ input_buffer : Vec < Vec < f32 > > ,
29+ /// Reusable buffer for upsampled frames.
30+ upsampled_buffer : Vec < Vec < f32 > > ,
31+ /// Reusable buffer for downsampled frames.
32+ downsampled_buffer : Vec < Vec < f32 > > ,
2533}
2634
2735impl Processor {
28- pub fn new_with_channel (
36+ pub fn new (
2937 client : & Client ,
3038 rx_chain : Receiver < Box < AmplifierChain > > ,
3139 tx_audio : Option < Sender < AudioBlock > > ,
32- ) -> Self {
33- let in_port = client. register_port ( "in" , AudioIn :: default ( ) ) . unwrap ( ) ;
34- let out_l = client. register_port ( "out_l" , AudioOut :: default ( ) ) . unwrap ( ) ;
35- let out_r = client. register_port ( "out_r" , AudioOut :: default ( ) ) . unwrap ( ) ;
36-
37- let _ = client. connect_ports_by_name ( "system:capture_1" , "rustortion:in" ) ;
38- let _ = client. connect_ports_by_name ( "rustortion:out_l" , "system:playback_1" ) ;
39- let _ = client. connect_ports_by_name ( "rustortion:out_r" , "system:playback_2" ) ;
40-
41- let channels = 1 ;
42- let oversample_factor: f32 = 4.0 ;
43- let max_chunk_size = 128 ;
40+ ) -> Result < Self > {
41+ let in_port = client
42+ . register_port ( "in_port" , AudioIn :: default ( ) )
43+ . context ( "failed to register in port" ) ?;
44+ let out_port_left = client
45+ . register_port ( "out_port_left" , AudioOut :: default ( ) )
46+ . context ( "failed to register out port left" ) ?;
47+ let out_port_right = client
48+ . register_port ( "out_port_right" , AudioOut :: default ( ) )
49+ . context ( "failed to register out port right" ) ?;
50+
51+ client
52+ . connect_ports_by_name ( "system:capture_1" , "rustortion:in_port" )
53+ . context ( "failed to connect to in port" ) ?;
54+ client
55+ . connect_ports_by_name ( "rustortion:out_port_left" , "system:playback_1" )
56+ . context ( "failed to connect to out port left" ) ?;
57+ client
58+ . connect_ports_by_name ( "rustortion:out_port_right" , "system:playback_2" )
59+ . context ( "failed to connect to out port right" ) ?;
4460
4561 let interp_params = SincInterpolationParameters {
4662 sinc_len : 256 ,
@@ -57,107 +73,151 @@ impl Processor {
5773 window : WindowFunction :: BlackmanHarris2 ,
5874 } ;
5975
60- let upsampler = SincFixedIn :: < f32 > :: new (
61- oversample_factor as f64 ,
76+ let mut upsampler = SincFixedIn :: < f32 > :: new (
77+ OVERSAMPLE_FACTOR ,
6278 1.0 ,
6379 interp_params,
64- max_chunk_size ,
65- channels ,
80+ MAX_BLOCK_SIZE ,
81+ CHANNELS ,
6682 )
67- . unwrap ( ) ;
83+ . context ( "failed to create upsampler" ) ? ;
6884
69- let downsampler = SincFixedIn :: < f32 > :: new (
70- 1.0 / oversample_factor as f64 ,
85+ let mut downsampler = SincFixedIn :: < f32 > :: new (
86+ 1.0 / OVERSAMPLE_FACTOR ,
7187 1.0 ,
7288 down_interp_params,
73- ( max_chunk_size as f32 * oversample_factor ) as usize ,
74- channels ,
89+ MAX_BLOCK_SIZE * OVERSAMPLE_FACTOR as usize ,
90+ CHANNELS ,
7591 )
76- . unwrap ( ) ;
92+ . context ( "failed to create downsampler" ) ? ;
7793
78- let input_frames = vec ! [ Vec :: with_capacity( client. buffer_size( ) as usize ) ] ;
94+ let buffer_size = client. buffer_size ( ) as usize ;
95+ upsampler
96+ . set_chunk_size ( buffer_size)
97+ . context ( "failed to set upsampler chunk size" ) ?;
98+ downsampler
99+ . set_chunk_size ( buffer_size * OVERSAMPLE_FACTOR as usize )
100+ . context ( "failed to set downsampler chunk size" ) ?;
79101
80- Self {
102+ let input_buffer = vec ! [ Vec :: with_capacity( buffer_size) ] ;
103+ let upsampled_buffer = upsampler. output_buffer_allocate ( true ) ;
104+ let downsampled_buffer = downsampler. output_buffer_allocate ( true ) ;
105+
106+ Ok ( Self {
81107 chain : Box :: new ( AmplifierChain :: new ( "Default" ) ) ,
82108 rx_chain,
83109 tx_audio,
84110 in_port,
85- out_l ,
86- out_r ,
111+ out_port_left ,
112+ out_port_right ,
87113 upsampler,
88114 downsampler,
89- input_frames,
90- }
115+ input_buffer,
116+ upsampled_buffer,
117+ downsampled_buffer,
118+ } )
91119 }
120+ }
92121
93- pub fn into_process_handler ( mut self ) -> ProcessHandler {
94- Box :: new ( move | _client : & Client , ps : & ProcessScope | -> Control {
95- if let Ok ( new_chain) = self . rx_chain . try_recv ( ) {
96- self . chain = new_chain;
97- info ! ( "Received new chain" ) ;
98- }
122+ impl ProcessHandler for Processor {
123+ fn process ( & mut self , _c : & Client , ps : & ProcessScope ) -> Control {
124+ if let Ok ( new_chain) = self . rx_chain . try_recv ( ) {
125+ self . chain = new_chain;
126+ debug ! ( "Received new chain" ) ;
127+ }
99128
100- let n_frames = ps. n_frames ( ) as usize ;
101- let in_buf = self . in_port . as_slice ( ps) ;
129+ let n_frames = ps. n_frames ( ) as usize ;
130+ let input = self . in_port . as_slice ( ps) ;
102131
103- let out_buf_l = self . out_l . as_mut_slice ( ps) ;
104- let out_buf_r = self . out_r . as_mut_slice ( ps) ;
132+ self . input_buffer [ 0 ] . clear ( ) ;
105133
106- {
107- let input_channel = & mut self . input_frames [ 0 ] ;
108- input_channel. clear ( ) ;
134+ debug_assert ! (
135+ self . input_buffer[ 0 ] . capacity( ) >= n_frames,
136+ "input_buffer too small; buffer_size callback missing an allocation"
137+ ) ;
109138
110- if input_channel. capacity ( ) < n_frames {
111- input_channel. reserve ( n_frames - input_channel. capacity ( ) ) ;
112- }
139+ self . input_buffer [ 0 ] . extend_from_slice ( input) ;
113140
114- input_channel. extend_from_slice ( in_buf) ;
141+ let ( _, upsampled_frames) = match self . upsampler . process_into_buffer (
142+ & self . input_buffer ,
143+ & mut self . upsampled_buffer ,
144+ None ,
145+ ) {
146+ Ok ( data) => data,
147+ Err ( e) => {
148+ error ! ( "Upsampler error: {e}" ) ;
149+ return Control :: Continue ;
115150 }
151+ } ;
116152
117- let mut upsampled = match self . upsampler . process ( & self . input_frames , None ) {
118- Ok ( data) => data,
119- Err ( e) => {
120- error ! ( "Upsampler error: {e}" ) ;
121- return Control :: Continue ;
122- }
123- } ;
124-
125- let chain = self . chain . as_mut ( ) ;
126- for s in & mut upsampled[ 0 ] {
127- * s = chain. process ( * s) ;
128- }
153+ let chain = self . chain . as_mut ( ) ;
154+ for s in & mut self . upsampled_buffer [ 0 ] [ ..upsampled_frames] {
155+ * s = chain. process ( * s) ;
156+ }
129157
130- let downsampled = match self . downsampler . process ( & upsampled, None ) {
131- Ok ( data) => data,
132- Err ( e) => {
133- error ! ( "Downsampler error: {e}" ) ;
134- return Control :: Continue ;
135- }
136- } ;
137-
138- let final_samples = & downsampled[ 0 ] ;
139- let frames_to_copy = final_samples. len ( ) . min ( n_frames) ;
140-
141- out_buf_l[ ..frames_to_copy] . copy_from_slice ( & final_samples[ ..frames_to_copy] ) ;
142- out_buf_r[ ..frames_to_copy] . copy_from_slice ( & final_samples[ ..frames_to_copy] ) ;
143- for i in frames_to_copy..n_frames {
144- out_buf_l[ i] = 0.0 ;
145- out_buf_r[ i] = 0.0 ;
158+ let ( _, downsampled_frames) = match self . downsampler . process_into_buffer (
159+ & self . upsampled_buffer ,
160+ & mut self . downsampled_buffer ,
161+ None ,
162+ ) {
163+ Ok ( data) => data,
164+ Err ( e) => {
165+ error ! ( "Downsampler error: {e}" ) ;
166+ return Control :: Continue ;
146167 }
168+ } ;
169+
170+ let final_samples = & self . downsampled_buffer [ 0 ] [ ..downsampled_frames] ;
171+ let frames_to_copy = final_samples. len ( ) . min ( n_frames) ;
172+
173+ let out_buffer_left = self . out_port_left . as_mut_slice ( ps) ;
174+ let out_buffer_right = self . out_port_right . as_mut_slice ( ps) ;
147175
148- if let Some ( ref tx ) = self . tx_audio {
149- let mut block = AudioBlock :: with_capacity ( BLOCK_FRAMES * 2 ) ;
150- for & s in final_samples . iter ( ) . take ( BLOCK_FRAMES ) {
151- let v = ( s * i16 :: MAX as f32 ) . clamp ( i16 :: MIN as f32 , i16 :: MAX as f32 ) as i16 ;
152- block . extend_from_slice ( & [ v , v ] ) ;
153- }
176+ out_buffer_left [ ..frames_to_copy ] . copy_from_slice ( & final_samples [ ..frames_to_copy ] ) ;
177+ out_buffer_right [ ..frames_to_copy ] . copy_from_slice ( & final_samples [ ..frames_to_copy ] ) ;
178+ for i in frames_to_copy..n_frames {
179+ out_buffer_left [ i ] = 0.0 ;
180+ out_buffer_right [ i ] = 0.0 ;
181+ }
154182
155- if let Err ( e) = tx. try_send ( block) {
156- error ! ( "Error sending audio block: {e}" ) ;
157- }
183+ // If the recording channel is available, handle sending audio blocks to the recorder.
184+ if let Some ( ref tx) = self . tx_audio {
185+ let mut block = AudioBlock :: with_capacity ( BLOCK_FRAMES * 2 ) ;
186+ for & s in final_samples. iter ( ) . take ( BLOCK_FRAMES ) {
187+ let v = ( s * i16:: MAX as f32 ) . clamp ( i16:: MIN as f32 , i16:: MAX as f32 ) as i16 ;
188+ block. extend_from_slice ( & [ v, v] ) ;
158189 }
159190
160- Control :: Continue
161- } )
191+ if let Err ( e) = tx. try_send ( block) {
192+ error ! ( "Error sending audio block: {e}" ) ;
193+ }
194+ }
195+
196+ Control :: Continue
197+ }
198+
199+ fn buffer_size ( & mut self , _c : & Client , frames : Frames ) -> Control {
200+ debug ! ( "JACK buffer size changed to {frames} frames" ) ;
201+ let new_size = frames as usize ;
202+ let cap = self . input_buffer [ 0 ] . capacity ( ) ;
203+
204+ if cap < new_size {
205+ self . input_buffer [ 0 ] . reserve_exact ( new_size - cap) ;
206+ }
207+
208+ if let Err ( e) = self . upsampler . set_chunk_size ( new_size) {
209+ error ! ( "Upsampler cannot grow to {new_size}: {e}" ) ;
210+ } else {
211+ self . upsampled_buffer = self . upsampler . output_buffer_allocate ( true ) ;
212+ }
213+
214+ let needed_down = new_size * OVERSAMPLE_FACTOR as usize ;
215+ if let Err ( e) = self . downsampler . set_chunk_size ( needed_down) {
216+ error ! ( "Downsampler cannot grow to {needed_down}: {e}" ) ;
217+ } else {
218+ self . downsampled_buffer = self . downsampler . output_buffer_allocate ( true ) ;
219+ }
220+
221+ Control :: Continue
162222 }
163223}
0 commit comments