Skip to content

Commit a0bf7d3

Browse files
authored
Implement monitor_audio_levels (#89)
* Initial code for monitor_audio_levels command Signed-off-by: falkTX <[email protected]> * Finish monitor_audio_levels implementation Signed-off-by: falkTX <[email protected]> --------- Signed-off-by: falkTX <[email protected]>
1 parent d157ce0 commit a0bf7d3

File tree

5 files changed

+172
-2
lines changed

5 files changed

+172
-2
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,10 @@ The commands supported by mod-host are:
204204
* unmap the MIDI controller from a control port
205205
e.g.: midi_unmap 0 "gain"
206206

207+
monitor_audio_levels <source_port_name> <enable>
208+
* monitor audio levels for a specific jack port (on the feedback port)
209+
e.g.: monitor_audio_levels "system:capture_1" 1
210+
207211
monitor_midi_program <midi_channel> <enable>
208212
* listen to MIDI program change messages (on the feedback port)
209213
e.g.: monitor_midi_program 0 1

src/effects.c

Lines changed: 157 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ enum {
277277

278278
enum PostPonedEventType {
279279
POSTPONED_PARAM_SET,
280+
POSTPONED_AUDIO_MONITOR,
280281
POSTPONED_OUTPUT_MONITOR,
281282
POSTPONED_MIDI_PROGRAM_CHANGE,
282283
POSTPONED_MIDI_MAP,
@@ -305,6 +306,12 @@ typedef struct HMI_ADDRESSING_T hmi_addressing_t;
305306
#endif
306307
typedef struct PORT_T port_t;
307308

309+
typedef struct AUDIO_MONITOR_T {
310+
jack_port_t *port;
311+
char *source_port_name;
312+
float value;
313+
} audio_monitor_t;
314+
308315
typedef struct CV_SOURCE_T {
309316
port_t *port;
310317
jack_port_t *jack_port;
@@ -586,6 +593,11 @@ typedef struct POSTPONED_PARAMETER_EVENT_T {
586593
float value;
587594
} postponed_parameter_event_t;
588595

596+
typedef struct POSTPONED_AUDIO_MONITOR_EVENT_T {
597+
int index;
598+
float value;
599+
} postponed_audio_monitor_event_t;
600+
589601
typedef struct POSTPONED_MIDI_PROGRAM_CHANGE_EVENT_T {
590602
int8_t program;
591603
int8_t channel;
@@ -628,6 +640,7 @@ typedef struct POSTPONED_EVENT_T {
628640
enum PostPonedEventType type;
629641
union {
630642
postponed_parameter_event_t parameter;
643+
postponed_audio_monitor_event_t audio_monitor;
631644
postponed_midi_program_change_event_t program_change;
632645
postponed_midi_map_event_t midi_map;
633646
postponed_transport_event_t transport;
@@ -725,6 +738,9 @@ static jack_port_t *g_audio_in2_port;
725738
static jack_port_t *g_audio_out1_port;
726739
static jack_port_t *g_audio_out2_port;
727740
#endif
741+
static audio_monitor_t *g_audio_monitors;
742+
static pthread_mutex_t g_audio_monitor_mutex;
743+
static int g_audio_monitor_count;
728744
static jack_port_t *g_midi_in_port;
729745
static jack_position_t g_jack_pos;
730746
static bool g_jack_rolling;
@@ -1226,16 +1242,18 @@ static void RunPostPonedEvents(int ignored_effect_id)
12261242
// cached data, to make sure we only handle similar events once
12271243
bool got_midi_program = false;
12281244
bool got_transport = false;
1229-
postponed_cached_effect_events cached_process_out_buf;
1245+
postponed_cached_effect_events cached_audio_monitor, cached_process_out_buf;
12301246
postponed_cached_symbol_events cached_param_set, cached_output_mon;
12311247

1248+
cached_audio_monitor.last_effect_id = -1;
12321249
cached_process_out_buf.last_effect_id = -1;
12331250
cached_param_set.last_effect_id = -1;
1234-
cached_output_mon.last_effect_id = -1;
12351251
cached_param_set.last_symbol[0] = '\0';
12361252
cached_param_set.last_symbol[MAX_CHAR_BUF_SIZE] = '\0';
1253+
cached_output_mon.last_effect_id = -1;
12371254
cached_output_mon.last_symbol[0] = '\0';
12381255
cached_output_mon.last_symbol[MAX_CHAR_BUF_SIZE] = '\0';
1256+
INIT_LIST_HEAD(&cached_audio_monitor.effects.siblings);
12391257
INIT_LIST_HEAD(&cached_process_out_buf.effects.siblings);
12401258
INIT_LIST_HEAD(&cached_param_set.symbols.siblings);
12411259
INIT_LIST_HEAD(&cached_output_mon.symbols.siblings);
@@ -1284,6 +1302,23 @@ static void RunPostPonedEvents(int ignored_effect_id)
12841302
strncpy(cached_param_set.last_symbol, eventptr->event.parameter.symbol, MAX_CHAR_BUF_SIZE);
12851303
break;
12861304

1305+
case POSTPONED_AUDIO_MONITOR:
1306+
if (ShouldIgnorePostPonedEffectEvent(eventptr->event.audio_monitor.index, &cached_audio_monitor))
1307+
continue;
1308+
1309+
pthread_mutex_lock(&g_audio_monitor_mutex);
1310+
if (eventptr->event.audio_monitor.index < g_audio_monitor_count)
1311+
g_audio_monitors[eventptr->event.audio_monitor.index].value = 0.f;
1312+
pthread_mutex_unlock(&g_audio_monitor_mutex);
1313+
1314+
snprintf(buf, FEEDBACK_BUF_SIZE, "audio_monitor %i %f", eventptr->event.audio_monitor.index,
1315+
eventptr->event.audio_monitor.value);
1316+
socket_send_feedback_debug(buf);
1317+
1318+
// save for fast checkup next time
1319+
cached_audio_monitor.last_effect_id = eventptr->event.audio_monitor.index;
1320+
break;
1321+
12871322
case POSTPONED_OUTPUT_MONITOR:
12881323
if (eventptr->event.parameter.effect_id == ignored_effect_id)
12891324
continue;
@@ -1553,6 +1588,11 @@ static void RunPostPonedEvents(int ignored_effect_id)
15531588
postponed_cached_effect_list_data *peffect;
15541589
postponed_cached_symbol_list_data *psymbol;
15551590

1591+
list_for_each_safe(it, it2, &cached_audio_monitor.effects.siblings)
1592+
{
1593+
peffect = list_entry(it, postponed_cached_effect_list_data, siblings);
1594+
free(peffect);
1595+
}
15561596
list_for_each_safe(it, it2, &cached_process_out_buf.effects.siblings)
15571597
{
15581598
peffect = list_entry(it, postponed_cached_effect_list_data, siblings);
@@ -2790,6 +2830,49 @@ static int ProcessGlobalClient(jack_nframes_t nframes, void *arg)
27902830
}
27912831
#endif
27922832

2833+
// Handle audio monitors
2834+
if (pthread_mutex_trylock(&g_audio_monitor_mutex) == 0)
2835+
{
2836+
float *monitorbuf;
2837+
float absvalue, oldvalue;
2838+
2839+
for (int i = 0; i < g_audio_monitor_count; ++i)
2840+
{
2841+
monitorbuf = (float*)jack_port_get_buffer(g_audio_monitors[i].port, nframes);
2842+
oldvalue = value = g_audio_monitors[i].value;
2843+
2844+
for (jack_nframes_t i = 0 ; i < nframes; i++)
2845+
{
2846+
absvalue = fabsf(monitorbuf[i]);
2847+
2848+
if (absvalue > value)
2849+
value = absvalue;
2850+
}
2851+
2852+
if (oldvalue < value)
2853+
{
2854+
g_audio_monitors[i].value = value;
2855+
2856+
postponed_event_list_data* const posteventptr = rtsafe_memory_pool_allocate_atomic(g_rtsafe_mem_pool);
2857+
2858+
if (posteventptr)
2859+
{
2860+
posteventptr->event.type = POSTPONED_AUDIO_MONITOR;
2861+
posteventptr->event.audio_monitor.index = i;
2862+
posteventptr->event.audio_monitor.value = value;
2863+
2864+
pthread_mutex_lock(&g_rtsafe_mutex);
2865+
list_add_tail(&posteventptr->siblings, &g_rtsafe_list);
2866+
pthread_mutex_unlock(&g_rtsafe_mutex);
2867+
2868+
needs_post = true;
2869+
}
2870+
}
2871+
}
2872+
2873+
pthread_mutex_unlock(&g_audio_monitor_mutex);
2874+
}
2875+
27932876
if (UpdateGlobalJackPosition(pos_flag, false))
27942877
needs_post = true;
27952878

@@ -3958,6 +4041,7 @@ int effects_init(void* client)
39584041

39594042
pthread_mutex_init(&g_rtsafe_mutex, &mutex_atts);
39604043
pthread_mutex_init(&g_raw_midi_port_mutex, &mutex_atts);
4044+
pthread_mutex_init(&g_audio_monitor_mutex, &mutex_atts);
39614045
pthread_mutex_init(&g_midi_learning_mutex, &mutex_atts);
39624046
#ifdef __MOD_DEVICES__
39634047
pthread_mutex_init(&g_hmi_mutex, &mutex_atts);
@@ -4533,6 +4617,7 @@ int effects_finish(int close_client)
45334617
sem_destroy(&g_postevents_semaphore);
45344618
pthread_mutex_destroy(&g_rtsafe_mutex);
45354619
pthread_mutex_destroy(&g_raw_midi_port_mutex);
4620+
pthread_mutex_destroy(&g_audio_monitor_mutex);
45364621
pthread_mutex_destroy(&g_midi_learning_mutex);
45374622
#ifdef __MOD_DEVICES__
45384623
pthread_mutex_destroy(&g_hmi_mutex);
@@ -8255,6 +8340,76 @@ int effects_processing_enable(int enable)
82558340
return SUCCESS;
82568341
}
82578342

8343+
int effects_monitor_audio_levels(const char *source_port_name, int enable)
8344+
{
8345+
if (g_jack_global_client == NULL)
8346+
return ERR_INVALID_OPERATION;
8347+
8348+
if (enable)
8349+
{
8350+
for (int i = 0; i < g_audio_monitor_count; ++i)
8351+
{
8352+
if (!strcmp(g_audio_monitors[i].source_port_name, source_port_name))
8353+
return SUCCESS;
8354+
}
8355+
8356+
pthread_mutex_lock(&g_audio_monitor_mutex);
8357+
g_audio_monitors = realloc(g_audio_monitors, sizeof(audio_monitor_t) * (g_audio_monitor_count + 1));
8358+
pthread_mutex_unlock(&g_audio_monitor_mutex);
8359+
8360+
if (g_audio_monitors == NULL)
8361+
return ERR_MEMORY_ALLOCATION;
8362+
8363+
audio_monitor_t *monitor = &g_audio_monitors[g_audio_monitor_count];
8364+
8365+
char port_name[0xff];
8366+
snprintf(port_name, sizeof(port_name) - 1, "monitor_%d", g_audio_monitor_count + 1);
8367+
8368+
jack_port_t *port = jack_port_register(g_jack_global_client,
8369+
port_name,
8370+
JACK_DEFAULT_AUDIO_TYPE,
8371+
JackPortIsInput,
8372+
0);
8373+
if (port == NULL)
8374+
return ERR_JACK_PORT_REGISTER;
8375+
8376+
snprintf(port_name, sizeof(port_name) - 1, "%s:monitor_%d",
8377+
jack_get_client_name(g_jack_global_client), g_audio_monitor_count + 1);
8378+
jack_connect(g_jack_global_client, source_port_name, port_name);
8379+
8380+
monitor->port = port;
8381+
monitor->source_port_name = strdup(source_port_name);
8382+
monitor->value = 0.f;
8383+
8384+
++g_audio_monitor_count;
8385+
}
8386+
else
8387+
{
8388+
if (g_audio_monitor_count == 0)
8389+
return ERR_INVALID_OPERATION;
8390+
8391+
audio_monitor_t *monitor = &g_audio_monitors[g_audio_monitor_count - 1];
8392+
8393+
if (strcmp(monitor->source_port_name, source_port_name))
8394+
return ERR_INVALID_OPERATION;
8395+
8396+
pthread_mutex_lock(&g_audio_monitor_mutex);
8397+
--g_audio_monitor_count;
8398+
pthread_mutex_unlock(&g_audio_monitor_mutex);
8399+
8400+
jack_port_unregister(g_jack_global_client, monitor->port);
8401+
free(monitor->source_port_name);
8402+
8403+
if (g_audio_monitor_count == 0)
8404+
{
8405+
free(g_audio_monitors);
8406+
g_audio_monitors = NULL;
8407+
}
8408+
}
8409+
8410+
return SUCCESS;
8411+
}
8412+
82588413
int effects_monitor_midi_program(int channel, int enable)
82598414
{
82608415
if (channel < 0 || channel > 15)

src/effects.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ int effects_state_set_tmpdir(const char *dir);
183183
int effects_aggregated_midi_enable(int enable);
184184
int effects_freewheeling_enable(int enable);
185185
int effects_processing_enable(int enable);
186+
int effects_monitor_audio_levels(const char *source_port_name, int enable);
186187
int effects_monitor_midi_program(int channel, int enable);
187188
void effects_transport(int rolling, double beats_per_bar, double beats_per_minute);
188189
int effects_transport_sync_mode(const char *mode);

src/mod-host.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,13 @@ static void monitor_output_cb(proto_t *proto)
318318
protocol_response_int(resp, proto);
319319
}
320320

321+
static void monitor_audio_levels_cb(proto_t *proto)
322+
{
323+
int resp;
324+
resp = effects_monitor_audio_levels(proto->list[1], atoi(proto->list[2]));
325+
protocol_response_int(resp, proto);
326+
}
327+
321328
static void monitor_midi_program_cb(proto_t *proto)
322329
{
323330
int resp;
@@ -380,6 +387,7 @@ static void cc_map_cb(proto_t *proto)
380387
}
381388
else
382389
{
390+
scalepoints_count = 0;
383391
scalepoints = NULL;
384392
}
385393

@@ -714,6 +722,7 @@ static int mod_host_init(jack_client_t* client, int socket_port, int feedback_po
714722
protocol_add_command(EFFECT_SET_BPB, effects_set_beats_per_bar_cb);
715723
protocol_add_command(MONITOR_ADDR_SET, monitor_addr_set_cb);
716724
protocol_add_command(MONITOR_OUTPUT, monitor_output_cb);
725+
protocol_add_command(MONITOR_AUDIO_LEVELS, monitor_audio_levels_cb);
717726
protocol_add_command(MONITOR_MIDI_PROGRAM, monitor_midi_program_cb);
718727
protocol_add_command(MIDI_LEARN, midi_learn_cb);
719728
protocol_add_command(MIDI_MAP, midi_map_cb);

src/mod-host.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
#define EFFECT_SET_BPB "set_bpb %f"
7373
#define MONITOR_ADDR_SET "monitor %s %i %i"
7474
#define MONITOR_OUTPUT "monitor_output %i %s"
75+
#define MONITOR_AUDIO_LEVELS "monitor_audio_levels %i %s"
7576
#define MONITOR_MIDI_PROGRAM "monitor_midi_program %i %i"
7677
#define MIDI_LEARN "midi_learn %i %s %f %f"
7778
#define MIDI_MAP "midi_map %i %s %i %i %f %f"

0 commit comments

Comments
 (0)