diff options
author | Hanspeter Portner <dev@open-music-kontrollers.ch> | 2017-03-22 22:55:23 +0100 |
---|---|---|
committer | Hanspeter Portner <dev@open-music-kontrollers.ch> | 2017-03-22 22:55:23 +0100 |
commit | ce87996f72f3a3eb294e2f8458434cb437235dad (patch) | |
tree | 03ac85809a3d279b5380dac8996a04b11695c5f8 | |
parent | d405ab264332903f908a5668bb95cf05cc43e8c7 (diff) | |
download | vm.lv2-ce87996f72f3a3eb294e2f8458434cb437235dad.tar.xz |
prototype vm:atom plugin.
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | manifest.ttl.in | 8 | ||||
-rw-r--r-- | vm.c | 198 | ||||
-rw-r--r-- | vm.ttl | 231 | ||||
-rw-r--r-- | vm_ui.ttl | 5 |
5 files changed, 404 insertions, 40 deletions
@@ -1 +1 @@ -0.1.2879 +0.1.2881 diff --git a/manifest.ttl.in b/manifest.ttl.in index 2c96c8f..fd51fa9 100644 --- a/manifest.ttl.in +++ b/manifest.ttl.in @@ -43,6 +43,14 @@ vm:audio ui:ui vm:vm_ui ; rdfs:seeAlso <vm.ttl> . +vm:atom + a lv2:Plugin ; + lv2:minorVersion @VM_MINOR_VERSION@ ; + lv2:microVersion @VM_MICRO_VERSION@ ; + lv2:binary <vm@CMAKE_SHARED_MODULE_SUFFIX@> ; + ui:ui vm:vm_ui ; + rdfs:seeAlso <vm.ttl> . + vm:vm_ui a ui:@VM_UI_TYPE@ ; ui:binary <vm_ui@CMAKE_SHARED_MODULE_SUFFIX@> ; @@ -28,11 +28,23 @@ #define REG_MAX 0x20 #define REG_MASK (REG_MAX - 1) +typedef union _vm_port_t vm_port_t; +typedef union _vm_const_port_t vm_const_port_t; typedef struct _vm_stack_t vm_stack_t; typedef struct _plughandle_t plughandle_t; typedef double num_t; +union _vm_port_t { + float *flt; + LV2_Atom_Sequence *seq; +}; + +union _vm_const_port_t { + const float *flt; + const LV2_Atom_Sequence *seq; +}; + struct _vm_stack_t { num_t slots [SLOT_MAX]; num_t regs [REG_MAX]; @@ -51,8 +63,8 @@ struct _plughandle_t { const LV2_Atom_Sequence *control; LV2_Atom_Sequence *notify; - const float *in [CTRL_MAX]; - float *out [CTRL_MAX]; + vm_const_port_t in [CTRL_MAX]; + vm_port_t out [CTRL_MAX]; num_t in0 [CTRL_MAX]; num_t out0 [CTRL_MAX]; @@ -244,7 +256,7 @@ connect_port(LV2_Handle instance, uint32_t port, void *data) case 7: case 8: case 9: - handle->in[port - 2] = data; + handle->in[port - 2].flt = data; break; case 10: case 11: @@ -254,7 +266,7 @@ connect_port(LV2_Handle instance, uint32_t port, void *data) case 15: case 16: case 17: - handle->out[port - 10] = data; + handle->out[port - 10].flt = data; break; } } @@ -871,25 +883,25 @@ run_control(LV2_Handle instance, uint32_t nsamples) { const float *in [CTRL_MAX ] = { - handle->in[0], - handle->in[1], - handle->in[2], - handle->in[3], - handle->in[4], - handle->in[5], - handle->in[6], - handle->in[7] + handle->in[0].flt, + handle->in[1].flt, + handle->in[2].flt, + handle->in[3].flt, + handle->in[4].flt, + handle->in[5].flt, + handle->in[6].flt, + handle->in[7].flt }; float *out [CTRL_MAX ] = { - handle->out[0], - handle->out[1], - handle->out[2], - handle->out[3], - handle->out[4], - handle->out[5], - handle->out[6], - handle->out[7] + handle->out[0].flt, + handle->out[1].flt, + handle->out[2].flt, + handle->out[3].flt, + handle->out[4].flt, + handle->out[5].flt, + handle->out[6].flt, + handle->out[7].flt }; const bool notify = true; @@ -910,7 +922,7 @@ run_control(LV2_Handle instance, uint32_t nsamples) } static void -run_cv(LV2_Handle instance, uint32_t nsamples) +run_cv_audio(LV2_Handle instance, uint32_t nsamples) { plughandle_t *handle = instance; @@ -938,28 +950,29 @@ run_cv(LV2_Handle instance, uint32_t nsamples) handle->needs_sync = false; } + //FIXME needs to be muxed with control for(unsigned i = 0; i < nsamples; i++) { const float *in [CTRL_MAX ] = { - &handle->in[0][i], - &handle->in[1][i], - &handle->in[2][i], - &handle->in[3][i], - &handle->in[4][i], - &handle->in[5][i], - &handle->in[6][i], - &handle->in[7][i] + &handle->in[0].flt[i], + &handle->in[1].flt[i], + &handle->in[2].flt[i], + &handle->in[3].flt[i], + &handle->in[4].flt[i], + &handle->in[5].flt[i], + &handle->in[6].flt[i], + &handle->in[7].flt[i] }; float *out [CTRL_MAX ] = { - &handle->out[0][i], - &handle->out[1][i], - &handle->out[2][i], - &handle->out[3][i], - &handle->out[4][i], - &handle->out[5][i], - &handle->out[6][i], - &handle->out[7][i] + &handle->out[0].flt[i], + &handle->out[1].flt[i], + &handle->out[2].flt[i], + &handle->out[3].flt[i], + &handle->out[4].flt[i], + &handle->out[5].flt[i], + &handle->out[6].flt[i], + &handle->out[7].flt[i] }; const bool notify = (i == 0); @@ -980,6 +993,100 @@ run_cv(LV2_Handle instance, uint32_t nsamples) } static void +run_atom(LV2_Handle instance, uint32_t nsamples) +{ + plughandle_t *handle = instance; + + const uint32_t capacity = handle->notify->atom.size; + LV2_Atom_Forge_Frame frame; + lv2_atom_forge_set_buffer(&handle->forge, (uint8_t *)handle->notify, capacity); + handle->ref = lv2_atom_forge_sequence_head(&handle->forge, &frame, 0); + + int64_t last_t = 0; + LV2_ATOM_SEQUENCE_FOREACH(handle->control, ev) + { + const LV2_Atom *atom= &ev->body; + const LV2_Atom_Object *obj = (const LV2_Atom_Object *)&ev->body; + + if(!timely_advance(&handle->timely, obj, last_t, ev->time.frames)) + props_advance(&handle->props, &handle->forge, ev->time.frames, obj, &handle->ref); + + last_t = ev->time.frames; + } + timely_advance(&handle->timely, NULL, last_t, nsamples); + + if(handle->needs_sync) + { + props_set(&handle->props, &handle->forge, nsamples - 1, handle->vm_graph, &handle->ref); + handle->needs_sync = false; + } + + float pin [CTRL_MAX]; + float pout [CTRL_MAX]; + + for(unsigned i = 0; i < CTRL_MAX; i++) + { + pin[i] = handle->in0[i]; + pout[i] = handle->out0[i]; + } + + const float *in [CTRL_MAX ] = { + &pin[0], + &pin[1], + &pin[2], + &pin[3], + &pin[4], + &pin[5], + &pin[6], + &pin[7] + }; + + float *out [CTRL_MAX ] = { + &pout[0], + &pout[1], + &pout[2], + &pout[3], + &pout[4], + &pout[5], + &pout[6], + &pout[7] + }; + + //FIXME needs to be muxed with control + for(unsigned i = 0; i < CTRL_MAX; i++) + { + LV2_ATOM_SEQUENCE_FOREACH(handle->in[i].seq, ev) + { + const LV2_Atom_Float *f32 = (const LV2_Atom_Float *)&ev->body; + + //printf("got atom:Float: %u %f\n", i, f32->body); + + if(f32->atom.type == handle->forge.Float) + { + pin[i] = f32->body; + + const bool notify = true; //FIXME + run_internal(handle, nsamples - 1, notify, in, out); //FIXME use ev.time.frames + + //FIXME send floats to output sequences + } + } + } + + if(handle->ref) + handle->ref = lv2_atom_forge_frame_time(&handle->forge, nsamples - 1); + if(handle->ref) + handle->ref = lv2_atom_forge_long(&handle->forge, handle->off); + + if(handle->ref) + lv2_atom_forge_pop(&handle->forge, &frame); + else + lv2_atom_sequence_clear(handle->notify); + + handle->off += nsamples; +} + +static void cleanup(LV2_Handle instance) { plughandle_t *handle = instance; @@ -1060,7 +1167,7 @@ static const LV2_Descriptor vm_cv = { .instantiate = instantiate, .connect_port = connect_port, .activate = NULL, - .run = run_cv, + .run = run_cv_audio, .deactivate = NULL, .cleanup = cleanup, .extension_data = extension_data @@ -1071,7 +1178,18 @@ static const LV2_Descriptor vm_audio = { .instantiate = instantiate, .connect_port = connect_port, .activate = NULL, - .run = run_cv, + .run = run_cv_audio, + .deactivate = NULL, + .cleanup = cleanup, + .extension_data = extension_data +}; + +static const LV2_Descriptor vm_atom = { + .URI = VM_PREFIX"atom", + .instantiate = instantiate, + .connect_port = connect_port, + .activate = NULL, + .run = run_atom, .deactivate = NULL, .cleanup = cleanup, .extension_data = extension_data @@ -1088,6 +1206,8 @@ lv2_descriptor(uint32_t index) return &vm_cv; case 2: return &vm_audio; + case 3: + return &vm_atom; default: return NULL; @@ -757,10 +757,232 @@ vm:audio ] ] . +# Plugin +vm:atom + a lv2:Plugin, + lv2:ConverterPlugin ; + doap:name "VM Atom" ; + doap:license lic:Artistic-2.0 ; + lv2:project proj:vm ; + lv2:requiredFeature urid:map, work:schedule, state:loadDefaultState ; + lv2:optionalFeature lv2:isLive, lv2:hardRTCapable, log:log, state:threadSafeRestore ; + lv2:extensionData state:interface, work:interface ; + + lv2:port [ + a lv2:InputPort , + atom:AtomPort ; + atom:bufferType atom:Sequence ; + atom:supports time:Position , + patch:Message ; + lv2:index 0 ; + lv2:symbol "control" ; + lv2:name "Control" ; + lv2:designation lv2:control ; + rsz:minimumSize 8192 ; + ] , [ + a lv2:OutputPort , + atom:AtomPort ; + atom:bufferType atom:Sequence ; + atom:supports patch:Message ; + lv2:index 1 ; + lv2:symbol "notify" ; + lv2:name "Notify" ; + lv2:designation lv2:control ; + rsz:minimumSize 8192 ; + ] , [ + a lv2:InputPort, + atom:AtomPort; + atom:bufferType atom:Sequence ; + atom:supports atom:Float ; + lv2:index 2 ; + lv2:symbol "event_in_0" ; + lv2:name "Event In 0" ; + lv2:minimum -1.0; + lv2:maximum 1.0; + lv2:default 0.0; + ] , [ + a lv2:InputPort, + atom:AtomPort; + atom:bufferType atom:Sequence ; + atom:supports atom:Float ; + lv2:index 3 ; + lv2:symbol "event_in_1" ; + lv2:name "Event In 1" ; + lv2:minimum -1.0; + lv2:maximum 1.0; + lv2:default 0.0; + ] , [ + a lv2:InputPort, + atom:AtomPort; + atom:bufferType atom:Sequence ; + atom:supports atom:Float ; + lv2:index 4 ; + lv2:symbol "event_in_2" ; + lv2:name "Event In 2" ; + lv2:minimum -1.0; + lv2:maximum 1.0; + lv2:default 0.0; + ] , [ + a lv2:InputPort, + atom:AtomPort; + atom:bufferType atom:Sequence ; + atom:supports atom:Float ; + lv2:index 5 ; + lv2:symbol "event_in_3" ; + lv2:name "Event In 3" ; + lv2:minimum -1.0; + lv2:maximum 1.0; + lv2:default 0.0; + ] , [ + a lv2:InputPort, + atom:AtomPort; + atom:bufferType atom:Sequence ; + atom:supports atom:Float ; + lv2:index 6 ; + lv2:symbol "event_in_4" ; + lv2:name "Event In 4" ; + lv2:minimum -1.0; + lv2:maximum 1.0; + lv2:default 0.0; + ] , [ + a lv2:InputPort, + atom:AtomPort; + atom:bufferType atom:Sequence ; + atom:supports atom:Float ; + lv2:index 7 ; + lv2:symbol "event_in_5" ; + lv2:name "Event In 5" ; + lv2:minimum -1.0; + lv2:maximum 1.0; + lv2:default 0.0; + ] , [ + a lv2:InputPort, + atom:AtomPort; + atom:bufferType atom:Sequence ; + atom:supports atom:Float ; + lv2:index 8 ; + lv2:symbol "event_in_6" ; + lv2:name "Event In 6" ; + lv2:minimum -1.0; + lv2:maximum 1.0; + lv2:default 0.0; + ] , [ + a lv2:InputPort, + atom:AtomPort; + atom:bufferType atom:Sequence ; + atom:supports atom:Float ; + lv2:index 9 ; + lv2:symbol "event_in_7" ; + lv2:name "Event In 7" ; + lv2:minimum -1.0; + lv2:maximum 1.0; + lv2:default 0.0; + ] , [ + a lv2:OutputPort, + atom:AtomPort; + atom:bufferType atom:Sequence ; + atom:supports atom:Float ; + lv2:index 10 ; + lv2:symbol "event_out_0" ; + lv2:name "Event Out 0" ; + lv2:minimum -1.0; + lv2:maximum 1.0; + ] , [ + a lv2:OutputPort, + atom:AtomPort; + atom:bufferType atom:Sequence ; + atom:supports atom:Float ; + lv2:index 11 ; + lv2:symbol "event_out_1" ; + lv2:name "Event Out 1" ; + lv2:minimum -1.0; + lv2:maximum 1.0; + ] , [ + a lv2:OutputPort, + atom:AtomPort; + atom:bufferType atom:Sequence ; + atom:supports atom:Float ; + lv2:index 12 ; + lv2:symbol "event_out_2" ; + lv2:name "Event Out 2" ; + lv2:minimum -1.0; + lv2:maximum 1.0; + ] , [ + a lv2:OutputPort, + atom:AtomPort; + atom:bufferType atom:Sequence ; + atom:supports atom:Float ; + lv2:index 13 ; + lv2:symbol "event_out_3" ; + lv2:name "Event Out 3" ; + lv2:minimum -1.0; + lv2:maximum 1.0; + ] , [ + a lv2:OutputPort, + atom:AtomPort; + atom:bufferType atom:Sequence ; + atom:supports atom:Float ; + lv2:index 14 ; + lv2:symbol "event_out_4" ; + lv2:name "Event Out 4" ; + lv2:minimum -1.0; + lv2:maximum 1.0; + ] , [ + a lv2:OutputPort, + atom:AtomPort; + atom:bufferType atom:Sequence ; + atom:supports atom:Float ; + lv2:index 15 ; + lv2:symbol "event_out_5" ; + lv2:name "Event Out 5" ; + lv2:minimum -1.0; + lv2:maximum 1.0; + ] , [ + a lv2:OutputPort, + atom:AtomPort; + atom:bufferType atom:Sequence ; + atom:supports atom:Float ; + lv2:index 16 ; + lv2:symbol "event_out_6" ; + lv2:name "Event Out 6" ; + lv2:minimum -1.0; + lv2:maximum 1.0; + ] , [ + a lv2:OutputPort, + atom:AtomPort; + atom:bufferType atom:Sequence ; + atom:supports atom:Float ; + lv2:index 17 ; + lv2:symbol "event_out_7" ; + lv2:name "Event Out 7" ; + lv2:minimum -1.0; + lv2:maximum 1.0; + ] ; + + #patch:writable + # vm:graph ; + + state:state [ + vm:graph [ + a atom:Tuple ; + rdf:value ( + 7 vm:opInput + 6 vm:opInput + 5 vm:opInput + 4 vm:opInput + 3 vm:opInput + 2 vm:opInput + 1 vm:opInput + 0 vm:opInput + ) + ] + ] . + vm:add a pset:Preset ; lv2:appliesTo vm:control , vm:cv , + vm:atom , vm:audio ; rdfs:label "Add" ; state:state [ @@ -778,6 +1000,7 @@ vm:sub a pset:Preset ; lv2:appliesTo vm:control , vm:cv , + vm:atom , vm:audio ; rdfs:label "Subtract" ; state:state [ @@ -795,6 +1018,7 @@ vm:mul a pset:Preset ; lv2:appliesTo vm:control , vm:cv , + vm:atom , vm:audio ; rdfs:label "Multiply" ; state:state [ @@ -812,6 +1036,7 @@ vm:div a pset:Preset ; lv2:appliesTo vm:control , vm:cv , + vm:atom , vm:audio ; rdfs:label "Divide" ; state:state [ @@ -829,6 +1054,7 @@ vm:mod a pset:Preset ; lv2:appliesTo vm:control , vm:cv , + vm:atom , vm:audio ; rdfs:label "Modulo" ; state:state [ @@ -846,6 +1072,7 @@ vm:pow a pset:Preset ; lv2:appliesTo vm:control , vm:cv , + vm:atom , vm:audio ; rdfs:label "Power" ; state:state [ @@ -863,6 +1090,7 @@ vm:dBFS a pset:Preset ; lv2:appliesTo vm:control , vm:cv , + vm:atom , vm:audio ; rdfs:label "dBFS" ; lv2:port [ @@ -887,6 +1115,7 @@ vm:rand a pset:Preset ; lv2:appliesTo vm:control , vm:cv , + vm:atom , vm:audio ; rdfs:label "Random" ; state:state [ @@ -909,6 +1138,7 @@ vm:sampleAndHold a pset:Preset ; lv2:appliesTo vm:control , vm:cv , + vm:atom , vm:audio ; rdfs:label "Sample and hold" ; state:state [ @@ -930,6 +1160,7 @@ vm:lfo a pset:Preset ; lv2:appliesTo vm:control , vm:cv , + vm:atom , vm:audio ; rdfs:label "LFO" ; state:state [ @@ -37,6 +37,11 @@ vm:vm_ui lv2:symbol "notify" ; ui:protocol atom:eventTransfer ] ; + ui:portNotification [ + ui:plugin vm:atom ; + lv2:symbol "notify" ; + ui:protocol atom:eventTransfer + ] ; lv2:requiredFeature ui:idleInterface, urid:map, urid:unmap ; lv2:optionalFeature log:log ; lv2:extensionData ui:idleInterface . |