Skip to content

Commit 4136c60

Browse files
committed
Fix issue #17 and issue #16
1 parent a15f60a commit 4136c60

File tree

8 files changed

+375
-48
lines changed

8 files changed

+375
-48
lines changed

NeuralAudio

NeuralRack/clap/NeuralRack.cc

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99

10+
#include <atomic>
1011
#include <errno.h>
1112
#include <unistd.h>
1213
#include <signal.h>
@@ -29,6 +30,8 @@ class NeuralRack
2930
{
3031
public:
3132
Widget_t* TopWin;
33+
std::atomic<bool> paramChanged;
34+
std::atomic<bool> controllerChanged;
3235

3336
NeuralRack() : engine() {
3437
workToDo.store(false, std::memory_order_release);
@@ -44,6 +47,8 @@ class NeuralRack
4447
title = "NeuralRack";
4548
firstLoop = true;
4649
p = 0;
50+
paramChanged.store(false, std::memory_order_release);
51+
controllerChanged.store(false, std::memory_order_release);
4752
for(int i = 0;i<CONTROLS;i++)
4853
ui->widget[i] = NULL;
4954
}
@@ -149,6 +154,10 @@ class NeuralRack
149154
checkParentWindowSize(TopWin->width, TopWin->height);
150155
firstLoop = false;
151156
}
157+
if (paramChanged.load(std::memory_order_acquire)) {
158+
getEngineValues();
159+
paramChanged.store(false, std::memory_order_release);
160+
}
152161
run_embedded(&ui->main);
153162
}
154163

@@ -180,6 +189,10 @@ class NeuralRack
180189
return &ui->main;
181190
}
182191

192+
neuralrack::Engine *getEngine() {
193+
return &engine;
194+
}
195+
183196
void initEQ() {
184197
engine.eqOnOff = 0;
185198
engine.peq->fVslider1 = -20.0;
@@ -349,6 +362,8 @@ class NeuralRack
349362
default:
350363
break;
351364
}
365+
// inform the process thread that a controller value was changed by the GUI thread
366+
controllerChanged.store(true, std::memory_order_release);
352367
}
353368

354369
// send a file name from GUI to the engine
@@ -590,3 +605,21 @@ class NeuralRack
590605
}
591606

592607
};
608+
609+
610+
/****************************************************************
611+
** connect value change messages from the GUI (C) to the engine (C++)
612+
*/
613+
614+
// send value changes from GUI to the engine
615+
void sendValueChanged(X11_UI *ui, int port, float value) {
616+
NeuralRack *r = (NeuralRack*)ui->win->private_struct;
617+
r->sendValueChanged(port, value);
618+
}
619+
620+
// send a file name from GUI to the engine
621+
void sendFileName(X11_UI *ui, ModelPicker* m, int old){
622+
NeuralRack *r = (NeuralRack*)ui->win->private_struct;
623+
r->sendFileName(m, old);
624+
}
625+

NeuralRack/clap/NeuralRackClap.cpp

Lines changed: 134 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,15 @@
77
*/
88

99
#include <clap.h>
10+
#include <ext/params.h>
11+
#include <events.h>
1012
#include <stdlib.h>
1113
#include <stdio.h>
1214
#include <string.h>
13-
#include "NeuralRack.cc"
15+
16+
typedef struct neuralrack_plugin_t neuralrack_plugin_t;
17+
18+
#include "NeuralRackParameter.h"
1419

1520
#define WINDOW_WIDTH 620
1621
#define WINDOW_HEIGHT 580
@@ -26,46 +31,131 @@
2631
** neuralrack_plugin_t -> the plugin struct
2732
*/
2833

34+
#include "NeuralRack.cc"
35+
2936
// Plugin data structure
30-
typedef struct {
37+
struct neuralrack_plugin_t {
3138
clap_plugin_t plugin;
3239
const clap_host_t *host;
3340
NeuralRack *r;
41+
NeuralRackParams params;
3442
bool guiIsCreated;
3543
uint32_t latency;
3644
uint32_t width;
3745
uint32_t height;
38-
} neuralrack_plugin_t;
39-
46+
};
4047

4148
/****************************************************************
42-
** connect value change messages from the GUI to the engine
49+
** Parameter handling
4350
*/
4451

45-
// send value changes from GUI to the engine
46-
void sendValueChanged(X11_UI *ui, int port, float value) {
47-
NeuralRack *r = (NeuralRack*)ui->win->private_struct;
48-
r->sendValueChanged(port, value);
52+
#include "NeuralRackParameter.cc"
53+
54+
static uint32_t params_count(const clap_plugin_t*) {
55+
return (uint32_t)neuralrack_parameters.size();
56+
}
57+
58+
static bool params_get_info(const clap_plugin_t*, uint32_t param_index, clap_param_info_t* param_info) {
59+
if (param_index >= neuralrack_parameters.size()) return false;
60+
const auto& def = neuralrack_parameters[param_index];
61+
memset(param_info, 0, sizeof(*param_info));
62+
param_info->id = def.id;
63+
strncpy(param_info->name, def.name.c_str(), CLAP_NAME_SIZE-1);
64+
strncpy(param_info->module, def.module.c_str(), CLAP_PATH_SIZE-1);
65+
param_info->default_value = def.def;
66+
param_info->min_value = def.min;
67+
param_info->max_value = def.max;
68+
param_info->flags = def.flags;
69+
param_info->cookie = nullptr;
70+
return true;
71+
}
72+
73+
static bool params_get_value(const clap_plugin_t* plugin, clap_id param_id, double* value) {
74+
neuralrack_plugin_t *plug = (neuralrack_plugin_t *)plugin->plugin_data;
75+
if (param_id < 0 || param_id >= PARAM_COUNT) return false;
76+
*value = plug->params.getParam(plug, param_id);
77+
return true;
78+
}
79+
80+
static bool params_value_to_text(const clap_plugin_t*, clap_id param_id, double value, char* out, uint32_t size) {
81+
if (param_id < 0 || param_id >= PARAM_COUNT) return false;
82+
snprintf(out, size, "%.2f", value);
83+
return true;
84+
}
85+
86+
static bool params_text_to_value(const clap_plugin_t*, clap_id param_id, const char* text, double* out_value) {
87+
if (param_id < 0 || param_id >= PARAM_COUNT) return false;
88+
*out_value = atof(text);
89+
return true;
90+
}
91+
92+
static void sync_params_to_plug(const clap_plugin_t *plugin, const clap_event_header_t *hdr) {
93+
neuralrack_plugin_t *plug = (neuralrack_plugin_t *)plugin->plugin_data;
94+
if (hdr->space_id == CLAP_CORE_EVENT_SPACE_ID) {
95+
switch (hdr->type) {
96+
case CLAP_EVENT_PARAM_VALUE: {
97+
const clap_event_param_value_t *ev = (const clap_event_param_value_t *)hdr;
98+
plug->params.setParam(plug, ev->param_id, ev->value);
99+
break;
100+
}
101+
}
102+
}
49103
}
50104

51-
// send a file name from GUI to the engine
52-
void sendFileName(X11_UI *ui, ModelPicker* m, int old){
53-
NeuralRack *r = (NeuralRack*)ui->win->private_struct;
54-
r->sendFileName(m, old);
105+
static void sync_params_to_host(const clap_plugin_t *plugin, const clap_output_events_t *out) {
106+
neuralrack_plugin_t *plug = (neuralrack_plugin_t *)plugin->plugin_data;
107+
for (uint32_t i = 0; i < PARAM_COUNT; i++) {
108+
clap_event_param_value_t event = {};
109+
event.header.size = sizeof(event);
110+
event.header.time = 0;
111+
event.header.space_id = CLAP_CORE_EVENT_SPACE_ID;
112+
event.header.type = CLAP_EVENT_PARAM_VALUE;
113+
event.header.flags = 0;
114+
event.param_id = i;
115+
event.cookie = NULL;
116+
event.note_id = -1;
117+
event.port_index = -1;
118+
event.channel = -1;
119+
event.key = -1;
120+
event.value = plug->params.getParam(plug, i);;
121+
out->try_push(out, &event.header);
122+
}
55123
}
56124

125+
static void params_flush(const clap_plugin_t *plugin,
126+
const clap_input_events_t *in,
127+
const clap_output_events_t *out) {
128+
neuralrack_plugin_t *plug = (neuralrack_plugin_t *)plugin->plugin_data;
129+
for (uint32_t i = 0; i < in->size(in); ++i) {
130+
const clap_event_header_t *ev = in->get(in, i);
131+
if (ev->type == CLAP_EVENT_PARAM_VALUE) {
132+
auto *p = (const clap_event_param_value_t *)ev;
133+
if (p->param_id >= 0 && p->param_id < PARAM_COUNT) {
134+
plug->params.setParam(plug, p->param_id, p->value);
135+
}
136+
}
137+
}
138+
}
139+
140+
const clap_plugin_params_t neuralrack_params = {
141+
.count = params_count,
142+
.get_info = params_get_info,
143+
.get_value = params_get_value,
144+
.value_to_text = params_value_to_text,
145+
.text_to_value = params_text_to_value,
146+
.flush = params_flush,
147+
};
57148

58149
/****************************************************************
59150
** define the audio ports
60151
*/
61152

62-
// Audio Ports
63-
static uint32_t audio_ports_count(const clap_plugin_t *plugin, bool is_input) {
153+
static uint32_t audio_ports_count(const clap_plugin_t*, bool is_input) {
64154
if (is_input) return 1; // 1 input
65155
else return 2; // and 2 output
66156
}
67157

68-
static bool audio_ports_get(const clap_plugin_t *plugin, uint32_t index, bool is_input, clap_audio_port_info_t *info) {
158+
static bool audio_ports_get(const clap_plugin_t*, uint32_t index, bool is_input, clap_audio_port_info_t *info) {
69159
if (index > 0) return false;
70160
info->id = index;
71161
snprintf(info->name, sizeof(info->name), "%s", is_input ? "Input" : "Output");
@@ -89,7 +179,6 @@ static const clap_plugin_audio_ports_t audio_ports = {
89179
** Latency reporting
90180
*/
91181

92-
// Latency
93182
static uint32_t neuralrack_latency_get(const clap_plugin_t *plugin) {
94183
neuralrack_plugin_t *plug = (neuralrack_plugin_t *)plugin->plugin_data;
95184
plug->r->getLatency(&plug->latency);
@@ -133,7 +222,6 @@ static const clap_plugin_state_t state_extension = {
133222
** GUI handling
134223
*/
135224

136-
// GUI Callbacks
137225
static bool neuralrack_gui_is_api_supported(const clap_plugin *plugin, const char *api, bool is_floating) {
138226
return strcmp(api, GUIAPI) == 0;
139227
}
@@ -294,6 +382,33 @@ static clap_process_status neuralrack_process(const clap_plugin_t *plugin, const
294382
float *left_output = process->audio_outputs[0].data32[0]; // Left channel of stereo output
295383
float *right_output = process->audio_outputs[0].data32[1]; // Right channel of stereo output
296384
uint32_t nframes = process->frames_count;
385+
const uint32_t nev = process->in_events->size(process->in_events);
386+
uint32_t ev_index = 0;
387+
uint32_t next_ev_frame = nev > 0 ? 0 : nframes;
388+
389+
if (plug->r->controllerChanged.load(std::memory_order_acquire)) {
390+
sync_params_to_host(plugin, process->out_events);
391+
plug->r->controllerChanged.store(false, std::memory_order_release);
392+
}
393+
394+
for (uint32_t i = 0; i < nframes;++i) {
395+
while (ev_index < nev && next_ev_frame == i) {
396+
const clap_event_header_t *hdr = process->in_events->get(process->in_events, ev_index);
397+
if (hdr->time != i) {
398+
next_ev_frame = hdr->time;
399+
break;
400+
}
401+
sync_params_to_plug(plugin, hdr);
402+
++ev_index;
403+
404+
if (ev_index == nev) {
405+
// we reached the end of the event list
406+
next_ev_frame = nframes;
407+
break;
408+
}
409+
}
410+
}
411+
297412
// in-place processing
298413
if(left_output != input)
299414
memcpy(left_output, input, nframes*sizeof(float));
@@ -304,7 +419,6 @@ static clap_process_status neuralrack_process(const clap_plugin_t *plugin, const
304419
return CLAP_PROCESS_CONTINUE;
305420
}
306421

307-
308422
// Finally get the sample rate and re-init the engine
309423
static bool neuralrack_activate(const struct clap_plugin *plugin,
310424
double sample_rate,
@@ -343,6 +457,7 @@ static const void *neuralrack_get_extension(const clap_plugin_t *plugin, const c
343457
if (!strcmp(id, CLAP_EXT_AUDIO_PORTS)) return &audio_ports;
344458
if (!strcmp(id, CLAP_EXT_LATENCY)) return &latency_extension;
345459
if (!strcmp(id, CLAP_EXT_GUI)) return &extensionGUI;
460+
if (!strcmp(id, CLAP_EXT_PARAMS)) return &neuralrack_params;
346461
if (!strcmp(id, CLAP_EXT_STATE)) return &state_extension;
347462
return NULL;
348463
}
@@ -371,7 +486,6 @@ static const clap_plugin_t *neuralrack_create(const clap_host_t *host) {
371486
return &plug->plugin;
372487
}
373488

374-
375489
/****************************************************************
376490
** the factory entry
377491
*/

0 commit comments

Comments
 (0)