Skip to content

Commit d157ce0

Browse files
committed
Allow to fade-in/out while enabling/disabling processing
Signed-off-by: falkTX <falktx@falktx.com>
1 parent 83e5da4 commit d157ce0

File tree

3 files changed

+137
-26
lines changed

3 files changed

+137
-26
lines changed

src/effects.c

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8211,10 +8211,45 @@ int effects_freewheeling_enable(int enable)
82118211

82128212
int effects_processing_enable(int enable)
82138213
{
8214-
g_processing_enabled = enable;
8214+
switch (enable)
8215+
{
8216+
// regular on/off
8217+
case 0:
8218+
case 1:
8219+
g_processing_enabled = enable != 0;
8220+
break;
82158221

8216-
if (enable > 1) {
8222+
// turn on while reporting feedback data ready
8223+
case 2:
8224+
g_processing_enabled = true;
82178225
effects_output_data_ready();
8226+
break;
8227+
8228+
// use fade-out while turning off
8229+
case -1:
8230+
monitor_client_setup_volume(-30.f);
8231+
if (g_processing_enabled)
8232+
{
8233+
monitor_client_wait_volume();
8234+
g_processing_enabled = false;
8235+
}
8236+
break;
8237+
8238+
// don't use fade-out while turning off, mute right away
8239+
case -2:
8240+
monitor_client_setup_volume(-30.f);
8241+
monitor_client_flush_volume();
8242+
g_processing_enabled = false;
8243+
break;
8244+
8245+
// use fade-in while turning on
8246+
case 3:
8247+
g_processing_enabled = true;
8248+
monitor_client_setup_volume(0.f);
8249+
break;
8250+
8251+
default:
8252+
return ERR_INVALID_OPERATION;
82188253
}
82198254

82208255
return SUCCESS;

src/monitor/monitor-client.c

Lines changed: 98 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
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+
551608
bool 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
}

src/monitor/monitor-client.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ void monitor_client_stop(void);
7979

8080
bool monitor_client_setup_compressor(int mode, float release);
8181
bool monitor_client_setup_volume(float volume);
82+
bool monitor_client_flush_volume(void);
83+
bool monitor_client_wait_volume(void);
8284

8385

8486
/*

0 commit comments

Comments
 (0)