#include #include #include #include #include "lv2_event.h" #include "lv2_event_helpers.h" #include "lv2_uri_map.h" #include "osc.h" #include "filter.h" #include "voice.h" #include "engine.h" #include "psyn.h" double _sample_rate; struct psyn_t { LV2_Event_Buffer *events; LV2_Event_Feature *event_ref; int midi_event_id; float *out_l; float *out_r; struct engine_t eng; }; static void psyn_init(struct psyn_t *psyn, uint32_t sample_rate) { _sample_rate = sample_rate; engine_init(); } static LV2_Handle instantiate( const LV2_Descriptor *descriptor, double sample_rate, const char *bundle_path, const LV2_Feature * const *host_features) { struct psyn_t *psyn; LV2_URI_Map_Feature *map_feature; int i; psyn = malloc(sizeof *psyn); memset(psyn, 0, sizeof *psyn); psyn_init(psyn, sample_rate); for (i = 0; host_features[i]; i++) { if (!strcmp(host_features[i]->URI, "http://lv2plug.in/ns/ext/uri-map")) { map_feature = host_features[i]->data; psyn->midi_event_id = map_feature->uri_to_id(map_feature->callback_data, "http://lv2plug.in/ns/ext/event", "http://lv2plug.in/ns/ext/midi#MidiEvent"); } else if (!strcmp(host_features[i]->URI, "http://lv2plug.in/ns/ext/event")) { psyn->event_ref = host_features[i]->data; } } if (psyn->midi_event_id == 0 || psyn->event_ref == NULL) { printf("psyn instantiate failed, leaving\n"); return NULL; } return (LV2_Handle)psyn; } static void connect_port(LV2_Handle lv2instance, uint32_t port, void *data) { struct psyn_t *psyn = (struct psyn_t *)lv2instance; switch (port) { case 0: psyn->events = data; break; case 1: psyn->out_l = data; break; case 2: psyn->out_r = data; break; } } static void cleanup(LV2_Handle lv2instance) { struct psyn_t *psyn = (struct psyn_t *)lv2instance; free(psyn); } static void run(LV2_Handle lv2instance, uint32_t sample_count) { struct psyn_t *psyn = (struct psyn_t *)lv2instance; uint32_t frame = 0; LV2_Event *ev = NULL; LV2_Event_Iterator iterator; lv2_event_begin(&iterator, psyn->events); if (lv2_event_is_valid(&iterator)) ev = lv2_event_get(&iterator, NULL); while (frame < sample_count) { uint32_t to; if (ev != NULL) { to = ev->frames; } else { to = sample_count; } engine_run(&psyn->eng, to - frame, psyn->out_l + frame, psyn->out_r + frame); frame = to; if (ev != NULL) { if (ev->type == 0) { psyn->event_ref->lv2_event_unref(psyn->event_ref->callback_data, ev); } else if (ev->type == psyn->midi_event_id && ev->size == 3) { uint8_t *data = (uint8_t *)(ev + 1); switch (data[0] & 0xF0) { case 0x80: engine_endvoice(&psyn->eng, data[1], data[2]); break; case 0x90: engine_startvoice(&psyn->eng, data[1], data[2]); break; } } lv2_event_increment(&iterator); if (lv2_event_is_valid(&iterator)) { ev = lv2_event_get(&iterator, NULL); } else { ev = NULL; } } } } static LV2_Descriptor g_lv2descriptor = { .URI = "http://fuzzle.org/~petern/psyn/1", .instantiate = &instantiate, .connect_port = &connect_port, .run = &run, .cleanup = &cleanup, }; const LV2_Descriptor *lv2_descriptor(uint32_t index) { if (index == 0) { return &g_lv2descriptor; } return NULL; }