1 /* fat1 -- LV2 autotuner 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 #include <math.h> 20 #include <stdint.h> 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <string.h> 24 25 #include <lv2/lv2plug.in/ns/ext/atom/atom.h> 26 #include <lv2/lv2plug.in/ns/ext/atom/forge.h> 27 #include <lv2/lv2plug.in/ns/ext/log/logger.h> 28 #include <lv2/lv2plug.in/ns/ext/midi/midi.h> 29 #include <lv2/lv2plug.in/ns/lv2core/lv2.h> 30 31 #include "fat1.h" 32 #include "retuner.h" 33 34 static pthread_mutex_t fftw_planner_lock = PTHREAD_MUTEX_INITIALIZER; 35 static unsigned int instance_count = 0; 36 37 typedef struct { 38 const LV2_Atom_Sequence* midiin; 39 40 /* URI mapping */ 41 LV2_URID midi_MidiEvent; 42 LV2_URID atom_Object; 43 LV2_URID fat_panic; 44 LV2_URID atom_eventTransfer; 45 46 /* LV2 Output */ 47 LV2_Log_Log* log; 48 LV2_Log_Logger logger; 49 50 /* I/O Ports */ 51 float* port[FAT_LAST]; 52 53 /* internal state */ 54 LV2AT::Retuner* retuner; 55 56 int notes[12]; 57 int notemask; 58 int midimask; 59 int midichan; 60 float pitchbend; 61 float latency; 62 63 bool panic_btn; 64 bool microtonal; 65 bool scales; 66 67 uint32_t noteset_update_interval; 68 uint32_t noteset_update_counter; 69 int noteset; 70 } Fat1; 71 72 /* ***************************************************************************** 73 * helper functions 74 */ 75 76 static void 77 clear_midimask (Fat1* self) 78 { 79 for (int i = 0; i < 12; ++i) { 80 self->notes[i] = 0; 81 } 82 self->midimask = 0; 83 self->pitchbend = 0; 84 } 85 86 static void 87 update_midimask (Fat1* self) 88 { 89 self->midimask = 0; 90 int b, i; 91 for (i = 0, b = 1; i < 12; i++, b <<= 1) { 92 if (self->notes[i]) 93 self->midimask |= b; 94 } 95 } 96 97 static int 98 midi_14bit (const uint8_t* const b) 99 { 100 return (b[1]) | (b[2] << 7); 101 } 102 103 static int 104 parse_midi (Fat1* self, 105 uint32_t tme, 106 const uint8_t* const msg, 107 const uint32_t size) 108 { 109 if (size != 3) { 110 return 0; 111 } 112 113 if ((self->midichan < 0) || ((msg[0] & 0x0f) == self->midichan)) { 114 const uint32_t n = msg[1]; 115 switch (msg[0] & 0xf0) { 116 case 0xe0: 117 self->pitchbend = (midi_14bit (msg) - 8192) / 8192.f; 118 break; 119 case 0xb0: 120 if ((n == 123 || n == 120) && msg[2] == 0) { // midi-panic 121 clear_midimask (self); 122 } 123 break; 124 case 0x90: 125 if (msg[2] > 0) { 126 self->notes[n % 12] += 1; 127 return 1; 128 } 129 // no break -- fallthrough, note-on velocity 0 130 case 0x80: 131 if (self->notes[n % 12]) { 132 self->notes[n % 12] -= 1; 133 return 1; 134 } 135 default: 136 break; 137 } 138 } 139 return 0; 140 } 141 142 static int 143 set_scale (int scale_id) { 144 if (scale_id <= 0 || scale_id > 24) { 145 /* chromatic */ 146 return 4095; 147 } 148 149 static const bool western[12] = { 150 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1 151 }; 152 153 if (scale_id > 12) { 154 scale_id = 1 + (scale_id + 2) % 12; 155 } 156 157 int b, i; 158 int notemask = 0; 159 for (i = 0, b = 1; i < 12; i++, b <<= 1) { 160 int s = (i + 13 - scale_id) % 12; 161 if (western[s]) { 162 notemask |= b; 163 } 164 } 165 166 return notemask; 167 } 168 169 /* ***************************************************************************** 170 * LV2 Plugin 171 */ 172 173 static LV2_Handle 174 instantiate (const LV2_Descriptor* descriptor, 175 double rate, 176 const char* bundle_path, 177 const LV2_Feature* const* features) 178 { 179 Fat1* self = (Fat1*)calloc (1, sizeof (Fat1)); 180 LV2_URID_Map* map = NULL; 181 182 if (0 == strcmp (descriptor->URI, FAT1_URI)) { 183 self->microtonal = false; 184 self->scales = false; 185 } else if (0 == strcmp (descriptor->URI, FAT1_URI "#microtonal")) { 186 self->microtonal = true; 187 self->scales = false; 188 } else if (0 == strcmp (descriptor->URI, FAT1_URI "#scales")) { 189 self->microtonal = false; 190 self->scales = true; 191 } else { 192 free (self); 193 return 0; 194 } 195 196 int i; 197 for (i = 0; features[i]; ++i) { 198 if (!strcmp (features[i]->URI, LV2_URID__map)) { 199 map = (LV2_URID_Map*)features[i]->data; 200 } else if (!strcmp (features[i]->URI, LV2_LOG__log)) { 201 self->log = (LV2_Log_Log*)features[i]->data; 202 } 203 } 204 205 lv2_log_logger_init (&self->logger, map, self->log); 206 207 if (!map) { 208 lv2_log_error (&self->logger, "Fat1.lv2 error: Host does not support urid:map\n"); 209 free (self); 210 return NULL; 211 } 212 213 pthread_mutex_lock (&fftw_planner_lock); 214 self->retuner = new LV2AT::Retuner (rate); 215 ++instance_count; 216 pthread_mutex_unlock (&fftw_planner_lock); 217 218 self->notemask = 0xfff; 219 self->midichan = -1; 220 clear_midimask (self); 221 222 self->midi_MidiEvent = map->map (map->handle, LV2_MIDI__MidiEvent); 223 self->atom_Object = map->map (map->handle, LV2_ATOM__Object); 224 self->fat_panic = map->map (map->handle, FAT1_URI "#panic"); 225 self->atom_eventTransfer = map->map (map->handle, LV2_ATOM__eventTransfer); 226 227 // compare Retuner c'tor 228 if (rate < 64000) { 229 self->latency = 1024; 230 } else if (rate < 128000) { 231 self->latency = 2048; 232 } else { 233 self->latency = 4096; 234 } 235 self->noteset_update_interval = rate / 20; 236 self->noteset_update_counter = self->noteset_update_interval; 237 return (LV2_Handle)self; 238 } 239 240 static void 241 connect_port (LV2_Handle instance, 242 uint32_t port, 243 void* data) 244 { 245 Fat1* self = (Fat1*)instance; 246 247 if (port == FAT_MIDI_IN) { 248 self->midiin = (const LV2_Atom_Sequence*)data; 249 } else if (port < FAT_LAST) { 250 self->port[port] = (float*)data; 251 } 252 } 253 254 static void 255 connect_port_scales (LV2_Handle instance, 256 uint32_t port, 257 void* data) 258 { 259 Fat1* self = (Fat1*)instance; 260 261 if (port == FAT_MIDI_IN) { 262 self->midiin = (const LV2_Atom_Sequence*)data; 263 } else if (port <= FAT_NOTE) { 264 self->port[port] = (float*)data; 265 } else { 266 switch (port) { 267 case 13: 268 self->port[FAT_MASK] = (float*)data; 269 break; 270 case 14: 271 self->port[FAT_NSET] = (float*)data; 272 break; 273 case 15: 274 self->port[FAT_BEND] = (float*)data; 275 break; 276 case 16: 277 self->port[FAT_ERRR] = (float*)data; 278 break; 279 case 17: 280 self->port[FAT_LTNC] = (float*)data; 281 break; 282 default: 283 break; 284 } 285 } 286 } 287 288 static void 289 run (LV2_Handle instance, uint32_t n_samples) 290 { 291 Fat1* self = (Fat1*)instance; 292 293 self->retuner->set_fastmode (*self->port[FAT_FAST]); 294 295 if (*self->port[FAT_FAST]) { 296 *self->port[FAT_LTNC] = self->latency / 4; 297 } else { 298 *self->port[FAT_LTNC] = self->latency; 299 } 300 301 if (!self->midiin || n_samples == 0) { 302 return; 303 } 304 305 /* set mode and midi-channel */ 306 const int mchn = rint (*self->port[FAT_MCHN]); 307 if (mchn <= 0 || mchn > 16) { 308 self->midichan = -1; 309 } else { 310 self->midichan = mchn - 1; 311 } 312 313 int mode = rint (*self->port[FAT_MODE]); 314 if (mode < 0) 315 mode = 0; 316 if (mode > 2) 317 mode = 2; 318 319 if (mode == 2) { 320 clear_midimask (self); 321 } 322 323 /* Process incoming midi events */ 324 bool update_midi = false; 325 LV2_Atom_Event* ev = lv2_atom_sequence_begin (&(self->midiin)->body); 326 while (!lv2_atom_sequence_is_end (&(self->midiin)->body, (self->midiin)->atom.size, ev)) { 327 if (ev->body.type == self->midi_MidiEvent) { 328 update_midi |= parse_midi (self, ev->time.frames, (uint8_t*)(ev + 1), ev->body.size); 329 330 } else if (ev->body.type == self->atom_Object) { 331 const LV2_Atom_Object* obj = (LV2_Atom_Object*)&ev->body; 332 if (obj->body.otype == self->fat_panic) { 333 clear_midimask (self); 334 } 335 } 336 ev = lv2_atom_sequence_next (ev); 337 } 338 if (update_midi) { 339 update_midimask (self); 340 } 341 342 /* prepare key-range midi/fixed */ 343 if (mode != 1) { 344 if (self->scales) { 345 self->notemask = set_scale (rint (*self->port[FAT_NOTE])); 346 } else { 347 self->notemask = 0; 348 for (int i = 0; i < 12; ++i) { 349 if (*self->port[FAT_NOTE + i] > 0) { 350 self->notemask |= 1 << i; 351 } 352 } 353 } 354 } 355 356 int notes; 357 switch (mode) { 358 case 1: 359 notes = self->midimask; 360 break; 361 case 2: 362 notes = self->notemask; 363 self->pitchbend = 0.f; 364 break; 365 default: 366 notes = self->midimask ? self->midimask : self->notemask; 367 } 368 369 /* push config to retuner */ 370 self->retuner->set_refpitch (*self->port[FAT_TUNE]); 371 self->retuner->set_notebias (*self->port[FAT_BIAS]); 372 self->retuner->set_corrfilt (*self->port[FAT_FILT]); 373 self->retuner->set_corrgain (*self->port[FAT_CORR]); 374 self->retuner->set_corroffs (*self->port[FAT_OFFS] + *self->port[FAT_PBST] * self->pitchbend); 375 self->retuner->set_notemask (notes); 376 377 if (self->microtonal) { 378 for (int i = 0; i < 12; ++i) { 379 self->retuner->set_notescale (i, *self->port[FAT_SCALE + i]); 380 } 381 } 382 383 /* process */ 384 self->retuner->process (n_samples, self->port[FAT_INPUT], self->port[FAT_OUTPUT]); 385 386 self->noteset_update_counter += n_samples; 387 388 if (self->noteset_update_counter > self->noteset_update_interval) { 389 self->noteset = self->retuner->get_noteset (); 390 self->noteset_update_counter = 0; 391 } 392 393 /* report */ 394 *self->port[FAT_MASK] = notes; 395 *self->port[FAT_NSET] = self->noteset; 396 *self->port[FAT_ERRR] = self->retuner->get_error (); 397 *self->port[FAT_BEND] = self->pitchbend; 398 } 399 400 static void 401 cleanup (LV2_Handle instance) 402 { 403 Fat1* self = (Fat1*)instance; 404 pthread_mutex_lock (&fftw_planner_lock); 405 delete self->retuner; 406 if (instance_count > 0) { 407 --instance_count; 408 } 409 #ifdef WITH_STATIC_FFTW_CLEANUP 410 /* use this only when statically linking to a local fftw! 411 * 412 * "After calling fftw_cleanup, all existing plans become undefined, 413 * and you should not attempt to execute them nor to destroy them." 414 * [http://www.fftw.org/fftw3_doc/Using-Plans.html] 415 * 416 * If libfftwf is shared with other plugins or the host this can 417 * cause undefined behavior. 418 */ 419 if (instance_count == 0) { 420 fftwf_cleanup (); 421 } 422 #endif 423 pthread_mutex_unlock (&fftw_planner_lock); 424 free (instance); 425 } 426 427 static void 428 activate (LV2_Handle instance) 429 { 430 Fat1* self = (Fat1*)instance; 431 clear_midimask (self); 432 } 433 434 const void* 435 extension_data (const char* uri) 436 { 437 return NULL; 438 } 439 440 static const LV2_Descriptor descriptor = { 441 FAT1_URI, 442 instantiate, 443 connect_port, 444 activate, 445 run, 446 NULL, 447 cleanup, 448 extension_data 449 }; 450 451 static const LV2_Descriptor descriptor_microtonal = { 452 FAT1_URI "#microtonal", 453 instantiate, 454 connect_port, 455 activate, 456 run, 457 NULL, 458 cleanup, 459 extension_data 460 }; 461 462 static const LV2_Descriptor descriptor_scales = { 463 FAT1_URI "#scales", 464 instantiate, 465 connect_port_scales, 466 activate, 467 run, 468 NULL, 469 cleanup, 470 extension_data 471 }; 472 473 #undef LV2_SYMBOL_EXPORT 474 #ifdef _WIN32 475 # define LV2_SYMBOL_EXPORT __declspec(dllexport) 476 #else 477 # define LV2_SYMBOL_EXPORT __attribute__ ((visibility ("default"))) 478 #endif 479 LV2_SYMBOL_EXPORT 480 const LV2_Descriptor* 481 lv2_descriptor (uint32_t index) 482 { 483 switch (index) { 484 case 0: 485 return &descriptor; 486 case 1: 487 return &descriptor_microtonal; 488 case 2: 489 return &descriptor_scales; 490 default: 491 return NULL; 492 } 493 } 494