3131#include <jack/jack.h>
3232
3333#include "monitor-client.h"
34+ #include "../mod-semaphore.h"
3435#include "../utils.h"
3536#include "../dsp/compressor_core.h"
3637
@@ -67,9 +68,10 @@ typedef struct MONITOR_CLIENT_T {
6768 jack_client_t * client ;
6869 jack_port_t * * in_ports ;
6970 jack_port_t * * out_ports ;
71+ sem_t wait_volume_sem ;
7072 uint64_t connected ;
7173 uint32_t numports ;
72- float volume , smooth_volume ;
74+ float volume , smooth_volume , step_volume ;
7375 #ifdef MOD_IO_PROCESSING_ENABLED
7476 sf_compressor_state_st compressor ;
7577 #endif
@@ -83,6 +85,7 @@ typedef struct MONITOR_CLIENT_T {
8385 bool apply_compressor ;
8486 bool apply_volume , apply_smoothing ;
8587 bool muted ;
88+ bool wait_volume ;
8689} monitor_client_t ;
8790
8891/*
@@ -145,11 +148,8 @@ static void ProcessMonitorLoopStereo(monitor_client_t *const mon, jack_nframes_t
145148 const bool apply_smoothing = mon -> apply_smoothing ;
146149 const bool apply_volume = mon -> apply_volume ;
147150
148- const float new_volume_weight = 0.001f ;
149- const float old_volume_weight = 1.f - new_volume_weight ;
150-
151151 const float volume = mon -> volume ;
152-
152+ const float step_volume = mon -> step_volume ;
153153 float smooth_volume = mon -> smooth_volume ;
154154
155155 const bool in1_connected = mon -> connected & (1 << offset );
@@ -176,10 +176,16 @@ static void ProcessMonitorLoopStereo(monitor_client_t *const mon, jack_nframes_t
176176
177177 if (apply_volume )
178178 {
179+ float dy ;
180+
179181 for (jack_nframes_t i = 0 ; i < nframes ; ++ i )
180182 {
181183 if (apply_smoothing )
182- smooth_volume = new_volume_weight * volume + old_volume_weight * smooth_volume ;
184+ {
185+ dy = volume - smooth_volume ;
186+ smooth_volume += copysignf (fminf (fabsf (dy ), step_volume ), dy );
187+ }
188+
183189 bufOut1 [i ] *= smooth_volume ;
184190 bufOut2 [i ] *= smooth_volume ;
185191 }
@@ -190,10 +196,16 @@ static void ProcessMonitorLoopStereo(monitor_client_t *const mon, jack_nframes_t
190196 {
191197 if (apply_volume )
192198 {
199+ float dy ;
200+
193201 for (jack_nframes_t i = 0 ; i < nframes ; ++ i )
194202 {
195203 if (apply_smoothing )
196- smooth_volume = new_volume_weight * volume + old_volume_weight * smooth_volume ;
204+ {
205+ dy = volume - smooth_volume ;
206+ smooth_volume += copysignf (fminf (fabsf (dy ), step_volume ), dy );
207+ }
208+
197209 bufOut1 [i ] *= smooth_volume ;
198210 bufOut2 [i ] *= smooth_volume ;
199211 }
@@ -217,10 +229,16 @@ static void ProcessMonitorLoopStereo(monitor_client_t *const mon, jack_nframes_t
217229
218230 if (apply_volume )
219231 {
232+ float dy ;
233+
220234 for (jack_nframes_t i = 0 ; i < nframes ; ++ i )
221235 {
222236 if (apply_smoothing )
223- smooth_volume = new_volume_weight * volume + old_volume_weight * smooth_volume ;
237+ {
238+ dy = volume - smooth_volume ;
239+ smooth_volume += copysignf (fminf (fabsf (dy ), step_volume ), dy );
240+ }
241+
224242 bufOutR [i ] *= smooth_volume ;
225243 }
226244 }
@@ -230,10 +248,16 @@ static void ProcessMonitorLoopStereo(monitor_client_t *const mon, jack_nframes_t
230248 {
231249 if (apply_volume )
232250 {
251+ float dy ;
252+
233253 for (jack_nframes_t i = 0 ; i < nframes ; ++ i )
234254 {
235255 if (apply_smoothing )
236- smooth_volume = new_volume_weight * volume + old_volume_weight * smooth_volume ;
256+ {
257+ dy = volume - smooth_volume ;
258+ smooth_volume += copysignf (fminf (fabsf (dy ), step_volume ), dy );
259+ }
260+
237261 bufOutR [i ] *= smooth_volume ;
238262 }
239263 }
@@ -261,13 +285,14 @@ static int ProcessMonitor(jack_nframes_t nframes, void *arg)
261285
262286 if (mon -> muted )
263287 {
264- for (uint32_t i = 0 ; i < mon -> numports ; ++ i )
288+ for (uint32_t i = 0 ; i < mon -> numports ; ++ i )
265289 memset (jack_port_get_buffer (mon -> out_ports [i ], nframes ), 0 , sizeof (float )* nframes );
266290
267291 return 0 ;
268292 }
269293
270294 const float volume = mon -> volume ;
295+ const float step_volume = mon -> step_volume ;
271296 float smooth_volume = mon -> smooth_volume ;
272297
273298 if (floats_differ_enough (volume , smooth_volume ))
@@ -287,14 +312,11 @@ static int ProcessMonitor(jack_nframes_t nframes, void *arg)
287312 const float * bufIn [mon -> numports ];
288313 /* */ float * bufOut [mon -> numports ];
289314
290- const float new_volume_weight = 0.001f ;
291- const float old_volume_weight = 1.f - new_volume_weight ;
292-
293315 const bool apply_smoothing = mon -> apply_smoothing ;
294316 const bool apply_volume = mon -> apply_volume ;
295317 const uint64_t connected = mon -> connected ;
296318
297- for (uint32_t i = 0 ; i < mon -> numports ; ++ i )
319+ for (uint32_t i = 0 ; i < mon -> numports ; ++ i )
298320 {
299321 bufIn [i ] = jack_port_get_buffer (mon -> in_ports [i ], nframes );
300322 bufOut [i ] = jack_port_get_buffer (mon -> out_ports [i ], nframes );
@@ -312,10 +334,15 @@ static int ProcessMonitor(jack_nframes_t nframes, void *arg)
312334
313335 if (apply_volume )
314336 {
337+ float dy ;
338+
315339 for (jack_nframes_t i = 0 ; i < nframes ; ++ i )
316340 {
317341 if (apply_smoothing )
318- smooth_volume = new_volume_weight * volume + old_volume_weight * smooth_volume ;
342+ {
343+ dy = volume - smooth_volume ;
344+ smooth_volume += copysignf (fminf (fabsf (dy ), step_volume ), dy );
345+ }
319346
320347 for (uint32_t j = 0 ; j < mon -> numports ; ++ j )
321348 bufOut [j ][i ] *= smooth_volume ;
@@ -325,6 +352,14 @@ static int ProcessMonitor(jack_nframes_t nframes, void *arg)
325352
326353 mon -> apply_volume = floats_differ_enough (smooth_volume , 1.0f );
327354 mon -> smooth_volume = smooth_volume ;
355+ mon -> muted = smooth_volume <= db2lin (-30.f ) || !floats_differ_enough (smooth_volume , db2lin (-30.0f ));
356+
357+ if (mon -> wait_volume && fabsf (volume - smooth_volume ) < 0.000001f )
358+ {
359+ mon -> wait_volume = false;
360+ sem_post (& mon -> wait_volume_sem );
361+ }
362+
328363 return 0 ;
329364}
330365
@@ -390,7 +425,9 @@ int jack_initialize(jack_client_t* client, const char* load_init)
390425
391426 mon -> apply_volume = false;
392427 mon -> muted = false;
393- mon -> volume = 1.0f ;
428+ mon -> wait_volume = false;
429+ mon -> volume = mon -> smooth_volume = 1.0f ;
430+ mon -> step_volume = 0.f ;
394431
395432 /* Register jack ports */
396433 #if defined(_MOD_DEVICE_DUO ) || defined(_MOD_DEVICE_DWARF )
@@ -449,6 +486,8 @@ int jack_initialize(jack_client_t* client, const char* load_init)
449486 jack_port_tie (mon -> in_ports [i ], mon -> out_ports [i ]);
450487 }
451488
489+ sem_init (& mon -> wait_volume_sem , 0 , 0 );
490+
452491 /* Set jack callbacks */
453492 jack_set_graph_order_callback (client , GraphOrder , mon );
454493 jack_set_process_callback (client , ProcessMonitor , mon );
@@ -457,6 +496,7 @@ int jack_initialize(jack_client_t* client, const char* load_init)
457496 if (jack_activate (client ) != 0 )
458497 {
459498 fprintf (stderr , "can't activate jack client\n" );
499+ sem_destroy (& mon -> wait_volume_sem );
460500 free (mon );
461501 return 1 ;
462502 }
@@ -514,6 +554,7 @@ void jack_finish(void* arg)
514554 monitor_client_t * const mon = arg ;
515555
516556 jack_deactivate (mon -> client );
557+ sem_destroy (& mon -> wait_volume_sem );
517558
518559 g_monitor_handle = NULL ;
519560 g_active = false;
@@ -548,6 +589,22 @@ bool monitor_client_init(void)
548589 return true;
549590}
550591
592+ void monitor_client_stop (void )
593+ {
594+ monitor_client_t * const mon = g_monitor_handle ;
595+
596+ if (!mon )
597+ {
598+ fprintf (stderr , "failed to close mod-monitor client\n" );
599+ return ;
600+ }
601+
602+ jack_client_t * const client = mon -> client ;
603+
604+ jack_finish (mon );
605+ jack_client_close (client );
606+ }
607+
551608bool monitor_client_setup_compressor (int mode , float release )
552609{
553610 #ifdef MOD_IO_PROCESSING_ENABLED
@@ -614,27 +671,44 @@ bool monitor_client_setup_volume(float volume)
614671
615672 // local variables for calculations before changing the real struct values
616673 const float final_volume = db2lin (volume );
674+ const float step_volume = fabsf (final_volume - mon -> smooth_volume ) / (0.03f * jack_get_sample_rate (mon -> client ));
617675 const bool apply_volume = floats_differ_enough (final_volume , 1.0f );
618- const bool muted = volume <= -30.f || ! floats_differ_enough ( volume , -30.0f ) ;
676+ const bool unmute = volume > -30.f ;
619677
620678 mon -> volume = final_volume ;
679+ mon -> step_volume = step_volume ;
621680 mon -> apply_volume = apply_volume ;
622- mon -> muted = muted ;
681+
682+ if (unmute )
683+ mon -> muted = false;
684+
623685 return true;
624686}
625687
626- void monitor_client_stop (void )
688+ bool monitor_client_flush_volume (void )
627689{
628690 monitor_client_t * const mon = g_monitor_handle ;
629691
630692 if (!mon )
631693 {
632- fprintf (stderr , "failed to close mod- monitor client\n" );
633- return ;
694+ fprintf (stderr , "asked to flush volume while monitor client is not active \n" );
695+ return false ;
634696 }
635697
636- jack_client_t * const client = mon -> client ;
698+ mon -> smooth_volume = mon -> volume ;
699+ return true;
700+ }
637701
638- jack_finish (mon );
639- jack_client_close (client );
702+ bool monitor_client_wait_volume (void )
703+ {
704+ monitor_client_t * const mon = g_monitor_handle ;
705+
706+ if (!mon )
707+ {
708+ fprintf (stderr , "asked to wait for volume while monitor client is not active\n" );
709+ return false;
710+ }
711+
712+ mon -> wait_volume = true;
713+ return sem_timedwait_secs (& mon -> wait_volume_sem , 1 ) == 0 ;
640714}
0 commit comments