1 /*
2 InterChange.cpp - General communications
3
4 Copyright 2016-2019, Will Godfrey & others
5 Copyright 2020-2020, Kristian Amlie, Will Godfrey, & others
6 Copyright 2021, Will Godfrey, Rainer Hans Liffers, & others
7
8 This file is part of yoshimi, which is free software: you can redistribute
9 it and/or modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either version 2 of
11 the License, or (at your option) any later version.
12
13 yoshimi is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 FOR A PARTICULAR PURPOSE. See the GNU General Public License (version 2 or
16 later) for more details.
17
18 You should have received a copy of the GNU General Public License along with
19 yoshimi; if not, write to the Free Software Foundation, Inc., 51 Franklin
20 Street, Fifth Floor, Boston, MA 02110-1301, USA.
21
22 */
23
24 #include <iostream>
25 #include <string>
26 #include <algorithm>
27 #include <cfloat>
28 #include <bitset>
29 #include <unistd.h>
30 #include <thread>
31
32 #include "Interface/InterChange.h"
33 #include "Interface/Data2Text.h"
34 #include "Interface/TextLists.h"
35 #include "Misc/FileMgrFuncs.h"
36 #include "Misc/NumericFuncs.h"
37 #include "Misc/FormatFuncs.h"
38 #include "Misc/Microtonal.h"
39 #include "Misc/SynthEngine.h"
40 #include "Misc/Part.h"
41 #include "Misc/TextMsgBuffer.h"
42 #include "Params/Controller.h"
43 #include "Params/ADnoteParameters.h"
44 #include "Params/SUBnoteParameters.h"
45 #include "Params/PADnoteParameters.h"
46 #include "Params/LFOParams.h"
47 #include "Params/FilterParams.h"
48 #include "Params/EnvelopeParams.h"
49 #include "Effects/EffectMgr.h"
50 #include "Synth/Resonance.h"
51 #include "Synth/OscilGen.h"
52 #ifdef GUI_FLTK
53 #include "MasterUI.h"
54 #endif
55
56 using file::localPath;
57 using file::findFile;
58 using file::isRegularFile;
59 using file::createDir;
60 using file::listDir;
61 using file::isDirectory;
62 using file::setExtension;
63 using file::findLeafName;
64 using file::createEmptyFile;
65 using file::deleteFile;
66 using file::loadText;
67 using file::saveText;
68
69 using func::bitSet;
70 using func::bitClear;
71 using func::nearestPowerOf2;
72
73 using func::asString;
74
75 extern void mainRegisterAudioPort(SynthEngine *s, int portnum);
76 extern SynthEngine *firstSynth;
77
78 int startInstance = 0;
79
InterChange(SynthEngine * _synth)80 InterChange::InterChange(SynthEngine *_synth) :
81 synth(_synth),
82 #ifndef YOSHIMI_LV2_PLUGIN
83 fromCLI(),
84 #endif
85 decodeLoopback(),
86 #ifdef GUI_FLTK
87 fromGUI(),
88 toGUI(),
89 #endif
90 fromMIDI(),
91 returnsBuffer(),
92 syncWrite(false),
93 lowPrioWrite(false),
94 tick(0),
95 sortResultsThreadHandle(0),
96 swapRoot1(UNUSED),
97 swapBank1(UNUSED),
98 swapInstrument1(UNUSED),
99 searchInst(0),
100 searchBank(0),
101 searchRoot(0)
102 {
103 ;
104 }
105
106
Init()107 bool InterChange::Init()
108 {
109 #ifndef YOSHIMI_LV2_PLUGIN
110 fromCLI.init ();
111 #endif
112 decodeLoopback.init ();
113 #ifdef GUI_FLTK
114 fromGUI.init ();
115 toGUI.init ();
116 #endif
117 fromMIDI.init ();
118 returnsBuffer.init ();
119 muteQueue.init ();
120 if (!synth->getRuntime().startThread(&sortResultsThreadHandle, _sortResultsThread, this, false, 0, "CLI"))
121 {
122 synth->getRuntime().Log("Failed to start CLI resolve thread");
123 return false;
124 }
125 else
126 {
127 searchInst = searchBank = searchRoot = 0;
128 return true;
129 }
130 }
131
132
_sortResultsThread(void * arg)133 void *InterChange::_sortResultsThread(void *arg)
134 {
135 return static_cast<InterChange*>(arg)->sortResultsThread();
136 }
137
138
sortResultsThread(void)139 void *InterChange::sortResultsThread(void)
140 {
141 while (synth->getRuntime().runSynth)
142 {
143 /*
144 * To maintain portability we synthesise a very simple low accuracy
145 * timer based on the loop time of this function. As it makes no system
146 * calls apart from usleep() it is lightweight and should have no thread
147 * safety issues. It is used mostly for low priority timeouts.
148 */
149 ++ tick;
150
151 /*if (!(tick & 8191))
152 {
153 if (tick & 16383)
154 std::cout << "Tick" << std::endl;
155 else
156 std::cout << "Tock" << std::endl;
157 }*/
158
159 CommandBlock getData;
160
161 /* It is possible that several operations initiated from
162 * different sources complete within the same period
163 * (especially with large buffer sizes) so this small
164 * ring buffer ensures they can all clear together.
165 */
166 while (synth->audioOut.load() == _SYS_::mute::Active)
167 {
168 //std::cout << "here fetching" << std:: endl;
169 if (muteQueue.read(getData.bytes))
170 indirectTransfers(&getData);
171 else
172 synth->audioOut.store(_SYS_::mute::Complete);
173 }
174
175 while (decodeLoopback.read(getData.bytes))
176 {
177 if (getData.data.part == TOPLEVEL::section::midiLearn)
178 synth->midilearn.generalOperations(&getData);
179 else if (getData.data.source >= TOPLEVEL::action::lowPrio)
180 indirectTransfers(&getData);
181 else
182 resolveReplies(&getData);
183 }
184 usleep(80); // actually gives around 120 uS
185 }
186 return NULL;
187 }
188
189
~InterChange()190 InterChange::~InterChange()
191 {
192 if (sortResultsThreadHandle)
193 pthread_join(sortResultsThreadHandle, 0);
194 }
195
196
muteQueueWrite(CommandBlock * getData)197 void InterChange::muteQueueWrite(CommandBlock *getData)
198 {
199 if (!muteQueue.write(getData->bytes))
200 {
201 std::cout << "failed to write to muteQueue" << std::endl;
202 return;
203 }
204 if (synth->audioOut.load() == _SYS_::mute::Idle)
205 {
206 //std::cout << "here pending" << std:: endl;
207 synth->audioOut.store(_SYS_::mute::Pending);
208 }
209 }
210
211
findHtmlManual(void)212 std::string InterChange::findHtmlManual(void)
213 {
214 string namestring = "doc/yoshimi/yoshimi_user_guide/files/yoshimi_user_guide_version";
215 string namelist = "";
216 if (isRegularFile("/usr/share/" + namestring))
217 namelist += ("/usr/share/" + namestring + "\n");
218 if (isRegularFile("/usr/local/share/" + namestring))
219 namelist += ("/usr/local/share/" + namestring + "\n");
220 if (namelist.empty())
221 {
222 if(!file::cmd2string("find /home/ -type f -name 'yoshimi_user_guide_version' 2>/dev/null", namelist))
223 return "";
224 }
225 //std::cout << namelist << std::endl;
226
227 size_t next = 0;
228 size_t lastversion = 0;
229 string found = "";
230 string name = "";
231 while (next != string::npos)
232 {
233 next = namelist.find("\n");
234 if (next != string::npos)
235 {
236 name = namelist.substr(0, next);
237
238 // check it's there and the most recent
239 size_t current = isRegularFile(name);
240 if (current > lastversion)
241 {
242 lastversion = current;
243 found = name;
244 }
245 namelist = namelist.substr( next +1);
246 }
247 }
248 return found;
249 }
250
251
manualSearch(std::string dir2search,std::string path2match)252 std::string InterChange::manualSearch(std::string dir2search, std::string path2match)
253 {
254 std::list<string> wanted;
255 listDir(&wanted, dir2search);
256 if (wanted.empty())
257 return "";
258 wanted.sort();
259
260 std::string path = "";
261 std::list<string>::reverse_iterator itr = wanted.rbegin();
262 while (itr != wanted.rend())
263 {
264 std::string tmp = *itr;
265 // some installs have a missing third digit so we trap it
266 if (tmp.find(path2match) != std::string::npos && tmp.rfind("2.0.pdf") == std::string::npos)
267 {
268 path = tmp;
269 itr = wanted.rend();
270 }
271 else
272 ++itr;
273 }
274 return path;
275 }
276
277
indirectTransfers(CommandBlock * getData,bool noForward)278 void InterChange::indirectTransfers(CommandBlock *getData, bool noForward)
279 {
280 int value = lrint(getData->data.value);
281 unsigned char type = getData->data.type;
282 unsigned char control = getData->data.control;
283 unsigned char switchNum = getData->data.part;
284 unsigned char kititem = getData->data.kit;
285 unsigned char engine = getData->data.engine;
286 unsigned char insert = getData->data.insert;
287 //unsigned char parameter = getData->data.parameter;
288 //unsigned char miscmsg = getData->data.miscmsg;
289
290 while (syncWrite)
291 usleep(10);
292 bool write = (type & TOPLEVEL::type::Write);
293 if (write)
294 lowPrioWrite = true;
295 bool guiTo = false;
296 (void) guiTo; // suppress warning when headless build
297 unsigned char newMsg = false;//NO_MSG;
298
299 if (switchNum == TOPLEVEL::section::main && control == MAIN::control::loadFileFromList)
300 {
301 int result = synth->LoadNumbered(kititem, engine);
302 if (result > NO_MSG)
303 getData->data.miscmsg = result & NO_MSG;
304 else
305 {
306 getData->data.miscmsg = result;
307 switch (kititem) // group
308 {
309 case TOPLEVEL::XML::Instrument:
310 {
311 control = MAIN::control::loadInstrumentByName;
312 getData->data.kit = insert;
313 break;
314 }
315 case TOPLEVEL::XML::Patch:
316 {
317 control = MAIN::control::loadNamedPatchset;
318 break;
319 }
320 case TOPLEVEL::XML::Scale:
321 {
322 control = MAIN::control::loadNamedScale;
323 break;
324 }
325 case TOPLEVEL::XML::State:
326 {
327 control = MAIN::control::loadNamedState;
328 break;
329 }
330 case TOPLEVEL::XML::Vector:
331 {
332 control = MAIN::control::loadNamedVector;
333 break;
334 }
335 case TOPLEVEL::XML::MLearn:
336 { // this is a bit messy MIDI learn is an edge case
337 getData->data.control = MIDILEARN::control::loadList;
338 synth->midilearn.generalOperations(getData);
339 lowPrioWrite = false;
340 return;
341 break;
342 }
343 }
344 getData->data.control = control;
345 }
346 }
347
348 std::string text;
349 if (getData->data.miscmsg != NO_MSG)
350 {
351 text = textMsgBuffer.fetch(getData->data.miscmsg);
352 getData->data.miscmsg = NO_MSG; // this may be reset later
353 }
354 else
355 text = "";
356
357 if (control == TOPLEVEL::control::textMessage)
358 switchNum = TOPLEVEL::section::message; // this is a bit hacky :(
359
360 switch(switchNum)
361 {
362 case TOPLEVEL::section::vector:
363 value = indirectVector(getData, synth, newMsg, guiTo, text);
364 break;
365 case TOPLEVEL::section::midiLearn:
366 if (control == MIDILEARN::control::findSize)
367 value = synth->midilearn.findSize();
368 // very naughty! should do better
369 break;
370 case TOPLEVEL::section::midiIn: // program / bank / root
371 value = indirectMidi(getData, synth, newMsg, guiTo, text);
372 break;
373 case TOPLEVEL::section::scales:
374 value = indirectScales(getData, synth, newMsg, guiTo, text);
375 break;
376
377 case TOPLEVEL::section::main:
378 value = indirectMain(getData, synth, newMsg, guiTo, text);
379 break;
380
381 case TOPLEVEL::section::bank: // instrument / bank
382 value = indirectBank(getData, synth, newMsg, guiTo, text);
383 break;
384
385 case TOPLEVEL::section::config:
386 value = indirectConfig(getData, synth, newMsg, guiTo, text);
387 break;
388
389 case TOPLEVEL::section::message:
390 newMsg = true;
391 getData->data.source &= ~TOPLEVEL::action::lowPrio;
392 break;
393 default:
394 if (switchNum < NUM_MIDI_PARTS)
395 {
396 value = indirectPart(getData, synth, newMsg, guiTo, text);
397 }
398 break;
399 }
400
401 // CLI message text has to be set here.
402 if (!synth->fileCompatible)
403 text += "\nIncompatible file from ZynAddSubFX 3.x";
404
405 if (newMsg)
406 value = textMsgBuffer.push(text);
407 // TODO need to improve message handling for multiple receivers
408
409 getData->data.value = float(value);
410 if (write)
411 lowPrioWrite = false;
412 if (noForward)
413 return;
414
415
416 if (getData->data.source < TOPLEVEL::action::lowPrio)
417 {
418 #ifdef GUI_FLTK
419 if (text != "" && synth->getRuntime().showGui && (write || guiTo))
420 {
421 getData->data.miscmsg = textMsgBuffer.push(text); // pass it on to GUI
422 }
423 #endif
424 bool ok = returnsBuffer.write(getData->bytes);
425 #ifdef GUI_FLTK
426 if (synth->getRuntime().showGui)
427 {
428 if (switchNum == TOPLEVEL::section::scales && control == SCALES::control::importScl)
429 { // loading a tuning includes a name and comment!
430 getData->data.control = SCALES::control::name;
431 getData->data.miscmsg = textMsgBuffer.push(synth->microtonal.Pname);
432 returnsBuffer.write(getData->bytes);
433 getData->data.control = SCALES::control::comment;
434 getData->data.miscmsg = textMsgBuffer.push(synth->microtonal.Pcomment);
435 ok &= returnsBuffer.write(getData->bytes);
436 }
437 if (switchNum == TOPLEVEL::section::main && control == MAIN::control::loadNamedState)
438 synth->midilearn.updateGui();
439 /*
440 * This needs improving. We should only set it
441 * when the state file contains a learn list.
442 */
443 }
444 #endif
445 if (!ok)
446 synth->getRuntime().Log("Unable to write to returnsBuffer buffer");
447
448 // cancelling and GUI report must be set after action completed.
449 if (!synth->fileCompatible)
450 {
451 synth->fileCompatible = true;
452 #ifdef GUI_FLTK
453 if (synth->getRuntime().showGui &&
454 (getData->data.source & TOPLEVEL::action::noAction) == TOPLEVEL::action::fromGUI)
455 {
456 getData->data.control = TOPLEVEL::control::textMessage;
457 getData->data.miscmsg = textMsgBuffer.push("File from ZynAddSubFX 3.0 or later has parameter types changed incompatibly with earlier versions, and with Yoshimi. It may not perform correctly.");
458 returnsBuffer.write(getData->bytes);
459 }
460 #endif
461 }
462 }
463 else // don't leave this hanging
464 {
465 synth->fileCompatible = true;
466 std::cout << "No indirect return" << std::endl;
467 }
468 }
469
470
indirectVector(CommandBlock * getData,SynthEngine * synth,unsigned char & newMsg,bool & guiTo,std::string & text)471 int InterChange::indirectVector(CommandBlock *getData, SynthEngine *synth, unsigned char &newMsg, bool &guiTo, std::string &text)
472 {
473 bool write = (getData->data.type & TOPLEVEL::type::Write);
474 int value = getData->data.value;
475 int control = getData->data.control;
476 int insert = getData->data.insert;
477
478 switch(control)
479 {
480 case VECTOR::control::name:
481 if (write)
482 synth->getRuntime().vectordata.Name[insert] = text;
483 else
484 text = synth->getRuntime().vectordata.Name[insert];
485 newMsg = true;
486 getData->data.source &= ~TOPLEVEL::action::lowPrio;
487 guiTo = true;
488 break;
489 }
490
491 return value;
492 }
493
494
indirectMidi(CommandBlock * getData,SynthEngine * synth,unsigned char & newMsg,bool & guiTo,std::string & text)495 int InterChange::indirectMidi(CommandBlock *getData, SynthEngine *synth, unsigned char &newMsg, bool &guiTo, std::string &text)
496 {
497 int value = getData->data.value;
498 int control = getData->data.control;
499 int msgID;
500 if (control == MIDI::control::instrument)
501 {
502 msgID = synth->setProgramFromBank(getData);
503 getData->data.control = MAIN::control::loadInstrumentFromBank;
504 getData->data.part = TOPLEVEL::section::main;
505 // moved to 'main' for return updates.
506 if (msgID > NO_MSG)
507 text = " FAILED " + text;
508 else
509 text = "ed ";
510 }
511 else
512 {
513 msgID = synth->setRootBank(getData->data.insert, getData->data.engine);
514 if (msgID > NO_MSG)
515 text = "FAILED " + text;
516 else
517 text = "";
518 }
519 text += textMsgBuffer.fetch(msgID & NO_MSG);
520 newMsg = true;
521 getData->data.source = TOPLEVEL::action::toAll;
522 // everyone will want to know about these!
523 guiTo = true;
524 return value;
525 }
526
527
indirectScales(CommandBlock * getData,SynthEngine * synth,unsigned char & newMsg,bool & guiTo,std::string & text)528 int InterChange::indirectScales(CommandBlock *getData, SynthEngine *synth, unsigned char &newMsg, bool &guiTo, std::string &text)
529 {
530 bool write = (getData->data.type & TOPLEVEL::type::Write);
531 int value = getData->data.value;
532 int control = getData->data.control;
533
534 switch(control)
535 {
536 case SCALES::control::tuning:
537 text = formatScales(text);
538 value = synth->microtonal.texttotunings(text.c_str());
539 if (value > 0)
540 synth->setAllPartMaps();
541 break;
542 case SCALES::control::keyboardMap:
543 text = formatScales(text);
544 value = synth->microtonal.texttomapping(text.c_str());
545 if (value > 0)
546 synth->setAllPartMaps();
547 break;
548
549 case SCALES::control::importScl:
550 value = synth->microtonal.loadscl(setExtension(text,EXTEN::scalaTuning));
551 if (value > 0)
552 {
553 text = "";
554 char *buf = new char[100];
555 for (int i = 0; i < value; ++ i)
556 {
557 synth->microtonal.tuningtoline(i, buf, 100);
558 if (i > 0)
559 text += "\n";
560 text += std::string(buf);
561 }
562 delete [] buf;
563 }
564 break;
565 case SCALES::control::importKbm:
566 value = synth->microtonal.loadkbm(setExtension(text,EXTEN::scalaKeymap));
567 if (value > 0)
568 {
569 text = "";
570 int map;
571 for (int i = 0; i < value; ++ i)
572 {
573 if (i > 0)
574 text += "\n";
575 map = synth->microtonal.Pmapping[i];
576 if (map == -1)
577 text += 'x';
578 else
579 text += std::to_string(map);
580 }
581 getData->data.kit = synth->microtonal.PrefNote;
582 getData->data.engine = synth->microtonal.Pfirstkey;
583 getData->data.insert = synth->microtonal.Pmiddlenote;
584 getData->data.parameter |= synth->microtonal.Plastkey; // need to keep top bit
585 synth->setAllPartMaps();
586 }
587 break;
588
589 case SCALES::control::name:
590 if (write)
591 {
592 synth->microtonal.Pname = text;
593 }
594 else
595 text = synth->microtonal.Pname;
596 newMsg = true;
597 break;
598 case SCALES::control::comment:
599 if (write)
600 synth->microtonal.Pcomment = text;
601 else
602 text = synth->microtonal.Pcomment;
603 newMsg = true;
604 break;
605 }
606 getData->data.source &= ~TOPLEVEL::action::lowPrio;
607 guiTo = true;
608 return value;
609 }
610
611
indirectMain(CommandBlock * getData,SynthEngine * synth,unsigned char & newMsg,bool & guiTo,std::string & text)612 int InterChange::indirectMain(CommandBlock *getData, SynthEngine *synth, unsigned char &newMsg, bool &guiTo, std::string &text)
613 {
614 bool write = (getData->data.type & TOPLEVEL::type::Write);
615 int value = getData->data.value;
616 int control = getData->data.control;
617 int kititem = getData->data.kit;
618 int insert = getData->data.insert;
619 switch (control)
620 {
621 case MAIN::control::detune:
622 {
623 if (write)
624 {
625 synth->microtonal.Pglobalfinedetune = value;
626 synth->setAllPartMaps();
627 }
628 else
629 value = synth->microtonal.Pglobalfinedetune;
630 break;
631 }
632 case MAIN::control::keyShift:
633 {
634 if (write)
635 {
636 synth->setPkeyshift(value + 64);
637 synth->setAllPartMaps();
638 }
639 else
640 value = synth->Pkeyshift - 64;
641 break;
642 }
643
644 case MAIN::control::exportBank:
645 {
646 if (kititem == UNUSED)
647 kititem = synth->getRuntime().currentRoot;
648 text = synth->bank.exportBank(text, kititem, value);
649 newMsg = true;
650 break;
651 }
652 case MAIN::control::importBank:
653 {
654 if (kititem == UNUSED)
655 kititem = synth->getRuntime().currentRoot;
656 text = synth->bank.importBank(text, kititem, value);
657 newMsg = true;
658 break;
659 }
660 case MAIN::control::deleteBank:
661 {
662 text = synth->bank.removebank(value, kititem);
663 newMsg = true;
664 break;
665 }
666 case MAIN::control::loadInstrumentFromBank:
667 {
668 unsigned int result = synth->setProgramFromBank(getData);
669 text = textMsgBuffer.fetch(result & NO_MSG);
670 if (result < 0x1000)
671 {
672 if (synth->getRuntime().bankHighlight)
673 synth->getRuntime().lastBankPart = (value << 15) | (synth->getRuntime().currentBank << 8) | synth->getRuntime().currentRoot;
674 else
675 synth->getRuntime().lastBankPart = UNUSED;
676 text = "ed " + text;
677 }
678 else
679 text = " FAILED " + text;
680 newMsg = true;
681 break;
682 }
683
684 case MAIN::control::loadInstrumentByName:
685 {
686 getData->data.miscmsg = textMsgBuffer.push(text);
687 unsigned int result = synth->setProgramByName(getData);
688 text = textMsgBuffer.fetch(result & NO_MSG);
689 synth->getRuntime().lastBankPart = UNUSED;
690 if (result < 0x1000)
691 text = "ed " + text;
692 else
693 text = " FAILED " + text;
694 newMsg = true;
695 break;
696 }
697
698 case MAIN::control::saveNamedInstrument:
699 {
700 bool ok = true;
701 int saveType = synth->getRuntime().instrumentFormat;
702 // This is both. Below we send them individually.
703
704 if (saveType & 2) // Yoshimi format
705 ok = synth->part[value]->saveXML(text, true);
706 if (ok && (saveType & 1)) // legacy
707 ok = synth->part[value]->saveXML(text, false);
708
709 if (ok)
710 {
711 synth->getRuntime().sessionSeen[TOPLEVEL::XML::Instrument] = true;
712 synth->addHistory(setExtension(text, EXTEN::zynInst), TOPLEVEL::XML::Instrument);
713 synth->part[value]->PyoshiType = (saveType & 2);
714 text = "d " + text;
715 }
716 else
717 text = " FAILED " + text;
718 newMsg = true;
719 break;
720 }
721 case MAIN::control::loadNamedPatchset:
722 vectorClear(NUM_MIDI_CHANNELS);
723 if (synth->loadPatchSetAndUpdate(text))
724 {
725 synth->addHistory(setExtension(text, EXTEN::patchset), TOPLEVEL::XML::Patch);
726 text = "ed " + text;
727 }
728 else
729 text = " FAILED " + text;
730 synth->getRuntime().lastBankPart = UNUSED;
731 newMsg = true;
732 break;
733 case MAIN::control::saveNamedPatchset:
734 if (synth->savePatchesXML(text))
735 {
736 synth->addHistory(setExtension(text, EXTEN::patchset), TOPLEVEL::XML::Patch);
737 text = "d " + text;
738 }
739 else
740 text = " FAILED " + text;
741 newMsg = true;
742 break;
743 case MAIN::control::loadNamedVector:
744 {
745 int tmp = synth->loadVectorAndUpdate(insert, text);
746 if (tmp < NO_MSG)
747 {
748 getData->data.insert = tmp;
749 synth->addHistory(setExtension(text, EXTEN::vector), TOPLEVEL::XML::Vector);
750 text = "ed " + text + " to chan " + std::to_string(int(tmp + 1));
751 }
752 else
753 text = " FAILED " + text;
754 synth->getRuntime().lastBankPart = UNUSED;
755 newMsg = true;
756 break;
757 }
758 case MAIN::control::saveNamedVector:
759 {
760 std::string oldname = synth->getRuntime().vectordata.Name[insert];
761 int pos = oldname.find("No Name");
762 if (pos >=0 && pos < 2)
763 synth->getRuntime().vectordata.Name[insert] = findLeafName(text);
764 int tmp = synth->saveVector(insert, text, true);
765 if (tmp == NO_MSG)
766 {
767 synth->addHistory(setExtension(text, EXTEN::vector), TOPLEVEL::XML::Vector);
768 text = "d " + text;
769 }
770 else
771 {
772 string name = textMsgBuffer.fetch(tmp);
773 if (name != "FAIL")
774 text = " " + name;
775 else
776 text = " FAILED " + text;
777 }
778 newMsg = true;
779 break;
780 }
781 case MAIN::control::loadNamedScale:
782 if (synth->loadMicrotonal(text))
783 {
784 synth->addHistory(setExtension(text, EXTEN::scale), TOPLEVEL::XML::Scale);
785 text = "ed " + text;
786 }
787 else
788 text = " FAILED " + text;
789 newMsg = true;
790 break;
791 case MAIN::control::saveNamedScale:
792 if (synth->saveMicrotonal(text))
793 {
794 synth->addHistory(setExtension(text, EXTEN::scale), TOPLEVEL::XML::Scale);
795 text = "d " + text;
796 }
797 else
798 text = " FAILED " + text;
799 newMsg = true;
800 break;
801 case MAIN::control::loadNamedState:
802 vectorClear(NUM_MIDI_CHANNELS);
803 if (synth->loadStateAndUpdate(text))
804 {
805 text = setExtension(text, EXTEN::state);
806 string name = file::configDir() + "/yoshimi";
807 name += ("-" + to_string(synth->getUniqueId()));
808 name += ".state";
809 if ((text != name)) // never include default state
810 synth->addHistory(text, TOPLEVEL::XML::State);
811 text = "ed " + text;
812 }
813 else
814 text = " FAILED " + text;
815 synth->getRuntime().lastBankPart = UNUSED;
816 newMsg = true;
817 break;
818 case MAIN::control::saveNamedState:
819 {
820 string filename = setExtension(text, EXTEN::state);
821 if (synth->saveState(filename))
822 {
823 string name = file::configDir() + "/yoshimi";
824 name += ("-" + to_string(synth->getUniqueId()));
825 name += ".state";
826 if ((text != name)) // never include default state
827 synth->addHistory(filename, TOPLEVEL::XML::State);
828 text = "d " + text;
829 }
830 else
831 text = " FAILED " + text;
832 newMsg = true;
833 break;
834 }
835 case MAIN::control::readLastSeen:
836 break; // do nothing here
837 case MAIN::control::loadFileFromList:
838 break; // do nothing here
839
840 case MAIN::control::defaultPart: // clear part
841 if (write)
842 {
843 doClearPart(value);
844 synth->getRuntime().sessionSeen[TOPLEVEL::XML::Instrument] = false;
845 getData->data.source &= ~TOPLEVEL::action::lowPrio;
846 }
847 break;
848
849 case MAIN::control::exportPadSynthSamples:
850 {
851 unsigned char partnum = insert;
852 synth->partonoffWrite(partnum, -1);
853 setpadparams(partnum, kititem);
854 if (synth->part[partnum]->kit[kititem].padpars->export2wav(text))
855 {
856 synth->addHistory(text, TOPLEVEL::XML::PadSample);
857 text = "d " + text;
858 }
859 else
860 text = " FAILED some samples " + text;
861 newMsg = true;
862 break;
863 }
864 case MAIN::control::masterReset:
865 synth->resetAll(0);
866 break;
867 case MAIN::control::masterResetAndMlearn:
868 synth->resetAll(1);
869 break;
870 case MAIN::control::openManual: // display user guide
871 {
872 // first try html version
873 text = "";
874 getData->data.control = TOPLEVEL::control::textMessage;
875 string found = findHtmlManual();
876 if (!found.empty())
877 {
878
879 size_t pos = found.rfind("files/yoshimi_user_guide_version");
880 found = found.substr(0, pos);
881 file::cmd2string("xdg-open " + found + "index.html &");
882 }
883 else
884 text = "Can't find manual :(";
885
886 if (found.empty())
887 { // fall back to older PDF version
888 std::string manfile = synth->manualname();
889 std::string stub = manfile.substr(0, manfile.rfind("-"));
890
891 std::string path = "";
892 std::string lastdir = "";
893 std::string search = "/usr/share/doc/yoshimi";
894 path = manualSearch(search, stub);
895 //std::cout << "name1 " << path << std::endl;
896 found = path;
897 lastdir = search;
898
899 search = "/usr/local/share/doc/yoshimi";
900 path = manualSearch(search, stub);
901 //std::cout << "name2 " << path << std::endl;
902 if (path >= found)
903 {
904 found = path;
905 lastdir = search;
906 }
907
908 search = localPath();
909 if (!search.empty())
910 {
911 path = manualSearch(search, stub);
912 //std::cout << "name3 " << path << std::endl;
913 if (path >= found)
914 {
915 found = path;
916 lastdir = search;
917 }
918 }
919
920 if (found.empty())
921 {
922 getData->data.miscmsg = textMsgBuffer.push("Can't find PDF manual :(");
923 returnsBuffer.write(getData->bytes);
924 }
925 else
926 {
927 if (found.substr(0, found.rfind(".")) != manfile)
928 getData->data.miscmsg = textMsgBuffer.push("Can't find last PDF. Looking for older one");
929 returnsBuffer.write(getData->bytes);
930 }
931 std::string command = "xdg-open " + lastdir + "/" + found + "&";
932 if (!file::cmd2string(command))
933 {
934 getData->data.miscmsg = textMsgBuffer.push("Can't find PDF reader :(");
935 returnsBuffer.write(getData->bytes);
936 found = "";
937 }
938 }
939 if (!found.empty())
940 {
941 text = "";
942 getData->data.miscmsg = NO_MSG;
943 returnsBuffer.write(getData->bytes);
944 }
945 newMsg = true;
946 break;
947
948 }
949 case MAIN::control::startInstance:
950 if (synth == firstSynth)
951 {
952 if (value > 0 && value < 32)
953 startInstance = value | 0x80;
954 else
955 startInstance = 0x81; // next available
956 while (startInstance > 0x80)
957 usleep(1000);
958 value = startInstance; // actual instance found
959 startInstance = 0; // just to be sure
960 }
961 break;
962 case MAIN::control::stopInstance:
963 text = std::to_string(value) + " ";
964 if (value < 0 || value >= 32)
965 text += "Out of range";
966 else
967 {
968 SynthEngine *toClose = firstSynth->getSynthFromId(value);
969 if (toClose == firstSynth && value > 0)
970 text += "Can't find";
971 else
972 {
973 toClose->getRuntime().runSynth = false;
974 text += "Closed";
975 }
976 }
977 newMsg = true;
978 break;
979
980 case MAIN::control::stopSound:
981 #ifdef REPORT_NOTES_ON_OFF
982 // note test
983 synth->getRuntime().Log("note on sent " + std::to_string(synth->getRuntime().noteOnSent));
984 synth->getRuntime().Log("note on seen " + std::to_string(synth->getRuntime().noteOnSeen));
985 synth->getRuntime().Log("note off sent " + std::to_string(synth->getRuntime().noteOffSent));
986 synth->getRuntime().Log("note off seen " + std::to_string(synth->getRuntime().noteOffSeen));
987 synth->getRuntime().Log("notes hanging sent " + std::to_string(synth->getRuntime().noteOnSent - synth->getRuntime().noteOffSent));
988 synth->getRuntime().Log("notes hanging seen " + std::to_string(synth->getRuntime().noteOnSeen - synth->getRuntime().noteOffSeen));
989 #endif
990 synth->ShutUp();
991 break;
992 }
993 getData->data.source &= ~TOPLEVEL::action::lowPrio;
994 if (control != MAIN::control::startInstance && control != MAIN::control::stopInstance)
995 guiTo = true;
996 return value;
997 }
998
999
1000
indirectBank(CommandBlock * getData,SynthEngine * synth,unsigned char & newMsg,bool & guiTo,std::string & text)1001 int InterChange::indirectBank(CommandBlock *getData, SynthEngine *synth, unsigned char &newMsg, bool &guiTo, std::string &text)
1002 {
1003 bool write = (getData->data.type & TOPLEVEL::type::Write);
1004 int value = getData->data.value;
1005 int control = getData->data.control;
1006 int kititem = getData->data.kit;
1007 int engine = getData->data.engine;
1008 int insert = getData->data.insert;
1009 int parameter = getData->data.parameter;
1010 switch (control)
1011 {
1012 case BANK::control::renameInstrument:
1013 {
1014 if (kititem == UNUSED)
1015 {
1016 kititem = synth->getRuntime().currentBank;
1017 getData->data.kit = kititem;
1018 }
1019 if (engine == UNUSED)
1020 {
1021 engine = synth->getRuntime().currentRoot;
1022 getData->data.engine = engine;
1023 }
1024 int msgID = synth->bank.setInstrumentName(text, insert, kititem, engine);
1025 if (msgID > NO_MSG)
1026 text = " FAILED ";
1027 else
1028 text = " ";
1029 text += textMsgBuffer.fetch(msgID & NO_MSG);
1030 synth->getRuntime().lastBankPart = UNUSED;
1031 newMsg = true;
1032 break;
1033 }
1034 case BANK::control::saveInstrument:
1035 {
1036 if (kititem == UNUSED)
1037 {
1038 kititem = synth->getRuntime().currentBank;
1039 getData->data.kit = kititem;
1040 }
1041 if (engine == UNUSED)
1042 {
1043 engine = synth->getRuntime().currentRoot;
1044 getData->data.engine = engine;
1045 }
1046 if (parameter == UNUSED)
1047 {
1048 parameter = synth->getRuntime().currentPart;
1049 getData->data.parameter = parameter;
1050 }
1051 text = synth->part[parameter]->Pname;
1052 if (text == DEFAULT_NAME)
1053 text = "FAILED Can't save default instrument type";
1054 else if (!synth->bank.savetoslot(engine, kititem, insert, parameter))
1055 text = "FAILED Could not save " + text + " to " + to_string(insert + 1);
1056 else
1057 { // 0x80 on engine indicates it is a save not a load
1058 if (synth->getRuntime().bankHighlight)
1059 synth->getRuntime().lastBankPart = (insert << 15) | (kititem << 8) | engine | 0x80;
1060 text = "" + to_string(insert + 1) +". " + text;
1061 }
1062 newMsg = true;
1063 break;
1064 }
1065 case BANK::control::deleteInstrument:
1066 {
1067 text = synth->bank.clearslot(value, synth->getRuntime().currentRoot, synth->getRuntime().currentBank);
1068 synth->getRuntime().lastBankPart = UNUSED;
1069 newMsg = true;
1070 break;
1071 }
1072
1073 case BANK::control::selectFirstInstrumentToSwap:
1074 {
1075 if (kititem == UNUSED)
1076 {
1077 kititem = synth->getRuntime().currentBank;
1078 getData->data.kit = kititem;
1079 }
1080 if (engine == UNUSED)
1081 {
1082 engine = synth->getRuntime().currentRoot;
1083 getData->data.engine = engine;
1084 }
1085 swapInstrument1 = insert;
1086 swapBank1 = kititem;
1087 swapRoot1 = engine;
1088 break;
1089 }
1090 case BANK::control::selectSecondInstrumentAndSwap:
1091 {
1092 if (kititem == UNUSED)
1093 {
1094 kititem = synth->getRuntime().currentBank;
1095 getData->data.kit = kititem;
1096 }
1097 if (engine == UNUSED)
1098 {
1099 engine = synth->getRuntime().currentRoot;
1100 getData->data.engine = engine;
1101 }
1102 text = synth->bank.swapslot(swapInstrument1, insert, swapBank1, kititem, swapRoot1, engine);
1103 swapInstrument1 = UNUSED;
1104 swapBank1 = UNUSED;
1105 swapRoot1 = UNUSED;
1106 synth->getRuntime().lastBankPart = UNUSED;
1107 newMsg = true;
1108 guiTo = true;
1109 break;
1110 }
1111 case BANK::control::selectBank:
1112 if (engine == UNUSED)
1113 engine = getData->data.engine = synth->getRuntime().currentRoot;
1114 if (write)
1115 {
1116 text = textMsgBuffer.fetch(synth->setRootBank(engine, value) & NO_MSG);
1117
1118 }
1119 else
1120 {
1121 int tmp = synth->getRuntime().currentBank;
1122 text = "Current: " +(to_string(tmp)) + " " + synth->bank.getBankName(tmp, getData->data.engine);
1123 }
1124 newMsg = true;
1125 break;
1126 case BANK::control::renameBank:
1127 if (engine == UNUSED)
1128 engine = getData->data.engine = synth->getRuntime().currentRoot;
1129 if (write)
1130 {
1131 int tmp = synth->bank.changeBankName(getData->data.engine, value, text);
1132 text = textMsgBuffer.fetch(tmp & NO_MSG);
1133 if (tmp > NO_MSG)
1134 text = "FAILED: " + text;
1135 guiTo = true;
1136 }
1137 else
1138 {
1139 text = " Name: " + synth->bank.getBankName(value, getData->data.engine);
1140 }
1141 newMsg = true;
1142 break;
1143 case BANK::control::createBank:
1144 {
1145 bool isOK = true;
1146 int newbank = kititem;
1147 int rootID = engine;
1148 if (rootID == UNUSED)
1149 rootID = synth->getRuntime().currentRoot;
1150 if (newbank == UNUSED)
1151 {
1152 isOK = false;
1153 newbank = 5; // offset to avoid zero for as long as possible
1154 for (int i = 0; i < MAX_BANKS_IN_ROOT; ++i)
1155 {
1156 newbank = (newbank + 5) & 0x7f;
1157 if (synth->getBankRef().getBankName(newbank, rootID).empty())
1158 {
1159 isOK = true;
1160 break;
1161 }
1162 }
1163 if (!isOK)
1164 text = "FAILED: Root " + to_string(rootID) + " has no space";
1165 }
1166 if (isOK)
1167 {
1168 string trytext = synth->bank.getBankName(newbank, rootID);
1169 if (!trytext.empty())
1170 {
1171 text = "FAILED: ID " + to_string(newbank) + " already contains " + trytext;
1172 isOK = false;
1173 }
1174
1175 if (isOK && !synth->getBankRef().newIDbank(text, newbank))
1176 {
1177 text = "FAILED Could not create bank " + text + " for ID " + asString(newbank);
1178 isOK = false;
1179 }
1180 }
1181 if (isOK)
1182 text = "Created " + text + " at ID " + to_string(newbank) + " in root " + to_string(rootID);
1183 newMsg = true;
1184 guiTo = true;
1185 }
1186 break;
1187
1188 case BANK::control::deleteBank:
1189 break; // not yet!
1190
1191 case BANK::control::findBankSize:
1192 if (engine == UNUSED)
1193 engine = synth->getRuntime().currentRoot;
1194 if (synth->bank.getBankName(kititem, engine).empty())
1195 value = UNUSED;
1196 else
1197 value = synth->bank.getBankSize(kititem, engine);
1198 break;
1199
1200 case BANK::control::selectFirstBankToSwap:
1201 if (engine == UNUSED)
1202 {
1203 engine = synth->getRuntime().currentRoot;
1204 getData->data.engine = engine;
1205 }
1206 swapBank1 = kititem;
1207 swapRoot1 = engine;
1208 break;
1209 case BANK::control::selectSecondBankAndSwap:
1210 if (engine == UNUSED)
1211 {
1212 engine = synth->getRuntime().currentRoot;
1213 getData->data.engine = engine;
1214 }
1215 text = synth->bank.swapbanks(swapBank1, kititem, swapRoot1, engine);
1216 swapBank1 = UNUSED;
1217 swapRoot1 = UNUSED;
1218 newMsg = true;
1219 guiTo = true;
1220 break;
1221
1222 case BANK::control::selectRoot:
1223 if (write)
1224 {
1225 int msgID = synth->setRootBank(value, UNUSED);
1226 if (msgID < NO_MSG)
1227 synth->saveBanks(); // do we need this when only selecting?
1228 text = textMsgBuffer.fetch(msgID & NO_MSG);
1229 }
1230 else
1231 {
1232 int tmp = synth->getRuntime().currentRoot;
1233 text = "Current Root: " +(to_string(tmp)) + " " + synth->bank.getRootPath(tmp);
1234 }
1235 newMsg = true;
1236 break;
1237 case BANK::control::changeRootId:
1238 if (engine == UNUSED)
1239 getData->data.engine = synth->getRuntime().currentRoot;
1240 synth->bank.changeRootID(getData->data.engine, value);
1241 synth->saveBanks();
1242 break;
1243 case BANK::addNamedRoot:
1244 if (write) // not realistically readable
1245 {
1246 if (kititem != UNUSED)
1247 {
1248 kititem = synth->getBankRef().generateSingleRoot(text, false);
1249 getData->data.kit = kititem;
1250 synth->getBankRef().installNewRoot(kititem, text);
1251 synth->saveBanks();
1252 }
1253 else
1254 {
1255 size_t found = synth->getBankRef().addRootDir(text);
1256 if (found)
1257 {
1258 synth->getBankRef().installNewRoot(found, text);
1259 synth->saveBanks();
1260 }
1261 else
1262 {
1263 value = UNUSED;
1264 text = "Can't find path " + text;
1265 }
1266 }
1267 newMsg = true;
1268 }
1269 break;
1270 case BANK::deselectRoot:
1271 if (write) // not realistically readable
1272 {
1273 if (synth->getBankRef().removeRoot(kititem))
1274 value = UNUSED;
1275 synth->saveBanks();
1276 }
1277 break;
1278
1279 case BANK::control::refreshDefaults:
1280 if (value)
1281 synth->bank.checkLocalBanks();
1282 synth->getRuntime().banksChecked = true;
1283 break;
1284 }
1285 getData->data.source &= ~TOPLEVEL::action::lowPrio;
1286 return value;
1287 }
1288
1289
indirectConfig(CommandBlock * getData,SynthEngine * synth,unsigned char & newMsg,bool & guiTo,std::string & text)1290 int InterChange::indirectConfig(CommandBlock *getData, SynthEngine *synth, unsigned char &newMsg, bool &guiTo, std::string &text)
1291 {
1292 bool write = (getData->data.type & TOPLEVEL::type::Write);
1293 int value = getData->data.value;
1294 int control = getData->data.control;
1295 int kititem = getData->data.kit;
1296 switch (control)
1297 {
1298 case CONFIG::control::jackMidiSource:
1299 if (write)
1300 {
1301 synth->getRuntime().jackMidiDevice = text;
1302 synth->getRuntime().configChanged = true;
1303 }
1304 else
1305 text = synth->getRuntime().jackMidiDevice;
1306 newMsg = true;
1307 break;
1308 case CONFIG::control::jackServer:
1309 if (write)
1310 {
1311 synth->getRuntime().jackServer = text;
1312 synth->getRuntime().configChanged = true;
1313 }
1314 else
1315 text = synth->getRuntime().jackServer;
1316 newMsg = true;
1317 break;
1318 case CONFIG::control::alsaMidiSource:
1319 if (write)
1320 {
1321 synth->getRuntime().alsaMidiDevice = text;
1322 synth->getRuntime().configChanged = true;
1323 }
1324 else
1325 text = synth->getRuntime().alsaMidiDevice;
1326 newMsg = true;
1327 break;
1328 case CONFIG::control::alsaAudioDevice:
1329 if (write)
1330 {
1331 synth->getRuntime().alsaAudioDevice = text;
1332 synth->getRuntime().configChanged = true;
1333 }
1334 else
1335 text = synth->getRuntime().alsaAudioDevice;
1336 newMsg = true;
1337 break;
1338 case CONFIG::control::addPresetRootDir:
1339 {
1340 bool isOK = false;
1341 if (isDirectory(text))
1342 isOK= true;
1343 else
1344 {
1345 if (createDir(text))
1346 {
1347 text = " FAILED could not create " + text;
1348 }
1349 else
1350 isOK = true;
1351 }
1352 if (isOK)
1353 {
1354 int i = 0;
1355 while (!firstSynth->getRuntime().presetsDirlist[i].empty())
1356 ++i;
1357 if (i > (MAX_PRESETS - 2))
1358 text = " FAILED preset list full";
1359 else
1360 {
1361 firstSynth->getRuntime().presetsDirlist[i] = text;
1362 text = "ed " + text;
1363 }
1364 }
1365 newMsg = true;
1366 synth->getRuntime().configChanged = true;
1367 break;
1368 }
1369 case CONFIG::control::removePresetRootDir:
1370 {
1371 int i = value;
1372 text = firstSynth->getRuntime().presetsDirlist[i];
1373 while (!firstSynth->getRuntime().presetsDirlist[i + 1].empty())
1374 {
1375 firstSynth->getRuntime().presetsDirlist[i] = firstSynth->getRuntime().presetsDirlist[i + 1];
1376 ++i;
1377 }
1378 firstSynth->getRuntime().presetsDirlist[i] = "";
1379 synth->getRuntime().currentPreset = 0;
1380 newMsg = true;
1381 synth->getRuntime().configChanged = true;
1382 break;
1383 }
1384 case CONFIG::control::currentPresetRoot:
1385 {
1386 if (write)
1387 {
1388 synth->getRuntime().currentPreset = value;
1389 synth->getRuntime().configChanged = true;
1390 }
1391 else
1392 value = synth->getRuntime().currentPreset = value;
1393 text = firstSynth->getRuntime().presetsDirlist[value];
1394 newMsg = true;
1395 break;
1396 }
1397 case CONFIG::control::saveCurrentConfig:
1398 if (write)
1399 {
1400 text = synth->getRuntime().ConfigFile;
1401 if (synth->getRuntime().saveConfig())
1402 text = "d " + text;
1403 else
1404 text = " FAILED " + text;
1405 }
1406 else
1407 text = "READ";
1408 newMsg = true;
1409 getData->data.miscmsg = textMsgBuffer.push(text); // slightly odd case
1410 break;
1411 case CONFIG::control::historyLock:
1412 {
1413 if (write)
1414 {
1415 synth->setHistoryLock(kititem, value);
1416 synth->getRuntime().configChanged = true;
1417 }
1418 else
1419 value = synth->getHistoryLock(kititem);
1420 break;
1421 }
1422 }
1423 if ((getData->data.source & TOPLEVEL::action::noAction) != TOPLEVEL::action::fromGUI)
1424 guiTo = true;
1425 getData->data.source &= ~TOPLEVEL::action::lowPrio;
1426 return value;
1427 }
1428
1429
indirectPart(CommandBlock * getData,SynthEngine * synth,unsigned char & newMsg,bool & guiTo,std::string & text)1430 int InterChange::indirectPart(CommandBlock *getData, SynthEngine *synth, unsigned char &newMsg, bool &guiTo, std::string &text)
1431 {
1432 bool write = (getData->data.type & TOPLEVEL::type::Write);
1433 int value = getData->data.value;
1434 int control = getData->data.control;
1435 int npart = getData->data.part;
1436 int kititem = getData->data.kit;
1437 int parameter = getData->data.parameter;
1438
1439 Part *part = synth->part[npart];
1440
1441 switch(control)
1442 {
1443 case PART::control::keyShift:
1444 {
1445 if (write)
1446 {
1447 part->Pkeyshift = value + 64;
1448 synth->setPartMap(npart);
1449 }
1450 else
1451 value = part->Pkeyshift - 64;
1452 getData->data.source &= ~TOPLEVEL::action::lowPrio;
1453 }
1454 break;
1455 case PART::control::enableKitLine:
1456 if (write)
1457 {
1458 part->setkititemstatus(kititem, value);
1459 synth->partonoffWrite(npart, 2);
1460 getData->data.source &= ~TOPLEVEL::action::lowPrio;
1461 }
1462 break;
1463
1464 case PART::control::enablePad:
1465 if (write)
1466 {
1467 int temp = kititem;
1468 if (temp >= NUM_KIT_ITEMS)
1469 temp = 0;
1470 setpadparams(npart, temp);
1471 getData->data.source &= ~TOPLEVEL::action::lowPrio;
1472 }
1473 break;
1474 case PART::control::padsynthParameters:
1475 if (write)
1476 {
1477 setpadparams(npart, kititem);
1478 getData->data.source &= ~TOPLEVEL::action::lowPrio;
1479 }
1480 else
1481 value = part->kit[kititem].padpars->Papplied;
1482 break;
1483
1484 case PART::control::audioDestination:
1485 if (npart < synth->getRuntime().NumAvailableParts)
1486 {
1487 if (value & 2)
1488 {
1489 mainRegisterAudioPort(synth, npart);
1490 }
1491 getData->data.source &= ~TOPLEVEL::action::lowPrio;
1492 }
1493 break;
1494 case PART::control::instrumentCopyright:
1495 if (write)
1496 {
1497 part->info.Pauthor = text;
1498 guiTo = true;
1499 }
1500 else
1501 text = part->info.Pauthor;
1502 getData->data.source &= ~TOPLEVEL::action::lowPrio;
1503 newMsg = true;
1504 break;
1505 case PART::control::instrumentComments:
1506 if (write)
1507 {
1508 part->info.Pcomments = text;
1509 guiTo = true;
1510 }
1511 else
1512 text = part->info.Pcomments;
1513 getData->data.source &= ~TOPLEVEL::action::lowPrio;
1514 newMsg = true;
1515 break;
1516 case PART::control::instrumentName: // part or kit item names
1517 if (kititem == UNUSED)
1518 {
1519 if (write)
1520 {
1521 part->Pname = text;
1522 if (part->Poriginal.empty())
1523 part->Poriginal = text;
1524 guiTo = true;
1525 }
1526 else
1527 {
1528 text = part->Pname;
1529 }
1530 }
1531 else if (part->Pkitmode)
1532 {
1533 if (kititem >= NUM_KIT_ITEMS)
1534 text = " FAILED out of range";
1535 else
1536 {
1537 if (write)
1538 {
1539 part->kit[kititem].Pname = text;
1540 guiTo = true;
1541 }
1542 else
1543 {
1544 text = part->kit[kititem].Pname;
1545 }
1546 }
1547 }
1548 else
1549 text = " FAILED Not in kit mode";
1550 getData->data.source &= ~TOPLEVEL::action::lowPrio;
1551 newMsg = true;
1552 break;
1553 case PART::control::instrumentType:
1554 if (write)
1555 {
1556 part->info.Ptype = value;
1557 guiTo = true;
1558 }
1559 else
1560 value = part->info.Ptype;
1561 getData->data.source &= ~TOPLEVEL::action::lowPrio;
1562 break;
1563 case PART::control::defaultInstrumentCopyright:
1564 std::string name = file::configDir() + "/copyright.txt";
1565 if (parameter == 0) // load
1566 {
1567 text = loadText(name); // TODO provide failure warning
1568 text = func::formatTextLines(text, 54);
1569 part->info.Pauthor = text;
1570 guiTo = true;
1571 }
1572 else
1573 {
1574 text = part->info.Pauthor;
1575 saveText(text, name);
1576 }
1577 getData->data.source &= ~TOPLEVEL::action::lowPrio;
1578 newMsg = true;
1579 break;
1580 }
1581 return value;
1582 }
1583
formatScales(std::string text)1584 std::string InterChange::formatScales(std::string text)
1585 {
1586 text.erase(remove(text.begin(), text.end(), ' '), text.end());
1587 std::string delimiters = ",";
1588 size_t current;
1589 size_t next = -1;
1590 size_t found;
1591 std::string word;
1592 std::string newtext = "";
1593 do
1594 {
1595 current = next + 1;
1596 next = text.find_first_of(delimiters, current );
1597 word = text.substr(current, next - current );
1598
1599 found = word.find('.');
1600 if (found != string::npos)
1601 {
1602 if (found < 4)
1603 {
1604 std::string tmp (4 - found, '0'); // leading zeros
1605 word = tmp + word;
1606 }
1607 found = word.size();
1608 if (found < 11)
1609 {
1610 std::string tmp (11 - found, '0'); // trailing zeros
1611 word += tmp;
1612 }
1613 }
1614 newtext += word;
1615 if (next != string::npos)
1616 newtext += "\n";
1617 }
1618 while (next != string::npos);
1619 return newtext;
1620 }
1621
1622
readAllData(CommandBlock * getData)1623 float InterChange::readAllData(CommandBlock *getData)
1624 {
1625 if (getData->data.type & TOPLEVEL::type::Limits) // these are static
1626 {
1627 /*
1628 * commandtype limits values
1629 * 0 adjusted input value
1630 * 1 min
1631 * 2 max
1632 * 3 default
1633 *
1634 * tryData.data.type will be updated:
1635 * bit 5 set MIDI-learnable
1636 * bit 7 set Is an integer value
1637 */
1638 getData->data.type -= TOPLEVEL::type::Limits;
1639 float value = returnLimits(getData);
1640 synth->getRuntime().finishedCLI = true;
1641 return value;
1642 }
1643
1644 // these are not!
1645
1646 /*
1647 * VU always responds even when loading a *huge*
1648 * PadSynth instrument. This is safe because the part
1649 * being changed is disabled, so won't be seen.
1650 *
1651 * Other reads will be blocked.
1652 * This needs improving.
1653 */
1654 CommandBlock tryData;
1655 unsigned char control = getData->data.control;
1656 if (getData->data.part == TOPLEVEL::section::main && (control >= MAIN::control::readPartPeak && control <= MAIN::control::readMainLRrms))
1657 {
1658 commandSendReal(getData);
1659 synth->fetchMeterData();
1660 return getData->data.value;
1661 }
1662 int npart = getData->data.part;
1663 bool indirect = ((getData->data.source & TOPLEVEL::action::muteAndLoop) == TOPLEVEL::action::lowPrio);
1664 if (npart < NUM_MIDI_PARTS && synth->part[npart]->busy)
1665 {
1666 getData->data.control = PART::control::partBusy; // part busy message
1667 getData->data.kit = UNUSED;
1668 getData->data.engine = UNUSED;
1669 getData->data.insert = UNUSED;
1670 }
1671 reTry:
1672 memcpy(tryData.bytes, getData->bytes, sizeof(tryData));
1673 while (syncWrite || lowPrioWrite)
1674 usleep(10);
1675 if (indirect)
1676 {
1677 /*
1678 * This still isn't quite right there is a very
1679 * remote chance of getting garbled text :(
1680 */
1681 indirectTransfers(&tryData, true);
1682 synth->getRuntime().finishedCLI = true;
1683 return tryData.data.value;
1684 }
1685 else
1686 commandSendReal(&tryData);
1687 if (syncWrite || lowPrioWrite)
1688 goto reTry; // it may have changed mid-process
1689
1690 if ((tryData.data.source & TOPLEVEL::action::noAction) == TOPLEVEL::action::fromCLI)
1691 resolveReplies(&tryData);
1692
1693
1694 synth->getRuntime().finishedCLI = true; // in case it misses lines above
1695 return tryData.data.value;
1696 }
1697
1698
resolveReplies(CommandBlock * getData)1699 void InterChange::resolveReplies(CommandBlock *getData)
1700 {
1701 if (false)
1702 {
1703 std::cout << "\nType " << int(getData->data.type) << " Action " << int(getData->data.source) << " Control " << int(getData->data.control) << " Value " << getData->data.value
1704 << "\nPart " << int(getData->data.part) << " Kit " << int(getData->data.kit) << " Engine " << int(getData->data.engine)
1705 << "\nInsert " << int(getData->data.insert) << " Parameter " << int(getData->data.parameter) << " Offset " << int(getData->data.offset)
1706 << "\nMiscMsg " << int(getData->data.miscmsg) << " Spare1 " << int(getData->data.spare1) << " Spare0 " << int(getData->data.spare0) << std::endl;
1707 }
1708 unsigned char source = getData->data.source & TOPLEVEL::action::noAction;
1709 // making sure there are no stray top bits.
1710 if (source == TOPLEVEL::action::noAction)
1711 {
1712 // in case it was originally called from CLI
1713 synth->getRuntime().finishedCLI = true;
1714 return; // no further action
1715 }
1716
1717 if (getData->data.type & TOPLEVEL::type::LearnRequest)
1718 {
1719 synth->midilearn.setTransferBlock(getData);
1720 return;
1721 }
1722
1723 if (source != TOPLEVEL::action::fromMIDI)
1724 synth->getRuntime().Log(resolveAll(synth, getData, _SYS_::LogNotSerious));
1725
1726 if (source == TOPLEVEL::action::fromCLI)
1727 synth->getRuntime().finishedCLI = true;
1728 }
1729
1730
1731 // This is only used when no valid banks can be found
generateSpecialInstrument(int npart,std::string name)1732 void InterChange::generateSpecialInstrument(int npart, std::string name)
1733 {
1734 synth->part[npart]->Pname = name;
1735 Part *part;
1736 part = synth->part[npart];
1737 part->partefx[0]->changeeffect(1);
1738 part->kit[0].Padenabled = false;
1739 part->kit[0].Psubenabled = true;
1740
1741 SUBnoteParameters *pars;
1742 pars = part->kit[0].subpars;
1743 pars->Phmag[1] = 75;
1744 pars->Phmag[2] = 40;
1745 pars->Pbandwidth = 60;
1746 }
1747
1748
mediate()1749 void InterChange::mediate()
1750 {
1751 CommandBlock getData;
1752 getData.data.control = UNUSED; // No other data element could be read uninitialised
1753 syncWrite = true;
1754 bool more;
1755 do
1756 {
1757 more = false;
1758 #ifndef YOSHIMI_LV2_PLUGIN
1759 if (fromCLI.read(getData.bytes))
1760 {
1761 more = true;
1762 if (getData.data.part != TOPLEVEL::section::midiLearn) // Not special midi-learn message
1763 commandSend(&getData);
1764 returns(&getData);
1765 }
1766 #endif
1767 #ifdef GUI_FLTK
1768 if (synth->getRuntime().showGui
1769 && fromGUI.read(getData.bytes))
1770 {
1771 more = true;
1772 if (getData.data.part != TOPLEVEL::section::midiLearn) // Not special midi-learn message
1773 commandSend(&getData);
1774 returns(&getData);
1775 }
1776 #endif
1777 if (fromMIDI.read(getData.bytes))
1778 {
1779 more = true;
1780 if (getData.data.part != TOPLEVEL::section::midiLearn)
1781 // Normal MIDI message, not special midi-learn message
1782 {
1783 historyActionCheck(&getData);
1784 commandSend(&getData);
1785 returns(&getData);
1786 }
1787 #ifdef GUI_FLTK
1788 else if (synth->getRuntime().showGui
1789 && getData.data.control == MIDILEARN::control::reportActivity)
1790 toGUI.write(getData.bytes);
1791 #endif
1792 }
1793 else if (getData.data.control == TOPLEVEL::section::midiLearn)
1794 {
1795 // we are looking at the MIDI learn control type that any section *except* MIDI can send.
1796 synth->mididecode.midiProcess(getData.data.kit, getData.data.engine, getData.data.insert, false);
1797 }
1798 if (returnsBuffer.read(getData.bytes))
1799 {
1800 returns(&getData);
1801 more = true;
1802 }
1803
1804 // temporary fix block
1805 // TODO find a better place to put this out of the main process!
1806
1807 int effpar = synth->getRuntime().effectChange;
1808 if (effpar > 0xffff)
1809 {
1810 #ifdef GUI_FLTK
1811 if (synth->getRuntime().showGui)
1812 {
1813 CommandBlock effData;
1814 memset(&effData.bytes, 255, sizeof(effData));
1815 unsigned char npart = effpar & 0xff;
1816 unsigned char effnum = (effpar >> 8) & 0xff;
1817 unsigned char efftype;
1818 if (npart < NUM_MIDI_PARTS)
1819 {
1820 efftype = synth->part[npart]->partefx[effnum]->geteffect();
1821 effData.data.control = PART::control::effectType;
1822 }
1823 else
1824 {
1825 effData.data.control = EFFECT::sysIns::effectType;
1826 if (npart == TOPLEVEL::section::systemEffects)
1827 efftype = synth->sysefx[effnum]->geteffect();
1828 else
1829 efftype = synth->insefx[effnum]->geteffect();
1830 }
1831 effData.data.source = TOPLEVEL::action::fromGUI | TOPLEVEL::action::forceUpdate;
1832 effData.data.type = TOPLEVEL::type::Write;
1833 effData.data.value = efftype;
1834 effData.data.part = npart;
1835 effData.data.engine = effnum;
1836 toGUI.write(effData.bytes);
1837 }
1838 #endif
1839 synth->getRuntime().effectChange = UNUSED;
1840 } // end of temporary fix
1841
1842 }
1843 while (more && synth->getRuntime().runSynth);
1844 syncWrite = false;
1845 }
1846
1847
1848 /*
1849 * Currently this is only used by MIDI NRPNs but eventually
1850 * be used as a unified way of catching all list loads.
1851 */
historyActionCheck(CommandBlock * getData)1852 void InterChange::historyActionCheck(CommandBlock *getData)
1853 {
1854 if (getData->data.part != TOPLEVEL::section::main || getData->data.control != MAIN::control::loadFileFromList)
1855 return;
1856 getData->data.type |= TOPLEVEL::type::Write; // just to be sure
1857 switch (getData->data.kit)
1858 {
1859 case TOPLEVEL::XML::Instrument:
1860 getData->data.source |= TOPLEVEL::action::lowPrio;
1861 synth->partonoffWrite((getData->data.insert << 4), -1);
1862 break;
1863 case TOPLEVEL::XML::Patch:
1864 getData->data.source |= TOPLEVEL::action::muteAndLoop;
1865 break;
1866 case TOPLEVEL::XML::Scale:
1867 getData->data.source |= TOPLEVEL::action::lowPrio;
1868 break;
1869 case TOPLEVEL::XML::State:
1870 getData->data.source |= TOPLEVEL::action::muteAndLoop;
1871 break;
1872 case TOPLEVEL::XML::Vector:
1873 getData->data.source |= TOPLEVEL::action::muteAndLoop;
1874 break;
1875 }
1876 }
1877
1878
returns(CommandBlock * getData)1879 void InterChange::returns(CommandBlock *getData)
1880 {
1881 synth->getRuntime().finishedCLI = true; // belt and braces :)
1882 if ((getData->data.source & TOPLEVEL::action::noAction) == TOPLEVEL::action::noAction)
1883 return; // no further action
1884
1885 if (getData->data.source < TOPLEVEL::action::lowPrio)
1886 { // currently only used by gui. this may change!
1887 #ifdef GUI_FLTK
1888 if (synth->getRuntime().showGui)
1889 {
1890 unsigned char type = getData->data.type; // back from synth
1891 int tmp = (getData->data.source & TOPLEVEL::action::noAction);
1892 if (getData->data.source & TOPLEVEL::action::forceUpdate)
1893 tmp = TOPLEVEL::action::toAll;
1894
1895 if ((type & TOPLEVEL::type::Write) && tmp != TOPLEVEL::action::fromGUI)
1896 toGUI.write(getData->bytes);
1897 }
1898 #endif
1899 }
1900 if (!decodeLoopback.write(getData->bytes))
1901 synth->getRuntime().Log("Unable to write to decodeLoopback buffer");
1902 }
1903
1904
setpadparams(int npart,int kititem)1905 void InterChange::setpadparams(int npart, int kititem)
1906 {
1907 synth->part[npart]->busy = true;
1908 if (synth->part[npart]->kit[kititem].padpars != NULL)
1909 synth->part[npart]->kit[kititem].padpars->applyparameters();
1910 synth->part[npart]->busy = false;
1911 synth->partonoffWrite(npart, 2);
1912 }
1913
1914
doClearPart(int npart)1915 void InterChange::doClearPart(int npart)
1916 {
1917 synth->part[npart]->defaultsinstrument();
1918 synth->part[npart]->cleanup();
1919 synth->getRuntime().currentPart = npart;
1920 synth->partonoffWrite(npart, 2);
1921 }
1922
commandSend(CommandBlock * getData)1923 bool InterChange::commandSend(CommandBlock *getData)
1924 {
1925 bool isChanged = commandSendReal(getData);
1926 bool isWrite = (getData->data.type & TOPLEVEL::type::Write) > 0;
1927 if (isWrite && isChanged) //write command
1928 {
1929 synth->setNeedsSaving(true);
1930 unsigned char control = getData->data.control;
1931 unsigned char npart = getData->data.part;
1932 unsigned char insert = getData->data.insert;
1933 if (npart < NUM_MIDI_PARTS && (insert != UNUSED || (control != PART::control::enable && control != PART::control::instrumentName)))
1934 {
1935 if (synth->part[npart]->Pname == DEFAULT_NAME)
1936 {
1937 synth->part[npart]->Pname = UNTITLED;
1938 getData->data.source |= TOPLEVEL::action::forceUpdate;
1939 }
1940 }
1941 }
1942 return isChanged;
1943 }
1944
1945
commandSendReal(CommandBlock * getData)1946 bool InterChange::commandSendReal(CommandBlock *getData)
1947 {
1948 unsigned char npart = getData->data.part;
1949 if (npart == TOPLEVEL::section::midiIn) // music input takes priority!
1950 {
1951 commandMidi(getData);
1952 return false;
1953 }
1954 if (getData->data.control == TOPLEVEL::control::forceExit)
1955 {
1956 getData->data.source = TOPLEVEL::action::noAction;
1957 firstSynth->getRuntime().exitType = FORCED_EXIT;
1958 firstSynth->getRuntime().runSynth = false;
1959 return false;
1960 }
1961
1962 if ((getData->data.source & TOPLEVEL::action::muteAndLoop) == TOPLEVEL::action::lowPrio)
1963 return true; // indirect transfer
1964
1965 unsigned char type = getData->data.type;
1966 unsigned char control = getData->data.control;
1967 unsigned char kititem = getData->data.kit;
1968 unsigned char engine = getData->data.engine;
1969 unsigned char insert = getData->data.insert;
1970
1971 bool isGui = ((getData->data.source & TOPLEVEL::action::noAction) == TOPLEVEL::action::fromGUI);
1972 char button = type & 3;
1973
1974 if (!isGui && button == 1)
1975 {
1976 return false;
1977 }
1978
1979 if (npart == TOPLEVEL::section::vector)
1980 {
1981 commandVector(getData);
1982 return true;
1983 }
1984 if (npart == TOPLEVEL::section::scales)
1985 {
1986 commandMicrotonal(getData);
1987 return true;
1988 }
1989 if (npart == TOPLEVEL::section::config)
1990 {
1991 commandConfig(getData);
1992 return true;
1993 }
1994 if (npart == TOPLEVEL::section::main)
1995 {
1996 commandMain(getData);
1997 return true;
1998 }
1999 if (npart == TOPLEVEL::section::bank)
2000 {
2001 commandBank(getData);
2002 return true;
2003 }
2004
2005
2006 if ((npart == TOPLEVEL::section::systemEffects || npart == TOPLEVEL::section::insertEffects) && kititem == UNUSED)
2007 {
2008 commandSysIns(getData);
2009 return true;
2010 }
2011 if (kititem >= EFFECT::type::none && kititem <= EFFECT::type::dynFilter)
2012 {
2013 commandEffects(getData);
2014 return true;
2015 }
2016
2017 if (npart >= NUM_MIDI_PARTS)
2018 {
2019 return false; // invalid part number
2020 }
2021
2022 if (kititem >= NUM_KIT_ITEMS && kititem != UNUSED)
2023 {
2024 return false; // invalid kit number
2025 }
2026
2027 Part *part = synth->part[npart];
2028 if (part->busy && engine == PART::engine::padSynth)
2029 {
2030 getData->data.type &= ~TOPLEVEL::type::Write; // turn it into a read
2031 getData->data.control = PART::control::partBusy;
2032 getData->data.kit = UNUSED;
2033 getData->data.engine = UNUSED;
2034 getData->data.insert = UNUSED;
2035 return false;
2036 }
2037 if (control == PART::control::partBusy)
2038 {
2039 getData->data.value = part->busy;
2040 return false;
2041 }
2042 if (kititem == UNUSED || insert == TOPLEVEL::insert::kitGroup)
2043 {
2044 commandPart(getData);
2045 return true;
2046 }
2047
2048 if (kititem > 0 && kititem != UNUSED)
2049 {
2050 if (part->Pkitmode == 0)
2051 return false;
2052 else if (!part->kit[kititem].Penabled)
2053 return false;
2054 }
2055
2056 if (engine == PART::engine::addSynth)
2057 return processAdd(getData, synth);
2058
2059 if (engine == PART::engine::subSynth)
2060 return processSub(getData, synth);
2061
2062 if (engine == PART::engine::padSynth)
2063 return processPad(getData, synth);
2064
2065 if (engine >= PART::engine::addVoice1)
2066 {
2067 if ((engine > PART::engine::addVoice8 && engine < PART::engine::addMod1) || engine > PART::engine::addMod8)
2068 {
2069 getData->data.source = TOPLEVEL::action::noAction;
2070 synth->getRuntime().Log("Invalid voice number");
2071 synth->getRuntime().finishedCLI = true;
2072 return false;
2073 }
2074 return processVoice(getData, synth);
2075 }
2076
2077 getData->data.source = TOPLEVEL::action::noAction;
2078 synth->getRuntime().Log("Invalid engine number");
2079 synth->getRuntime().finishedCLI = true;
2080 return false;
2081 }
2082
2083
processAdd(CommandBlock * getData,SynthEngine * synth)2084 bool InterChange::processAdd(CommandBlock *getData, SynthEngine *synth)
2085 {
2086 Part *part = synth->part[getData->data.part];
2087 int kititem = getData->data.kit;
2088 switch(getData->data.insert)
2089 {
2090 case UNUSED:
2091 commandAdd(getData);
2092 part->kit[kititem].adpars->presetsUpdated();
2093 break;
2094 case TOPLEVEL::insert::LFOgroup:
2095 commandLFO(getData);
2096 break;
2097 case TOPLEVEL::insert::filterGroup:
2098 commandFilter(getData);
2099 break;
2100 case TOPLEVEL::insert::envelopeGroup:
2101 case TOPLEVEL::insert::envelopePoints:
2102 case TOPLEVEL::insert::envelopePointChange:
2103 commandEnvelope(getData);
2104 break;
2105 case TOPLEVEL::insert::resonanceGroup:
2106 case TOPLEVEL::insert::resonanceGraphInsert:
2107 commandResonance(getData, part->kit[kititem].adpars->GlobalPar.Reson);
2108 part->kit[kititem].adpars->presetsUpdated();
2109 break;
2110 }
2111 return true;
2112 }
2113
2114
processVoice(CommandBlock * getData,SynthEngine * synth)2115 bool InterChange::processVoice(CommandBlock *getData, SynthEngine *synth)
2116 {
2117 Part *part = synth->part[getData->data.part];
2118 int control = getData->data.control;
2119 int kititem = getData->data.kit;
2120 int engine = getData->data.engine;
2121 switch(getData->data.insert)
2122 {
2123 case UNUSED:
2124 commandAddVoice(getData);
2125 part->kit[kititem].adpars->presetsUpdated();
2126 break;
2127 case TOPLEVEL::insert::LFOgroup:
2128 commandLFO(getData);
2129 break;
2130 case TOPLEVEL::insert::filterGroup:
2131 commandFilter(getData);
2132 break;
2133 case TOPLEVEL::insert::envelopeGroup:
2134 case TOPLEVEL::insert::envelopePoints:
2135 case TOPLEVEL::insert::envelopePointChange:
2136 commandEnvelope(getData);
2137 break;
2138 case TOPLEVEL::insert::oscillatorGroup:
2139 case TOPLEVEL::insert::harmonicAmplitude:
2140 case TOPLEVEL::insert::harmonicPhaseBandwidth:
2141 if (engine >= PART::engine::addMod1)
2142 {
2143 engine -= PART::engine::addMod1;
2144 if (control != ADDVOICE::control::modulatorOscillatorSource)
2145 {
2146 int voicechange = part->kit[kititem].adpars->VoicePar[engine].PextFMoscil;
2147 if (voicechange != -1)
2148 {
2149 engine = voicechange;
2150 getData->data.engine = engine + PART::addMod1;
2151 } // force it to external mod
2152 }
2153
2154 commandOscillator(getData, part->kit[kititem].adpars->VoicePar[engine].POscilFM);
2155 }
2156 else
2157 {
2158 engine -= PART::engine::addVoice1;
2159 if (control != PART::control::sustainPedalEnable) // how can this ever be true!!!
2160 {
2161 int voicechange = part->kit[kititem].adpars->VoicePar[engine].Pextoscil;
2162 if (voicechange != -1)
2163 {
2164 engine = voicechange;
2165 getData->data.engine = engine | PART::engine::addVoice1;
2166 } // force it to external voice
2167 }
2168 commandOscillator(getData, part->kit[kititem].adpars->VoicePar[engine].POscil);
2169 }
2170 part->kit[kititem].adpars->presetsUpdated();
2171 break;
2172 }
2173 return true;
2174 }
2175
2176
processSub(CommandBlock * getData,SynthEngine * synth)2177 bool InterChange::processSub(CommandBlock *getData, SynthEngine *synth)
2178 {
2179 Part *part = synth->part[getData->data.part];
2180 int kititem = getData->data.kit;
2181 switch(getData->data.insert)
2182 {
2183 case UNUSED:
2184 commandSub(getData);
2185 part->kit[kititem].subpars->presetsUpdated();
2186 break;
2187 case TOPLEVEL::insert::harmonicAmplitude:
2188 commandSub(getData);
2189 part->kit[kititem].subpars->presetsUpdated();
2190 break;
2191 case TOPLEVEL::insert::harmonicPhaseBandwidth:
2192 commandSub(getData);
2193 part->kit[kititem].subpars->presetsUpdated();
2194 break;
2195 case TOPLEVEL::insert::filterGroup:
2196 commandFilter(getData);
2197 break;
2198 case TOPLEVEL::insert::envelopeGroup:
2199 commandEnvelope(getData);
2200 break;
2201 case TOPLEVEL::insert::envelopePoints:
2202 commandEnvelope(getData);
2203 break;
2204 case TOPLEVEL::insert::envelopePointChange:
2205 commandEnvelope(getData);
2206 break;
2207 }
2208 return true;
2209 }
2210
2211
processPad(CommandBlock * getData,SynthEngine * synth)2212 bool InterChange::processPad(CommandBlock *getData, SynthEngine *synth)
2213 {
2214 Part *part = synth->part[getData->data.part];
2215 int kititem = getData->data.kit;
2216 bool needApply = false;
2217 switch(getData->data.insert)
2218 {
2219 case UNUSED:
2220 commandPad(getData);
2221 part->kit[kititem].padpars->presetsUpdated();
2222 break;
2223 case TOPLEVEL::insert::LFOgroup:
2224 commandLFO(getData);
2225 break;
2226 case TOPLEVEL::insert::filterGroup:
2227 commandFilter(getData);
2228 break;
2229 case TOPLEVEL::insert::envelopeGroup:
2230 commandEnvelope(getData);
2231 break;
2232 case TOPLEVEL::insert::envelopePoints:
2233 commandEnvelope(getData);
2234 break;
2235 case TOPLEVEL::insert::envelopePointChange:
2236 commandEnvelope(getData);
2237 break;
2238 case TOPLEVEL::insert::oscillatorGroup:
2239 commandOscillator(getData, part->kit[kititem].padpars->POscil);
2240 part->kit[kititem].padpars->presetsUpdated();
2241 needApply = true;
2242 break;
2243 case TOPLEVEL::insert::harmonicAmplitude:
2244 commandOscillator(getData, part->kit[kititem].padpars->POscil);
2245 part->kit[kititem].padpars->presetsUpdated();
2246 needApply = true;
2247 break;
2248 case TOPLEVEL::insert::harmonicPhaseBandwidth:
2249 commandOscillator(getData, part->kit[kititem].padpars->POscil);
2250 part->kit[kititem].padpars->presetsUpdated();
2251 needApply = true;
2252 break;
2253 case TOPLEVEL::insert::resonanceGroup:
2254 commandResonance(getData, part->kit[kititem].padpars->resonance);
2255 part->kit[kititem].padpars->presetsUpdated();
2256 needApply = true;
2257 break;
2258 case TOPLEVEL::insert::resonanceGraphInsert:
2259 commandResonance(getData, part->kit[kititem].padpars->resonance);
2260 part->kit[kititem].padpars->presetsUpdated();
2261 needApply = true;
2262 break;
2263 }
2264 if (needApply)
2265 {
2266 part->kit[kititem].padpars->Papplied = 0;
2267 getData->data.offset = 0;
2268 }
2269 return true;
2270 }
2271
2272
commandMidi(CommandBlock * getData)2273 void InterChange::commandMidi(CommandBlock *getData)
2274 {
2275 int value_int = lrint(getData->data.value);
2276 unsigned char control = getData->data.control;
2277 unsigned char chan = getData->data.kit;
2278 unsigned int char1 = getData->data.engine;
2279 unsigned char miscmsg = getData->data.miscmsg;
2280
2281 //std::cout << "here MIDI " << control << " " << value_int << " " << int(chan) << " " << int(char1) << std::endl;
2282
2283 if (control == MIDI::control::controller && char1 >= 0x80)
2284 char1 |= 0x200; // for 'specials'
2285
2286 switch(control)
2287 {
2288 case MIDI::control::noteOn:
2289 synth->NoteOn(chan, char1, value_int);
2290 synth->getRuntime().finishedCLI = true;
2291 getData->data.source = TOPLEVEL::action::noAction; // till we know what to do!
2292 break;
2293 case MIDI::control::noteOff:
2294 synth->NoteOff(chan, char1);
2295 synth->getRuntime().finishedCLI = true;
2296 getData->data.source = TOPLEVEL::action::noAction; // till we know what to do!
2297 break;
2298 case MIDI::control::controller:
2299 synth->SetController(chan, char1, value_int);
2300 break;
2301
2302 case MIDI::control::instrument:
2303 getData->data.source |= TOPLEVEL::action::lowPrio;
2304 getData->data.part = TOPLEVEL::section::midiIn;
2305 synth->partonoffLock(chan & 0x3f, -1);
2306 synth->getRuntime().finishedCLI = true;
2307 break;
2308
2309 case MIDI::control::bankChange:
2310 getData->data.source = TOPLEVEL::action::lowPrio;
2311 if ((value_int != UNUSED || miscmsg != NO_MSG) && chan < synth->getRuntime().NumAvailableParts)
2312 {
2313 synth->partonoffLock(chan & 0x3f, -1);
2314 synth->getRuntime().finishedCLI = true;
2315 }
2316 break;
2317 }
2318 }
2319
2320
vectorClear(int Nvector)2321 void InterChange::vectorClear(int Nvector)
2322 {
2323 int start;
2324 int end;
2325 if (Nvector >= NUM_MIDI_CHANNELS)
2326 {
2327 start = 0;
2328 end = NUM_MIDI_CHANNELS;
2329 }
2330 else
2331 {
2332 start = Nvector;
2333 end = Nvector + 1;
2334 }
2335 for (int ch = start; ch < end; ++ ch)
2336 {
2337 synth->getRuntime().vectordata.Xaxis[ch] = UNUSED;
2338 synth->getRuntime().vectordata.Yaxis[ch] = UNUSED;
2339 synth->getRuntime().vectordata.Xfeatures[ch] = 0;
2340 synth->getRuntime().vectordata.Yfeatures[ch] = 0;
2341 synth->getRuntime().vectordata.Enabled[ch] = false;
2342 synth->getRuntime().vectordata.Name[ch] = "No Name " + std::to_string(ch + 1);
2343 }
2344 }
2345
2346
commandVector(CommandBlock * getData)2347 void InterChange::commandVector(CommandBlock *getData)
2348 {
2349 int value = getData->data.value; // no floats here
2350 unsigned char type = getData->data.type;
2351 unsigned char control = getData->data.control;
2352 unsigned int chan = getData->data.insert;
2353 bool write = (type & TOPLEVEL::type::Write) > 0;
2354
2355 unsigned int features = 0;
2356
2357 if (control == VECTOR::control::erase)
2358 {
2359 vectorClear(chan);
2360 return;
2361 }
2362 if (write)
2363 {
2364 if (control >= VECTOR::control::Xfeature0 && control <= VECTOR::control::Xfeature3)
2365 features = synth->getRuntime().vectordata.Xfeatures[chan];
2366 else if (control >= VECTOR::control::Yfeature0 && control <= VECTOR::control::Yfeature3)
2367 features = synth->getRuntime().vectordata.Yfeatures[chan];
2368 }
2369
2370 switch (control)
2371 {
2372 case 0:
2373 break;
2374 case 1:
2375 if (write)
2376 {
2377 switch (value)
2378 {
2379 case 0:
2380 case 1:
2381 case 2: // local to source
2382 break;
2383 case 3:
2384 synth->vectorSet(127, chan, 0);
2385 break;
2386 case 4:
2387 for (int ch = 0; ch < NUM_MIDI_CHANNELS; ++ ch)
2388 synth->vectorSet(127, ch, 0);
2389 break;
2390 }
2391 }
2392 break;
2393
2394 case VECTOR::control::name:
2395 break; // handled elsewhere
2396
2397 case VECTOR::control::Xcontroller: // also enable vector
2398 if (write)
2399 {
2400 if (value >= 14)
2401 {
2402 if (!synth->vectorInit(0, chan, value))
2403 synth->vectorSet(0, chan, value);
2404 else
2405 getData->data.value = 0;
2406 }
2407 }
2408 else
2409 {
2410 ;
2411 }
2412 break;
2413 case VECTOR::control::XleftInstrument:
2414 if (write)
2415 synth->vectorSet(4, chan, value);
2416 else
2417 {
2418 ;
2419 }
2420 break;
2421 case VECTOR::control::XrightInstrument:
2422 if (write)
2423 synth->vectorSet(5, chan, value);
2424 else
2425 {
2426 ;
2427 }
2428 break;
2429 case VECTOR::control::Xfeature0:
2430 case VECTOR::control::Yfeature0: // volume
2431 if (write)
2432 if (value == 0)
2433 bitClear(features, 0);
2434 else
2435 bitSet(features, 0);
2436 else
2437 {
2438 ;
2439 }
2440 break;
2441 case VECTOR::control::Xfeature1:
2442 case VECTOR::control::Yfeature1: // panning
2443 if (write)
2444 {
2445 bitClear(features, 1);
2446 bitClear(features, 4);
2447 if (value > 0)
2448 {
2449 bitSet(features, 1);
2450 if (value == 2)
2451 bitSet(features, 4);
2452 }
2453 }
2454 else
2455 {
2456 ;
2457 }
2458 break;
2459 case VECTOR::control::Xfeature2:
2460 case VECTOR::control::Yfeature2: // filter cutoff
2461 if (write)
2462 {
2463 bitClear(features, 2);
2464 bitClear(features, 5);
2465 if (value > 0)
2466 {
2467 bitSet(features, 2);
2468 if (value == 2)
2469 bitSet(features, 5);
2470 }
2471 }
2472 else
2473 {
2474 ;
2475 }
2476 break;
2477 case VECTOR::control::Xfeature3:
2478 case VECTOR::control::Yfeature3: // modulation
2479 if (write)
2480 {
2481 bitClear(features, 3);
2482 bitClear(features, 6);
2483 if (value > 0)
2484 {
2485 bitSet(features, 3);
2486 if (value == 2)
2487 bitSet(features, 6);
2488 }
2489 }
2490 else
2491 {
2492 ;
2493 }
2494 break;
2495
2496 case VECTOR::control::Ycontroller: // also enable Y
2497 if (write)
2498 {
2499 if (value >= 14)
2500 {
2501 if (!synth->vectorInit(1, chan, value))
2502 synth->vectorSet(1, chan, value);
2503 else
2504 getData->data.value = 0;
2505 }
2506 }
2507 else
2508 {
2509 ;
2510 }
2511 break;
2512 case VECTOR::control::YupInstrument:
2513 if (write)
2514 synth->vectorSet(6, chan, value);
2515 else
2516 {
2517 ;
2518 }
2519 break;
2520 case VECTOR::control::YdownInstrument:
2521 if (write)
2522 synth->vectorSet(7, chan, value);
2523 else
2524 {
2525 ;
2526 }
2527 break;
2528 }
2529
2530 if (write)
2531 {
2532 if (control >= VECTOR::control::Xfeature0 && control <= VECTOR::control::Xfeature3)
2533 synth->getRuntime().vectordata.Xfeatures[chan] = features;
2534 else if (control >= VECTOR::control::Yfeature0 && control <= VECTOR::control::Yfeature3)
2535 synth->getRuntime().vectordata.Yfeatures[chan] = features;
2536 }
2537 }
2538
2539
commandMicrotonal(CommandBlock * getData)2540 void InterChange::commandMicrotonal(CommandBlock *getData)
2541 {
2542 float value = getData->data.value;
2543 unsigned char type = getData->data.type;
2544 unsigned char control = getData->data.control;
2545
2546 bool write = (type & TOPLEVEL::type::Write) > 0;
2547
2548 int value_int = lrint(value);
2549 bool value_bool = _SYS_::F2B(value);
2550
2551 switch (control)
2552 {
2553 case SCALES::control::refFrequency:
2554 if (write)
2555 {
2556 if (value > 2000)
2557 value = 2000;
2558 else if (value < 1)
2559 value = 1;
2560 synth->microtonal.PrefFreq = value;
2561 }
2562 else
2563 value = synth->microtonal.PrefFreq;
2564 getData->data.parameter = synth->microtonal.PrefNote;
2565 break;
2566
2567 case SCALES::control::refNote:
2568 if (write)
2569 synth->microtonal.PrefNote = value_int;
2570 else
2571 value = synth->microtonal.PrefNote;
2572 break;
2573 case SCALES::control::invertScale:
2574 if (write)
2575 synth->microtonal.Pinvertupdown = value_bool;
2576 else
2577 value = synth->microtonal.Pinvertupdown;
2578 break;
2579 case SCALES::control::invertedScaleCenter:
2580 if (write)
2581 synth->microtonal.Pinvertupdowncenter = value_int;
2582 else
2583 value = synth->microtonal.Pinvertupdowncenter;
2584 break;
2585 case SCALES::control::scaleShift:
2586 if (write)
2587 synth->microtonal.Pscaleshift = value_int + 64;
2588 else
2589 value = synth->microtonal.Pscaleshift - 64;
2590 break;
2591
2592 case SCALES::control::enableMicrotonal:
2593 if (write)
2594 synth->microtonal.Penabled = value_bool;
2595 else
2596 value = synth->microtonal.Penabled;
2597 break;
2598
2599 case SCALES::control::enableKeyboardMap:
2600 if (write)
2601 synth->microtonal.Pmappingenabled = value_bool;
2602 else
2603 value = synth->microtonal.Pmappingenabled;
2604 break;
2605 case SCALES::control::lowKey:
2606 if (write)
2607 {
2608 if (value_int < 0)
2609 {
2610 value_int = 0;
2611 getData->data.value = value_int;
2612 }
2613 else if (value_int >= synth->microtonal.Pmiddlenote)
2614 {
2615 value_int = synth->microtonal.Pmiddlenote - 1;
2616 getData->data.value = value_int;
2617 }
2618 synth->microtonal.Pfirstkey = value_int;
2619 }
2620 else
2621 value = synth->microtonal.Pfirstkey;
2622 break;
2623 case SCALES::control::middleKey:
2624 if (write)
2625 {
2626 if (value_int <= synth->microtonal.Pfirstkey)
2627 {
2628 value_int = synth->microtonal.Pfirstkey + 1;
2629 getData->data.value = value_int;
2630 }
2631 else if (value_int >= synth->microtonal.Plastkey)
2632 {
2633 value_int = synth->microtonal.Plastkey - 1;
2634 getData->data.value = value_int;
2635 }
2636 synth->microtonal.Pmiddlenote = value_int;
2637 }
2638 else
2639 value = synth->microtonal.Pmiddlenote;
2640 break;
2641 case SCALES::control::highKey:
2642 if (write)
2643 {
2644 if (value_int <= synth->microtonal.Pmiddlenote)
2645 {
2646 value_int = synth->microtonal.Pmiddlenote + 1;
2647 getData->data.value = value_int;
2648 }
2649 else if (value_int > 127)
2650 {
2651 value_int = 127;
2652 getData->data.value = value_int;
2653 }
2654 synth->microtonal.Plastkey = value_int;
2655 }
2656 else
2657 value = synth->microtonal.Plastkey;
2658 break;
2659
2660 case SCALES::control::tuning:
2661 // done elsewhere
2662 break;
2663 case SCALES::control::keyboardMap:
2664 // done elsewhere
2665 break;
2666
2667 case SCALES::control::importScl:
2668 // done elsewhere
2669 break;
2670 case SCALES::control::importKbm:
2671 // done elsewhere
2672 break;
2673
2674 case SCALES::control::name:
2675 // done elsewhere
2676 break;
2677 case SCALES::control::comment:
2678 // done elsewhere
2679 break;
2680
2681 case SCALES::control::retune:
2682 // done elsewhere
2683 break;
2684 case SCALES::control::clearAll: // Clear scales
2685 synth->microtonal.defaults();
2686 break;
2687 }
2688
2689 if (!write)
2690 getData->data.value = value;
2691 }
2692
2693
commandConfig(CommandBlock * getData)2694 void InterChange::commandConfig(CommandBlock *getData)
2695 {
2696 float value = getData->data.value;
2697 unsigned char type = getData->data.type;
2698 unsigned char control = getData->data.control;
2699
2700 bool write = (type & TOPLEVEL::type::Write) > 0;
2701
2702 bool mightChange = true;
2703 int value_int = lrint(value);
2704 bool value_bool = _SYS_::F2B(value);
2705
2706 switch (control)
2707 {
2708 // main
2709 case CONFIG::control::oscillatorSize:
2710 if (write)
2711 {
2712 value = nearestPowerOf2(value_int, MIN_OSCIL_SIZE, MAX_OSCIL_SIZE);
2713 getData->data.value = value;
2714 synth->getRuntime().Oscilsize = value;
2715 }
2716 else
2717 value = synth->getRuntime().Oscilsize;
2718 break;
2719 case CONFIG::control::bufferSize:
2720 if (write)
2721 {
2722 value = nearestPowerOf2(value_int, MIN_BUFFER_SIZE, MAX_BUFFER_SIZE);
2723 getData->data.value = value;
2724 synth->getRuntime().Buffersize = value;
2725 }
2726 else
2727 value = synth->getRuntime().Buffersize;
2728 break;
2729 case CONFIG::control::padSynthInterpolation:
2730 if (write)
2731 synth->getRuntime().Interpolation = value_bool;
2732 else
2733 value = synth->getRuntime().Interpolation;
2734 break;
2735 case CONFIG::control::virtualKeyboardLayout:
2736 if (write)
2737 synth->getRuntime().VirKeybLayout = value_int;
2738 else
2739 value = synth->getRuntime().VirKeybLayout;
2740 break;
2741 case CONFIG::control::XMLcompressionLevel:
2742 if (write)
2743 synth->getRuntime().GzipCompression = value_int;
2744 else
2745 value = synth->getRuntime().GzipCompression;
2746 break;
2747 case CONFIG::control::reportsDestination:
2748 if (write)
2749 synth->getRuntime().toConsole = value_bool;
2750 else
2751 value = synth->getRuntime().toConsole;
2752 break;
2753 case CONFIG::control::logTextSize:
2754 if (write)
2755 synth->getRuntime().consoleTextSize = value_int;
2756 else
2757 value = synth->getRuntime().consoleTextSize;
2758 break;
2759 case CONFIG::control::savedInstrumentFormat:
2760 if (write)
2761 synth->getRuntime().instrumentFormat = value_int;
2762 else
2763 value = synth->getRuntime().instrumentFormat;
2764 break;
2765 // switches
2766 case CONFIG::control::defaultStateStart:
2767 if (write)
2768 synth->getRuntime().loadDefaultState = value_bool;
2769 else
2770 value = synth->getRuntime().loadDefaultState;
2771 break;
2772 case CONFIG::control::hideNonFatalErrors:
2773 if (write)
2774 synth->getRuntime().hideErrors = value_bool;
2775 else
2776 value = synth->getRuntime().hideErrors;
2777 break;
2778 case CONFIG::control::showSplash:
2779 if (write)
2780 synth->getRuntime().showSplash = value_bool;
2781 else
2782 value = synth->getRuntime().showSplash;
2783 break;
2784 case CONFIG::control::logInstrumentLoadTimes:
2785 if (write)
2786 synth->getRuntime().showTimes = value_bool;
2787 else
2788 value = synth->getRuntime().showTimes;
2789 break;
2790 case CONFIG::control::logXMLheaders:
2791 if (write)
2792 synth->getRuntime().logXMLheaders = value_bool;
2793 else
2794 value = synth->getRuntime().logXMLheaders;
2795 break;
2796 case CONFIG::control::saveAllXMLdata:
2797 if (write)
2798 synth->getRuntime().xmlmax = value_bool;
2799 else
2800 value = synth->getRuntime().xmlmax;
2801 break;
2802 case CONFIG::control::enableGUI:
2803 if (write)
2804 synth->getRuntime().showGui = value_bool;
2805 else
2806 value = synth->getRuntime().showGui;
2807 break;
2808 case CONFIG::control::enableCLI:
2809 if (write)
2810 synth->getRuntime().showCli = value_bool;
2811 else
2812 value = synth->getRuntime().showCli;
2813 break;
2814 case CONFIG::control::enableAutoInstance:
2815 if (write)
2816 synth->getRuntime().autoInstance = value_bool;
2817 else
2818 value = synth->getRuntime().autoInstance;
2819 break;
2820 case CONFIG::control::enableSinglePath:
2821 if (write)
2822 synth->getRuntime().singlePath = value;
2823 else
2824 value = synth->getRuntime().singlePath;
2825 break;
2826 case CONFIG::control::enableHighlight:
2827 if (write)
2828 synth->getRuntime().bankHighlight = value;
2829 else
2830 value = synth->getRuntime().bankHighlight;
2831 break;
2832 case CONFIG::control::exposeStatus:
2833 if (write)
2834 firstSynth->getRuntime().showCLIcontext = value_int;
2835 else
2836 value = firstSynth->getRuntime().showCLIcontext;
2837 break;
2838
2839 case CONFIG::control::readAudio:
2840 value = int(synth->getRuntime().audioEngine);
2841 break;
2842 case CONFIG::control::readMIDI:
2843 value = int(synth->getRuntime().midiEngine);
2844 break;
2845 // jack
2846 case CONFIG::control::jackMidiSource: // done elsewhere
2847 break;
2848 case CONFIG::control::jackPreferredMidi:
2849 if (write)
2850 {
2851 if (value_bool)
2852 synth->getRuntime().midiEngine = jack_midi;
2853 else
2854 synth->getRuntime().midiEngine = alsa_midi;
2855 }
2856 else
2857 value = (synth->getRuntime().midiEngine == jack_midi);
2858 break;
2859 case CONFIG::control::jackServer: // done elsewhere
2860 break;
2861 case CONFIG::control::jackPreferredAudio:
2862 if (write)
2863 {
2864 if (value_bool)
2865 synth->getRuntime().audioEngine = jack_audio;
2866 else
2867 synth->getRuntime().audioEngine = alsa_audio;
2868 }
2869 else
2870 value = (synth->getRuntime().audioEngine == jack_audio);
2871 break;
2872 case CONFIG::control::jackAutoConnectAudio:
2873 if (write)
2874 {
2875 synth->getRuntime().connectJackaudio = value_bool;
2876 synth->getRuntime().audioEngine = jack_audio;
2877 }
2878 else
2879 value = synth->getRuntime().connectJackaudio;
2880 break;
2881 // alsa
2882 case CONFIG::control::alsaMidiSource: // done elsewhere
2883 break;
2884 case CONFIG::control::alsaPreferredMidi:
2885 if (write)
2886 {
2887 if (value_bool)
2888 synth->getRuntime().midiEngine = alsa_midi;
2889 else
2890 synth->getRuntime().midiEngine = jack_midi;
2891 }
2892 else
2893 value = (synth->getRuntime().midiEngine == alsa_midi);
2894 break;
2895 case CONFIG::control::alsaMidiType:
2896 if (write)
2897 synth->getRuntime().alsaMidiType = value_int;
2898 else
2899 value = synth->getRuntime().alsaMidiType;
2900 break;
2901
2902 case CONFIG::control::alsaAudioDevice: // done elsewhere
2903 break;
2904 case CONFIG::control::alsaPreferredAudio:
2905 if (write)
2906 {
2907 if (value_bool)
2908 synth->getRuntime().audioEngine = alsa_audio;
2909 else
2910 synth->getRuntime().audioEngine = jack_audio;
2911 }
2912 else
2913 value = (synth->getRuntime().audioEngine == alsa_audio);
2914 break;
2915 case CONFIG::control::alsaSampleRate:
2916 if (write)
2917 {
2918 switch(value_int)
2919 {
2920 case 0:
2921 value = 192000;
2922 break;
2923 case 1:
2924 value = 96000;
2925 break;
2926 case 2:
2927 value = 48000;
2928 break;
2929 case 3:
2930 value = 44100;
2931 break;
2932 default:
2933 value = 44100;
2934 break;
2935 }
2936 synth->getRuntime().Samplerate = value;
2937 getData->data.value = value;
2938 }
2939 else
2940 switch(synth->getRuntime().Samplerate)
2941 {
2942 case 192000:
2943 value = 0;
2944 break;
2945 case 96000:
2946 value = 1;
2947 break;
2948 case 48000:
2949 value = 2;
2950 break;
2951 case 44100:
2952 value = 3;
2953 break;
2954 default:
2955 value = 3;
2956 break;
2957 }
2958 break;
2959 // midi
2960 case CONFIG::control::bankRootCC:
2961 if (write)
2962 {
2963 if (value_int != 0 && value_int != 32)
2964 {
2965 value_int = 128;
2966 getData->data.value = value_int;
2967 }
2968 synth->getRuntime().midi_bank_root = value_int;
2969 }
2970 else
2971 value = synth->getRuntime().midi_bank_root;
2972 break;
2973
2974 case CONFIG::control::bankCC:
2975 if (write)
2976 {
2977 if (value_int != 0 && value_int != 32)
2978 {
2979 value_int = 128;
2980 getData->data.value = value_int;
2981 }
2982 synth->getRuntime().midi_bank_C = value_int;
2983 }
2984 else
2985 value = synth->getRuntime().midi_bank_C;
2986 break;
2987 case CONFIG::control::enableProgramChange:
2988 if (write)
2989 synth->getRuntime().EnableProgChange = value_bool;
2990 else
2991 value = synth->getRuntime().EnableProgChange;
2992 break;
2993 case CONFIG::control::extendedProgramChangeCC:
2994 if (write)
2995 {
2996 if (value_int > 119)
2997 {
2998 value_int = 128;
2999 getData->data.value = value_int;
3000 }
3001 synth->getRuntime().midi_upper_voice_C = value_int;
3002 }
3003 else
3004 value = synth->getRuntime().midi_upper_voice_C;
3005 break;
3006 case CONFIG::control::ignoreResetAllCCs:
3007 if (write)
3008 synth->getRuntime().ignoreResetCCs = value_bool;
3009 else
3010 value = synth->getRuntime().ignoreResetCCs;
3011 break;
3012 case CONFIG::control::logIncomingCCs:
3013 if (write)
3014 synth->getRuntime().monitorCCin = value_bool;
3015 else
3016 value = synth->getRuntime().monitorCCin;
3017 break;
3018 case CONFIG::control::showLearnEditor:
3019 if (write)
3020 synth->getRuntime().showLearnedCC = value_bool;
3021 else
3022 value = synth->getRuntime().showLearnedCC;
3023 break;
3024 case CONFIG::control::enableNRPNs:
3025 if (write)
3026 synth->getRuntime().enable_NRPN = value_bool;
3027 else
3028 value = synth->getRuntime().enable_NRPN;
3029 break;
3030 // save config
3031 case CONFIG::control::saveCurrentConfig: //done elsewhere
3032 break;
3033 default:
3034 mightChange = false;
3035 break;
3036 }
3037 if (!write)
3038 getData->data.value = value;
3039 else if (mightChange)
3040 synth->getRuntime().configChanged = true;
3041 }
3042
3043
commandMain(CommandBlock * getData)3044 void InterChange::commandMain(CommandBlock *getData)
3045 {
3046 float value = getData->data.value;
3047 unsigned char type = getData->data.type;
3048 unsigned char action = getData->data.source;
3049 unsigned char control = getData->data.control;
3050 unsigned char kititem = getData->data.kit;
3051 unsigned char engine = getData->data.engine;
3052
3053 bool write = (type & TOPLEVEL::type::Write) > 0;
3054 int value_int = lrint(value);
3055
3056 switch (control)
3057 {
3058 case MAIN::control::volume:
3059 if (write)
3060 synth->setPvolume(value);
3061 else
3062 value = synth->Pvolume;
3063 break;
3064
3065 case MAIN::control::partNumber:
3066 if (write)
3067 synth->getRuntime().currentPart = value_int;
3068 else
3069 value = synth->getRuntime().currentPart;
3070 break;
3071 case MAIN::control::availableParts:
3072 if ((write) && (value == 16 || value == 32 || value == 64))
3073 synth->getRuntime().NumAvailableParts = value;
3074 else
3075 value = synth->getRuntime().NumAvailableParts;
3076 break;
3077 case MAIN::control::panLawType:
3078 if (write)
3079 synth->getRuntime().panLaw = value_int;
3080 else
3081 value = synth->getRuntime().panLaw;
3082 break;
3083
3084
3085 case MAIN::control::detune: // done elsewhere
3086 break;
3087 case MAIN::control::keyShift: // done elsewhere
3088 break;
3089
3090 case MAIN::control::mono:
3091 if (write)
3092 synth->masterMono = value;
3093 else
3094 value = synth->masterMono;
3095 break;
3096
3097 case MAIN::control::reseed:
3098 synth->setReproducibleState(int(value));
3099 // std::cout << "rnd " << synth->randomINT() << std::endl;
3100 break;
3101
3102 case MAIN::control::soloType:
3103 if (write && value_int <= MIDI::SoloType::Channel)
3104 {
3105 synth->getRuntime().channelSwitchType = value_int;
3106 synth->getRuntime().channelSwitchCC = 128;
3107 synth->getRuntime().channelSwitchValue = 0;
3108 switch (value_int)
3109 {
3110 case MIDI::SoloType::Disabled:
3111 for (int i = 0; i < NUM_MIDI_PARTS; ++i)
3112 synth->part[i]->Prcvchn = (i & (NUM_MIDI_CHANNELS - 1));
3113 break;
3114
3115 case MIDI::SoloType::Row:
3116 for (int i = 1; i < NUM_MIDI_CHANNELS; ++i)
3117 synth->part[i]->Prcvchn = NUM_MIDI_CHANNELS;
3118 synth->part[0]->Prcvchn = 0;
3119 break;
3120
3121 case MIDI::SoloType::Column:
3122 for (int i = 0; i < NUM_MIDI_PARTS; ++i)
3123 synth->part[i]->Prcvchn = (i & (NUM_MIDI_CHANNELS - 1));
3124 break;
3125
3126 case MIDI::SoloType::Loop:
3127 case MIDI::SoloType::TwoWay:
3128 for (int i = 0; i < NUM_MIDI_CHANNELS; ++i)
3129 synth->part[i]->Prcvchn = NUM_MIDI_CHANNELS;
3130 synth->part[0]->Prcvchn = 0;
3131 break;
3132
3133 case MIDI::SoloType::Channel:
3134 for (int p = 0; p < NUM_MIDI_PARTS; ++p)
3135 {
3136 if (synth->part[p]->Prcvchn >= NUM_MIDI_CHANNELS)
3137 synth->part[p]->Prcvchn = p &(NUM_MIDI_CHANNELS - 1);
3138 }
3139 break;
3140 }
3141 }
3142 else
3143 {
3144 write = false; // for an invalid write attempt
3145 value = synth->getRuntime().channelSwitchType;
3146 }
3147 break;
3148 case MAIN::control::soloCC:
3149 if (write && synth->getRuntime().channelSwitchType > 0)
3150 synth->getRuntime().channelSwitchCC = value_int;
3151 else
3152 {
3153 write = false; // for an invalid write attempt
3154 value = synth->getRuntime().channelSwitchCC;
3155 }
3156 break;
3157
3158 case MAIN::control::loadInstrumentFromBank:
3159 synth->partonoffLock(kititem, -1);
3160 getData->data.source |= TOPLEVEL::action::lowPrio;
3161 break;
3162
3163 case MAIN::control::loadInstrumentByName:
3164 synth->partonoffLock(kititem, -1);
3165 getData->data.source |= TOPLEVEL::action::lowPrio;
3166 break;
3167
3168 case MAIN::control::loadNamedPatchset:
3169 if (write && ((action & TOPLEVEL::action::muteAndLoop) == TOPLEVEL::action::muteAndLoop))
3170 {
3171 muteQueueWrite(getData);
3172 getData->data.source = TOPLEVEL::action::noAction;
3173 }
3174 break;
3175
3176 case MAIN::control::loadNamedVector:
3177 if (write && ((action & TOPLEVEL::action::muteAndLoop) == TOPLEVEL::action::muteAndLoop))
3178 {
3179 muteQueueWrite(getData);
3180 getData->data.source = TOPLEVEL::action::noAction;
3181 }
3182 break;
3183 case MAIN::control::saveNamedVector: // done elsewhere
3184 break;
3185 case MAIN::control::loadNamedScale: // done elsewhere
3186 break;
3187 case MAIN::control::saveNamedScale: // done elsewhere
3188 break;
3189 case MAIN::control::loadNamedState:
3190 if (write && ((action & TOPLEVEL::action::muteAndLoop) == TOPLEVEL::action::muteAndLoop))
3191 {
3192 muteQueueWrite(getData);
3193 getData->data.source = TOPLEVEL::action::noAction;
3194 }
3195 break;
3196 case MAIN::control::saveNamedState: // done elsewhere
3197 break;
3198 case MAIN::control::readLastSeen: // read only
3199 value = textMsgBuffer.push(synth->lastItemSeen(value));
3200 break;
3201 case MAIN::control::loadFileFromList:
3202 muteQueueWrite(getData);
3203 getData->data.source = TOPLEVEL::action::noAction;
3204 break;
3205
3206 case MAIN::control::defaultPart: // doClearPart
3207 if (write)
3208 {
3209 synth->partonoffWrite(value_int, -1);
3210 getData->data.source = TOPLEVEL::action::lowPrio;
3211 }
3212 else
3213 getData->data.source = TOPLEVEL::action::noAction;
3214 break;
3215
3216 case MAIN::control::masterReset:
3217 case MAIN::control::masterResetAndMlearn:
3218 if (write && ((action & TOPLEVEL::action::muteAndLoop) == TOPLEVEL::action::muteAndLoop))
3219 {
3220 muteQueueWrite(getData);
3221 getData->data.source = TOPLEVEL::action::noAction;
3222 }
3223 break;
3224 case MAIN::control::startInstance: // done elsewhere
3225 break;
3226 case MAIN::control::stopInstance: // done elsewhere
3227 break;
3228 case MAIN::control::stopSound: // just stop
3229 if (write)
3230 muteQueueWrite(getData);
3231 getData->data.source = TOPLEVEL::action::noAction;
3232 break;
3233
3234 case MAIN::control::readPartPeak:
3235 if (!write && kititem < NUM_MIDI_PARTS)
3236 {
3237 if (engine == 1)
3238 value = synth->VUdata.values.partsR[kititem];
3239 else
3240 value = synth->VUdata.values.parts[kititem];
3241 }
3242 break;
3243 case MAIN::control::readMainLRpeak:
3244 if (!write)
3245 {
3246 if (kititem == 1)
3247 value = synth->VUdata.values.vuOutPeakR;
3248 else
3249 value = synth->VUdata.values.vuOutPeakL;
3250 }
3251 break;
3252 case MAIN::control::readMainLRrms:
3253 if (!write)
3254 {
3255 if (kititem == 1)
3256 value = synth->VUdata.values.vuRmsPeakR;
3257 else
3258 value = synth->VUdata.values.vuRmsPeakL;
3259 }
3260 break;
3261
3262 case TOPLEVEL::control::textMessage:
3263 getData->data.source = TOPLEVEL::action::noAction;
3264 break;
3265 }
3266
3267 if (!write)
3268 getData->data.value = value;
3269 }
3270
3271
commandBank(CommandBlock * getData)3272 void InterChange::commandBank(CommandBlock *getData)
3273 {
3274 int value_int = int(getData->data.value + 0.5f);
3275 unsigned char type = getData->data.type;
3276 unsigned char control = getData->data.control;
3277 unsigned char kititem = getData->data.kit;
3278 unsigned char engine = getData->data.engine;
3279 unsigned char parameter = getData->data.parameter;
3280
3281 bool write = (type & TOPLEVEL::type::Write) > 0;
3282
3283 switch (control)
3284 {
3285 case BANK::control::readInstrumentName:
3286 {
3287 if (kititem == UNUSED)
3288 {
3289 kititem = synth->getRuntime().currentBank;
3290 getData->data.kit = kititem;
3291 }
3292 if (engine == UNUSED)
3293 {
3294 engine = synth->getRuntime().currentRoot;
3295 getData->data.engine = engine;
3296 }
3297 textMsgBuffer.push(synth->getBankRef().getname(parameter, kititem, engine));
3298 break;
3299 }
3300 case BANK::control::findInstrumentName:
3301 {
3302 if (parameter == UNUSED) // return the name of a specific instrument.
3303 textMsgBuffer.push(synth->getBankRef().getname(value_int, kititem, engine));
3304 else
3305 {
3306 int offset = type_offset [parameter];
3307 /*
3308 * This version of the call is for building up lists of instruments that match the given type.
3309 * It will find the next in the series until the entire bank structure has been scanned.
3310 * It returns the terminator when this has been completed so the calling function knows the
3311 * entire list has been scanned, and resets ready for a new set of calls.
3312 */
3313
3314 if (offset == -1)
3315 {
3316 synth->getRuntime().Log("caught invalid instrument type (-1)");
3317 textMsgBuffer.push("@end");
3318 }
3319
3320 do {
3321 do {
3322 do {
3323 if (synth->getBankRef().getType(searchInst, searchBank, searchRoot) == offset)
3324 {
3325 textMsgBuffer.push(asString(searchRoot, 3) + ": " + asString(searchBank, 3) + ". " + asString(searchInst + 1, 3) + " " + synth->getBankRef().getname(searchInst, searchBank, searchRoot));
3326 ++ searchInst;
3327 return;
3328 /*
3329 * notice this exit point!
3330 */
3331 }
3332 ++searchInst;
3333 } while (searchInst < MAX_INSTRUMENTS_IN_BANK);
3334
3335 searchInst = 0;
3336 ++searchBank;
3337 } while (searchBank < MAX_BANKS_IN_ROOT);
3338 searchBank = 0;
3339 ++searchRoot;
3340 } while (searchRoot < MAX_BANK_ROOT_DIRS);
3341 searchRoot = 0;
3342 textMsgBuffer.push("@end");
3343 }
3344 break;
3345 }
3346 case BANK::control::lastSeenInBank: // read only
3347 value_int = synth->getRuntime().lastBankPart;
3348 break;
3349 case BANK::control::selectBank: // done elsewhere for write
3350 value_int = synth->ReadBank();
3351 break;
3352 case BANK::control::selectRoot:
3353 value_int = synth->getRuntime().currentRoot; // currently read only
3354 break;
3355 default:
3356 getData->data.source = TOPLEVEL::action::noAction;
3357 break;
3358 }
3359
3360 if (!write)
3361 getData->data.value = value_int;
3362 }
3363
3364
commandPart(CommandBlock * getData)3365 void InterChange::commandPart(CommandBlock *getData)
3366 {
3367 float value = getData->data.value;
3368 unsigned char type = getData->data.type;
3369 unsigned char control = getData->data.control;
3370 unsigned char npart = getData->data.part;
3371 unsigned char kititem = getData->data.kit;
3372 unsigned char engine = getData->data.engine;
3373 unsigned char insert = getData->data.insert;
3374
3375 bool write = (type & TOPLEVEL::type::Write) > 0;
3376
3377 bool kitType = (insert == TOPLEVEL::insert::kitGroup);
3378
3379 if (kitType && kititem >= NUM_KIT_ITEMS)
3380 {
3381 getData->data.source = TOPLEVEL::action::noAction;
3382 synth->getRuntime().Log("Invalid kit number");
3383 return;
3384 }
3385 int value_int = lrint(value);
3386 char value_bool = _SYS_::F2B(value);
3387
3388 Part *part;
3389 part = synth->part[npart];
3390 if (part->Pkitmode == 0)
3391 {
3392 kitType = false;
3393 if (control != PART::control::kitMode && kititem != UNUSED)
3394 {
3395 getData->data.source = TOPLEVEL::action::noAction;
3396 synth->getRuntime().Log("Not in kit mode");
3397 }
3398 }
3399 else if (control != PART::control::enableKitLine && !part->kit[kititem].Penabled && kititem < UNUSED)
3400 {
3401 getData->data.source = TOPLEVEL::action::noAction;
3402 synth->getRuntime().Log("Kit item " + to_string(kititem + 1) + " not enabled");
3403 return;
3404 }
3405
3406 unsigned char effNum = part->Peffnum;
3407 if (!kitType)
3408 kititem = 0;
3409
3410 switch (control)
3411 {
3412 case PART::control::enable:
3413 if (write)
3414 {
3415 if (value_bool && synth->getRuntime().currentPart != npart) // make it a part change
3416 {
3417 synth->partonoffWrite(npart, 1);
3418 synth->getRuntime().currentPart = npart;
3419 getData->data.value = npart;
3420 getData->data.control = MAIN::control::partNumber;
3421 getData->data.part = TOPLEVEL::section::main;
3422 }
3423 else
3424 synth->partonoffWrite(npart, value_int);
3425 }
3426 else
3427 value = synth->partonoffRead(npart);
3428 break;
3429 case PART::control::enableAdd:
3430 if (write)
3431 part->kit[kititem].Padenabled = value_bool;
3432 else
3433 value = part->kit[kititem].Padenabled;
3434 break;
3435 case PART::control::enableSub:
3436 if (write)
3437 part->kit[kititem].Psubenabled = value_bool;
3438 else
3439 value = part->kit[kititem].Psubenabled;
3440 break;
3441 case PART::control::enablePad:
3442 if (write)
3443 {
3444 part->kit[kititem].Ppadenabled = value_bool;
3445 if (!part->kit[kititem].padpars->Papplied)
3446 {
3447 synth->partonoffWrite(npart, -1);
3448 getData->data.source = TOPLEVEL::action::lowPrio;
3449 }
3450 }
3451 else
3452 value = part->kit[kititem].Ppadenabled;
3453 break;
3454 case PART::control::enableKitLine:
3455 if (write)
3456 {
3457 synth->partonoffWrite(npart, -1);
3458 getData->data.source = TOPLEVEL::action::lowPrio;
3459 }
3460 else
3461 value = part->kit[kititem].Penabled;
3462 break;
3463
3464 case PART::control::volume:
3465 if (write)
3466 part->setVolume(value);
3467 else
3468 value = part->Pvolume;
3469 break;
3470 case PART::control::velocitySense:
3471 if (write)
3472 part->Pvelsns = value;
3473 else
3474 value = part->Pvelsns;
3475 break;
3476 case PART::control::panning:
3477 if (write)
3478 part->SetController(MIDI::CC::panning, value);
3479 else
3480 value = part->Ppanning;
3481 break;
3482 case PART::control::velocityOffset:
3483 if (write)
3484 part->Pveloffs = value;
3485 else
3486 value = part->Pveloffs;
3487 break;
3488 case PART::control::midiChannel:
3489 if (write)
3490 part->Prcvchn = value_int;
3491 else
3492 value = part->Prcvchn;
3493 break;
3494 case PART::control::keyMode:
3495 if (write)
3496 synth->SetPartKeyMode(npart, value_int);
3497 else
3498 value = (synth->ReadPartKeyMode(npart)) & 3; // clear out temporary legato
3499 break;
3500 case PART::control::channelATset:
3501 if (write)
3502 {
3503 part->PchannelATchoice = value_int;
3504 int tmp1, tmp2;
3505 tmp1 = tmp2 = part->PkeyATchoice;
3506 tmp1 &= ~value_int;
3507 if (tmp1 != tmp2)
3508 {
3509 part->PkeyATchoice = tmp1; // can't have the same
3510 getData->data.parameter = tmp1; // send possible correction
3511 }
3512 }
3513 else
3514 value = part->PchannelATchoice;
3515 break;
3516 case PART::control::keyATset:
3517 if (write)
3518 {
3519 part->PkeyATchoice = value_int;
3520 int tmp1, tmp2;
3521 tmp1 = tmp2 = part->PchannelATchoice;
3522 tmp1 &= ~value_int;
3523 if (tmp1 != tmp2)
3524 {
3525 part->PchannelATchoice = tmp1; // can't have the same
3526 getData->data.parameter = tmp1; // send possible correction
3527 }
3528 }
3529 else
3530 value = part->PkeyATchoice;
3531 break;
3532 case PART::control::portamento:
3533 if (write)
3534 part->ctl->portamento.portamento = value_bool;
3535 else
3536 value = part->ctl->portamento.portamento;
3537 break;
3538 case PART::control::kitItemMute:
3539 if (kitType)
3540 {
3541 if (write)
3542 part->kit[kititem].Pmuted = value_bool;
3543 else
3544 value = part->kit[kititem].Pmuted;
3545 }
3546 break;
3547
3548 case PART::control::minNote: // always return actual value
3549 if (kitType)
3550 {
3551 if (write)
3552 {
3553 if (value_int > part->kit[kititem].Pmaxkey)
3554 part->kit[kititem].Pminkey = part->kit[kititem].Pmaxkey;
3555 else
3556 part->kit[kititem].Pminkey = value_int;
3557 }
3558 value = part->kit[kititem].Pminkey;
3559 }
3560 else
3561 {
3562 if (write)
3563 {
3564 if (value_int > part->Pmaxkey)
3565 part->Pminkey = part->Pmaxkey;
3566 else
3567 part->Pminkey = value_int;
3568 }
3569 value = part->Pminkey;
3570 }
3571 break;
3572 case PART::control::maxNote: // always return actual value
3573 if (kitType)
3574 {
3575 if (write)
3576 {
3577 if (value_int < part->kit[kititem].Pminkey)
3578 part->kit[kititem].Pmaxkey = part->kit[kititem].Pminkey;
3579 else
3580 part->kit[kititem].Pmaxkey = value_int;
3581 }
3582 value = part->kit[kititem].Pmaxkey;
3583 }
3584 else
3585 {
3586 if (write)
3587 {
3588 if (value_int < part->Pminkey)
3589 part->Pmaxkey = part->Pminkey;
3590 else
3591 part->Pmaxkey = value_int;
3592 }
3593 value = part->Pmaxkey;
3594 }
3595 break;
3596 case PART::control::minToLastKey: // always return actual value
3597 value_int = part->lastnote;
3598 if (kitType)
3599 {
3600 if ((write) && value_int >= 0)
3601 {
3602 if (value_int > part->kit[kititem].Pmaxkey)
3603 part->kit[kititem].Pminkey = part->kit[kititem].Pmaxkey;
3604 else
3605 part->kit[kititem].Pminkey = part->lastnote;
3606 }
3607 value = part->kit[kititem].Pminkey;
3608 }
3609 else
3610 {
3611 if ((write) && part->lastnote >= 0)
3612 {
3613 if (value_int > part->Pmaxkey)
3614 part->Pminkey = part->Pmaxkey;
3615 else
3616 part->Pminkey = part->lastnote;
3617 }
3618 value = part->Pminkey;
3619 }
3620 break;
3621 case PART::control::maxToLastKey: // always return actual value
3622 value_int = part->lastnote;
3623 if (kitType)
3624 {
3625 if ((write) && part->lastnote >= 0)
3626 {
3627 if (value_int < part->kit[kititem].Pminkey)
3628 part->kit[kititem].Pmaxkey = part->kit[kititem].Pminkey;
3629 else
3630 part->kit[kititem].Pmaxkey = part->lastnote;
3631 }
3632 value = part->kit[kititem].Pmaxkey;
3633 }
3634 else
3635 {
3636 if ((write) && part->lastnote >= 0)
3637 {
3638 if (value_int < part->Pminkey)
3639 part->Pmaxkey = part->Pminkey;
3640 else
3641 part->Pmaxkey = part->lastnote;
3642 }
3643 value = part->Pmaxkey;
3644 }
3645 break;
3646 case PART::control::resetMinMaxKey:
3647 if (kitType)
3648 {
3649 if (write)
3650 {
3651 part->kit[kititem].Pminkey = 0;
3652 part->kit[kititem].Pmaxkey = 127;
3653 }
3654 }
3655 else
3656 {
3657 if (write)
3658 {
3659 part->Pminkey = 0;
3660 part->Pmaxkey = 127;
3661 }
3662 }
3663 break;
3664
3665 case PART::control::kitEffectNum:
3666 if (kitType)
3667 {
3668 if (write)
3669 {
3670 if (value_int == 0 )
3671 part->kit[kititem].Psendtoparteffect = 127;
3672 else
3673 part->kit[kititem].Psendtoparteffect = value_int - 1;
3674 }
3675 else
3676 value = part->kit[kititem].Psendtoparteffect;
3677 }
3678 break;
3679
3680 case PART::control::maxNotes:
3681 if (write)
3682 {
3683 part->Pkeylimit = value_int;
3684 if (part->Pkeymode == PART_NORMAL)
3685 part->enforcekeylimit();
3686 }
3687 else
3688 value = part->Pkeylimit;
3689 break;
3690 case PART::control::keyShift: // done elsewhere
3691 break;
3692
3693 case PART::control::partToSystemEffect1:
3694 if (write)
3695 synth->setPsysefxvol(npart,0, value);
3696 else
3697 value = synth->Psysefxvol[0][npart];
3698 break;
3699 case PART::control::partToSystemEffect2:
3700 if (write)
3701 synth->setPsysefxvol(npart,1, value);
3702 else
3703 value = synth->Psysefxvol[1][npart];
3704 break;
3705 case PART::control::partToSystemEffect3:
3706 if (write)
3707 synth->setPsysefxvol(npart,2, value);
3708 else
3709 value = synth->Psysefxvol[2][npart];
3710 break;
3711 case PART::control::partToSystemEffect4:
3712 if (write)
3713 synth->setPsysefxvol(npart,3, value);
3714 else
3715 value = synth->Psysefxvol[3][npart];
3716 break;
3717
3718 case PART::control::humanise:
3719 if (write)
3720 part->Pfrand = value;
3721 else
3722 value = part->Pfrand;
3723 break;
3724
3725 case PART::control::humanvelocity:
3726 if (write)
3727 part->Pvelrand = value;
3728 else
3729 value = part->Pvelrand;
3730 break;
3731
3732 case PART::control::drumMode:
3733 if (write)
3734 {
3735 part->Pdrummode = value_bool;
3736 synth->setPartMap(npart);
3737 }
3738 else
3739 value = part->Pdrummode;
3740 break;
3741 case PART::control::kitMode:
3742 if (write)
3743 {
3744 if (value == 3)
3745 {
3746 part->Pkitmode = 1;
3747 part->Pkitfade = true;
3748 value = 1; // just to be sure
3749 }
3750 else
3751 {
3752 part->Pkitfade = false;
3753 part->Pkitmode = value_int;
3754 }
3755 }
3756 else
3757 {
3758 value = part->Pkitmode;
3759 if (value == 1 && part->Pkitfade == true)
3760 value = 3;
3761 }
3762 break;
3763
3764 case PART::control::effectNumber:
3765 if (write)
3766 {
3767 part->Peffnum = value_int;
3768 getData->data.parameter = (part->partefx[value_int]->geteffectpar(-1) != 0);
3769 getData->data.engine = value_int;
3770 getData->data.source |= getData->data.source |= TOPLEVEL::action::forceUpdate;
3771 // the line above is to show it's changed from preset values
3772
3773 }
3774 else
3775 value = part->Peffnum;
3776 break;
3777
3778 case PART::control::effectType:
3779 if (write)
3780 part->partefx[effNum]->changeeffect(value_int);
3781 else
3782 value = part->partefx[effNum]->geteffect();
3783 getData->data.parameter = (part->partefx[effNum]->geteffectpar(-1) != 0);
3784 getData->data.offset = 0;
3785 break;
3786 case PART::control::effectDestination:
3787 if (write)
3788 {
3789 part->Pefxroute[effNum] = value_int;
3790 part->partefx[effNum]->setdryonly(value_int == 2);
3791 }
3792 else
3793 value = part->Pefxroute[effNum];
3794 break;
3795 case PART::control::effectBypass:
3796 {
3797 int tmp = part->Peffnum;
3798 part->Peffnum = engine;
3799 if (write)
3800 {
3801 bool newSwitch = value_bool;
3802 bool oldSwitch = part->Pefxbypass[engine];
3803 part->Pefxbypass[engine] = newSwitch;
3804 if (newSwitch != oldSwitch)
3805 part->partefx[engine]->cleanup();
3806 }
3807 else
3808 value = part->Pefxbypass[engine];
3809 part->Peffnum = tmp; // leave it as it was before
3810 break;
3811 }
3812
3813 case PART::control::audioDestination:
3814 if (synth->partonoffRead(npart) != 1)
3815 {
3816 getData->data.value = part->Paudiodest; // specific for this control
3817 return;
3818 }
3819 else if (write)
3820 {
3821 if (npart < synth->getRuntime().NumAvailableParts)
3822 synth->part[npart]->Paudiodest = value_int;
3823 getData->data.source = TOPLEVEL::action::lowPrio;
3824 }
3825 else
3826 value = part->Paudiodest;
3827 break;
3828
3829 case PART::control::volumeRange: // start of controllers
3830 if (write)
3831 part->ctl->setvolume(value_int); // not the *actual* volume
3832 else
3833 value = part->ctl->volume.data;
3834 break;
3835 case PART::control::volumeEnable:
3836 if (write)
3837 part->ctl->volume.receive = value_bool;
3838 else
3839 value = part->ctl->volume.receive;
3840 break;
3841 case PART::control::panningWidth:
3842 if (write)
3843 part->ctl->setPanDepth(value_int);
3844 else
3845 value = part->ctl->panning.depth;
3846 break;
3847 case PART::control::modWheelDepth:
3848 if (write)
3849 part->ctl->modwheel.depth = value;
3850 else
3851 value = part->ctl->modwheel.depth;
3852 break;
3853 case PART::control::exponentialModWheel:
3854 if (write)
3855 part->ctl->modwheel.exponential = value_bool;
3856 else
3857 value = part->ctl->modwheel.exponential;
3858 break;
3859 case PART::control::bandwidthDepth:
3860 if (write)
3861 part->ctl->bandwidth.depth = value;
3862 else
3863 value = part->ctl->bandwidth.depth;
3864 break;
3865 case PART::control::exponentialBandwidth:
3866 if (write)
3867 part->ctl->bandwidth.exponential = value_bool;
3868 else
3869 value = part->ctl->bandwidth.exponential;
3870 break;
3871 case PART::control::expressionEnable:
3872 if (write)
3873 part->ctl->expression.receive = value_bool;
3874 else
3875 value = part->ctl->expression.receive;
3876 break;
3877 case PART::control::FMamplitudeEnable:
3878 if (write)
3879 part->ctl->fmamp.receive = value_bool;
3880 else
3881 value = part->ctl->fmamp.receive;
3882 break;
3883 case PART::control::sustainPedalEnable:
3884 if (write)
3885 part->ctl->sustain.receive = value_bool;
3886 else
3887 value = part->ctl->sustain.receive;
3888 break;
3889 case PART::control::pitchWheelRange:
3890 if (write)
3891 part->ctl->pitchwheel.bendrange = value_int;
3892 else
3893 value = part->ctl->pitchwheel.bendrange;
3894 break;
3895 case PART::control::filterQdepth:
3896 if (write)
3897 part->ctl->filterq.depth = value;
3898 else
3899 value = part->ctl->filterq.depth;
3900 break;
3901 case PART::control::filterCutoffDepth:
3902 if (write)
3903 part->ctl->filtercutoff.depth = value;
3904 else
3905 value = part->ctl->filtercutoff.depth;
3906 break;
3907 case PART::control::breathControlEnable:
3908 if (write)
3909 if (value_bool)
3910 part->PbreathControl = MIDI::CC::breath;
3911 else
3912 part->PbreathControl = 128; // impossible CC value
3913 else
3914 value = part->PbreathControl;
3915 break;
3916
3917 case PART::control::resonanceCenterFrequencyDepth:
3918 if (write)
3919 part->ctl->resonancecenter.depth = value;
3920 else
3921 value = part->ctl->resonancecenter.depth;
3922 break;
3923 case PART::control::resonanceBandwidthDepth:
3924 if (write)
3925 part->ctl->resonancebandwidth.depth = value;
3926 else
3927 value = part->ctl->resonancebandwidth.depth;
3928 break;
3929
3930 case PART::control::portamentoTime:
3931 if (write)
3932 part->ctl->portamento.time = value;
3933 else
3934 value = part->ctl->portamento.time;
3935 break;
3936 case PART::control::portamentoTimeStretch:
3937 if (write)
3938 part->ctl->portamento.updowntimestretch = value;
3939 else
3940 value = part->ctl->portamento.updowntimestretch;
3941 break;
3942 case PART::control::portamentoThreshold:
3943 if (write)
3944 part->ctl->portamento.pitchthresh = value;
3945 else
3946 value = part->ctl->portamento.pitchthresh;
3947 break;
3948 case PART::control::portamentoThresholdType:
3949 if (write)
3950 part->ctl->portamento.pitchthreshtype = value_int;
3951 else
3952 value = part->ctl->portamento.pitchthreshtype;
3953 break;
3954 case PART::control::enableProportionalPortamento:
3955 if (write)
3956 part->ctl->portamento.proportional = value_int;
3957 else
3958 value = part->ctl->portamento.proportional;
3959 break;
3960 case PART::control::proportionalPortamentoRate:
3961 if (write)
3962 part->ctl->portamento.propRate = value;
3963 else
3964 value = part->ctl->portamento.propRate;
3965 break;
3966 case PART::control::proportionalPortamentoDepth:
3967 if (write)
3968 part->ctl->portamento.propDepth = value;
3969 else
3970 value = part->ctl->portamento.propDepth;
3971 break;
3972
3973 case PART::control::receivePortamento: // end of controllers
3974 if (write)
3975 part->ctl->portamento.receive = value_bool;
3976 else
3977 value = part->ctl->portamento.receive;
3978 break;
3979
3980 case PART::control::midiModWheel:
3981 if (write)
3982 part->ctl->setmodwheel(value);
3983 else
3984 value = part->ctl->modwheel.data;
3985 break;
3986 case PART::control::midiBreath:
3987 ; // not yet
3988 break;
3989 case PART::control::midiExpression:
3990 if (write)
3991 part->SetController(MIDI::CC::expression, value);
3992 else
3993 value = part->ctl->expression.data;
3994 break;
3995 case PART::control::midiSustain:
3996 if (write)
3997 part->ctl->setsustain(value);
3998 else
3999 value = part->ctl->sustain.data;
4000 break;
4001 case PART::control::midiPortamento:
4002 if (write)
4003 part->ctl->setportamento(value);
4004 else
4005 value = part->ctl->portamento.data;
4006 break;
4007 case PART::control::midiFilterQ:
4008 if (write)
4009 part->ctl->setfilterq(value);
4010 else
4011 value = part->ctl->filterq.data;
4012 break;
4013 case PART::control::midiFilterCutoff:
4014 if (write)
4015 part->ctl->setfiltercutoff(value);
4016 else
4017 value = part->ctl->filtercutoff.data;
4018 break;
4019 case PART::control::midiBandwidth:
4020 if (write)
4021 part->ctl->setbandwidth(value);
4022 else
4023 value = part->ctl->bandwidth.data;
4024 break;
4025
4026 case PART::control::midiFMamp:
4027 if (write)
4028 part->ctl->setfmamp(value);
4029 else
4030 value = part->ctl->fmamp.data;
4031 break;
4032 case PART::control::midiResonanceCenter:
4033 if (write)
4034 part->ctl->setresonancecenter(value);
4035 else
4036 value = part->ctl->resonancecenter.data;
4037 break;
4038 case PART::control::midiResonanceBandwidth:
4039 if (write)
4040 part->ctl->setresonancebw(value);
4041 else
4042 value = part->ctl->resonancebandwidth.data;
4043 break;
4044
4045 case PART::control::instrumentCopyright: // done elsewhere
4046 break;
4047 case PART::control::instrumentComments: // done elsewhere
4048 break;
4049 case PART::control::instrumentName: // done elsewhere
4050 break;
4051 case PART::control::instrumentType:// done elsewhere
4052 break;
4053 case PART::control::defaultInstrumentCopyright: // done elsewhere
4054 ;
4055 case PART::control::resetAllControllers:
4056 if (write)
4057 part->SetController(0x79,0);
4058 break;
4059 }
4060
4061 if (!write || control == PART::control::minToLastKey || control == PART::control::maxToLastKey)
4062 getData->data.value = value;
4063 }
4064
4065
commandAdd(CommandBlock * getData)4066 void InterChange::commandAdd(CommandBlock *getData)
4067 {
4068 float value = getData->data.value;
4069 unsigned char type = getData->data.type;
4070 unsigned char control = getData->data.control;
4071 unsigned char npart = getData->data.part;
4072 unsigned char kititem = getData->data.kit;
4073
4074 bool write = (type & TOPLEVEL::type::Write) > 0;
4075
4076 int value_int = lrint(value);
4077 char value_bool = _SYS_::F2B(value);
4078
4079 Part *part;
4080 part = synth->part[npart];
4081 ADnoteParameters *pars;
4082 pars = part->kit[kititem].adpars;
4083
4084 switch (control)
4085 {
4086 case ADDSYNTH::control::volume:
4087 if (write)
4088 pars->GlobalPar.PVolume = value_int;
4089 else
4090 value = pars->GlobalPar.PVolume;
4091 break;
4092 case ADDSYNTH::control::velocitySense:
4093 if (write)
4094 pars->GlobalPar.PAmpVelocityScaleFunction = value_int;
4095 else
4096 value = pars->GlobalPar.PAmpVelocityScaleFunction;
4097 break;
4098 case ADDSYNTH::control::panning:
4099 if (write)
4100 pars->setGlobalPan(value_int, synth->getRuntime().panLaw);
4101 else
4102 value = pars->GlobalPar.PPanning;
4103 break;
4104 case ADDSYNTH::control::enableRandomPan:
4105 if (write)
4106 pars->GlobalPar.PRandom = value_int;
4107 else
4108 value = pars->GlobalPar.PRandom;
4109 break;
4110 case ADDSYNTH::control::randomWidth:
4111 if (write)
4112 pars->GlobalPar.PWidth = value_int;
4113 else
4114 value = pars->GlobalPar.PWidth;
4115 break;
4116
4117 case ADDSYNTH::control::detuneFrequency:
4118 if (write)
4119 pars->GlobalPar.PDetune = value_int + 8192;
4120 else
4121 value = pars->GlobalPar.PDetune - 8192;
4122 break;
4123
4124 case ADDSYNTH::control::octave:
4125 {
4126 int k;
4127 if (write)
4128 {
4129 k = value;
4130 if (k < 0)
4131 k += 16;
4132 pars->GlobalPar.PCoarseDetune = k * 1024 + pars->GlobalPar.PCoarseDetune % 1024;
4133 }
4134 else
4135 {
4136 k = pars->GlobalPar.PCoarseDetune / 1024;
4137 if (k >= 8)
4138 k -= 16;
4139 value = k;
4140 }
4141 break;
4142 }
4143 case ADDSYNTH::control::detuneType:
4144 if (write)
4145 {
4146 if (value_int < 1) // can't be default for addsynth
4147 {
4148 getData->data.value = 1;
4149 value_int = 1;
4150 }
4151 pars->GlobalPar.PDetuneType = value_int;
4152 }
4153 else
4154 {
4155 value = pars->GlobalPar.PDetuneType;
4156 if (value < 1)
4157 value = 1;
4158 }
4159 break;
4160 case ADDSYNTH::control::coarseDetune:
4161 {
4162 int k;
4163 if (write)
4164 {
4165 k = value;
4166 if (k < 0)
4167 k += 1024;
4168 pars->GlobalPar.PCoarseDetune = k + (pars->GlobalPar.PCoarseDetune / 1024) * 1024;
4169 }
4170 else
4171 {
4172 k = pars->GlobalPar.PCoarseDetune % 1024;
4173 if (k >= 512)
4174 k -= 1024;
4175 value = k;
4176 }
4177 break;
4178 }
4179 case ADDSYNTH::control::relativeBandwidth:
4180 if (write)
4181 {
4182 pars->GlobalPar.PBandwidth = value_int;
4183 pars->getBandwidthDetuneMultiplier();
4184 }
4185 else
4186 value = pars->GlobalPar.PBandwidth;
4187 break;
4188
4189 case ADDSYNTH::control::stereo:
4190 if (write)
4191 pars->GlobalPar.PStereo = value_bool;
4192 else
4193 value = pars->GlobalPar.PStereo;
4194 break;
4195 case ADDSYNTH::control::randomGroup:
4196 if (write)
4197 pars->GlobalPar.Hrandgrouping = value_bool;
4198 else
4199 value = pars->GlobalPar.Hrandgrouping;
4200 break;
4201
4202 case ADDSYNTH::control::dePop:
4203 if (write)
4204 pars->GlobalPar.Fadein_adjustment = value_int;
4205 else
4206 value = pars->GlobalPar.Fadein_adjustment;
4207 break;
4208 case ADDSYNTH::control::punchStrength:
4209 if (write)
4210 pars->GlobalPar.PPunchStrength = value_int;
4211 else
4212 value = pars->GlobalPar.PPunchStrength;
4213 break;
4214 case ADDSYNTH::control::punchDuration:
4215 if (write)
4216 pars->GlobalPar.PPunchTime = value_int;
4217 else
4218 value = pars->GlobalPar.PPunchTime;
4219 break;
4220 case ADDSYNTH::control::punchStretch:
4221 if (write)
4222 pars->GlobalPar.PPunchStretch = value_int;
4223 else
4224 value = pars->GlobalPar.PPunchStretch;
4225 break;
4226 case ADDSYNTH::control::punchVelocity:
4227 if (write)
4228 pars->GlobalPar.PPunchVelocitySensing = value_int;
4229 else
4230 value = pars->GlobalPar.PPunchVelocitySensing;
4231 break;
4232 }
4233 if (!write)
4234 getData->data.value = value;
4235 }
4236
4237
commandAddVoice(CommandBlock * getData)4238 void InterChange::commandAddVoice(CommandBlock *getData)
4239 {
4240 float value = getData->data.value;
4241 unsigned char type = getData->data.type;
4242 unsigned char control = getData->data.control;
4243 unsigned char npart = getData->data.part;
4244 unsigned char kititem = getData->data.kit;
4245 unsigned char engine = getData->data.engine;
4246 int nvoice;
4247 if (engine >= PART::engine::addMod1)
4248 nvoice = engine - PART::engine::addMod1;
4249 else
4250 nvoice = engine - PART::engine::addVoice1;
4251
4252 bool write = (type & TOPLEVEL::type::Write) > 0;
4253
4254 int value_int = lrint(value);
4255 char value_bool = _SYS_::F2B(value);
4256
4257 Part *part;
4258 part = synth->part[npart];
4259 ADnoteParameters *pars;
4260 pars = part->kit[kititem].adpars;
4261
4262 switch (control)
4263 {
4264 case ADDVOICE::control::volume:
4265 if (write)
4266 pars->VoicePar[nvoice].PVolume = value_int;
4267 else
4268 value = pars->VoicePar[nvoice].PVolume;
4269 break;
4270 case ADDVOICE::control::velocitySense:
4271 if (write)
4272 pars->VoicePar[nvoice].PAmpVelocityScaleFunction = value_int;
4273 else
4274 value = pars->VoicePar[nvoice].PAmpVelocityScaleFunction;
4275 break;
4276 case ADDVOICE::control::panning:
4277 if (write)
4278 pars->setVoicePan(nvoice, value_int, synth->getRuntime().panLaw);
4279 else
4280 value = pars->VoicePar[nvoice].PPanning;
4281 break;
4282 case ADDVOICE::control::enableRandomPan:
4283 if (write)
4284 pars->VoicePar[nvoice].PRandom = value_int;
4285 else
4286 value = pars->VoicePar[nvoice].PRandom;
4287 break;
4288 case ADDVOICE::control::randomWidth:
4289 if (write)
4290 pars->VoicePar[nvoice].PWidth = value_int;
4291 else
4292 value = pars->VoicePar[nvoice].PWidth;
4293 break;
4294
4295 case ADDVOICE::control::invertPhase:
4296 if (write)
4297 pars->VoicePar[nvoice].PVolumeminus = value_bool;
4298 else
4299 value = pars->VoicePar[nvoice].PVolumeminus;
4300 break;
4301 case ADDVOICE::control::enableAmplitudeEnvelope:
4302 if (write)
4303 pars->VoicePar[nvoice].PAmpEnvelopeEnabled = value_bool;
4304 else
4305 value = pars->VoicePar[nvoice].PAmpEnvelopeEnabled;
4306 break;
4307 case ADDVOICE::control::enableAmplitudeLFO:
4308 if (write)
4309 pars->VoicePar[nvoice].PAmpLfoEnabled = value_bool;
4310 else
4311 value = pars->VoicePar[nvoice].PAmpLfoEnabled;
4312 break;
4313
4314 case ADDVOICE::control::modulatorType:
4315 if (write)
4316 {
4317 pars->VoicePar[nvoice].PFMEnabled = value_int;
4318 getData->data.value = value_int; // we have to do this otherwise GUI goes out of sync
4319 }
4320 else
4321 value = pars->VoicePar[nvoice].PFMEnabled;
4322 break;
4323 case ADDVOICE::control::externalModulator:
4324 if (write)
4325 pars->VoicePar[nvoice].PFMVoice = value_int;
4326 else
4327 value = pars->VoicePar[nvoice].PFMVoice;
4328 break;
4329
4330 case ADDVOICE::control::externalOscillator:
4331 if (write)
4332 pars->VoicePar[nvoice].PVoice = value_int;
4333 else
4334 value = pars->VoicePar[nvoice].PVoice;
4335 break;
4336
4337 case ADDVOICE::control::detuneFrequency:
4338 if (write)
4339 pars->VoicePar[nvoice].PDetune = value_int + 8192;
4340 else
4341 value = pars->VoicePar[nvoice].PDetune-8192;
4342 break;
4343 case ADDVOICE::control::equalTemperVariation:
4344 if (write)
4345 pars->VoicePar[nvoice].PfixedfreqET = value_int;
4346 else
4347 value = pars->VoicePar[nvoice].PfixedfreqET;
4348 break;
4349 case ADDVOICE::control::baseFrequencyAs440Hz:
4350 if (write)
4351 pars->VoicePar[nvoice].Pfixedfreq = value_bool;
4352 else
4353 value = pars->VoicePar[nvoice].Pfixedfreq;
4354 break;
4355 case ADDVOICE::control::octave:
4356 {
4357 int k;
4358 if (write)
4359 {
4360 k = value;
4361 if (k < 0)
4362 k += 16;
4363 pars->VoicePar[nvoice].PCoarseDetune = k * 1024 + pars->VoicePar[nvoice].PCoarseDetune % 1024;
4364 }
4365 else
4366 {
4367 k = pars->VoicePar[nvoice].PCoarseDetune / 1024;
4368 if (k >= 8)
4369 k -= 16;
4370 value = k;
4371 }
4372 break;
4373 }
4374 case ADDVOICE::control::detuneType:
4375 if (write)
4376 pars->VoicePar[nvoice].PDetuneType = value_int;
4377 else
4378 value = pars->VoicePar[nvoice].PDetuneType;
4379 break;
4380 case ADDVOICE::control::coarseDetune:
4381 {
4382 int k;
4383 if (write)
4384 {
4385 k = value;
4386 if (k < 0)
4387 k += 1024;
4388 pars->VoicePar[nvoice].PCoarseDetune = k + (pars->VoicePar[nvoice].PCoarseDetune / 1024) * 1024;
4389 }
4390 else
4391 {
4392 k = pars->VoicePar[nvoice].PCoarseDetune % 1024;
4393 if (k >= 512)
4394 k -= 1024;
4395 value = k;
4396 }
4397 break;
4398 }
4399 case ADDVOICE::control::pitchBendAdjustment:
4400 if (write)
4401 pars->VoicePar[nvoice].PBendAdjust = value_int;
4402 else
4403 value = pars->VoicePar[nvoice].PBendAdjust;
4404 break;
4405 case ADDVOICE::control::pitchBendOffset:
4406 if (write)
4407 pars->VoicePar[nvoice].POffsetHz = value_int;
4408 else
4409 value = pars->VoicePar[nvoice].POffsetHz;
4410 break;
4411 case ADDVOICE::control::enableFrequencyEnvelope:
4412 if (write)
4413 pars->VoicePar[nvoice].PFreqEnvelopeEnabled = value_int;
4414 else
4415 value = pars->VoicePar[nvoice].PFreqEnvelopeEnabled;
4416 break;
4417 case ADDVOICE::control::enableFrequencyLFO:
4418 if (write)
4419 pars->VoicePar[nvoice].PFreqLfoEnabled = value_int;
4420 else
4421 value = pars->VoicePar[nvoice].PFreqLfoEnabled;
4422 break;
4423
4424 case ADDVOICE::control::unisonFrequencySpread:
4425 if (write)
4426 pars->VoicePar[nvoice].Unison_frequency_spread = value_int;
4427 else
4428 value = pars->VoicePar[nvoice].Unison_frequency_spread;
4429 break;
4430 case ADDVOICE::control::unisonPhaseRandomise:
4431 if (write)
4432 pars->VoicePar[nvoice].Unison_phase_randomness = value_int;
4433 else
4434 value = pars->VoicePar[nvoice].Unison_phase_randomness;
4435 break;
4436 case ADDVOICE::control::unisonStereoSpread:
4437 if (write)
4438 pars->VoicePar[nvoice].Unison_stereo_spread = value_int;
4439 else
4440 value = pars->VoicePar[nvoice].Unison_stereo_spread;
4441 break;
4442 case ADDVOICE::control::unisonVibratoDepth:
4443 if (write)
4444 pars->VoicePar[nvoice].Unison_vibratto = value_int;
4445 else
4446 value = pars->VoicePar[nvoice].Unison_vibratto;
4447 break;
4448 case ADDVOICE::control::unisonVibratoSpeed:
4449 if (write)
4450 pars->VoicePar[nvoice].Unison_vibratto_speed = value_int;
4451 else
4452 value = pars->VoicePar[nvoice].Unison_vibratto_speed;
4453 break;
4454 case ADDVOICE::control::unisonSize:
4455 if (write)
4456 {
4457 if (value < 2)
4458 value = 2;
4459 pars->VoicePar[nvoice].Unison_size = value_int;
4460 }
4461 else
4462 value = pars->VoicePar[nvoice].Unison_size;
4463 break;
4464 case ADDVOICE::control::unisonPhaseInvert:
4465 if (write)
4466 pars->VoicePar[nvoice].Unison_invert_phase = value_int;
4467 else
4468 value = pars->VoicePar[nvoice].Unison_invert_phase;
4469 break;
4470 case ADDVOICE::control::enableUnison:
4471 {
4472 int k;
4473 if (write)
4474 {
4475 k = value_bool + 1;
4476 if (pars->VoicePar[nvoice].Unison_size < 2 || k == 1)
4477 pars->VoicePar[nvoice].Unison_size = k;
4478 }
4479 else
4480 value = (pars->VoicePar[nvoice].Unison_size > 1);
4481 break;
4482 }
4483
4484 case ADDVOICE::control::bypassGlobalFilter:
4485 if (write)
4486 pars->VoicePar[nvoice].Pfilterbypass = value_bool;
4487 else
4488 value = pars->VoicePar[nvoice].Pfilterbypass;
4489 break;
4490 case ADDVOICE::control::enableFilter:
4491 if (write)
4492 pars->VoicePar[nvoice].PFilterEnabled = value_bool;
4493 else
4494 value = pars->VoicePar[nvoice].PFilterEnabled;
4495 break;
4496 case ADDVOICE::control::enableFilterEnvelope:
4497 if (write)
4498 pars->VoicePar[nvoice].PFilterEnvelopeEnabled= value_bool;
4499 else
4500 value = pars->VoicePar[nvoice].PFilterEnvelopeEnabled;
4501 break;
4502 case ADDVOICE::control::enableFilterLFO:
4503 if (write)
4504 pars->VoicePar[nvoice].PFilterLfoEnabled= value_bool;
4505 else
4506 value = pars->VoicePar[nvoice].PFilterLfoEnabled;
4507 break;
4508
4509 case ADDVOICE::control::modulatorAmplitude:
4510 if (write)
4511 pars->VoicePar[nvoice].PFMVolume = value_int;
4512 else
4513 value = pars->VoicePar[nvoice].PFMVolume;
4514 break;
4515 case ADDVOICE::control::modulatorVelocitySense:
4516 if (write)
4517 pars->VoicePar[nvoice].PFMVelocityScaleFunction = value_int;
4518 else
4519 value = pars->VoicePar[nvoice].PFMVelocityScaleFunction;
4520 break;
4521 case ADDVOICE::control::modulatorHFdamping:
4522 if (write)
4523 pars->VoicePar[nvoice].PFMVolumeDamp = value_int + 64;
4524 else
4525 value = pars->VoicePar[nvoice].PFMVolumeDamp - 64;
4526 break;
4527 case ADDVOICE::control::enableModulatorAmplitudeEnvelope:
4528 if (write)
4529 pars->VoicePar[nvoice].PFMAmpEnvelopeEnabled = value_bool;
4530 else
4531 value = pars->VoicePar[nvoice].PFMAmpEnvelopeEnabled;
4532 break;
4533
4534 case ADDVOICE::control::modulatorDetuneFrequency:
4535 if (write)
4536 pars->VoicePar[nvoice].PFMDetune = value_int + 8192;
4537 else
4538 value = pars->VoicePar[nvoice].PFMDetune - 8192;
4539 break;
4540 case ADDVOICE::control::modulatorDetuneFromBaseOsc:
4541 if (write)
4542 pars->VoicePar[nvoice].PFMDetuneFromBaseOsc = value_bool;
4543 else
4544 value = pars->VoicePar[nvoice].PFMDetuneFromBaseOsc;
4545 break;
4546 case ADDVOICE::control::modulatorFrequencyAs440Hz:
4547 if (write)
4548 pars->VoicePar[nvoice].PFMFixedFreq = value_bool;
4549 else
4550 value = pars->VoicePar[nvoice].PFMFixedFreq;
4551 break;
4552 case ADDVOICE::control::modulatorOctave:
4553 {
4554 int k;
4555 if (write)
4556 {
4557 k = value_int;
4558 if (k < 0)
4559 k += 16;
4560 pars->VoicePar[nvoice].PFMCoarseDetune = k * 1024 + pars->VoicePar[nvoice].PFMCoarseDetune % 1024;
4561 }
4562 else
4563 {
4564 k = pars->VoicePar[nvoice].PFMCoarseDetune / 1024;
4565 if (k >= 8)
4566 k -= 16;
4567 value = k;
4568 }
4569 break;
4570 }
4571 case ADDVOICE::control::modulatorDetuneType:
4572 if (write)
4573 pars->VoicePar[nvoice].PFMDetuneType = value_int;
4574 else
4575 value = pars->VoicePar[nvoice].PFMDetuneType;
4576 break;
4577 case ADDVOICE::control::modulatorCoarseDetune:
4578 {
4579 int k;
4580 if (write)
4581 {
4582 int k = value_int;
4583 if (k < 0)
4584 k += 1024;
4585 pars->VoicePar[nvoice].PFMCoarseDetune = k + (pars->VoicePar[nvoice].PFMCoarseDetune / 1024) * 1024;
4586 }
4587 else
4588 {
4589 k = pars->VoicePar[nvoice].PFMCoarseDetune % 1024;
4590 if (k >= 512)
4591 k-= 1024;
4592 value = k;
4593 }
4594 break;
4595 }
4596 case ADDVOICE::control::enableModulatorFrequencyEnvelope:
4597 if (write)
4598 pars->VoicePar[nvoice].PFMFreqEnvelopeEnabled = value_int;
4599 else
4600 value = pars->VoicePar[nvoice].PFMFreqEnvelopeEnabled;
4601 break;
4602
4603 case ADDVOICE::control::modulatorOscillatorPhase:
4604 if (write)
4605 pars->VoicePar[nvoice].PFMoscilphase = 64 - value_int;
4606 else
4607 value = 64 - pars->VoicePar[nvoice].PFMoscilphase;
4608 break;
4609 case ADDVOICE::control::modulatorOscillatorSource:
4610 if (write)
4611 pars->VoicePar[nvoice].PextFMoscil = value_int;
4612 else
4613 value = pars->VoicePar[nvoice].PextFMoscil;
4614 break;
4615
4616 case ADDVOICE::control::delay:
4617 if (write)
4618 pars->VoicePar[nvoice].PDelay = value_int;
4619 else
4620 value = pars->VoicePar[nvoice].PDelay;
4621 break;
4622 case ADDVOICE::control::enableVoice:
4623 if (write)
4624 pars->VoicePar[nvoice].Enabled = value_bool;
4625 else
4626 value = pars->VoicePar[nvoice].Enabled;
4627 break;
4628 case ADDVOICE::control::enableResonance:
4629 if (write)
4630 pars->VoicePar[nvoice].Presonance = value_bool;
4631 else
4632 value = pars->VoicePar[nvoice].Presonance;
4633 break;
4634 case ADDVOICE::control::voiceOscillatorPhase:
4635 if (write)
4636 pars->VoicePar[nvoice].Poscilphase = 64 - value_int;
4637 else
4638 value = 64 - pars->VoicePar[nvoice].Poscilphase;
4639 break;
4640 case ADDVOICE::control::voiceOscillatorSource:
4641 if (write)
4642 pars->VoicePar[nvoice].Pextoscil = value_int;
4643 else
4644 value = pars->VoicePar[nvoice].Pextoscil;
4645 break;
4646 case ADDVOICE::control::soundType:
4647 if (write)
4648 pars->VoicePar[nvoice].Type = value_int;
4649 else
4650 value = pars->VoicePar[nvoice].Type;
4651 break;
4652 }
4653
4654 if (!write)
4655 getData->data.value = value;
4656 }
4657
4658
commandSub(CommandBlock * getData)4659 void InterChange::commandSub(CommandBlock *getData)
4660 {
4661 float value = getData->data.value;
4662 unsigned char type = getData->data.type;
4663 unsigned char control = getData->data.control;
4664 unsigned char npart = getData->data.part;
4665 unsigned char kititem = getData->data.kit;
4666 unsigned char insert = getData->data.insert & 0x1f; // ensure no stray filter
4667
4668 bool write = (type & TOPLEVEL::type::Write) > 0;
4669
4670 int value_int = lrint(value);
4671 char value_bool = _SYS_::F2B(value);
4672
4673 Part *part;
4674 part = synth->part[npart];
4675 SUBnoteParameters *pars;
4676 pars = part->kit[kititem].subpars;
4677
4678 if (insert == TOPLEVEL::insert::harmonicAmplitude || insert == TOPLEVEL::insert::harmonicPhaseBandwidth)
4679 {
4680 if (insert == TOPLEVEL::insert::harmonicAmplitude)
4681 {
4682 if (write)
4683 pars->Phmag[control] = value;
4684 else
4685 value = pars->Phmag[control];
4686 }
4687 else
4688 {
4689 if (write)
4690 pars->Phrelbw[control] = value;
4691 else
4692 value = pars->Phrelbw[control];
4693 }
4694
4695 if (!write)
4696 getData->data.value = value;
4697 else
4698 pars->PfilterChanged[control] = insert;
4699 return;
4700 }
4701
4702 switch (control)
4703 {
4704 case SUBSYNTH::control::volume:
4705 if (write)
4706 pars->PVolume = value;
4707 else
4708 value = pars->PVolume;
4709 break;
4710 case SUBSYNTH::control::velocitySense:
4711 if (write)
4712 pars->PAmpVelocityScaleFunction = value;
4713 else
4714 value = pars->PAmpVelocityScaleFunction;
4715 break;
4716 case SUBSYNTH::control::panning:
4717 if (write)
4718 pars->setPan(value, synth->getRuntime().panLaw);
4719 else
4720 value = pars->PPanning;
4721 break;
4722 case SUBSYNTH::control::enableRandomPan:
4723 if (write)
4724 pars->PRandom = value_int;
4725 else
4726 value = pars->PRandom;
4727 break;
4728 case SUBSYNTH::control::randomWidth:
4729 if (write)
4730 pars->PWidth = value_int;
4731 else
4732 value = pars->PWidth;
4733 break;
4734
4735 case SUBSYNTH::control::bandwidth:
4736 if (write)
4737 pars->Pbandwidth = value;
4738 else
4739 value = pars->Pbandwidth;
4740 break;
4741 case SUBSYNTH::control::bandwidthScale:
4742 if (write)
4743 pars->Pbwscale = value + 64;
4744 else
4745 value = pars->Pbwscale - 64;
4746 break;
4747 case SUBSYNTH::control::enableBandwidthEnvelope:
4748 if (write)
4749 pars->PBandWidthEnvelopeEnabled = value_bool;
4750 else
4751 value = pars->PBandWidthEnvelopeEnabled;
4752 break;
4753
4754 case SUBSYNTH::control::detuneFrequency:
4755 if (write)
4756 pars->PDetune = value + 8192;
4757 else
4758 value = pars->PDetune - 8192;
4759 break;
4760 case SUBSYNTH::control::equalTemperVariation:
4761 if (write)
4762 pars->PfixedfreqET = value;
4763 else
4764 value = pars->PfixedfreqET;
4765 break;
4766 case SUBSYNTH::control::baseFrequencyAs440Hz:
4767 if (write)
4768 pars->Pfixedfreq = value_bool;
4769 else
4770 value = pars->Pfixedfreq;
4771 break;
4772 case SUBSYNTH::control::octave:
4773 {
4774 int k;
4775 if (write)
4776 {
4777 k = value;
4778 if (k < 0)
4779 k += 16;
4780 pars->PCoarseDetune = k * 1024 + pars->PCoarseDetune % 1024;
4781 }
4782 else
4783 {
4784 k = pars->PCoarseDetune / 1024;
4785 if (k >= 8)
4786 k -= 16;
4787 value = k;
4788 }
4789 break;
4790 }
4791 case SUBSYNTH::control::detuneType:
4792 if (write)
4793 {
4794 if (value_int < 1) // can't be default for subsynth
4795 {
4796 getData->data.value = 1;
4797 value_int = 1;
4798 }
4799 pars->PDetuneType = value_int;
4800 }
4801 else
4802 value = pars->PDetuneType;
4803 break;
4804 case SUBSYNTH::control::coarseDetune:
4805 {
4806 int k;
4807 if (write)
4808 {
4809 k = value;
4810 if (k < 0)
4811 k += 1024;
4812 pars->PCoarseDetune = k + (pars->PCoarseDetune / 1024) * 1024;
4813 }
4814 else
4815 {
4816 k = pars->PCoarseDetune % 1024;
4817 if (k >= 512)
4818 k -= 1024;
4819 value = k;
4820 }
4821 break;
4822 }
4823
4824 case SUBSYNTH::control::pitchBendAdjustment:
4825 if (write)
4826 pars->PBendAdjust = value;
4827 else
4828 value = pars->PBendAdjust;
4829 break;
4830
4831 case SUBSYNTH::control::pitchBendOffset:
4832 if (write)
4833 pars->POffsetHz = value;
4834 else
4835 value = pars->POffsetHz;
4836 break;
4837
4838 case SUBSYNTH::control::enableFrequencyEnvelope:
4839 if (write)
4840 pars->PFreqEnvelopeEnabled = value_bool;
4841 else
4842 value = pars->PFreqEnvelopeEnabled;
4843 break;
4844
4845 case SUBSYNTH::control::overtoneParameter1:
4846 if (write)
4847 {
4848 pars->POvertoneSpread.par1 = value;
4849 pars->updateFrequencyMultipliers();
4850 }
4851 else
4852 value = pars->POvertoneSpread.par1;
4853 break;
4854 case SUBSYNTH::control::overtoneParameter2:
4855 if (write)
4856 {
4857 pars->POvertoneSpread.par2 = value;
4858 pars->updateFrequencyMultipliers();
4859 }
4860 else
4861 value = pars->POvertoneSpread.par2;
4862 break;
4863 case SUBSYNTH::control::overtoneForceHarmonics:
4864 if (write)
4865 {
4866 pars->POvertoneSpread.par3 = value;
4867 pars->updateFrequencyMultipliers();
4868 }
4869 else
4870 value = pars->POvertoneSpread.par3;
4871 break;
4872 case SUBSYNTH::control::overtonePosition:
4873 if (write)
4874 {
4875 pars->POvertoneSpread.type = value_int;
4876 pars->updateFrequencyMultipliers();
4877 }
4878 else
4879 value = pars->POvertoneSpread.type;
4880 break;
4881
4882 case SUBSYNTH::control::enableFilter:
4883 if (write)
4884 pars->PGlobalFilterEnabled = value_bool;
4885 else
4886 value = pars->PGlobalFilterEnabled;
4887 break;
4888
4889 case SUBSYNTH::control::filterStages:
4890 if (write)
4891 pars->Pnumstages = value_int;
4892 else
4893 value = pars->Pnumstages;
4894 break;
4895 case SUBSYNTH::control::magType:
4896 if (write)
4897 pars->Phmagtype = value_int;
4898 else
4899 value = pars->Phmagtype;
4900 break;
4901 case SUBSYNTH::control::startPosition:
4902 if (write)
4903 pars->Pstart = value_int;
4904 else
4905 value = pars->Pstart;
4906 break;
4907
4908 case SUBSYNTH::control::clearHarmonics:
4909 if (write)
4910 {
4911 for (int i = 0; i < MAX_SUB_HARMONICS; i++)
4912 {
4913 pars->Phmag[i] = 0;
4914 pars->Phrelbw[i] = 64;
4915 }
4916 pars->Phmag[0] = 127;
4917 }
4918 break;
4919
4920 case SUBSYNTH::control::stereo:
4921 if (write)
4922 pars->Pstereo = value_bool;
4923 else
4924 value = pars->Pstereo;
4925 break;
4926 }
4927
4928 if (!write)
4929 getData->data.value = value;
4930 }
4931
4932
commandPad(CommandBlock * getData)4933 void InterChange::commandPad(CommandBlock *getData)
4934 {
4935 float value = getData->data.value;
4936 unsigned char type = getData->data.type;
4937 unsigned char control = getData->data.control;
4938 unsigned char npart = getData->data.part;
4939 unsigned char kititem = getData->data.kit;
4940
4941 bool write = (type & TOPLEVEL::type::Write) > 0;
4942
4943 int value_int = lrint(value);
4944 char value_bool = _SYS_::F2B(value);
4945
4946 Part *part;
4947 part = synth->part[npart];
4948 PADnoteParameters *pars;
4949 pars = part->kit[kititem].padpars;
4950
4951 switch (control)
4952 {
4953 case PADSYNTH::control::volume:
4954 if (write)
4955 pars->PVolume = value;
4956 else
4957 value = pars->PVolume;
4958 break;
4959 case PADSYNTH::control::velocitySense:
4960 if (write)
4961 pars->PAmpVelocityScaleFunction = value;
4962 else
4963 value = pars->PAmpVelocityScaleFunction;
4964 break;
4965 case PADSYNTH::control::panning:
4966 if (write)
4967 pars->setPan(value, synth->getRuntime().panLaw);
4968 else
4969 value = pars->PPanning;
4970 break;
4971 case PADSYNTH::control::enableRandomPan:
4972 if (write)
4973 pars->PRandom = value_int;
4974 else
4975 value = pars->PRandom;
4976 break;
4977 case PADSYNTH::control::randomWidth:
4978 if (write)
4979 pars->PWidth = value_int;
4980 else
4981 value = pars->PWidth;
4982 break;
4983
4984 case PADSYNTH::control::bandwidth:
4985 if (write)
4986 pars->setPbandwidth(value_int);
4987 else
4988 value = pars->Pbandwidth;
4989 break;
4990 case PADSYNTH::control::bandwidthScale:
4991 if (write)
4992 pars->Pbwscale = value_int;
4993 else
4994 value = pars->Pbwscale;
4995 break;
4996 case PADSYNTH::control::spectrumMode:
4997 if (write)
4998 pars->Pmode = value_int;
4999 else
5000 value = pars->Pmode;
5001 break;
5002
5003 case PADSYNTH::control::detuneFrequency:
5004 if (write)
5005 pars->PDetune = value_int + 8192;
5006 else
5007 value = pars->PDetune - 8192;
5008 break;
5009 case PADSYNTH::control::equalTemperVariation:
5010 if (write)
5011 pars->PfixedfreqET = value_int;
5012 else
5013 value = pars->PfixedfreqET;
5014 break;
5015 case PADSYNTH::control::baseFrequencyAs440Hz:
5016 if (write)
5017 pars->Pfixedfreq = value_bool;
5018 else
5019 value = pars->Pfixedfreq;
5020 break;
5021 case PADSYNTH::control::octave:
5022 if (write)
5023 {
5024 int tmp = value;
5025 if (tmp < 0)
5026 tmp += 16;
5027 pars->PCoarseDetune = tmp * 1024 + pars->PCoarseDetune % 1024;
5028 }
5029 else
5030 {
5031 int tmp = pars->PCoarseDetune / 1024;
5032 if (tmp >= 8)
5033 tmp -= 16;
5034 value = tmp;
5035 }
5036 break;
5037 case PADSYNTH::control::detuneType:
5038 if (write)
5039 {
5040 if (value_int < 1) // can't be default for padsynth
5041 {
5042 getData->data.value = 1;
5043 value_int = 1;
5044 }
5045 pars->PDetuneType = value_int;
5046 }
5047 else
5048 value = pars->PDetuneType;
5049 break;
5050 case PADSYNTH::control::coarseDetune:
5051 if (write)
5052 {
5053 int tmp = value;
5054 if (tmp < 0)
5055 tmp += 1024;
5056 pars->PCoarseDetune = tmp + (pars->PCoarseDetune / 1024) * 1024;
5057 }
5058 else
5059 {
5060 int tmp = pars->PCoarseDetune % 1024;
5061 if (tmp >= 512)
5062 tmp -= 1024;
5063 value = tmp;
5064 }
5065 break;
5066
5067 case PADSYNTH::control::pitchBendAdjustment:
5068 if (write)
5069 pars->PBendAdjust = value_int;
5070 else
5071 value = pars->PBendAdjust;
5072 break;
5073 case PADSYNTH::control::pitchBendOffset:
5074 if (write)
5075 pars->POffsetHz = value_int;
5076 else
5077 value = pars->POffsetHz;
5078 break;
5079
5080 case PADSYNTH::control::overtoneParameter1:
5081 if (write)
5082 pars->Phrpos.par1 = value_int;
5083 else
5084 value = pars->Phrpos.par1;
5085 break;
5086 case PADSYNTH::control::overtoneParameter2:
5087 if (write)
5088 pars->Phrpos.par2 = value_int;
5089 else
5090 value = pars->Phrpos.par2;
5091 break;
5092 case PADSYNTH::control::overtoneForceHarmonics:
5093 if (write)
5094 pars->Phrpos.par3 = value_int;
5095 else
5096 value = pars->Phrpos.par3;
5097 break;
5098 case PADSYNTH::control::overtonePosition:
5099 if (write)
5100 pars->Phrpos.type = value_int;
5101 else
5102 value = pars->Phrpos.type;
5103 break;
5104
5105 case PADSYNTH::control::baseWidth:
5106 if (write)
5107 pars->Php.base.par1 = value_int;
5108 else
5109 value = pars->Php.base.par1;
5110 break;
5111 case PADSYNTH::control::frequencyMultiplier:
5112 if (write)
5113 pars->Php.freqmult = value_int;
5114 else
5115 value = pars->Php.freqmult;
5116 break;
5117 case PADSYNTH::control::modulatorStretch:
5118 if (write)
5119 pars->Php.modulator.par1 = value_int;
5120 else
5121 value = pars->Php.modulator.par1;
5122 break;
5123 case PADSYNTH::control::modulatorFrequency:
5124 if (write)
5125 pars->Php.modulator.freq = value_int;
5126 else
5127 value = pars->Php.modulator.freq;
5128 break;
5129 case PADSYNTH::control::size:
5130 if (write)
5131 pars->Php.width = value_int;
5132 else
5133 value = pars->Php.width;
5134 break;
5135 case PADSYNTH::control::baseType:
5136 if (write)
5137 pars->Php.base.type = value;
5138 else
5139 value = pars->Php.base.type;
5140 break;
5141 case PADSYNTH::control::harmonicSidebands:
5142 if (write)
5143 pars->Php.onehalf = value;
5144 else
5145 value = pars->Php.onehalf;
5146 break;
5147 case PADSYNTH::control::spectralWidth:
5148 if (write)
5149 pars->Php.amp.par1 = value_int;
5150 else
5151 value = pars->Php.amp.par1;
5152 break;
5153 case PADSYNTH::control::spectralAmplitude:
5154 if (write)
5155 pars->Php.amp.par2 = value_int;
5156 else
5157 value = pars->Php.amp.par2;
5158 break;
5159 case PADSYNTH::control::amplitudeMultiplier:
5160 if (write)
5161 pars->Php.amp.type = value;
5162 else
5163 value = pars->Php.amp.type;
5164 break;
5165 case PADSYNTH::control::amplitudeMode:
5166 if (write)
5167 pars->Php.amp.mode = value;
5168 else
5169 value = pars->Php.amp.mode;
5170 break;
5171 case PADSYNTH::control::autoscale:
5172 if (write)
5173 pars->Php.autoscale = value_bool;
5174 else
5175 value = pars->Php.autoscale;
5176 break;
5177
5178 case PADSYNTH::control::harmonicBase:
5179 if (write)
5180 pars->Pquality.basenote = value_int;
5181 else
5182 value = pars->Pquality.basenote;
5183 break;
5184 case PADSYNTH::control::samplesPerOctave:
5185 if (write)
5186 pars->Pquality.smpoct = value_int;
5187 else
5188 value = pars->Pquality.smpoct;
5189 break;
5190 case PADSYNTH::control::numberOfOctaves:
5191 if (write)
5192 pars->Pquality.oct = value_int;
5193 else
5194 value = pars->Pquality.oct;
5195 break;
5196 case PADSYNTH::control::sampleSize:
5197 if (write)
5198 pars->Pquality.samplesize = value_int;
5199 else
5200 value = pars->Pquality.samplesize;
5201 break;
5202
5203 case PADSYNTH::control::applyChanges:
5204 if (write && value >= 0.5f)
5205 { // this control is 'expensive' only used if necessary
5206 if (!pars->Papplied)
5207 {
5208 synth->partonoffWrite(npart, -1);
5209 getData->data.source = TOPLEVEL::action::lowPrio;
5210 getData->data.value = 1;
5211 }
5212 else
5213 getData->data.source = TOPLEVEL::action::noAction;
5214 }
5215 else
5216 value = pars->Papplied;
5217 break;
5218
5219 case PADSYNTH::control::stereo:
5220 if (write)
5221 pars->PStereo = value_bool;
5222 else
5223 value = pars->PStereo;
5224 break;
5225
5226 case PADSYNTH::control::dePop:
5227 if (write)
5228 pars->Fadein_adjustment = value_int;
5229 else
5230 value = pars->Fadein_adjustment;
5231 break;
5232 case PADSYNTH::control::punchStrength:
5233 if (write)
5234 pars->PPunchStrength = value_int;
5235 else
5236 value = pars->PPunchStrength;
5237 break;
5238 case PADSYNTH::control::punchDuration:
5239 if (write)
5240 pars->PPunchTime = value_int;
5241 else
5242 value = pars->PPunchTime;
5243 break;
5244 case PADSYNTH::control::punchStretch:
5245 if (write)
5246 pars->PPunchStretch = value_int;
5247 else
5248 value = pars->PPunchStretch;
5249 break;
5250 case PADSYNTH::control::punchVelocity:
5251 if (write)
5252 pars->PPunchVelocitySensing = value_int;
5253 else
5254 value = pars->PPunchVelocitySensing;
5255 break;
5256 }
5257
5258 if (control >= PADSYNTH::control::bandwidth && control < PADSYNTH::control::applyChanges)
5259 {
5260 pars->Papplied = 0;
5261 getData->data.offset = 0;
5262 }
5263 if (!write)
5264 getData->data.value = value;
5265 }
5266
5267
commandOscillator(CommandBlock * getData,OscilParameters * oscil)5268 void InterChange::commandOscillator(CommandBlock *getData, OscilParameters *oscil)
5269 {
5270 float value = getData->data.value;
5271 unsigned char type = getData->data.type;
5272 unsigned char control = getData->data.control;
5273 unsigned char insert = getData->data.insert;
5274
5275 int value_int = lrint(value);
5276 bool value_bool = _SYS_::F2B(value);
5277 bool write = (type & TOPLEVEL::type::Write) > 0;
5278
5279 if (insert == TOPLEVEL::insert::harmonicAmplitude)
5280 {
5281 if (write)
5282 {
5283 oscil->Phmag[control] = value_int;
5284 if (value_int == 64)
5285 oscil->Phphase[control] = 64;
5286 oscil->presetsUpdated();
5287 }
5288 else
5289 getData->data.value = oscil->Phmag[control];
5290 return;
5291 }
5292 else if (insert == TOPLEVEL::insert::harmonicPhaseBandwidth)
5293 {
5294 if (write)
5295 {
5296 oscil->Phphase[control] = value_int;
5297 oscil->presetsUpdated();
5298 }
5299 else
5300 getData->data.value = oscil->Phphase[control];
5301 return;
5302 }
5303
5304 switch (control)
5305 {
5306 case OSCILLATOR::control::phaseRandomness:
5307 if (write)
5308 oscil->Prand = value_int + 64;
5309 else
5310 value = oscil->Prand - 64;
5311 break;
5312 case OSCILLATOR::control::magType:
5313 if (write)
5314 oscil->Phmagtype = value_int;
5315 else
5316 value = oscil->Phmagtype;
5317 break;
5318 case OSCILLATOR::control::harmonicAmplitudeRandomness:
5319 if (write)
5320 oscil->Pamprandpower = value_int;
5321 else
5322 value = oscil->Pamprandpower;
5323 break;
5324 case OSCILLATOR::control::harmonicRandomnessType:
5325 if (write)
5326 oscil->Pamprandtype = value_int;
5327 else
5328 value = oscil->Pamprandtype;
5329 break;
5330
5331 case OSCILLATOR::control::baseFunctionParameter:
5332 if (write)
5333 oscil->Pbasefuncpar = value_int + 64;
5334 else
5335 value = oscil->Pbasefuncpar - 64;
5336 break;
5337 case OSCILLATOR::control::baseFunctionType:
5338 if (write)
5339 oscil->Pcurrentbasefunc = value_int;
5340 else
5341 value = oscil->Pcurrentbasefunc;
5342 break;
5343 case OSCILLATOR::control::baseModulationParameter1:
5344 if (write)
5345 oscil->Pbasefuncmodulationpar1 = value_int;
5346 else
5347 value = oscil->Pbasefuncmodulationpar1;
5348 break;
5349 case OSCILLATOR::control::baseModulationParameter2:
5350 if (write)
5351 oscil->Pbasefuncmodulationpar2 = value_int;
5352 else
5353 value = oscil->Pbasefuncmodulationpar2;
5354 break;
5355 case OSCILLATOR::control::baseModulationParameter3:
5356 if (write)
5357 oscil->Pbasefuncmodulationpar3 = value_int;
5358 else
5359 value = oscil->Pbasefuncmodulationpar3;
5360 break;
5361 case OSCILLATOR::control::baseModulationType:
5362 if (write)
5363 oscil->Pbasefuncmodulation = value_int;
5364 else
5365 value = oscil->Pbasefuncmodulation;
5366 break;
5367
5368 case OSCILLATOR::control::autoClear: // this is local to the GUI
5369 break;
5370 case OSCILLATOR::control::useAsBaseFunction:
5371 if (write)
5372 {
5373 FFTwrapper fft(synth->oscilsize);
5374 OscilGen gen(&fft, NULL, synth, oscil);
5375 gen.useasbase();
5376 if (value_bool)
5377 {
5378 for (int i = 0; i < MAX_AD_HARMONICS; ++ i)
5379 {
5380 oscil->Phmag[i] = 64;
5381 oscil->Phphase[i] = 64;
5382 }
5383 oscil->Phmag[0] = 127;
5384 oscil->Pharmonicshift = 0;
5385 oscil->Pwaveshapingfunction = 0;
5386 oscil->Pfiltertype = 0;
5387 oscil->Psatype = 0;
5388 }
5389 oscil->presetsUpdated();
5390 }
5391 break;
5392
5393 case OSCILLATOR::control::waveshapeParameter:
5394 if (write)
5395 oscil->Pwaveshaping = value_int + 64;
5396 else
5397 value = oscil->Pwaveshaping - 64;
5398 break;
5399 case OSCILLATOR::control::waveshapeType:
5400 if (write)
5401 oscil->Pwaveshapingfunction = value_int;
5402 else
5403 value = oscil->Pwaveshapingfunction;
5404 break;
5405
5406 case OSCILLATOR::control::filterParameter1:
5407 if (write)
5408 oscil->Pfilterpar1 = value_int;
5409 else
5410 value = oscil->Pfilterpar1;
5411 break;
5412 case OSCILLATOR::control::filterParameter2:
5413 if (write)
5414 oscil->Pfilterpar2 = value_int;
5415 else
5416 value = oscil->Pfilterpar2;
5417 break;
5418 case OSCILLATOR::control::filterBeforeWaveshape:
5419 if (write)
5420 oscil->Pfilterbeforews = value_bool;
5421 else
5422 value = oscil->Pfilterbeforews;
5423 break;
5424 case OSCILLATOR::control::filterType:
5425 if (write)
5426 oscil->Pfiltertype = value_int;
5427 else
5428 value = oscil->Pfiltertype;
5429 break;
5430 case OSCILLATOR::control::modulationParameter1:
5431 if (write)
5432 oscil->Pmodulationpar1 = value_int;
5433 else
5434 value = oscil->Pmodulationpar1;
5435 break;
5436 case OSCILLATOR::control::modulationParameter2:
5437 if (write)
5438 oscil->Pmodulationpar2 = value_int;
5439 else
5440 value = oscil->Pmodulationpar2;
5441 break;
5442 case OSCILLATOR::control::modulationParameter3:
5443 if (write)
5444 oscil->Pmodulationpar3 = value_int;
5445 else
5446 value = oscil->Pmodulationpar3;
5447 break;
5448 case OSCILLATOR::control::modulationType:
5449 if (write)
5450 oscil->Pmodulation = value_int;
5451 else
5452 value = oscil->Pmodulation;
5453 break;
5454 case OSCILLATOR::control::spectrumAdjustParameter:
5455 if (write)
5456 oscil->Psapar = value_int;
5457 else
5458 value = oscil->Psapar;
5459 break;
5460 case OSCILLATOR::control::spectrumAdjustType:
5461 if (write)
5462 oscil->Psatype = value_int;
5463 else
5464 value = oscil->Psatype;
5465 break;
5466
5467 case OSCILLATOR::control::harmonicShift:
5468 if (write)
5469 oscil->Pharmonicshift = value_int;
5470 else
5471 value = oscil->Pharmonicshift;
5472 break;
5473 case OSCILLATOR::control::clearHarmonicShift:
5474 if (write)
5475 oscil->Pharmonicshift = 0;
5476 break;
5477 case OSCILLATOR::control::shiftBeforeWaveshapeAndFilter:
5478 if (write)
5479 oscil->Pharmonicshiftfirst = value_bool;
5480 else
5481 value = oscil->Pharmonicshiftfirst;
5482 break;
5483 case OSCILLATOR::control::adaptiveHarmonicsParameter:
5484 if (write)
5485 oscil->Padaptiveharmonicspar = value_int;
5486 else
5487 value = oscil->Padaptiveharmonicspar;
5488 break;
5489 case OSCILLATOR::control::adaptiveHarmonicsBase:
5490 if (write)
5491 oscil->Padaptiveharmonicsbasefreq = value_int;
5492 else
5493 value = oscil->Padaptiveharmonicsbasefreq;
5494 break;
5495 case OSCILLATOR::control::adaptiveHarmonicsPower:
5496 if (write)
5497 oscil->Padaptiveharmonicspower = value_int;
5498 else
5499 value = oscil->Padaptiveharmonicspower;
5500 break;
5501 case OSCILLATOR::control::adaptiveHarmonicsType:
5502 if (write)
5503 oscil->Padaptiveharmonics = value_int;
5504 else
5505 value = oscil->Padaptiveharmonics;
5506 break;
5507
5508 case OSCILLATOR::control::clearHarmonics:
5509 if (write)
5510 {
5511 for (int i = 0; i < MAX_AD_HARMONICS; ++ i)
5512 {
5513 oscil->Phmag[i]=64;
5514 oscil->Phphase[i]=64;
5515 }
5516 oscil->Phmag[0]=127;
5517 oscil->presetsUpdated();
5518 }
5519 break;
5520 case OSCILLATOR::control::convertToSine:
5521 if (write)
5522 {
5523 FFTwrapper fft(synth->oscilsize);
5524 OscilGen gen(&fft, NULL, synth, oscil);
5525 gen.convert2sine();
5526 oscil->presetsUpdated();
5527 }
5528 break;
5529 }
5530 if (!write)
5531 getData->data.value = value;
5532 }
5533
5534
commandResonance(CommandBlock * getData,Resonance * respar)5535 void InterChange::commandResonance(CommandBlock *getData, Resonance *respar)
5536 {
5537 float value = getData->data.value;
5538 unsigned char type = getData->data.type;
5539 unsigned char control = getData->data.control;
5540 unsigned char insert = getData->data.insert;
5541 unsigned char parameter = getData->data.parameter;
5542 int value_int = lrint(value);
5543 bool value_bool = _SYS_::F2B(value);
5544 bool write = (type & TOPLEVEL::type::Write) > 0;
5545
5546 if (insert == TOPLEVEL::insert::resonanceGraphInsert)
5547 {
5548 if (write)
5549 respar->setpoint(parameter, value_int);
5550 else
5551 getData->data.value = respar->Prespoints[parameter];
5552 return;
5553 }
5554
5555 switch (control)
5556 {
5557 case RESONANCE::control::maxDb:
5558 if (write)
5559 respar->PmaxdB = value_int;
5560 else
5561 value = respar->PmaxdB;
5562 break;
5563 case RESONANCE::control::centerFrequency:
5564 if (write)
5565 respar->Pcenterfreq = value_int;
5566 else
5567 value = respar->Pcenterfreq;
5568 break;
5569 case RESONANCE::control::octaves:
5570 if (write)
5571 respar->Poctavesfreq = value_int;
5572 else
5573 value = respar->Poctavesfreq;
5574 break;
5575
5576 case RESONANCE::control::enableResonance:
5577 if (write)
5578 respar->Penabled = value_bool;
5579 else
5580 value = respar->Penabled;
5581 break;
5582
5583 case RESONANCE::control::randomType:
5584 if (write)
5585 respar->randomize(value_int);
5586 break;
5587
5588 case RESONANCE::control::interpolatePeaks:
5589 if (write)
5590 respar->interpolatepeaks(value_bool);
5591 break;
5592 case RESONANCE::control::protectFundamental:
5593 if (write)
5594 respar->Pprotectthefundamental = value_bool;
5595 else
5596 value = respar->Pprotectthefundamental;
5597 break;
5598
5599 case RESONANCE::control::clearGraph:
5600 if (write)
5601 for (int i = 0; i < MAX_RESONANCE_POINTS; ++ i)
5602 respar->setpoint(i, 64);
5603 break;
5604 case RESONANCE::control::smoothGraph:
5605 if (write)
5606 respar->smooth();
5607 break;
5608 }
5609 if (!write)
5610 getData->data.value = value;
5611 }
5612
5613
commandLFO(CommandBlock * getData)5614 void InterChange::commandLFO(CommandBlock *getData)
5615 {
5616 unsigned char npart = getData->data.part;
5617 unsigned char kititem = getData->data.kit;
5618 unsigned char engine = getData->data.engine;
5619 unsigned char insertParam = getData->data.parameter;
5620
5621 Part *part;
5622 part = synth->part[npart];
5623
5624 if (engine == PART::engine::addSynth)
5625 {
5626 switch (insertParam)
5627 {
5628 case TOPLEVEL::insertType::amplitude:
5629 lfoReadWrite(getData, part->kit[kititem].adpars->GlobalPar.AmpLfo);
5630 break;
5631 case TOPLEVEL::insertType::frequency:
5632 lfoReadWrite(getData, part->kit[kititem].adpars->GlobalPar.FreqLfo);
5633 break;
5634 case TOPLEVEL::insertType::filter:
5635 lfoReadWrite(getData, part->kit[kititem].adpars->GlobalPar.FilterLfo);
5636 break;
5637 }
5638 }
5639 else if (engine == PART::engine::padSynth)
5640 {
5641 switch (insertParam)
5642 {
5643 case TOPLEVEL::insertType::amplitude:
5644 lfoReadWrite(getData, part->kit[kititem].padpars->AmpLfo);
5645 break;
5646 case TOPLEVEL::insertType::frequency:
5647 lfoReadWrite(getData, part->kit[kititem].padpars->FreqLfo);
5648 break;
5649 case TOPLEVEL::insertType::filter:
5650 lfoReadWrite(getData, part->kit[kititem].padpars->FilterLfo);
5651 break;
5652 }
5653 }
5654 else if (engine >= PART::engine::addVoice1)
5655 {
5656 int nvoice = engine - PART::engine::addVoice1;
5657 switch (insertParam)
5658 {
5659 case TOPLEVEL::insertType::amplitude:
5660 lfoReadWrite(getData, part->kit[kititem].adpars->VoicePar[nvoice].AmpLfo);
5661 break;
5662 case TOPLEVEL::insertType::frequency:
5663 lfoReadWrite(getData, part->kit[kititem].adpars->VoicePar[nvoice].FreqLfo);
5664 break;
5665 case TOPLEVEL::insertType::filter:
5666 lfoReadWrite(getData, part->kit[kititem].adpars->VoicePar[nvoice].FilterLfo);
5667 break;
5668 }
5669 }
5670 }
5671
5672
lfoReadWrite(CommandBlock * getData,LFOParams * pars)5673 void InterChange::lfoReadWrite(CommandBlock *getData, LFOParams *pars)
5674 {
5675 bool write = (getData->data.type & TOPLEVEL::type::Write) > 0;
5676
5677 float val = getData->data.value;
5678
5679 switch (getData->data.control)
5680 {
5681 case LFOINSERT::control::speed:
5682 if(pars->Pbpm) // set a flag so CLI can read the status
5683 getData->data.offset = 1;
5684 if (write)
5685 pars->setPfreq(val * Fmul2I);
5686 else
5687 val = float(pars->PfreqI) / float(Fmul2I);
5688 break;
5689 case LFOINSERT::control::depth:
5690 if (write)
5691 pars->setPintensity(val);
5692 else
5693 val = pars->Pintensity;
5694 break;
5695 case LFOINSERT::control::delay:
5696 if (write)
5697 pars->setPdelay(val);
5698 else
5699 val = pars->Pdelay;
5700 break;
5701 case LFOINSERT::control::start:
5702 if (write)
5703 pars->setPstartphase(val);
5704 else
5705 val = pars->Pstartphase;
5706 break;
5707 case LFOINSERT::control::amplitudeRandomness:
5708 if (write)
5709 pars->setPrandomness(val);
5710 else
5711 val = pars->Prandomness;
5712 break;
5713 case LFOINSERT::control::type:
5714 if (write)
5715 pars->setPLFOtype(lrint(val));
5716 else
5717 val = pars->PLFOtype;
5718 break;
5719 case LFOINSERT::control::continuous:
5720 if (write)
5721 pars->setPcontinous(_SYS_::F2B(val));
5722 else
5723 val = pars->Pcontinous;
5724 break;
5725 case LFOINSERT::control::bpm:
5726 if (write)
5727 pars->setPbpm(_SYS_::F2B(val));
5728 else
5729 val = pars->Pbpm;
5730 break;
5731 case LFOINSERT::control::frequencyRandomness:
5732 if (write)
5733 pars->setPfreqrand(val);
5734 else
5735 val = pars->Pfreqrand;
5736 break;
5737 case LFOINSERT::control::stretch:
5738 if (write)
5739 pars->setPstretch(val);
5740 else
5741 val = pars->Pstretch;
5742 break;
5743 }
5744
5745 if (write)
5746 pars->presetsUpdated();
5747 else
5748 getData->data.value = val;
5749 }
5750
5751
commandFilter(CommandBlock * getData)5752 void InterChange::commandFilter(CommandBlock *getData)
5753 {
5754 unsigned char npart = getData->data.part;
5755 unsigned char kititem = getData->data.kit;
5756 unsigned char engine = getData->data.engine;
5757
5758 Part *part;
5759 part = synth->part[npart];
5760
5761 if (engine == PART::engine::addSynth)
5762 {
5763 filterReadWrite(getData, part->kit[kititem].adpars->GlobalPar.GlobalFilter
5764 , &part->kit[kititem].adpars->GlobalPar.PFilterVelocityScale
5765 , &part->kit[kititem].adpars->GlobalPar.PFilterVelocityScaleFunction);
5766 }
5767 else if (engine == PART::engine::subSynth)
5768 {
5769 filterReadWrite(getData, part->kit[kititem].subpars->GlobalFilter
5770 , &part->kit[kititem].subpars->PGlobalFilterVelocityScale
5771 , &part->kit[kititem].subpars->PGlobalFilterVelocityScaleFunction);
5772 }
5773 else if (engine == PART::engine::padSynth)
5774 {
5775 filterReadWrite(getData, part->kit[kititem].padpars->GlobalFilter
5776 , &part->kit[kititem].padpars->PFilterVelocityScale
5777 , &part->kit[kititem].padpars->PFilterVelocityScaleFunction);
5778 }
5779 else if (engine >= PART::engine::addVoice1)
5780 {
5781 int eng = engine - PART::engine::addVoice1;
5782 filterReadWrite(getData, part->kit[kititem].adpars->VoicePar[eng].VoiceFilter
5783 , &part->kit[kititem].adpars->VoicePar[eng].PFilterVelocityScale
5784 , &part->kit[kititem].adpars->VoicePar[eng].PFilterVelocityScaleFunction);
5785 }
5786 }
5787
5788
filterReadWrite(CommandBlock * getData,FilterParams * pars,unsigned char * velsnsamp,unsigned char * velsns)5789 void InterChange::filterReadWrite(CommandBlock *getData, FilterParams *pars, unsigned char *velsnsamp, unsigned char *velsns)
5790 {
5791 bool write = (getData->data.type & TOPLEVEL::type::Write) > 0;
5792
5793 float val = getData->data.value;
5794 int value_int = lrint(val);
5795
5796 int nseqpos = getData->data.parameter;
5797 int nformant = getData->data.parameter;
5798 int nvowel = getData->data.offset;
5799
5800 switch (getData->data.control)
5801 {
5802 case FILTERINSERT::control::centerFrequency:
5803 if (write)
5804 pars->Pfreq = val;
5805 else
5806 val = pars->Pfreq;
5807 break;
5808 case FILTERINSERT::control::Q:
5809 if (write)
5810 pars->Pq = val;
5811 else
5812 val = pars->Pq;
5813 break;
5814 case FILTERINSERT::control::frequencyTracking:
5815 if (write)
5816 pars->Pfreqtrack = val;
5817 else
5818 val = pars->Pfreqtrack;
5819 break;
5820 case FILTERINSERT::control::velocitySensitivity:
5821 if (velsnsamp != NULL)
5822 {
5823 if (write)
5824 *velsnsamp = value_int;
5825 else
5826 val = *velsnsamp;
5827 }
5828 break;
5829 case FILTERINSERT::control::velocityCurve:
5830 if (velsns != NULL)
5831 {
5832 if (write)
5833 *velsns = value_int;
5834 else
5835 val = *velsns;
5836 }
5837 break;
5838 case FILTERINSERT::control::gain:
5839 if (write)
5840 {
5841 pars->Pgain = val;
5842 pars->changed = true;
5843 }
5844 else
5845 val = pars->Pgain;
5846 break;
5847 case FILTERINSERT::control::stages:
5848 if (write)
5849 {
5850 pars->Pstages = value_int;
5851 pars->changed = true;
5852 }
5853 else
5854 val = pars->Pstages;
5855 break;
5856 case FILTERINSERT::control::baseType:
5857 if (write)
5858 {
5859 if (pars->Pcategory != value_int)
5860 {
5861 pars->Pgain = 64;
5862 pars->Ptype = 0;
5863 pars->changed = true;
5864 pars->Pcategory = value_int;
5865 }
5866 }
5867 else
5868 val = pars->Pcategory;
5869 break;
5870 case FILTERINSERT::control::analogType:
5871 case FILTERINSERT::control::stateVariableType:
5872 if (write)
5873 {
5874 pars->Ptype = value_int;
5875 pars->changed = true;
5876 }
5877 else
5878 val = pars->Ptype;
5879 break;
5880 case FILTERINSERT::control::frequencyTrackingRange:
5881 if (write)
5882 {
5883 pars->Pfreqtrackoffset = (value_int != 0);
5884 pars->changed = true;
5885 }
5886 else
5887 val = pars->Pfreqtrackoffset;
5888 break;
5889
5890 case FILTERINSERT::control::formantSlowness:
5891 if (write)
5892 {
5893 pars->Pformantslowness = val;
5894 pars->changed = true;
5895 }
5896 else
5897 val = pars->Pformantslowness;
5898 break;
5899 case FILTERINSERT::control::formantClearness:
5900 if (write)
5901 {
5902 pars->Pvowelclearness = val;
5903 pars->changed = true;
5904 }
5905 else
5906 val = pars->Pvowelclearness;
5907 break;
5908 case FILTERINSERT::control::formantFrequency:
5909 if (write)
5910 {
5911 pars->Pvowels[nvowel].formants[nformant].freq = val;
5912 pars->changed = true;
5913 }
5914 else
5915 val = pars->Pvowels[nvowel].formants[nformant].freq;
5916 break;
5917 case FILTERINSERT::control::formantQ:
5918 if (write)
5919 {
5920 pars->Pvowels[nvowel].formants[nformant].q = val;
5921 pars->changed = true;
5922 }
5923 else
5924 val = pars->Pvowels[nvowel].formants[nformant].q;
5925 break;
5926 case FILTERINSERT::control::formantAmplitude:
5927 if (write)
5928 {
5929 pars->Pvowels[nvowel].formants[nformant].amp = val;
5930 pars->changed = true;
5931 }
5932 else
5933 val = pars->Pvowels[nvowel].formants[nformant].amp;
5934 break;
5935 case FILTERINSERT::control::formantStretch:
5936 if (write)
5937 {
5938 pars->Psequencestretch = val;
5939 pars->changed = true;
5940 }
5941 else
5942 val = pars->Psequencestretch;
5943 break;
5944 case FILTERINSERT::control::formantCenter:
5945 if (write)
5946 {
5947 pars->Pcenterfreq = val;
5948 pars->changed = true;
5949 }
5950 else
5951 val = pars->Pcenterfreq;
5952 break;
5953 case FILTERINSERT::control::formantOctave:
5954 if (write)
5955 {
5956 pars->Poctavesfreq = val;
5957 pars->changed = true;
5958 }
5959 else
5960 val = pars->Poctavesfreq;
5961 break;
5962
5963 case FILTERINSERT::control::numberOfFormants:
5964 if (write)
5965 {
5966 pars->Pnumformants = value_int;
5967 pars->changed = true;
5968 }
5969 else
5970 val = pars->Pnumformants;
5971 break;
5972 case FILTERINSERT::control::vowelNumber: // this is local to the GUI
5973 break;
5974 case FILTERINSERT::control::formantNumber: // this is local to the GUI
5975 break;
5976 case FILTERINSERT::control::sequenceSize:
5977 if (write)
5978 {
5979 pars->Psequencesize = value_int;
5980 pars->changed = true;
5981 }
5982 else
5983 val = pars->Psequencesize;
5984 break;
5985 case FILTERINSERT::control::sequencePosition:
5986 /*
5987 * this appears to be just setting the GUI
5988 * reference point yet sets pars changed.
5989 * why?
5990 */
5991 if (write)
5992 pars->changed = true;
5993 else
5994 {
5995 ;
5996 }
5997 break;
5998 case FILTERINSERT::control::vowelPositionInSequence:
5999 if (write)
6000 {
6001 pars->Psequence[nseqpos].nvowel = value_int;
6002 pars->changed = true;
6003 }
6004 else
6005 val = pars->Psequence[nseqpos].nvowel;
6006 break;
6007 case FILTERINSERT::control::negateInput:
6008 if (write)
6009 {
6010 pars->Psequencereversed = (value_int != 0);
6011 pars->changed = true;
6012 }
6013 else
6014 val = pars->Psequencereversed;
6015 break;
6016 }
6017
6018 if (write)
6019 pars->presetsUpdated();
6020 else
6021 getData->data.value = val;
6022 }
6023
6024
commandEnvelope(CommandBlock * getData)6025 void InterChange::commandEnvelope(CommandBlock *getData)
6026 {
6027 unsigned char npart = getData->data.part;
6028 unsigned char kititem = getData->data.kit;
6029 unsigned char engine = getData->data.engine;
6030 unsigned char insertParam = getData->data.parameter;
6031
6032 Part *part;
6033 part = synth->part[npart];
6034
6035 std::string env;
6036 std::string name;
6037 if (engine == PART::engine::addSynth)
6038 {
6039 switch (insertParam)
6040 {
6041 case TOPLEVEL::insertType::amplitude:
6042 envelopeReadWrite(getData, part->kit[kititem].adpars->GlobalPar.AmpEnvelope);
6043 break;
6044 case TOPLEVEL::insertType::frequency:
6045 envelopeReadWrite(getData, part->kit[kititem].adpars->GlobalPar.FreqEnvelope);
6046 break;
6047 case TOPLEVEL::insertType::filter:
6048 envelopeReadWrite(getData, part->kit[kititem].adpars->GlobalPar.FilterEnvelope);
6049 break;
6050 }
6051 }
6052 else if (engine == PART::engine::subSynth)
6053 {
6054 switch (insertParam)
6055 {
6056 case TOPLEVEL::insertType::amplitude:
6057 envelopeReadWrite(getData, part->kit[kititem].subpars->AmpEnvelope);
6058 break;
6059 case TOPLEVEL::insertType::frequency:
6060 envelopeReadWrite(getData, part->kit[kititem].subpars->FreqEnvelope);
6061 break;
6062 case TOPLEVEL::insertType::filter:
6063 envelopeReadWrite(getData, part->kit[kititem].subpars->GlobalFilterEnvelope);
6064 break;
6065 case TOPLEVEL::insertType::bandwidth:
6066 envelopeReadWrite(getData, part->kit[kititem].subpars->BandWidthEnvelope);
6067 break;
6068 }
6069 }
6070 else if (engine == PART::engine::padSynth)
6071 {
6072 switch (insertParam)
6073 {
6074 case TOPLEVEL::insertType::amplitude:
6075 envelopeReadWrite(getData, part->kit[kititem].padpars->AmpEnvelope);
6076 break;
6077 case TOPLEVEL::insertType::frequency:
6078 envelopeReadWrite(getData, part->kit[kititem].padpars->FreqEnvelope);
6079 break;
6080 case TOPLEVEL::insertType::filter:
6081 envelopeReadWrite(getData, part->kit[kititem].padpars->FilterEnvelope);
6082 break;
6083 }
6084 }
6085
6086 else if (engine >= PART::engine::addMod1)
6087 {
6088 int nvoice = engine - PART::engine::addMod1;
6089 switch (insertParam)
6090 {
6091 case TOPLEVEL::insertType::amplitude:
6092 envelopeReadWrite(getData, part->kit[kititem].adpars->VoicePar[nvoice].FMAmpEnvelope);
6093 break;
6094 case TOPLEVEL::insertType::frequency:
6095 envelopeReadWrite(getData, part->kit[kititem].adpars->VoicePar[nvoice].FMFreqEnvelope);
6096 break;
6097 }
6098 }
6099
6100 else if (engine >= PART::engine::addVoice1)
6101 {
6102 int nvoice = engine - PART::engine::addVoice1;
6103 switch (insertParam)
6104 {
6105 case TOPLEVEL::insertType::amplitude:
6106 envelopeReadWrite(getData, part->kit[kititem].adpars->VoicePar[nvoice].AmpEnvelope);
6107 break;
6108 case TOPLEVEL::insertType::frequency:
6109 envelopeReadWrite(getData, part->kit[kititem].adpars->VoicePar[nvoice].FreqEnvelope);
6110 break;
6111 case TOPLEVEL::insertType::filter:
6112 envelopeReadWrite(getData, part->kit[kititem].adpars->VoicePar[nvoice].FilterEnvelope);
6113 break;
6114 }
6115 }
6116 }
6117
6118
envelopeReadWrite(CommandBlock * getData,EnvelopeParams * pars)6119 void InterChange::envelopeReadWrite(CommandBlock *getData, EnvelopeParams *pars)
6120 {
6121 int val = lrint(getData->data.value); // these are all integers or bool
6122 bool write = (getData->data.type & TOPLEVEL::type::Write) > 0;
6123
6124 unsigned char point = getData->data.control;
6125 unsigned char insert = getData->data.insert;
6126 unsigned char Xincrement = getData->data.offset;
6127
6128 int envpoints = pars->Penvpoints;
6129 bool isAddpoint = (Xincrement < UNUSED);
6130
6131 if (insert == TOPLEVEL::insert::envelopePoints) // here be dragons :(
6132 {
6133 if (!pars->Pfreemode)
6134 {
6135 getData->data.value = UNUSED;
6136 getData->data.offset = UNUSED;
6137 return;
6138 }
6139
6140 if (!write || point == 0 || point >= envpoints)
6141 {
6142 getData->data.value = UNUSED;
6143 getData->data.offset = envpoints;
6144 return;
6145 }
6146
6147 if (isAddpoint)
6148 {
6149 if (envpoints < MAX_ENVELOPE_POINTS)
6150 {
6151 pars->Penvpoints += 1;
6152 for (int i = envpoints; i >= point; -- i)
6153 {
6154 pars->Penvdt[i + 1] = pars->Penvdt[i];
6155 pars->Penvval[i + 1] = pars->Penvval[i];
6156 }
6157
6158 if (point == 0)
6159 pars->Penvdt[1] = 64;
6160
6161 if (point <= pars->Penvsustain)
6162 ++ pars->Penvsustain;
6163
6164 pars->Penvdt[point] = Xincrement;
6165 pars->Penvval[point] = val;
6166 getData->data.value = val;
6167 getData->data.offset = Xincrement;
6168 pars->presetsUpdated();
6169 }
6170 else
6171 getData->data.value = UNUSED;
6172 return;
6173 }
6174 else if (envpoints < 4)
6175 {
6176 getData->data.value = UNUSED;
6177 getData->data.offset = UNUSED;
6178 return; // can't have less than 4
6179 }
6180 else
6181 {
6182 envpoints -= 1;
6183 for (int i = point; i < envpoints; ++ i)
6184 {
6185 pars->Penvdt[i] = pars->Penvdt[i + 1];
6186 pars->Penvval[i] = pars->Penvval[i + 1];
6187 }
6188 if (point <= pars->Penvsustain)
6189 -- pars->Penvsustain;
6190 pars->Penvpoints = envpoints;
6191 getData->data.value = envpoints;
6192 pars->presetsUpdated();
6193 }
6194 return;
6195 }
6196
6197 if (insert == TOPLEVEL::insert::envelopePointChange)
6198 {
6199 if (!pars->Pfreemode || point >= envpoints)
6200 {
6201 getData->data.value = UNUSED;
6202 getData->data.offset = UNUSED;
6203 return;
6204 }
6205 if (write)
6206 {
6207 pars->Penvval[point] = val;
6208 if (point == 0)
6209 Xincrement = 0;
6210 else
6211 pars->Penvdt[point] = Xincrement;
6212 pars->presetsUpdated();
6213 }
6214 else
6215 {
6216 val = pars->Penvval[point];
6217 Xincrement = pars->Penvdt[point];
6218 }
6219 getData->data.value = val;
6220 getData->data.offset = Xincrement;
6221 return;
6222 }
6223
6224 switch (getData->data.control)
6225 {
6226 case ENVELOPEINSERT::control::attackLevel:
6227 if (write)
6228 pars->PA_val = val;
6229 else
6230 val = pars->PA_val;
6231 break;
6232 case ENVELOPEINSERT::control::attackTime:
6233 if (write)
6234 pars->PA_dt = val;
6235 else
6236 val = pars->PA_dt;
6237 break;
6238 case ENVELOPEINSERT::control::decayLevel:
6239 if (write)
6240 pars->PD_val = val;
6241 else
6242 val = pars->PD_val;
6243 break;
6244 case ENVELOPEINSERT::control::decayTime:
6245 if (write)
6246 pars->PD_dt = val;
6247 else
6248 val = pars->PD_dt;
6249 break;
6250 case ENVELOPEINSERT::control::sustainLevel:
6251 if (write)
6252 pars->PS_val = val;
6253 else
6254 val = pars->PS_val;
6255 break;
6256 case ENVELOPEINSERT::control::releaseTime:
6257 if (write)
6258 pars->PR_dt = val;
6259 else
6260 val = pars->PR_dt;
6261 break;
6262 case ENVELOPEINSERT::control::releaseLevel:
6263 if (write)
6264 pars->PR_val = val;
6265 else
6266 val = pars->PR_val;
6267 break;
6268 case ENVELOPEINSERT::control::stretch:
6269 if (write)
6270 pars->Penvstretch = val;
6271 else
6272 val = pars->Penvstretch;
6273 break;
6274
6275 case ENVELOPEINSERT::control::forcedRelease:
6276 if (write)
6277 pars->Pforcedrelease = (val != 0);
6278 else
6279 val = pars->Pforcedrelease;
6280 break;
6281 case ENVELOPEINSERT::control::linearEnvelope:
6282 if (write)
6283 pars->Plinearenvelope = (val != 0);
6284 else
6285 val = pars->Plinearenvelope;
6286 break;
6287
6288 case ENVELOPEINSERT::control::edit:
6289 break;
6290
6291 case ENVELOPEINSERT::control::enableFreeMode:
6292 if (write)
6293 {
6294 if (val != 0)
6295 pars->Pfreemode = 1;
6296 else
6297 pars->Pfreemode = 0;
6298 }
6299 else
6300 val = pars->Pfreemode;
6301 break;
6302 case ENVELOPEINSERT::control::points:
6303 if (!pars->Pfreemode)
6304 {
6305 val = UNUSED;
6306 Xincrement = UNUSED;
6307 }
6308 else
6309 {
6310 val = envpoints;
6311 Xincrement = envpoints; // don't really need this now
6312 }
6313 break;
6314 case ENVELOPEINSERT::control::sustainPoint:
6315 if (write)
6316 pars->Penvsustain = val;
6317 else
6318 val = pars->Penvsustain;
6319 break;
6320 }
6321 if (write)
6322 pars->presetsUpdated();
6323 getData->data.value = val;
6324 getData->data.offset = Xincrement;
6325 return;
6326 }
6327
6328
commandSysIns(CommandBlock * getData)6329 void InterChange::commandSysIns(CommandBlock *getData)
6330 {
6331 float value = getData->data.value;
6332 unsigned char type = getData->data.type;
6333 unsigned char control = getData->data.control;
6334 unsigned char npart = getData->data.part;
6335 unsigned char effnum = getData->data.engine;
6336 unsigned char insert = getData->data.insert;
6337
6338 bool write = (type & TOPLEVEL::type::Write) > 0;
6339 //std::cout << "Itype " << int(type) << " val " << value << " cont " << int(control) << " part " << int(npart) << " effnum " << int(effnum) << " insert " << int(insert) << std::endl;
6340
6341 int value_int = lrint(value);
6342 bool isSysEff = (npart == TOPLEVEL::section::systemEffects);
6343 if (isSysEff)
6344 effnum = synth->syseffnum;
6345 else
6346 effnum = synth->inseffnum;
6347
6348 if (insert == UNUSED)
6349 {
6350 switch (control)
6351 {
6352 case EFFECT::sysIns::effectNumber:
6353 if (write)
6354 {
6355 if (isSysEff)
6356 {
6357 synth->syseffnum = value_int;
6358 getData->data.parameter = (synth->sysefx[value_int]->geteffectpar(-1) != 0);
6359 }
6360 else
6361 {
6362 synth->inseffnum = value_int;
6363 getData->data.parameter = (synth->insefx[value_int]->geteffectpar(-1) != 0);
6364 }
6365 getData->data.source |= getData->data.source |= TOPLEVEL::action::forceUpdate;
6366 // the line above is to show it's changed from preset values
6367 getData->data.engine = value_int;
6368 }
6369 else
6370 {
6371 if (isSysEff)
6372 value = synth->syseffnum;
6373 else
6374 value = synth->inseffnum;
6375 }
6376 break;
6377 case EFFECT::sysIns::effectType:
6378 if (write)
6379 {
6380 if (isSysEff)
6381 {
6382 synth->sysefx[effnum]->changeeffect(value_int);
6383 getData->data.parameter = (synth->sysefx[effnum]->geteffectpar(-1) != 0);
6384 }
6385 else
6386 {
6387 synth->insefx[effnum]->changeeffect(value_int);
6388 getData->data.parameter = (synth->insefx[effnum]->geteffectpar(-1) != 0);
6389 }
6390 getData->data.offset = 0;
6391 }
6392 else
6393 {
6394 if (isSysEff)
6395 value = synth->sysefx[effnum]->geteffect();
6396 else
6397 value = synth->insefx[effnum]->geteffect();
6398 }
6399 break;
6400 case EFFECT::sysIns::effectDestination: // insert only
6401 if (write)
6402 {
6403 synth->Pinsparts[effnum] = value_int;
6404 if (value_int == -1)
6405 synth->insefx[effnum]->cleanup();
6406 }
6407 else
6408 value = synth->Pinsparts[effnum];
6409 break;
6410 case EFFECT::sysIns::effectEnable: // system only
6411 if (write)
6412 {
6413 bool newSwitch = _SYS_::F2B(value);
6414 bool oldSwitch = synth->syseffEnable[effnum];
6415 synth->syseffEnable[effnum] = newSwitch;
6416 if (newSwitch != oldSwitch)
6417 synth->sysefx[effnum]->cleanup();
6418 }
6419 else
6420 value = synth->syseffEnable[effnum];
6421 break;
6422 }
6423 }
6424 else // system only
6425 {
6426 if (write)
6427 synth->setPsysefxsend(effnum, control, value);
6428 else
6429 value = synth->Psysefxsend[effnum][control];
6430 }
6431
6432 if (!write)
6433 getData->data.value = value;
6434 }
6435
6436
commandEffects(CommandBlock * getData)6437 void InterChange::commandEffects(CommandBlock *getData)
6438 {
6439 float value = getData->data.value;
6440 int value_int = int(value + 0.5f);
6441 unsigned char type = getData->data.type;
6442 unsigned char control = getData->data.control;
6443 unsigned char npart = getData->data.part;
6444 unsigned char kititem = getData->data.kit;
6445 unsigned char effnum = getData->data.engine;
6446
6447 bool write = (type & TOPLEVEL::type::Write) > 0;
6448 if (write)
6449 {
6450 getData->data.source |= getData->data.source |= TOPLEVEL::action::forceUpdate;
6451 // the line above is to show it's changed from preset values
6452 }
6453
6454 EffectMgr *eff;
6455
6456 if (npart == TOPLEVEL::section::systemEffects)
6457 eff = synth->sysefx[effnum];
6458
6459 else if (npart == TOPLEVEL::section::insertEffects)
6460 eff = synth->insefx[effnum];
6461 else if (npart < NUM_MIDI_PARTS)
6462 eff = synth->part[npart]->partefx[effnum];
6463 else
6464 return; // invalid part number
6465 if (kititem > EFFECT::type::dynFilter)
6466 return; // invalid kit number
6467 if (control != PART::control::effectType && (kititem & 127) != eff->geteffect())
6468 {
6469 if ((getData->data.source & TOPLEVEL::action::noAction) != TOPLEVEL::action::fromMIDI)
6470 synth->getRuntime().Log("Not Available"); // TODO sort this better for CLI as well as MIDI
6471 getData->data.source = TOPLEVEL::action::noAction;
6472 return;
6473 }
6474
6475 if (eff->geteffectpar(EFFECT::control::bpm) == 1)
6476 getData->data.offset = 1; // mark this for reporting in Data2Text
6477
6478 if (kititem == EFFECT::type::dynFilter && getData->data.insert != UNUSED)
6479 {
6480 if (write)
6481 eff->seteffectpar(-1, true); // effect changed
6482 filterReadWrite(getData, eff->filterpars,NULL,NULL);
6483 return;
6484 }
6485 if (control >= EFFECT::control::changed)
6486 {
6487 if (!write)
6488 {
6489 value = eff->geteffectpar(-1);
6490 getData->data.value = value;
6491 }
6492 return; // specific for reading change status
6493 }
6494 if (write)
6495 {
6496 if (kititem == EFFECT::type::eq)
6497 /*
6498 * specific to EQ
6499 * Control 1 is not a saved parameter, but a band index.
6500 * Also, EQ does not have presets, and 16 is the control
6501 * for the band 1 frequency parameter
6502 */
6503 {
6504 if (control <= 1)
6505 eff->seteffectpar(control, value_int);
6506 else
6507 {
6508 eff->seteffectpar(control + (eff->geteffectpar(1) * 5), value_int);
6509 getData->data.parameter = eff->geteffectpar(1);
6510 }
6511 }
6512 else
6513 {
6514 if (control == EFFECT::control::preset)
6515 eff->changepreset(value_int);
6516 else
6517 {
6518 eff->seteffectpar(control, value_int);
6519 if (kititem == EFFECT::type::reverb && control == 10 && value_int == 2)
6520 // bandwidth type update for GUI
6521 getData->data.offset = eff->geteffectpar(12);
6522 }
6523 }
6524 }
6525 else
6526 {
6527 if (kititem == EFFECT::type::eq && control > 1) // specific to EQ
6528 {
6529 value = eff->geteffectpar(control + (eff->geteffectpar(1) * 5));
6530 getData->data.parameter = eff->geteffectpar(1);
6531 }
6532 else
6533 {
6534 if (control == EFFECT::control::preset)
6535 value = eff->getpreset();
6536 else
6537 value = eff->geteffectpar(control);
6538 }
6539 }
6540
6541 if (!write)
6542 getData->data.value = value;
6543 }
6544
6545 // tests and returns corrected values
testLimits(CommandBlock * getData)6546 void InterChange::testLimits(CommandBlock *getData)
6547 {
6548 float value = getData->data.value;
6549
6550 int control = getData->data.control;
6551 /*
6552 * This is a special case as existing defined
6553 * midi CCs need to be checked.
6554 * I don't like special cases either :(
6555 */
6556 if (getData->data.part == TOPLEVEL::section::config
6557 && (control == CONFIG::control::bankRootCC
6558 || control == CONFIG::control::bankCC
6559 || control == CONFIG::control::extendedProgramChangeCC))
6560 {
6561 getData->data.miscmsg = NO_MSG; // just to be sure
6562 if (value > 119)
6563 return;
6564 std::string text;
6565 if (control == CONFIG::control::bankRootCC)
6566 {
6567 text = synth->getRuntime().masterCCtest(int(value));
6568 if (text != "")
6569 getData->data.miscmsg = textMsgBuffer.push(text);
6570 return;
6571 }
6572 if (control == CONFIG::control::bankCC)
6573 {
6574 if (value != 0 && value != 32)
6575 return;
6576 text = synth->getRuntime().masterCCtest(int(value));
6577 if (text != "")
6578 getData->data.miscmsg = textMsgBuffer.push(text);
6579 return;
6580 }
6581 text = synth->getRuntime().masterCCtest(int(value));
6582 if (text != "")
6583 getData->data.miscmsg = textMsgBuffer.push(text);
6584 return;
6585 }
6586 }
6587
6588
6589 // more work needed here :(
returnLimits(CommandBlock * getData)6590 float InterChange::returnLimits(CommandBlock *getData)
6591 {
6592 // bit 5 set is used to denote midi learnable
6593 // bit 7 set denotes the value is used as an integer
6594
6595 int control = (int) getData->data.control;
6596 int npart = (int) getData->data.part;
6597 int kititem = (int) getData->data.kit;
6598 int engine = (int) getData->data.engine;
6599 int insert = (int) getData->data.insert;
6600 int parameter = (int) getData->data.parameter;
6601 int miscmsg = (int) getData->data.miscmsg;
6602
6603 float value = getData->data.value;
6604
6605 getData->data.type &= TOPLEVEL::type::Default; // clear all flags
6606 int request = getData->data.type; // catches Adj, Min, Max, Def
6607 getData->data.type |= TOPLEVEL::type::Integer; // default is integer & not learnable
6608
6609 if (npart == TOPLEVEL::section::config)
6610 return synth->getConfigLimits(getData);
6611
6612 if (npart == TOPLEVEL::section::bank)
6613 return value;
6614
6615 if (npart == TOPLEVEL::section::main)
6616 return synth->getLimits(getData);
6617
6618 if (npart == TOPLEVEL::section::scales)
6619 return synth->microtonal.getLimits(getData);
6620
6621 if (npart == TOPLEVEL::section::vector)
6622 return synth->getVectorLimits(getData);
6623
6624 float min;
6625 float max;
6626 float def;
6627
6628 if (insert == TOPLEVEL::insert::filterGroup)
6629 {
6630 filterLimit filterLimits;
6631 return filterLimits.getFilterLimits(getData);
6632 }
6633 // should prolly move other inserts up here
6634
6635 if (kititem >= EFFECT::type::none && kititem <= EFFECT::type::dynFilter)
6636 {
6637 LimitMgr limits;
6638 return limits.geteffectlimits(getData);
6639 }
6640
6641 if (npart < NUM_MIDI_PARTS)
6642 {
6643 Part *part;
6644 part = synth->part[npart];
6645
6646 if (engine == PART::engine::subSynth && (insert == UNUSED || (insert >= TOPLEVEL::oscillatorGroup && insert <= TOPLEVEL::harmonicPhaseBandwidth)) && parameter == UNUSED)
6647 {
6648 SUBnoteParameters *subpars;
6649 subpars = part->kit[kititem].subpars;
6650 return subpars->getLimits(getData);
6651 }
6652
6653 if (insert == TOPLEVEL::insert::partEffectSelect || (engine == UNUSED && (kititem == UNUSED || insert == TOPLEVEL::insert::kitGroup)))
6654 return part->getLimits(getData);
6655
6656 if ((insert == TOPLEVEL::insert::kitGroup || insert == UNUSED) && parameter == UNUSED && miscmsg == UNUSED)
6657 {
6658 if (engine == PART::engine::addSynth || (engine >= PART::engine::addVoice1 && engine <= PART::engine::addMod8))
6659 {
6660 ADnoteParameters *adpars;
6661 adpars = part->kit[kititem].adpars;
6662 return adpars->getLimits(getData);
6663 }
6664 if (engine == PART::engine::subSynth)
6665 {
6666 SUBnoteParameters *subpars;
6667 subpars = part->kit[kititem].subpars;
6668 return subpars->getLimits(getData);
6669 }
6670 if (engine == PART::engine::padSynth)
6671 {
6672 PADnoteParameters *padpars;
6673 padpars = part->kit[kititem].padpars;
6674 return padpars->getLimits(getData);
6675 }
6676 // there may be other stuff
6677
6678 min = 0;
6679 max = 127;
6680 def = 0;
6681
6682 std::cout << "Using engine defaults" << std::endl;
6683 switch (request)
6684 {
6685 case TOPLEVEL::type::Adjust:
6686 if (value < min)
6687 value = min;
6688 else if (value > max)
6689 value = max;
6690 break;
6691 case TOPLEVEL::type::Minimum:
6692 value = min;
6693 break;
6694 case TOPLEVEL::type::Maximum:
6695 value = max;
6696 break;
6697 case TOPLEVEL::type::Default:
6698 value = def;
6699 break;
6700 }
6701 return value;
6702 }
6703 if (insert >= TOPLEVEL::insert::oscillatorGroup && insert <= TOPLEVEL::insert::harmonicPhaseBandwidth)
6704 {
6705 return part->kit[0].adpars->VoicePar[0].POscil->getLimits(getData);
6706 // we also use this for pad limits
6707 // as oscillator values identical
6708 }
6709 if (insert == TOPLEVEL::insert::resonanceGroup || insert == TOPLEVEL::insert::resonanceGraphInsert)
6710 {
6711 ResonanceLimits resonancelimits;
6712 return resonancelimits.getLimits(getData);
6713 }
6714 if (insert == TOPLEVEL::insert::LFOgroup && engine != PART::engine::subSynth && parameter <= TOPLEVEL::insertType::filter)
6715 {
6716 LFOlimit lfolimits;
6717 return lfolimits.getLFOlimits(getData);
6718 }
6719 if (insert == TOPLEVEL::insert::envelopeGroup)
6720 {
6721 envelopeLimit envelopeLimits;
6722 return envelopeLimits.getEnvelopeLimits(getData);
6723 }
6724 if (insert == TOPLEVEL::insert::envelopePoints || insert == TOPLEVEL::insert::envelopePointChange)
6725 return 1; // temporary solution :(
6726 min = 0;
6727 max = 127;
6728 def = 0;
6729 std::cout << "Using insert defaults" << std::endl;
6730
6731 switch (request)
6732 {
6733 case TOPLEVEL::type::Adjust:
6734 if (value < min)
6735 value = min;
6736 else if (value > max)
6737 value = max;
6738 break;
6739 case TOPLEVEL::type::Minimum:
6740 value = min;
6741 break;
6742 case TOPLEVEL::type::Maximum:
6743 value = max;
6744 break;
6745 case TOPLEVEL::type::Default:
6746 value = def;
6747 break;
6748 }
6749 return value;
6750 }
6751
6752 // not sure where the following should realy be
6753 if (npart == TOPLEVEL::section::systemEffects)
6754 {
6755 min = 0;
6756 def = 0;
6757 max = 8;
6758 switch (control)
6759 {
6760 case EFFECT::sysIns::toEffect1:
6761 case EFFECT::sysIns::toEffect2:
6762 case EFFECT::sysIns::toEffect3:
6763 max = 127;
6764 getData->data.type |= TOPLEVEL::type::Learnable;
6765 break;
6766 case EFFECT::sysIns::effectNumber:
6767 max = 3;
6768 break;
6769 case EFFECT::sysIns::effectType:
6770 break;
6771 case EFFECT::sysIns::effectEnable:
6772 def = 1;
6773 max = 1;
6774 getData->data.type |= TOPLEVEL::type::Learnable;
6775 break;
6776 }
6777
6778 switch (request)
6779 {
6780 case TOPLEVEL::type::Adjust:
6781 if (value < min)
6782 value = min;
6783 else if (value > max)
6784 value = max;
6785 break;
6786 case TOPLEVEL::type::Minimum:
6787 value = min;
6788 break;
6789 case TOPLEVEL::type::Maximum:
6790 value = max;
6791 break;
6792 case TOPLEVEL::type::Default:
6793 value = def;
6794 break;
6795 }
6796 return value;
6797 }
6798
6799 if (npart == TOPLEVEL::section::insertEffects)
6800 {
6801 min = 0;
6802 def = 0;
6803 max = 8;
6804 switch (control)
6805 {
6806 case EFFECT::sysIns::effectNumber:
6807 max = 7;
6808 break;
6809 case EFFECT::sysIns::effectType:
6810 break;
6811 case EFFECT::sysIns::effectDestination:
6812 min = -2;
6813 def = -1;
6814 max = 63;
6815 break;
6816 }
6817
6818 switch (request)
6819 {
6820 case TOPLEVEL::type::Adjust:
6821 if (value < min)
6822 value = min;
6823 else if (value > max)
6824 value = max;
6825 break;
6826 case TOPLEVEL::type::Minimum:
6827 value = min;
6828 break;
6829 case TOPLEVEL::type::Maximum:
6830 value = max;
6831 break;
6832 case TOPLEVEL::type::Default:
6833 value = def;
6834 break;
6835 }
6836 return value;
6837 }
6838
6839 if (npart == TOPLEVEL::section::midiIn)
6840 {
6841 min = 0;
6842 max = 127;
6843 switch (control)
6844 {
6845 case PART::control::volume:
6846 def = 96;
6847 break;
6848 case PART::control::midiExpression:
6849 def = 127;
6850 break;
6851 case PART::control::midiSustain:
6852 def = 0;
6853 break;
6854 case PART::control::midiPortamento:
6855 def = 0;
6856 break;
6857 case PART::control::midiFMamp:
6858 def = 127;
6859 break;
6860 default:
6861 def = 64;
6862 }
6863 //std::cout << "here " << int(def) << std::endl;
6864
6865
6866 switch (request)
6867 {
6868 case TOPLEVEL::type::Adjust:
6869 if (value < min)
6870 value = min;
6871 else if (value > max)
6872 value = max;
6873 break;
6874 case TOPLEVEL::type::Minimum:
6875 value = min;
6876 break;
6877 case TOPLEVEL::type::Maximum:
6878 value = max;
6879 break;
6880 case TOPLEVEL::type::Default:
6881 value = def;
6882 break;
6883 }
6884 return value;
6885 }
6886
6887 min = 0;
6888 max = 127;
6889 def = 0;
6890 std::cout << "Using unknown defaults" << std::endl;
6891
6892 switch (request)
6893 {
6894 case TOPLEVEL::type::Adjust:
6895 if (value < min)
6896 value = min;
6897 else if (value > max)
6898 value = max;
6899 break;
6900 case TOPLEVEL::type::Minimum:
6901 value = min;
6902 break;
6903 case TOPLEVEL::type::Maximum:
6904 value = max;
6905 break;
6906 case TOPLEVEL::type::Default:
6907 value = def;
6908 break;
6909 }
6910 return value;
6911 }
6912