1 /* reasonable simple synth
3 * Copyright (C) 2013 Robin Gareus <robin@gareus.org>
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)
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.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 #include "lv2/lv2plug.in/ns/lv2core/lv2.h"
29 #include "lv2/lv2plug.in/ns/ext/atom/atom.h"
30 #include "lv2/lv2plug.in/ns/ext/urid/urid.h"
31 #include "lv2/lv2plug.in/ns/ext/midi/midi.h"
33 #define RSY_URI "https://community.ardour.org/node/7596"
35 /* the synth interface */
36 static void * synth_alloc (void);
37 static void synth_init (void *, double rate);
38 static void synth_free (void *);
39 static void synth_parse_midi (void *, const uint8_t *data, const size_t size);
40 static uint32_t synth_sound (void *, uint32_t written, uint32_t nframes, float **out);
51 const LV2_Atom_Sequence* midiin;
56 LV2_URID midi_MidiEvent;
66 instantiate(const LV2_Descriptor* descriptor,
68 const char* bundle_path,
69 const LV2_Feature* const* features)
71 (void) descriptor; /* unused variable */
72 (void) bundle_path; /* unused variable */
75 fprintf(stderr, "RSynth.lv2 error: unsupported sample-rate (must be > 8k)\n");
78 RSynth* self = (RSynth*)calloc(1, sizeof(RSynth));
83 self->SampleRateD = rate;
86 for (i=0; features[i]; ++i) {
87 if (!strcmp(features[i]->URI, LV2_URID__map)) {
88 self->map = (LV2_URID_Map*)features[i]->data;
93 fprintf(stderr, "RSynth.lv2 error: Host does not support urid:map\n");
98 self->midi_MidiEvent = self->map->map(self->map->handle, LV2_MIDI__MidiEvent);
100 self->synth = synth_alloc();
101 synth_init(self->synth, rate);
103 #ifndef PLATFORM_WINDOWS // easter egg is for sane platforms with native support for localtime_r only
107 localtime_r(&now, &date);
108 if (getenv("ITSXMAS") || (date.tm_mon == 11 /*dec*/ && date.tm_mday == 25)) {
109 printf("reasonable synth.lv2 says: happy holidays!\n");
114 return (LV2_Handle)self;
118 connect_port(LV2_Handle handle,
122 RSynth* self = (RSynth*)handle;
124 switch ((PortIndex)port) {
126 self->midiin = (const LV2_Atom_Sequence*)data;
129 self->outL = (float*)data;
132 self->outR = (float*)data;
138 run(LV2_Handle handle, uint32_t n_samples)
140 RSynth* self = (RSynth*)handle;
143 audio[0] = self->outL;
144 audio[1] = self->outR;
146 uint32_t written = 0;
148 /* Process incoming MIDI events */
150 LV2_Atom_Event const* ev = (LV2_Atom_Event const*)((uintptr_t)((&(self->midiin)->body) + 1)); // lv2_atom_sequence_begin
151 while( // !lv2_atom_sequence_is_end
152 (const uint8_t*)ev < ((const uint8_t*) &(self->midiin)->body + (self->midiin)->atom.size)
155 if (ev->body.type == self->midi_MidiEvent) {
156 #ifdef DEBUG_MIDI_EVENT // debug midi messages in synth -- not rt-safe(!)
157 printf ("%5d (%d):", ev->time.frames, ev->body.size);
158 for (uint8_t i = 0; i < ev->body.size; ++i) {
159 printf (" %02x", ((const uint8_t*)(ev+1))[i]);
163 if (written + BUFFER_SIZE_SAMPLES < ev->time.frames
164 && ev->time.frames < n_samples) {
165 /* first synthesize sound up until the message timestamp */
166 written = synth_sound(self->synth, written, ev->time.frames, audio);
168 /* send midi message to synth */
170 synth_parse_xmas(self->synth, (const uint8_t*)(ev+1), ev->body.size);
172 synth_parse_midi(self->synth, (const uint8_t*)(ev+1), ev->body.size);
175 ev = (LV2_Atom_Event const*) // lv2_atom_sequence_next()
176 ((uintptr_t)((const uint8_t*)ev + sizeof(LV2_Atom_Event) + ((ev->body.size + 7) & ~7)));
180 /* synthesize [remaining] sound */
181 synth_sound(self->synth, written, n_samples, audio);
185 cleanup(LV2_Handle handle)
187 RSynth* self = (RSynth*)handle;
188 synth_free(self->synth);
193 extension_data(const char* uri)
195 (void) uri; /* unused variable */
199 static const LV2_Descriptor descriptor = {
210 #if defined(COMPILER_MSVC)
211 __declspec(dllexport)
213 __attribute__ ((visibility ("default")))
215 const LV2_Descriptor*
216 lv2_descriptor(uint32_t idx)
226 /* vi:set ts=8 sts=2 sw=2 et: */