diff options
author | Hanspeter Portner <dev@open-music-kontrollers.ch> | 2015-08-02 10:46:31 +0200 |
---|---|---|
committer | Hanspeter Portner <dev@open-music-kontrollers.ch> | 2015-08-02 10:46:31 +0200 |
commit | 9672487e9af5d079a53e8d6afd90ce9d747ca888 (patch) | |
tree | e0380228a9ca919b17f0d695144f12800351403b /lib | |
parent | e5880dab603dac2ad5167bcd437f84d93b373642 (diff) | |
download | synthpod-9672487e9af5d079a53e8d6afd90ce9d747ca888.tar.xz |
prototype per/connection audio ramps.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/synthpod_app.c | 177 |
1 files changed, 114 insertions, 63 deletions
diff --git a/lib/synthpod_app.c b/lib/synthpod_app.c index f2f328c1..d6458f8d 100644 --- a/lib/synthpod_app.c +++ b/lib/synthpod_app.c @@ -46,6 +46,7 @@ typedef struct _mod_t mod_t; typedef struct _port_t port_t; typedef struct _work_t work_t; typedef struct _job_t job_t; +typedef struct _source_t source_t; enum _bypass_state_t { BYPASS_STATE_PAUSED = 0, @@ -137,6 +138,18 @@ struct _mod_t { void *buf; }; +struct _source_t { + port_t *port; + + // ramping + struct { + int can; + int samples; + ramp_state_t state; + float value; + } ramp; +}; + struct _port_t { mod_t *mod; int selected; @@ -147,7 +160,7 @@ struct _port_t { int num_sources; int num_feedbacks; - port_t *sources [MAX_SOURCES]; + source_t sources [MAX_SOURCES]; size_t size; void *buf; @@ -174,14 +187,6 @@ struct _port_t { System_Port_Type type; void *data; } sys; - - // ramping - struct { - int can; - int samples; - ramp_state_t state; - float value; - } ramp; }; struct _sp_app_t { @@ -234,7 +239,7 @@ static inline void * _port_sink_get(port_t *port) { return (port->num_sources + port->num_feedbacks) == 1 - ? port->sources[0]->buf + ? port->sources[0].port->buf : port->buf; } #define PORT_SINK_ALIGNED(PORT) ASSUME_ALIGNED(_port_sink_get((PORT))) @@ -694,10 +699,6 @@ _sp_app_mod_add(sp_app_t *app, const char *uri, uint32_t uid) tar->sys.data = NULL; } - tar->ramp.samples = 0; - tar->ramp.state = RAMP_STATE_NONE; - tar->ramp.value = 0.f; - if(lilv_port_is_a(plug, port, app->regs.port.audio.node)) { tar->size = app->driver->max_block_size * sizeof(float); @@ -902,7 +903,8 @@ _sp_app_port_connect(sp_app_t *app, port_t *src_port, port_t *snk_port) if(snk_port->num_sources >= MAX_SOURCES) return 0; - snk_port->sources[snk_port->num_sources] = src_port;; + source_t *conn = &snk_port->sources[snk_port->num_sources]; + conn->port = src_port;; snk_port->num_sources += 1; snk_port->num_feedbacks += src_port->mod == snk_port->mod ? 1 : 0; @@ -912,7 +914,7 @@ _sp_app_port_connect(sp_app_t *app, port_t *src_port, port_t *snk_port) lilv_instance_connect_port( snk_port->mod->inst, snk_port->index, - snk_port->sources[0]->buf); + snk_port->sources[0].port->buf); } else { @@ -927,9 +929,9 @@ _sp_app_port_connect(sp_app_t *app, port_t *src_port, port_t *snk_port) if( (src_port->type == PORT_TYPE_AUDIO) && (src_port->direction == PORT_DIRECTION_OUTPUT) ) { - src_port->ramp.samples = app->ramp_samples; - src_port->ramp.state = RAMP_STATE_UP; - src_port->ramp.value = 0.f; + conn->ramp.samples = app->ramp_samples; + conn->ramp.state = RAMP_STATE_UP; + conn->ramp.value = 0.f; } return 1; @@ -942,13 +944,13 @@ _sp_app_port_disconnect(sp_app_t *app, port_t *src_port, port_t *snk_port) int connected = 0; for(int i=0, j=0; i<snk_port->num_sources; i++) { - if(snk_port->sources[i] == src_port) + if(snk_port->sources[i].port == src_port) { connected = 1; continue; } - snk_port->sources[j++] = snk_port->sources[i]; + snk_port->sources[j++].port = snk_port->sources[i].port; } if(!connected) @@ -963,7 +965,7 @@ _sp_app_port_disconnect(sp_app_t *app, port_t *src_port, port_t *snk_port) lilv_instance_connect_port( snk_port->mod->inst, snk_port->index, - snk_port->sources[0]->buf); + snk_port->sources[0].port->buf); } else { @@ -973,8 +975,38 @@ _sp_app_port_disconnect(sp_app_t *app, port_t *src_port, port_t *snk_port) snk_port->index, snk_port->buf); } +} + +static inline void +_sp_app_port_disconnect_request(sp_app_t *app, port_t *src_port, port_t *snk_port) +{ + // only audio output ports need to be ramped to be clickless + if( (src_port->type == PORT_TYPE_AUDIO) + && (src_port->direction == PORT_DIRECTION_OUTPUT) ) + { + source_t *conn = NULL; + + // find connection + for(int i=0; i<snk_port->num_sources; i++) + { + if(snk_port->sources[i].port == src_port) + { + conn = &snk_port->sources[i]; + break; + } + } - //FIXME ramp audio output ports to be clickless + if(conn) + { + conn->ramp.samples = app->ramp_samples; + conn->ramp.state = RAMP_STATE_DOWN; + conn->ramp.value = 0.f; + } + } + else + { + _sp_app_port_disconnect(app, src_port, snk_port); + } } // non-rt @@ -1204,12 +1236,12 @@ sp_app_from_ui(sp_app_t *app, const LV2_Atom *atom) // disconnect sources for(int s=0; s<port->num_sources; s++) - _sp_app_port_disconnect(app, port->sources[s], port); + _sp_app_port_disconnect(app, port->sources[s].port, port); // disconnect sinks for(int m=0; m<app->num_mods; m++) for(int p2=0; p2<app->mods[m]->num_ports; p2++) - _sp_app_port_disconnect(app, port, &app->mods[m]->ports[p2]); + _sp_app_port_disconnect(app, port, &app->mods[m]->ports[p2]); //FIXME ramp } // send request to worker thread @@ -1374,7 +1406,7 @@ sp_app_from_ui(sp_app_t *app, const LV2_Atom *atom) { for(int s=0; s<snk_port->num_sources; s++) { - if(snk_port->sources[s] == src_port) + if(snk_port->sources[s].port == src_port) { state = 1; break; @@ -1384,7 +1416,7 @@ sp_app_from_ui(sp_app_t *app, const LV2_Atom *atom) } case 0: // disconnect { - _sp_app_port_disconnect(app, src_port, snk_port); + _sp_app_port_disconnect_request(app, src_port, snk_port); state = 0; break; } @@ -2193,6 +2225,26 @@ sp_app_run_pre(sp_app_t *app, uint32_t nsamples) } // rt +static inline void +_update_ramp(sp_app_t *app, source_t *source, port_t *port, uint32_t nsamples) +{ + // update ramp properties + source->ramp.samples -= nsamples; // update remaining samples to ramp over + if(source->ramp.samples <= 0) + { + if(source->ramp.state == RAMP_STATE_DOWN) + _sp_app_port_disconnect(app, source->port, port); + source->ramp.state = RAMP_STATE_NONE; // ramp is complete + } + else + { + source->ramp.value = (float)source->ramp.samples / (float)app->ramp_samples; + if(source->ramp.state == RAMP_STATE_UP) + source->ramp.value = 1.f - source->ramp.value; + } +} + +// rt void sp_app_run_post(sp_app_t *app, uint32_t nsamples) { @@ -2249,7 +2301,7 @@ sp_app_run_post(sp_app_t *app, uint32_t nsamples) *val = 0; // init for(int i=0; i<port->num_sources; i++) { - float *src = PORT_BUF_ALIGNED(port->sources[i]); + float *src = PORT_BUF_ALIGNED(port->sources[i].port); *val += *src; } } @@ -2260,13 +2312,24 @@ sp_app_run_post(sp_app_t *app, uint32_t nsamples) memset(val, 0, nsamples * sizeof(float)); // init for(int i=0; i<port->num_sources; i++) { - float *src = PORT_BUF_ALIGNED(port->sources[i]); - for(int j=0; j<nsamples; j++) + source_t *source = &port->sources[i]; + + // ramp audio output ports + if(source->ramp.state != RAMP_STATE_NONE) { - val[j] += src[j]; + float *src = PORT_BUF_ALIGNED(source->port); + for(int j=0; j<nsamples; j++) + val[j] += src[j] * source->ramp.value; + + _update_ramp(app, source, port, nsamples); + } + else // RAMP_STATE_NONE + { + float *src = PORT_BUF_ALIGNED(source->port); + for(int j=0; j<nsamples; j++) + val[j] += src[j]; } } - } else if( (port->type == PORT_TYPE_ATOM) && (port->buffer_type == PORT_BUFFER_TYPE_SEQUENCE) ) @@ -2281,7 +2344,7 @@ sp_app_run_post(sp_app_t *app, uint32_t nsamples) LV2_Atom_Event *itr [32]; //TODO how big? for(int i=0; i<port->num_sources; i++) { - seq[i] = PORT_BUF_ALIGNED(port->sources[i]); + seq[i] = PORT_BUF_ALIGNED(port->sources[i].port); itr[i] = lv2_atom_sequence_begin(&seq[i]->body); } @@ -2328,8 +2391,8 @@ sp_app_run_post(sp_app_t *app, uint32_t nsamples) } else if( (port->num_sources + port->num_feedbacks) == 1) // move messages from UI on default buffer { - if( (port->type == PORT_TYPE_ATOM) - && (port->buffer_type == PORT_BUFFER_TYPE_SEQUENCE) ) + if( (port->type == PORT_TYPE_ATOM) + && (port->buffer_type == PORT_BUFFER_TYPE_SEQUENCE) ) { const LV2_Atom_Sequence *seq = PORT_BUF_ALIGNED(port); if(seq->atom.size <= sizeof(LV2_Atom_Sequence_Body)) // no messages from UI @@ -2341,8 +2404,8 @@ sp_app_run_post(sp_app_t *app, uint32_t nsamples) LV2_Atom_Forge *forge = &app->forge; LV2_Atom_Forge_Frame frame; LV2_Atom_Forge_Ref ref; - ref = _lv2_atom_forge_sequence_append(forge, &frame, port->sources[0]->buf, - port->sources[0]->size); + ref = _lv2_atom_forge_sequence_append(forge, &frame, port->sources[0].port->buf, + port->sources[0].port->size); LV2_ATOM_SEQUENCE_FOREACH(seq, ev) { @@ -2360,6 +2423,19 @@ sp_app_run_post(sp_app_t *app, uint32_t nsamples) if(ref) lv2_atom_forge_pop(forge, &frame); } + else if(port->type == PORT_TYPE_AUDIO) + { + source_t *source = &port->sources[0]; + + if(source->ramp.state != RAMP_STATE_NONE) + { + float *src = PORT_BUF_ALIGNED(source->port); + for(int j=0; j<nsamples; j++) + src[j] *= source->ramp.value; + + _update_ramp(app, source, port, nsamples); + } + } } } @@ -2402,31 +2478,6 @@ sp_app_run_post(sp_app_t *app, uint32_t nsamples) { port_t *port = &mod->ports[i]; - // ramp audio output ports - if(port->ramp.state != RAMP_STATE_NONE) - { - float *buf = PORT_SINK_ALIGNED(port); - - // scale audio amplitude with ramp value - for(int s=0; s<nsamples; s++) - buf[s] *= port->ramp.value; - - // update ramp properties - port->ramp.samples -= nsamples; // update remaining samples to ramp over - if(port->ramp.samples <= 0) - { - if(port->ramp.state == RAMP_STATE_DOWN) - ; //FIXME call callback, e.g. disconnect, free - port->ramp.state = RAMP_STATE_NONE; // ramp is complete - } - else - { - port->ramp.value = (float)port->ramp.samples / (float)app->ramp_samples; - if(port->ramp.state == RAMP_STATE_UP) - port->ramp.value = 1.f - port->ramp.value; - } - } - // no notification/subscription and no support for patch:Message int subscribed = port->subscriptions != 0; int patchable = port->patchable && (port->direction == PORT_DIRECTION_OUTPUT); @@ -2758,7 +2809,7 @@ sp_app_save(sp_app_t *app, LV2_State_Store_Function store, cJSON *port_sources_json = cJSON_CreateArray(); for(int j=0; j<port->num_sources; j++) { - port_t *source = port->sources[j]; + port_t *source = port->sources[j].port; cJSON *conn_json = cJSON_CreateObject(); |