1 /* mclk -- LV2 midi clock generator
2  *
3  * Copyright (C) 2016 Robin Gareus <robin@gareus.org>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2, or (at your option)
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #define _GNU_SOURCE
20 
21 #define CLK_URI "http://gareus.org/oss/lv2/mclk"
22 
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <stdint.h>
27 #include <math.h>
28 
29 #include <lv2/lv2plug.in/ns/lv2core/lv2.h>
30 #include <lv2/lv2plug.in/ns/ext/atom/atom.h>
31 #include <lv2/lv2plug.in/ns/ext/atom/forge.h>
32 #include <lv2/lv2plug.in/ns/ext/log/logger.h>
33 #include <lv2/lv2plug.in/ns/ext/midi/midi.h>
34 #include "lv2/lv2plug.in/ns/ext/time/time.h"
35 #include <lv2/lv2plug.in/ns/ext/urid/urid.h>
36 
37 typedef struct {
38 	LV2_URID atom_Blank;
39 	LV2_URID atom_Object;
40 	LV2_URID atom_Sequence;
41 	LV2_URID midi_MidiEvent;
42 	LV2_URID atom_Float;
43 	LV2_URID atom_Int;
44 	LV2_URID atom_Long;
45 	LV2_URID time_Position;
46 	LV2_URID time_bar;
47 	LV2_URID time_barBeat;
48 	LV2_URID time_beatUnit;
49 	LV2_URID time_beatsPerBar;
50 	LV2_URID time_beatsPerMinute;
51 	LV2_URID time_speed;
52 	LV2_URID time_frame;
53 } MclkURIs;
54 
55 /* MIDI System Real-Time Messages */
56 #define MIDI_RT_CLOCK    (0xF8)
57 #define MIDI_RT_START    (0xFA)
58 #define MIDI_RT_CONTINUE (0xFB)
59 #define MIDI_RT_STOP     (0xFC)
60 
61 /* bitwise flags -- mode */
62 enum {
63 	MSG_NO_TRANSPORT  = 1, /**< do not send start/stop/continue messages */
64 	MSG_NO_POSITION   = 2, /**< do not send absolute song position */
65 	MSG_NO_CLOCK      = 4  /**< do not send MIDI Clock*/
66 };
67 
68 typedef struct {
69 	/* ports */
70 	const LV2_Atom_Sequence* control;
71 	LV2_Atom_Sequence* midiout;
72 	float* p_mode;
73 	float* p_sync;
74 	float* p_bpm;
75 	float* p_transport;
76 	float* p_rewind;
77 	float* p_hostbpm;
78 	float* p_songpos;
79 	float* p_bbt[3];
80 
81 	/* Cached Ports */
82 	float c_mode;
83 	float c_transport;
84 	float c_bpm;
85 
86 	/* atom-forge and URI mapping */
87 	LV2_Atom_Forge forge;
88 	LV2_Atom_Forge_Frame frame;
89 	MclkURIs uris;
90 
91 	/* LV2 Output */
92 	LV2_Log_Log* log;
93 	LV2_Log_Logger logger;
94 
95 	/* Host Time */
96 	bool     host_info;
97 	float    host_bpm;
98 	double   bar_beats;
99 	float    host_speed;
100 	int      host_div;
101 	int64_t  host_frame;
102 
103 	/* Settings */
104 	double sample_rate;
105 	int mode;
106 
107 	/* State */
108 	bool  rolling;
109 	double bb;
110 	int64_t last_bcnt;
111 	int64_t sample_pos;
112 	double mclk_last_tick; // in audio-samples
113 } Mclk;
114 
115 /* *****************************************************************************
116  * helper functions
117  */
118 
119 /** map uris */
120 static void
map_uris(LV2_URID_Map * map,MclkURIs * uris)121 map_uris (LV2_URID_Map* map, MclkURIs* uris)
122 {
123 	uris->atom_Blank          = map->map (map->handle, LV2_ATOM__Blank);
124 	uris->atom_Object         = map->map (map->handle, LV2_ATOM__Object);
125 	uris->midi_MidiEvent      = map->map (map->handle, LV2_MIDI__MidiEvent);
126 	uris->atom_Sequence       = map->map (map->handle, LV2_ATOM__Sequence);
127 	uris->time_Position       = map->map (map->handle, LV2_TIME__Position);
128 	uris->atom_Long           = map->map (map->handle, LV2_ATOM__Long);
129 	uris->atom_Int            = map->map (map->handle, LV2_ATOM__Int);
130 	uris->atom_Float          = map->map (map->handle, LV2_ATOM__Float);
131 	uris->time_bar            = map->map (map->handle, LV2_TIME__bar);
132 	uris->time_barBeat        = map->map (map->handle, LV2_TIME__barBeat);
133 	uris->time_beatUnit       = map->map (map->handle, LV2_TIME__beatUnit);
134 	uris->time_beatsPerBar    = map->map (map->handle, LV2_TIME__beatsPerBar);
135 	uris->time_beatsPerMinute = map->map (map->handle, LV2_TIME__beatsPerMinute);
136 	uris->time_speed          = map->map (map->handle, LV2_TIME__speed);
137 	uris->time_frame          = map->map (map->handle, LV2_TIME__frame);
138 }
139 
140 /**
141  * Update the current position based on a host message. This is called by
142  * run() when a time:Position is received.
143  */
144 static void
update_position(Mclk * self,const LV2_Atom_Object * obj)145 update_position (Mclk* self, const LV2_Atom_Object* obj)
146 {
147 	const MclkURIs* uris = &self->uris;
148 
149 	LV2_Atom* bar   = NULL;
150 	LV2_Atom* beat  = NULL;
151 	LV2_Atom* bunit = NULL;
152 	LV2_Atom* bpb   = NULL;
153 	LV2_Atom* bpm   = NULL;
154 	LV2_Atom* speed = NULL;
155 	LV2_Atom* frame = NULL;
156 
157 	lv2_atom_object_get (
158 			obj,
159 			uris->time_bar, &bar,
160 			uris->time_barBeat, &beat,
161 			uris->time_beatUnit, &bunit,
162 			uris->time_beatsPerBar, &bpb,
163 			uris->time_beatsPerMinute, &bpm,
164 			uris->time_speed, &speed,
165 			uris->time_frame, &frame,
166 			NULL);
167 
168 	if (   bpm   && bpm->type == uris->atom_Float
169 			&& bpb   && bpb->type == uris->atom_Float
170 			&& bar   && bar->type == uris->atom_Long
171 			&& beat  && beat->type == uris->atom_Float
172 			&& bunit && bunit->type == uris->atom_Int
173 			&& speed && speed->type == uris->atom_Float
174 			&& frame && frame->type == uris->atom_Long)
175 	{
176 		float    _bpb   = ((LV2_Atom_Float*)bpb)->body;
177 		int64_t  _bar   = ((LV2_Atom_Long*)bar)->body;
178 		float    _beat  = ((LV2_Atom_Float*)beat)->body;
179 
180 		self->host_div   = ((LV2_Atom_Int*)bunit)->body;
181 		self->host_bpm   = ((LV2_Atom_Float*)bpm)->body;
182 		self->host_speed = ((LV2_Atom_Float*)speed)->body;
183 		self->host_frame = ((LV2_Atom_Long*)frame)->body;
184 
185 		self->bar_beats  = _bar * _bpb + _beat * self->host_div / 4.0;
186 		self->host_info  = true;
187 		if (self->host_frame < 0) {
188 			self->host_info  = false;
189 		}
190 	}
191 }
192 
193 /**
194  * add a midi message to the output port
195  */
196 static void
forge_midimessage(Mclk * self,uint32_t tme,const uint8_t * const buffer,uint32_t size)197 forge_midimessage (Mclk* self,
198                    uint32_t tme,
199                    const uint8_t* const buffer,
200                    uint32_t size)
201 {
202 	LV2_Atom midiatom;
203 	midiatom.type = self->uris.midi_MidiEvent;
204 	midiatom.size = size;
205 
206 	if (0 == lv2_atom_forge_frame_time (&self->forge, tme)) return;
207 	if (0 == lv2_atom_forge_raw (&self->forge, &midiatom, sizeof (LV2_Atom))) return;
208 	if (0 == lv2_atom_forge_raw (&self->forge, buffer, size)) return;
209 	lv2_atom_forge_pad (&self->forge, sizeof (LV2_Atom) + size);
210 }
211 
212 /* *****************************************************************************
213  * Midi Clock
214  */
215 
216 static int64_t
send_pos_message(Mclk * self,const int64_t bcnt)217 send_pos_message (Mclk* self, const int64_t bcnt)
218 {
219 	if (self->mode & MSG_NO_POSITION) return -1;
220   /* send '0xf2' Song Position Pointer.
221    * This is an internal 14 bit register that holds the number of
222    * MIDI beats (1 beat = six MIDI clocks) since the start of the song.
223    */
224   if (bcnt < 0 || bcnt >= 16384) {
225     return bcnt;
226   }
227 
228   uint8_t buffer[3];
229   buffer[0] = 0xf2;
230   buffer[1] = bcnt & 0x7f; // LSB
231   buffer[2] = (bcnt >> 7) & 0x7f; // MSB
232 	forge_midimessage (self, 0, buffer, 3);
233 	return bcnt;
234 }
235 
236 /**
237  * send 1 byte MIDI Message
238  * @param port_buf buffer to write event to
239  * @param time sample offset of event
240  * @param rt_msg message byte
241  */
242 static void
send_rt_message(Mclk * self,uint32_t tme,uint8_t rt_msg)243 send_rt_message (Mclk* self, uint32_t tme, uint8_t rt_msg)
244 {
245 	forge_midimessage (self, tme, &rt_msg, 1);
246 }
247 
248 /**
249  * calculate song position (14 bit integer) from current BBT info.
250  *
251  * see "Song Position Pointer" at
252  * http://www.midi.org/techspecs/midimessages.php
253  *
254  * Because this value is also used internally to sync/send
255  * start/continue realtime messages, a 64 bit integer
256  * is used to cover the complete range.
257  */
258 static const int64_t
calc_song_pos(const double bar_beat,double bpm,int off)259 calc_song_pos (const double bar_beat, double bpm, int off)
260 {
261 	const double resync_delay = 1.0; /**< seconds between 'pos' and 'continue' message */
262 
263   if (off < 0) {
264     /* auto offset */
265     if (bar_beat == 0) off = 0;
266     else off = rint (bpm * 4.0 * resync_delay / 60.0);
267   }
268   return off + floor (4.0 * bar_beat);
269 }
270 
271 /* *****************************************************************************
272  * LV2 Plugin
273  */
274 
275 static LV2_Handle
instantiate(const LV2_Descriptor * descriptor,double rate,const char * bundle_path,const LV2_Feature * const * features)276 instantiate (const LV2_Descriptor*     descriptor,
277              double                    rate,
278              const char*               bundle_path,
279              const LV2_Feature* const* features)
280 {
281 	Mclk* self = (Mclk*)calloc (1, sizeof (Mclk));
282 	LV2_URID_Map* map = NULL;
283 
284 	int i;
285 	for (i=0; features[i]; ++i) {
286 		if (!strcmp (features[i]->URI, LV2_URID__map)) {
287 			map = (LV2_URID_Map*)features[i]->data;
288 		} else if (!strcmp (features[i]->URI, LV2_LOG__log)) {
289 			self->log = (LV2_Log_Log*)features[i]->data;
290 		}
291 	}
292 
293 	lv2_log_logger_init (&self->logger, map, self->log);
294 
295 	if (!map) {
296 		lv2_log_error (&self->logger, "Mclk.lv2 error: Host does not support urid:map\n");
297 		free (self);
298 		return NULL;
299 	}
300 
301 	lv2_atom_forge_init (&self->forge, map);
302 	map_uris (map, &self->uris);
303 
304 	self->sample_rate = rate;
305 
306 	self->bb = 0;
307 	self->rolling = false;
308 	self->last_bcnt = -1;
309 	self->mclk_last_tick = 0;
310 	self->sample_pos = 0;
311 
312 	return (LV2_Handle)self;
313 }
314 
315 static void
connect_port(LV2_Handle instance,uint32_t port,void * data)316 connect_port (LV2_Handle instance,
317               uint32_t   port,
318               void*      data)
319 {
320 	Mclk* self = (Mclk*)instance;
321 
322 	switch (port) {
323 		case 0:
324 			self->control = (const LV2_Atom_Sequence*)data;
325 			break;
326 		case 1:
327 			self->midiout = (LV2_Atom_Sequence*)data;
328 			break;
329 		case 2:
330 			self->p_mode = (float*)data;
331 			break;
332 		case 3:
333 			self->p_sync = (float*)data;
334 			break;
335 		case 4:
336 			self->p_bpm = (float*)data;
337 			break;
338 		case 5:
339 			self->p_transport = (float*)data;
340 			break;
341 		case 6:
342 			self->p_rewind = (float*)data;
343 			break;
344 		case 7:
345 			self->p_hostbpm = (float*)data;
346 			break;
347 		case 8:
348 			self->p_songpos = (float*)data;
349 			break;
350 		case 9:
351 			self->p_bbt[0] = (float*)data;
352 			break;
353 		case 10:
354 			self->p_bbt[1] = (float*)data;
355 			break;
356 		case 11:
357 			self->p_bbt[2] = (float*)data;
358 			break;
359 		default:
360 			break;
361 	}
362 }
363 
364 
365 static void
run(LV2_Handle instance,uint32_t n_samples)366 run (LV2_Handle instance, uint32_t n_samples)
367 {
368 	Mclk* self = (Mclk*)instance;
369 	if (!self->midiout || !self->control) {
370 		return;
371 	}
372 
373 	/* initialize output port */
374 	const uint32_t capacity = self->midiout->atom.size;
375 	lv2_atom_forge_set_buffer (&self->forge, (uint8_t*)self->midiout, capacity);
376 	lv2_atom_forge_sequence_head (&self->forge, &self->frame, 0);
377 
378 	/* process control events */
379 	LV2_Atom_Event* ev = lv2_atom_sequence_begin (&(self->control)->body);
380 	while (!lv2_atom_sequence_is_end (&(self->control)->body, (self->control)->atom.size, ev)) {
381 		if (ev->body.type == self->uris.atom_Blank || ev->body.type == self->uris.atom_Object) {
382 			const LV2_Atom_Object* obj = (LV2_Atom_Object*)&ev->body;
383 			if (obj->body.otype == self->uris.time_Position) {
384 				update_position (self, obj);
385 			}
386 		}
387 		ev = lv2_atom_sequence_next (ev);
388 	}
389 
390 	bool rolling;
391 	double bpm;
392 	double bb;
393 	double quarter_notes_per_beat = 1.0;
394 	int64_t sample_position;
395 
396 	/* set mode */
397 	switch ((int)rintf (*self->p_mode)) {
398 		case 0:
399 			self->mode = MSG_NO_POSITION | MSG_NO_CLOCK;
400 			break;
401 		case 1:
402 			self->mode = MSG_NO_POSITION | MSG_NO_TRANSPORT;
403 			break;
404 		case 2:
405 			self->mode = MSG_NO_POSITION;
406 			break;
407 		default:
408 		case 3:
409 			self->mode = 0;
410 			break;
411 	}
412 
413 	/* set BarBeat & transport state */
414 	if (self->host_info && *self->p_sync > 0) {
415 		*self->p_hostbpm = self->host_bpm;
416 		bpm = self->host_bpm * self->host_speed;
417 		sample_position = self->host_frame;
418 		rolling = self->host_speed > 0;
419 		bb = self->bar_beats;
420 		if (self->host_speed < 0) {
421 			goto noroll;
422 		}
423 		if (fabs(self->bb - self->bar_beats) > 1) {
424 			/* located */
425 			self->rolling = rolling = false;
426 			self->bb = -1;
427 		}
428 	} else {
429 		*self->p_hostbpm = self->host_info ? -1 : 0;
430 		bpm = *self->p_bpm;
431 		if (*self->p_rewind > 0) {
432 			bb = self->bb = 0;
433 			self->last_bcnt = -1;
434 			rolling = false;
435 			sample_position = self->sample_pos = 0;
436 		} else {
437 			rolling = *self->p_transport > 0;
438 			bb = self->bb;
439 			sample_position = self->sample_pos;
440 		}
441 	}
442 
443 	const double samples_per_beat = self->sample_rate * 60.0 / bpm;
444 	const double samples_per_quarter_note = samples_per_beat / quarter_notes_per_beat;
445 	const double clock_tick_interval = samples_per_quarter_note / 24.0;
446 
447 	/* send position updates if stopped and located */
448 	if (!rolling && !self->rolling) {
449 		if (bb != self->bb) {
450 			self->last_bcnt = send_pos_message (self, calc_song_pos (bb, bpm, -1));
451 		}
452 	}
453 
454 	/* send RT messages start/stop/continue if transport state changed */
455 	if (rolling != self->rolling) {
456 		if (rolling) {
457 			/* stop -> playing */
458 			if (bb == 0 || 0 != (self->mode & MSG_NO_POSITION)) {
459 				/* start playing now */
460 				if (!(self->mode & MSG_NO_TRANSPORT)) {
461 					send_rt_message (self, 0, MIDI_RT_START);
462 				}
463 				self->last_bcnt = -1; /* 'start' at 0, don't queue 'continue' message */
464 			} else {
465 				/* continue after pause
466 				 *
467 				 * only send continue message here if song-position is not used.
468 				 * w/song-pos it is queued just-in-time with clock
469 				 */
470 				if (0 != (self->mode & MSG_NO_POSITION)) {
471 					if (0 == (self->mode & MSG_NO_TRANSPORT)) {
472 						send_rt_message (self, 0, MIDI_RT_CONTINUE);
473 					}
474 				}
475 			}
476 			/* initial beat tick */
477 			if (0 == bb || 0 != (self->mode & (MSG_NO_POSITION))) {
478 				if (0 == (self->mode & MSG_NO_CLOCK)) {
479 					//send_rt_message (self, 0, MIDI_RT_CLOCK);
480 				}
481 			}
482 		} else {
483 			/* playing -> stop */
484 			if (0 == (self->mode & MSG_NO_TRANSPORT)) {
485 				send_rt_message (self, 0, MIDI_RT_STOP);
486 			}
487 			self->last_bcnt = send_pos_message (self, calc_song_pos (bb, bpm, -1));
488 		}
489 		self->mclk_last_tick = samples_per_beat * bb;
490 	}
491 
492 	self->rolling = rolling;
493 
494 	if (!rolling || (self->mode & MSG_NO_CLOCK)) {
495 		goto noroll;
496 	}
497 
498 	/* send clock ticks for this cycle */
499 	int ticks_sent_this_cycle = 0;
500 	while (1) {
501 		const double next_tick = self->mclk_last_tick + clock_tick_interval;
502 		const int64_t next_tick_offset = llrint (next_tick) - sample_position;
503 		if (next_tick_offset >= n_samples) break;
504 
505 		if (next_tick_offset >= 0) {
506 			if (self->last_bcnt > 0 && !(self->mode & MSG_NO_POSITION)) {
507 				/* send 'continue' realtime message on time */
508 				const int64_t bcnt = calc_song_pos (bb, bpm, 0);
509 				/* 4 MIDI-beats per quarter note (jack beat) */
510 				if (bcnt + ticks_sent_this_cycle / 6 >= self->last_bcnt) {
511 					if (!(self->mode & MSG_NO_TRANSPORT)) {
512 						send_rt_message (self, next_tick_offset, MIDI_RT_CONTINUE);
513 					}
514 					self->last_bcnt = -1;
515 				}
516 			}
517 			/* enqueue clock tick */
518 			send_rt_message (self, next_tick_offset, MIDI_RT_CLOCK);
519 			ticks_sent_this_cycle++;
520 		}
521 
522 		self->mclk_last_tick = next_tick;
523 	}
524 
525 noroll:
526 	*self->p_songpos = bb;
527 
528 	int bpb = 4;
529 	if (self->host_info && *self->p_sync > 0) {
530 		bpb = self->host_div;
531 	}
532 	*self->p_bbt[0] = 1.f + floor (bb / bpb); // limit to 4096 (song pos) ?
533 	*self->p_bbt[1] = 1.f + ((int) floor (bb) % bpb);
534 	*self->p_bbt[2] = floor (fmod (bb, 1.0) * 960.0);
535 
536 	/* keep track of host position.. */
537 	if (self->host_info) {
538 		self->bar_beats += n_samples * self->host_bpm * self->host_speed / (60.0 * self->sample_rate);
539 		self->host_frame += n_samples * self->host_speed;
540 	}
541 
542 	/* prepare for next cycle */
543 	if (self->host_info && *self->p_sync > 0) {
544 		self->bb = self->bar_beats;
545 		self->sample_pos = self->host_frame;
546 	} else if (rolling) {
547 		self->bb += n_samples * bpm / (60.0 * self->sample_rate);
548 		self->sample_pos += n_samples;
549 	}
550 }
551 
552 static void
cleanup(LV2_Handle instance)553 cleanup (LV2_Handle instance)
554 {
555 	free (instance);
556 }
557 
558 static const void*
extension_data(const char * uri)559 extension_data (const char* uri)
560 {
561 	return NULL;
562 }
563 
564 static const LV2_Descriptor descriptor = {
565 	CLK_URI,
566 	instantiate,
567 	connect_port,
568 	NULL,
569 	run,
570 	NULL,
571 	cleanup,
572 	extension_data
573 };
574 
575 #undef LV2_SYMBOL_EXPORT
576 #ifdef _WIN32
577 #    define LV2_SYMBOL_EXPORT __declspec(dllexport)
578 #else
579 #    define LV2_SYMBOL_EXPORT  __attribute__ ((visibility ("default")))
580 #endif
581 LV2_SYMBOL_EXPORT
582 const LV2_Descriptor*
lv2_descriptor(uint32_t index)583 lv2_descriptor (uint32_t index)
584 {
585 	switch (index) {
586 	case 0:
587 		return &descriptor;
588 	default:
589 		return NULL;
590 	}
591 }
592