1 /*
2  * Copyright (c) 2015-2017 Hanspeter Portner (dev@open-music-kontrollers.ch)
3  *
4  * This is free software: you can redistribute it and/or modify
5  * it under the terms of the Artistic License 2.0 as published by
6  * The Perl Foundation.
7  *
8  * This source is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * Artistic License 2.0 for more details.
12  *
13  * You should have received a copy of the Artistic License 2.0
14  * along the source as a COPYING file. If not, obtain it from
15  * http://www.perlfoundation.org/artistic_license_2_0.
16  */
17 
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <math.h>
21 
22 #include <espressivo.h>
23 #include <props.h>
24 
25 #define MAX_NPROPS (4*0x10)
26 
27 typedef struct _targetO_t targetO_t;
28 typedef struct _plugstate_t plugstate_t;
29 typedef struct _plughandle_t plughandle_t;
30 
31 typedef enum _pressure_mode_t
32 {
33 	MODE_CONTROLLER       = 0,
34 	MODE_NOTE_PRESSURE    = 1,
35 	MODE_CHANNEL_PRESSURE = 2,
36 	MODE_NOTE_VELOCITY    = 3
37 } pressure_mode_t;
38 
39 struct _targetO_t {
40 	uint8_t chan;
41 	uint8_t key;
42 	xpress_uuid_t uuid;
43 
44 	xpress_state_t state;
45 
46 	float range;
47 	uint8_t pressure;
48 	uint8_t timbre;
49 	pressure_mode_t mode;
50 
51 	uint8_t pressure_lsb;
52 	uint8_t timbre_lsb;
53 };
54 
55 struct _plugstate_t {
56 	float range [0x10];
57 	int32_t pressure [0x10];
58 	int32_t timbre [0x10];
59 	int32_t mode [0x10];
60 };
61 
62 struct _plughandle_t {
63 	LV2_URID_Map *map;
64 	struct {
65 		LV2_URID midi_MidiEvent;
66 		LV2_URID range [0x10];
67 	} uris;
68 	LV2_Atom_Forge forge;
69 	LV2_Atom_Forge_Ref ref;
70 
71 	const LV2_Atom_Sequence *control;
72 	LV2_Atom_Sequence *notify;
73 
74 	PROPS_T(props, MAX_NPROPS);
75 
76 	XPRESS_T(xpressO, MAX_NVOICES);
77 	targetO_t targetO [MAX_NVOICES];
78 
79 	plugstate_t state;
80 	plugstate_t stash;
81 
82 	uint16_t midi_rpn [0x10];
83 	uint16_t midi_data [0x10];
84 	int16_t midi_bender [0x10];
85 };
86 
87 static const targetO_t targetO_vanilla;
88 
89 static inline float
_get_pitch(plughandle_t * handle,targetO_t * target)90 _get_pitch(plughandle_t *handle, targetO_t *target)
91 {
92 	const float offset = handle->midi_bender[target->chan] / 0x1fff * target->range;
93 
94 	return ((float)target->key + offset) / 0x7f;
95 }
96 
97 #define RANGE(NUM) \
98 { \
99 	.property = ESPRESSIVO_URI"#midi_range_"#NUM, \
100 	.offset = offsetof(plugstate_t, range) + (NUM-1)*sizeof(float), \
101 	.type = LV2_ATOM__Float, \
102 }
103 
104 #define PRESSURE(NUM) \
105 { \
106 	.property = ESPRESSIVO_URI"#midi_pressure_controller_"#NUM, \
107 	.offset = offsetof(plugstate_t, pressure) + (NUM-1)*sizeof(int32_t), \
108 	.type = LV2_ATOM__Int, \
109 }
110 
111 #define TIMBRE(NUM) \
112 { \
113 	.property = ESPRESSIVO_URI"#midi_timbre_controller_"#NUM, \
114 	.offset = offsetof(plugstate_t, timbre) + (NUM-1)*sizeof(int32_t), \
115 	.type = LV2_ATOM__Int, \
116 }
117 
118 #define MODE(NUM) \
119 { \
120 	.property = ESPRESSIVO_URI"#midi_pressure_mode_"#NUM, \
121 	.offset = offsetof(plugstate_t, mode) + (NUM-1)*sizeof(int32_t), \
122 	.type = LV2_ATOM__Int, \
123 }
124 
125 static const props_def_t defs [MAX_NPROPS] = {
126 	RANGE(1),
127 	RANGE(2),
128 	RANGE(3),
129 	RANGE(4),
130 	RANGE(5),
131 	RANGE(6),
132 	RANGE(7),
133 	RANGE(8),
134 	RANGE(9),
135 	RANGE(10),
136 	RANGE(11),
137 	RANGE(12),
138 	RANGE(13),
139 	RANGE(14),
140 	RANGE(15),
141 	RANGE(16),
142 
143 	PRESSURE(1),
144 	PRESSURE(2),
145 	PRESSURE(3),
146 	PRESSURE(4),
147 	PRESSURE(5),
148 	PRESSURE(6),
149 	PRESSURE(7),
150 	PRESSURE(8),
151 	PRESSURE(9),
152 	PRESSURE(10),
153 	PRESSURE(11),
154 	PRESSURE(12),
155 	PRESSURE(13),
156 	PRESSURE(14),
157 	PRESSURE(15),
158 	PRESSURE(16),
159 
160 	TIMBRE(1),
161 	TIMBRE(2),
162 	TIMBRE(3),
163 	TIMBRE(4),
164 	TIMBRE(5),
165 	TIMBRE(6),
166 	TIMBRE(7),
167 	TIMBRE(8),
168 	TIMBRE(9),
169 	TIMBRE(10),
170 	TIMBRE(11),
171 	TIMBRE(12),
172 	TIMBRE(13),
173 	TIMBRE(14),
174 	TIMBRE(15),
175 	TIMBRE(16),
176 
177 	MODE(1),
178 	MODE(2),
179 	MODE(3),
180 	MODE(4),
181 	MODE(5),
182 	MODE(6),
183 	MODE(7),
184 	MODE(8),
185 	MODE(9),
186 	MODE(10),
187 	MODE(11),
188 	MODE(12),
189 	MODE(13),
190 	MODE(14),
191 	MODE(15),
192 	MODE(16)
193 };
194 
195 static const xpress_iface_t ifaceO = {
196 	.size = sizeof(targetO_t)
197 };
198 
199 static LV2_Handle
instantiate(const LV2_Descriptor * descriptor,double rate,const char * bundle_path,const LV2_Feature * const * features)200 instantiate(const LV2_Descriptor* descriptor, double rate,
201 	const char *bundle_path, const LV2_Feature *const *features)
202 {
203 	plughandle_t *handle = calloc(1, sizeof(plughandle_t));
204 	if(!handle)
205 		return NULL;
206 
207 	xpress_map_t *voice_map = NULL;
208 
209 	for(unsigned i=0; features[i]; i++)
210 	{
211 		if(!strcmp(features[i]->URI, LV2_URID__map))
212 			handle->map = features[i]->data;
213 		else if(!strcmp(features[i]->URI, ESPRESSIVO_URI"#voiceMap"))
214 			voice_map = features[i]->data;
215 	}
216 
217 	if(!handle->map)
218 	{
219 		fprintf(stderr, "%s: Host does not support urid:map\n", descriptor->URI);
220 		free(handle);
221 		return NULL;
222 	}
223 
224 	handle->uris.midi_MidiEvent = handle->map->map(handle->map->handle, LV2_MIDI__MidiEvent);
225 	handle->uris.range[0x0] = handle->map->map(handle->map->handle, ESPRESSIVO_URI"#midi_range_1");
226 	handle->uris.range[0x1] = handle->map->map(handle->map->handle, ESPRESSIVO_URI"#midi_range_2");
227 	handle->uris.range[0x2] = handle->map->map(handle->map->handle, ESPRESSIVO_URI"#midi_range_3");
228 	handle->uris.range[0x3] = handle->map->map(handle->map->handle, ESPRESSIVO_URI"#midi_range_4");
229 	handle->uris.range[0x4] = handle->map->map(handle->map->handle, ESPRESSIVO_URI"#midi_range_5");
230 	handle->uris.range[0x5] = handle->map->map(handle->map->handle, ESPRESSIVO_URI"#midi_range_6");
231 	handle->uris.range[0x6] = handle->map->map(handle->map->handle, ESPRESSIVO_URI"#midi_range_7");
232 	handle->uris.range[0x7] = handle->map->map(handle->map->handle, ESPRESSIVO_URI"#midi_range_8");
233 	handle->uris.range[0x8] = handle->map->map(handle->map->handle, ESPRESSIVO_URI"#midi_range_9");
234 	handle->uris.range[0x9] = handle->map->map(handle->map->handle, ESPRESSIVO_URI"#midi_range_10");
235 	handle->uris.range[0xa] = handle->map->map(handle->map->handle, ESPRESSIVO_URI"#midi_range_11");
236 	handle->uris.range[0xb] = handle->map->map(handle->map->handle, ESPRESSIVO_URI"#midi_range_12");
237 	handle->uris.range[0xc] = handle->map->map(handle->map->handle, ESPRESSIVO_URI"#midi_range_13");
238 	handle->uris.range[0xd] = handle->map->map(handle->map->handle, ESPRESSIVO_URI"#midi_range_14");
239 	handle->uris.range[0xe] = handle->map->map(handle->map->handle, ESPRESSIVO_URI"#midi_range_15");
240 	handle->uris.range[0xf] = handle->map->map(handle->map->handle, ESPRESSIVO_URI"#midi_range_16");
241 
242 	lv2_atom_forge_init(&handle->forge, handle->map);
243 
244 	if(  !xpress_init(&handle->xpressO, MAX_NVOICES, handle->map, voice_map,
245 			XPRESS_EVENT_NONE, &ifaceO, handle->targetO, handle) )
246 	{
247 		free(handle);
248 		return NULL;
249 	}
250 
251 	if(!props_init(&handle->props, descriptor->URI,
252 		defs, MAX_NPROPS, &handle->state, &handle->stash,
253 		handle->map, handle))
254 	{
255 		fprintf(stderr, "failed to allocate property structure\n");
256 		free(handle);
257 		return NULL;
258 	}
259 
260 	return handle;
261 }
262 
263 static void
connect_port(LV2_Handle instance,uint32_t port,void * data)264 connect_port(LV2_Handle instance, uint32_t port, void *data)
265 {
266 	plughandle_t *handle = instance;
267 
268 	switch(port)
269 	{
270 		case 0:
271 			handle->control = (const LV2_Atom_Sequence *)data;
272 			break;
273 		case 1:
274 			handle->notify = (LV2_Atom_Sequence *)data;
275 			break;
276 		default:
277 			break;
278 	}
279 }
280 
281 static targetO_t *
_midi_get(plughandle_t * handle,uint8_t chan,uint8_t key,xpress_uuid_t * uuid)282 _midi_get(plughandle_t *handle, uint8_t chan, uint8_t key, xpress_uuid_t *uuid)
283 {
284 	XPRESS_VOICE_FOREACH(&handle->xpressO, voice)
285 	{
286 		targetO_t *dst = voice->target;
287 
288 		if( (dst->chan == chan) && (dst->key == key) )
289 		{
290 			*uuid = voice->uuid;
291 			return dst;
292 		}
293 	}
294 
295 	*uuid = 0;
296 	return NULL;
297 }
298 
299 static void
_handle_midi_note_on(plughandle_t * handle,LV2_Atom_Forge * forge,int64_t frames,const uint8_t * m)300 _handle_midi_note_on(plughandle_t *handle, LV2_Atom_Forge *forge, int64_t frames,
301 	const uint8_t *m)
302 {
303 	const uint8_t chan = m[0] & 0x0f;
304 	const uint8_t key = m[1];
305 
306 	xpress_uuid_t uuid;
307 	targetO_t *target = xpress_create(&handle->xpressO, &uuid);
308 	if(target)
309 	{
310 		*target = targetO_vanilla;
311 
312 		// these will remain fixed per note
313 		target->chan = chan;
314 		target->key = key;
315 		target->uuid = uuid;
316 		target->range = handle->state.range[chan];
317 		target->mode = handle->state.mode[chan];
318 		target->pressure = handle->state.pressure[chan];
319 		target->timbre = handle->state.timbre[chan];
320 
321 		const float pressure = (target->mode == MODE_NOTE_VELOCITY)
322 			? (float)m[2] / 0x7f
323 			: 0.f; //FIXME make this configurable
324 
325 		target->state.zone = chan;
326 		target->state.pitch = _get_pitch(handle, target);
327 		target->state.pressure = pressure;
328 
329 		if(handle->ref)
330 			handle->ref = xpress_token(&handle->xpressO, forge, frames, target->uuid, &target->state);
331 	}
332 }
333 
334 static void
_handle_midi_note_off(plughandle_t * handle,LV2_Atom_Forge * forge,int64_t frames,const uint8_t * m)335 _handle_midi_note_off(plughandle_t *handle, LV2_Atom_Forge *forge, int64_t frames,
336 	const uint8_t *m)
337 {
338 	const uint8_t chan = m[0] & 0x0f;
339 	const uint8_t key = m[1];
340 
341 	xpress_uuid_t uuid;
342 	targetO_t *target = _midi_get(handle, chan, key, &uuid);
343 	if(target)
344 	{
345 		xpress_free(&handle->xpressO, uuid);
346 
347 		if(handle->ref)
348 			handle->ref = xpress_alive(&handle->xpressO, forge, frames);
349 	}
350 }
351 
352 static void
_handle_midi_note_pressure(plughandle_t * handle,LV2_Atom_Forge * forge,int64_t frames,const uint8_t * m)353 _handle_midi_note_pressure(plughandle_t *handle, LV2_Atom_Forge *forge, int64_t frames,
354 	const uint8_t *m)
355 {
356 	const uint8_t chan = m[0] & 0x0f;
357 	const uint8_t key = m[1];
358 
359 	xpress_uuid_t uuid;
360 	targetO_t *target = _midi_get(handle, chan, key, &uuid);
361 	if(target && (target->mode == MODE_NOTE_PRESSURE))
362 	{
363 		const float pressure = (float)m[2] / 0x7f;
364 		target->state.pressure = pressure;
365 
366 		if(handle->ref)
367 			handle->ref = xpress_token(&handle->xpressO, forge, frames, target->uuid, &target->state);
368 	}
369 }
370 
371 static void
_handle_midi_channel_pressure(plughandle_t * handle,LV2_Atom_Forge * forge,int64_t frames,const uint8_t * m)372 _handle_midi_channel_pressure(plughandle_t *handle, LV2_Atom_Forge *forge, int64_t frames,
373 	const uint8_t *m)
374 {
375 	const uint8_t chan = m[0] & 0x0f;
376 
377 	// set pressure on all notes with matching channel
378 	XPRESS_VOICE_FOREACH(&handle->xpressO, voice)
379 	{
380 		targetO_t *target = voice->target;
381 
382 		if(target && (target->chan == chan) && (target->mode == MODE_CHANNEL_PRESSURE) )
383 		{
384 			const float pressure = (float)m[1] / 0x7f;
385 			target->state.pressure = pressure;
386 
387 			if(handle->ref)
388 				handle->ref = xpress_token(&handle->xpressO, forge, frames, target->uuid, &target->state);
389 		}
390 	}
391 }
392 
393 static void
_handle_midi_bender(plughandle_t * handle,LV2_Atom_Forge * forge,int64_t frames,const uint8_t * m)394 _handle_midi_bender(plughandle_t *handle, LV2_Atom_Forge *forge, int64_t frames,
395 	const uint8_t *m)
396 {
397 	const uint8_t chan = m[0] & 0x0f;
398 
399 	handle->midi_bender[chan] = (((int16_t)m[2] << 7) | m[1]) - 0x2000;
400 
401 	XPRESS_VOICE_FOREACH(&handle->xpressO, voice)
402 	{
403 		targetO_t *target = voice->target;
404 
405 		if(target->chan != chan)
406 			continue; // channel not matching
407 
408 		target->state.pitch = _get_pitch(handle, target);
409 
410 		if(handle->ref)
411 			handle->ref = xpress_token(&handle->xpressO, forge, frames, target->uuid, &target->state);
412 	}
413 }
414 
415 static void
_handle_midi_controller(plughandle_t * handle,LV2_Atom_Forge * forge,int64_t frames,const uint8_t * m)416 _handle_midi_controller(plughandle_t *handle, LV2_Atom_Forge *forge, int64_t frames,
417 	const uint8_t *m)
418 {
419 	const uint8_t chan = m[0] & 0x0f;
420 	const uint8_t controller = m[1];
421 	const uint8_t value = m[2];
422 
423 	switch(controller)
424 	{
425 		case LV2_MIDI_CTL_RPN_LSB:
426 		{
427 			handle->midi_rpn[chan] &= 0x3f80; // clear LSB
428 			handle->midi_rpn[chan] |= m[2];
429 		} break;
430 		case LV2_MIDI_CTL_RPN_MSB:
431 		{
432 			handle->midi_rpn[chan] &= 0x7f; // clear MSB
433 			handle->midi_rpn[chan] |= m[2] << 7;
434 		} break;
435 
436 		case LV2_MIDI_CTL_LSB_DATA_ENTRY:
437 		{
438 			handle->midi_data[chan] &= 0x3f80; // clear LSB
439 			handle->midi_data[chan] |= m[2];
440 		} break;
441 		case LV2_MIDI_CTL_MSB_DATA_ENTRY:
442 		{
443 			handle->midi_data[chan] &= 0x7f; // clear MSB
444 			handle->midi_data[chan] |= m[2] << 7;
445 
446 			switch(handle->midi_rpn[chan])
447 			{
448 				case 0x0: // MIDI pitch bend range
449 				{
450 					const uint8_t semi = handle->midi_data[chan] >> 7; // MSB
451 					const uint8_t cent = handle->midi_data[chan] & 0x7f; // LSB
452 
453 					handle->state.range[chan] = (float)semi + cent*0.01f;
454 
455 					props_set(&handle->props, &handle->forge, frames,
456 						handle->uris.range[chan], &handle->ref);
457 				} break;
458 			}
459 		} break;
460 
461 		default:
462 		{
463 			XPRESS_VOICE_FOREACH(&handle->xpressO, voice)
464 			{
465 				targetO_t *target = voice->target;
466 				bool put = false;
467 
468 				if( (target->chan != chan) || (target->mode != MODE_CONTROLLER) )
469 				{
470 					continue; // channel and/or mode not matching
471 				}
472 
473 				if(controller == (target->pressure | 0x20))
474 				{
475 					target->pressure_lsb = value;
476 				}
477 				else if(controller == target->pressure)
478 				{
479 					target->state.pressure = (float)( (value << 7) | target->pressure_lsb) / 0x3fff;
480 					put = true;
481 				}
482 				else if(controller == (target->timbre | 0x20))
483 				{
484 					target->timbre_lsb = value;
485 				}
486 				else if(controller == target->timbre)
487 				{
488 					target->state.timbre = (float)( (value << 7) | target->timbre_lsb) / 0x3fff;
489 					put = true;
490 				}
491 
492 				if(put)
493 				{
494 					if(handle->ref)
495 						handle->ref = xpress_token(&handle->xpressO, forge, frames, target->uuid, &target->state);
496 				}
497 			}
498 		} break;
499 	}
500 }
501 
502 static void
_handle_midi(plughandle_t * handle,LV2_Atom_Forge * forge,int64_t frames,const uint8_t * m)503 _handle_midi(plughandle_t *handle, LV2_Atom_Forge *forge, int64_t frames,
504 	const uint8_t *m)
505 {
506 	const uint8_t comm = m[0] & 0xf0;
507 
508 	switch(comm)
509 	{
510 		case LV2_MIDI_MSG_NOTE_ON:
511 		{
512 			_handle_midi_note_on(handle, forge, frames, m);
513 		} break;
514 		case LV2_MIDI_MSG_NOTE_OFF:
515 		{
516 			_handle_midi_note_off(handle, forge, frames, m);
517 		} break;
518 		case LV2_MIDI_MSG_NOTE_PRESSURE:
519 		{
520 			_handle_midi_note_pressure(handle, forge, frames, m);
521 		} break;
522 		case LV2_MIDI_MSG_CHANNEL_PRESSURE:
523 		{
524 			_handle_midi_channel_pressure(handle, forge, frames, m);
525 		} break;
526 		case LV2_MIDI_MSG_BENDER:
527 		{
528 			_handle_midi_bender(handle, forge, frames, m);
529 		} break;
530 		case LV2_MIDI_MSG_CONTROLLER:
531 		{
532 			_handle_midi_controller(handle, forge, frames, m);
533 		} break;
534 	}
535 }
536 
537 static void
run(LV2_Handle instance,uint32_t nsamples)538 run(LV2_Handle instance, uint32_t nsamples)
539 {
540 	plughandle_t *handle = instance;
541 
542 	// prepare midi atom forge
543 	const uint32_t capacity = handle->notify->atom.size;
544 	LV2_Atom_Forge *forge = &handle->forge;
545 	lv2_atom_forge_set_buffer(forge, (uint8_t *)handle->notify, capacity);
546 	LV2_Atom_Forge_Frame frame;
547 	handle->ref = lv2_atom_forge_sequence_head(forge, &frame, 0);
548 
549 	props_idle(&handle->props, forge, 0, &handle->ref);
550 	xpress_rst(&handle->xpressO);
551 
552 	LV2_ATOM_SEQUENCE_FOREACH(handle->control, ev)
553 	{
554 		const LV2_Atom_Object *obj = (const LV2_Atom_Object *)&ev->body;
555 		const int64_t frames = ev->time.frames;
556 
557 		if(obj->atom.type == handle->uris.midi_MidiEvent)
558 		{
559 			const uint8_t *m = LV2_ATOM_BODY_CONST(&obj->atom);
560 
561 			_handle_midi(handle, forge, frames, m);
562 		}
563 		else
564 		{
565 			props_advance(&handle->props, forge, frames, obj, &handle->ref);
566 		}
567 	}
568 
569 	if(handle->ref && !xpress_synced(&handle->xpressO))
570 		handle->ref = xpress_alive(&handle->xpressO, forge, nsamples-1);
571 
572 	if(handle->ref)
573 		lv2_atom_forge_pop(forge, &frame);
574 	else
575 		lv2_atom_sequence_clear(handle->notify);
576 }
577 
578 static void
cleanup(LV2_Handle instance)579 cleanup(LV2_Handle instance)
580 {
581 	plughandle_t *handle = instance;
582 
583 	if(handle)
584 	{
585 		xpress_deinit(&handle->xpressO);
586 		free(handle);
587 	}
588 }
589 
590 static LV2_State_Status
_state_save(LV2_Handle instance,LV2_State_Store_Function store,LV2_State_Handle state,uint32_t flags,const LV2_Feature * const * features)591 _state_save(LV2_Handle instance, LV2_State_Store_Function store,
592 	LV2_State_Handle state, uint32_t flags,
593 	const LV2_Feature *const *features)
594 {
595 	plughandle_t *handle = instance;
596 
597 	return props_save(&handle->props, store, state, flags, features);
598 }
599 
600 static LV2_State_Status
_state_restore(LV2_Handle instance,LV2_State_Retrieve_Function retrieve,LV2_State_Handle state,uint32_t flags,const LV2_Feature * const * features)601 _state_restore(LV2_Handle instance, LV2_State_Retrieve_Function retrieve,
602 	LV2_State_Handle state, uint32_t flags,
603 	const LV2_Feature *const *features)
604 {
605 	plughandle_t *handle = instance;
606 
607 	return props_restore(&handle->props, retrieve, state, flags, features);
608 }
609 
610 static const LV2_State_Interface state_iface = {
611 	.save = _state_save,
612 	.restore = _state_restore
613 };
614 
615 static const void *
extension_data(const char * uri)616 extension_data(const char *uri)
617 {
618 	if(!strcmp(uri, LV2_STATE__interface))
619 		return &state_iface;
620 	return NULL;
621 }
622 
623 const LV2_Descriptor midi_in = {
624 	.URI						= ESPRESSIVO_MIDI_IN_URI,
625 	.instantiate		= instantiate,
626 	.connect_port		= connect_port,
627 	.activate				= NULL,
628 	.run						= run,
629 	.deactivate			= NULL,
630 	.cleanup				= cleanup,
631 	.extension_data	= extension_data
632 };
633