Part.cpp (50082B)
1 /* 2 ZynAddSubFX - a software synthesizer 3 4 Part.cpp - Part implementation 5 Copyright (C) 2002-2005 Nasca Octavian Paul 6 Author: Nasca Octavian Paul 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License 10 as published by the Free Software Foundation; either version 2 11 of the License, or (at your option) any later version. 12 */ 13 14 #include "Part.h" 15 #include "Microtonal.h" 16 #include "Util.h" 17 #include "XMLwrapper.h" 18 #include "Allocator.h" 19 #include "../Effects/EffectMgr.h" 20 #include "../Params/ADnoteParameters.h" 21 #include "../Params/SUBnoteParameters.h" 22 #include "../Params/PADnoteParameters.h" 23 #include "../Synth/Portamento.h" 24 #include "../Synth/Resonance.h" 25 #include "../Synth/SynthNote.h" 26 #include "../Synth/ADnote.h" 27 #include "../Synth/SUBnote.h" 28 #include "../Synth/PADnote.h" 29 #include "../Containers/ScratchString.h" 30 #include "../DSP/FFTwrapper.h" 31 #include <cstdlib> 32 #include <cstdio> 33 #include <cstring> 34 #include <cassert> 35 #include <ctime> 36 37 #include <rtosc/ports.h> 38 #include <rtosc/port-sugar.h> 39 #include <iostream> 40 41 namespace zyn { 42 43 using rtosc::Ports; 44 using rtosc::RtData; 45 46 #define rObject Part 47 static const Ports partPorts = { 48 rSelf(Part, rEnabledBy(Penabled)), 49 rRecurs(kit, 16, "Kit"),//NUM_KIT_ITEMS 50 rRecursp(partefx, 3, "Part Effect"), 51 rRecur(ctl, "Controller"), 52 rParamZyn(partno, rProp(internal), 53 "How many parts are before this in the Master"), 54 #undef rChangeCb 55 #define rChangeCb if(obj->Penabled == false) obj->AllNotesOff(); 56 rToggle(Penabled, rShort("enable"), 57 rPreset(0, true), rDefault(false), rDefaultDepends(partno), 58 "Part enable"), 59 #undef rChangeCb 60 #define rChangeCb 61 #undef rChangeCb 62 #define rChangeCb obj->setVolumedB(obj->Volume); 63 rParamF(Volume, rShort("Vol"), rDefault(0.0), rUnit(dB), 64 rLinear(-40.0, 13.3333), "Part Volume"), 65 #undef rChangeCb 66 {"Pvolume::i", rShort("Vol") rProp(parameter) rLinear(0,127) 67 rDefault(96) rDoc("Part Volume"), 0, 68 [](const char *m, rtosc::RtData &d) { 69 Part *obj = (Part*)d.obj; 70 if(rtosc_narguments(m)==0) { 71 d.reply(d.loc, "i", (int) roundf(96.0f * obj->Volume / 40.0f + 96.0f)); 72 } else if(rtosc_narguments(m)==1 && rtosc_type(m,0)=='i') { 73 obj->Volume = obj->volume127TodB(limit<unsigned char>(rtosc_argument(m, 0).i, 0, 127)); 74 obj->setVolumedB(obj->Volume); 75 d.broadcast(d.loc, "i", limit<char>(rtosc_argument(m, 0).i, 0, 127)); 76 }}}, 77 #define rChangeCb obj->setPpanning(obj->Ppanning); 78 rParamZyn(Ppanning, rShort("pan"), rDefault(64), "Set Panning"), 79 #undef rChangeCb 80 #define rChangeCb obj->setkeylimit(obj->Pkeylimit); 81 rParamI(Pkeylimit, rShort("limit"), rProp(parameter), 82 rMap(min,0), rMap(max, POLYPHONY), rDefault(15), "Key limit per part"), 83 #undef rChangeCb 84 #define rChangeCb obj->setvoicelimit(obj->Pvoicelimit); 85 rParamI(Pvoicelimit, rShort("vlimit"), rProp(parameter), 86 rMap(min,0), rMap(max, POLYPHONY), rDefault(0), "Voice limit per part"), 87 #undef rChangeCb 88 #define rChangeCb 89 rParamZyn(Pminkey, rShort("min"), rDefault(0), "Min Used Key"), 90 rParamZyn(Pmaxkey, rShort("max"), rDefault(127), "Max Used Key"), 91 {"Pkeyshift::i", rShort("shift") rProp(parameter) rLinear(-64,63) rUnit(semitones) 92 rDefault(0) rDoc("Part Key Shift"), 0, [](const char *m, RtData&d) { 93 if(rtosc_narguments(m)==0) { 94 d.reply(d.loc, "i", ((Part*)d.obj)->Pkeyshift-64); 95 } else if(rtosc_narguments(m)==1 && rtosc_type(m,0)=='i') { 96 ((Part*)d.obj)->Pkeyshift=(limit<char>(rtosc_argument(m,0).i+64,0,127)); 97 d.broadcast(d.loc, "i", ((Part*)d.obj)->Pkeyshift-64);}}}, 98 rOption(Prcvchn, rOptions(ch1, ch2, ch3, ch4, ch5, ch6, ch7, ch8, ch9, ch10, ch11, ch12, ch13, ch14, ch15, ch16), 99 rDefaultDepends(partno), 100 rPresets(ch1, ch2, ch3, ch4, ch5, ch6, ch7, ch8, ch9, ch10, ch11, ch12, ch13, ch14, ch15, ch16), 101 "Active MIDI channel"), 102 rParamZyn(Pvelsns, rShort("sense"), rDefault(64), "Velocity sensing"), 103 rParamZyn(Pveloffs, rShort("offset"), rDefault(64),"Velocity offset"), 104 rToggle(Pnoteon, rDefault(true), "If the channel accepts note on events"), 105 rOption(Pkitmode, rOptions(Off, Multi-Kit, Single-Kit), rDefault(Off), 106 "Kit mode/enable\n" 107 "Off - Only the first kit is ever utilized\n" 108 "Multi-kit - Every applicable kit is run for a note\n" 109 "Single-kit - The first applicable kit is run for a given note"), 110 rToggle(Pdrummode, rDefault(false), "Drum mode enable\n" 111 "When drum mode is enabled all keys are mapped to 12tET and legato is disabled"), 112 rToggle(Ppolymode, rDefault(true), "Polyphony mode"), 113 rToggle(Plegatomode, rDefault(false), "Legato mode"), 114 rParamZyn(info.Ptype, rDefault(0), "Class of Instrument"), 115 rString(info.Pauthor, MAX_INFO_TEXT_SIZE, rDefault(""), 116 "Instrument author"), 117 rString(info.Pcomments, MAX_INFO_TEXT_SIZE, rDefault(""), 118 "Instrument comments"), 119 rString(Pname, PART_MAX_NAME_LEN, rDefault(""), "User specified label"), 120 rArrayOption(Pefxroute, NUM_PART_EFX, 121 rOptions(Next Effect,Part Out,Dry Out), 122 ":default\0=[\"Next Effect\"S...]\0", 123 "Effect Routing"), 124 rArrayT(Pefxbypass, NUM_PART_EFX, rDefault([false...]), 125 "If an effect is bypassed"), 126 {"captureMin:", rDoc("Capture minimum valid note"), NULL, 127 [](const char *, RtData &r) 128 {Part *p = (Part*)r.obj; p->Pminkey = p->lastnote;}}, 129 {"captureMax:", rDoc("Capture maximum valid note"), NULL, 130 [](const char *, RtData &r) 131 {Part *p = (Part*)r.obj; p->Pmaxkey = p->lastnote;}}, 132 {"polyType::i:c:S", rProp(parameter) rOptions(Poly, Mono, Legato, Latch) 133 rDoc("Synthesis polyphony type\n"), NULL, 134 [](const char *msg, RtData &d) 135 { 136 Part *p = (Part*)d.obj; 137 auto get_polytype = [&p](){ 138 int res = 0; 139 if(!p->Ppolymode) 140 res = p->Plegatomode ? 2 : 1; 141 if(p->Platchmode) 142 res = 3; 143 return res; 144 }; 145 146 if(!rtosc_narguments(msg)) { 147 d.reply(d.loc, "i", get_polytype()); 148 return; 149 } 150 151 int i; 152 if(rtosc_type(msg, 0) == 'S') { 153 auto prop = d.port->meta(); 154 i = enum_key(prop, rtosc_argument(msg, 0).s); 155 assert(!prop["min"] || i >= atoi(prop["min"])); 156 assert(!prop["max"] || i <= atoi(prop["max"])); 157 } else { 158 i = rtosc_argument(msg, 0).i; 159 } 160 if(i == 0) { 161 p->Ppolymode = 1; 162 p->Plegatomode = 0; 163 p->Platchmode = 0; 164 } else if(i==1) { 165 p->Ppolymode = 0; 166 p->Plegatomode = 0; 167 p->Platchmode = 0; 168 } else if(i==2) { 169 p->Ppolymode = 0; 170 p->Plegatomode = 1; 171 p->Platchmode = 0; 172 } else { 173 p->Ppolymode = 1; 174 p->Plegatomode = 0; 175 p->Platchmode = 1; 176 } 177 d.broadcast(d.loc, "i", get_polytype()); 178 } 179 }, 180 {"clear:", rProp(internal) rDoc("Reset Part To Defaults"), 0, 181 [](const char *, RtData &) 182 { 183 //XXX todo forward this event for middleware to handle 184 //Part *p = (Part*)d.obj; 185 //p->defaults(); 186 //char part_loc[128]; 187 //strcpy(part_loc, d.loc); 188 //char *end = strrchr(part_loc, '/'); 189 //if(end) 190 // end[1] = 0; 191 192 //d.broadcast("/damage", "s", part_loc); 193 }}, 194 {"savexml:", rProp(internal) rDoc("Save Part to the file it has been loaded from"), 0, 195 [](const char *, RtData &d) 196 { 197 Part *p = (Part*)d.obj; 198 int err; 199 if (p->loaded_file[0] == '\0') { // if part was never loaded or saved 200 time_t rawtime; // make a new name from date and time 201 char filename[32]; 202 time (&rawtime); 203 const struct tm* timeinfo = localtime (&rawtime); 204 strftime (filename,23,"%F_%R.xiz",timeinfo); 205 err = p->saveXML(filename); 206 fprintf(stderr, "Part %d saved to %s: %s\n", (p->partno + 1), filename, err ? "failed" : "ok"); 207 } 208 else 209 { 210 err = p->saveXML(p->loaded_file); 211 fprintf(stderr, "Part %d saved to %s: %s\n", (p->partno + 1), p->loaded_file, err ? "failed" : "ok"); 212 } 213 if (err) 214 d.reply("/alert", "s", 215 "Failed To Save File, please check file permissions"); 216 }}, 217 //{"kit#16::T:F", "::Enables or disables kit item", 0, 218 // [](const char *m, RtData &d) { 219 // auto loc = d.loc; 220 // Part *p = (Part*)d.obj; 221 // unsigned kitid = -1; 222 // //Note that this event will be captured before transmitted, thus 223 // //reply/broadcast don't matter 224 // for(int i=0; i<NUM_KIT_ITEMS; ++i) { 225 // d.reply("/middleware/oscil", "siisb", loc, kitid, i, 226 // "oscil", sizeof(void*), 227 // p->kit[kitid]->adpars->voice[i]->OscilSmp); 228 // d.reply("/middleware/oscil", "siisb", loc, kitid, i, "oscil-mod" 229 // sizeof(void*), 230 // p->kit[kitid]->adpars->voice[i]->somethingelse); 231 // } 232 // d.reply("/middleware/pad", "sib", loc, kitid, 233 // sizeof(PADnoteParameters*), 234 // p->kit[kitid]->padpars) 235 // }} 236 }; 237 238 #undef rObject 239 #define rObject Part::Kit 240 static const Ports kitPorts = { 241 rSelf(Part::Kit, rEnabledBy(Penabled)), 242 rRecurp(padpars, rEnabledBy(Ppadenabled), "Padnote parameters"), 243 rRecurp(adpars, rEnabledBy(Padenabled), "Adnote parameters"), 244 rRecurp(subpars, rEnabledBy(Psubenabled), "Subnote parameters"), 245 rToggle(firstkit, rProp(internal), "If this is the part's first kit"), 246 rToggle(Penabled, rDefaultDepends(firstkit), 247 rPreset(true, true), rPreset(false, false), 248 "Kit item enable"), 249 rToggle(Pmuted, rDefault(false), "Kit item mute"), 250 rParamZyn(Pminkey, rDefault(0), "Kit item min key"), 251 rParamZyn(Pmaxkey, rDefault(127), "Kit item max key"), 252 rToggle(Padenabled, rDefaultDepends(firstkit), 253 rPreset(true, true), rPreset(false, false), 254 "ADsynth enable"), 255 rToggle(Psubenabled, rDefault(false), "SUBsynth enable"), 256 rToggle(Ppadenabled, rDefault(false), "PADsynth enable"), 257 rOption(Psendtoparteffect, 258 rOptions(FX1, FX2, FX3, Off), rDefault(FX1), 259 "Effect Levels"), 260 rString(Pname, PART_MAX_NAME_LEN, rDefault(""), "Kit User Specified Label"), 261 {"captureMin:", rDoc("Capture minimum valid note"), NULL, 262 [](const char *, RtData &r) 263 {Part::Kit *p = (Part::Kit*)r.obj; p->Pminkey = p->parent->lastnote;}}, 264 {"captureMax:", rDoc("Capture maximum valid note"), NULL, [](const char *, RtData &r) 265 {Part::Kit *p = (Part::Kit*)r.obj; p->Pmaxkey = p->parent->lastnote;}}, 266 {"padpars-data:b", rProp(internal) rDoc("Set PADsynth data pointer"), 0, 267 [](const char *msg, RtData &d) { 268 rObject &o = *(rObject*)d.obj; 269 assert(o.padpars == NULL); 270 o.padpars = *(decltype(o.padpars)*)rtosc_argument(msg, 0).b.data; 271 }}, 272 {"adpars-data:b", rProp(internal) rDoc("Set ADsynth data pointer"), 0, 273 [](const char *msg, RtData &d) { 274 rObject &o = *(rObject*)d.obj; 275 assert(o.adpars == NULL); 276 o.adpars = *(decltype(o.adpars)*)rtosc_argument(msg, 0).b.data; 277 }}, 278 {"subpars-data:b", rProp(internal) rDoc("Set SUBsynth data pointer"), 0, 279 [](const char *msg, RtData &d) { 280 rObject &o = *(rObject*)d.obj; 281 assert(o.subpars == NULL); 282 o.subpars = *(decltype(o.subpars)*)rtosc_argument(msg, 0).b.data; 283 }}, 284 }; 285 286 const Ports &Part::Kit::ports = kitPorts; 287 const Ports &Part::ports = partPorts; 288 289 Part::Part(Allocator &alloc, const SYNTH_T &synth_, const AbsTime &time_, Sync* sync_, 290 const int &gzip_compression, const int &interpolation, 291 Microtonal *microtonal_, FFTwrapper *fft_, WatchManager *wm_, const char *prefix_) 292 :Pdrummode(false), 293 Ppolymode(true), 294 Plegatomode(false), 295 Platchmode(false), 296 partoutl(new float[synth_.buffersize]), 297 partoutr(new float[synth_.buffersize]), 298 ctl(synth_, &time_), 299 microtonal(microtonal_), 300 fft(fft_), 301 wm(wm_), 302 memory(alloc), 303 synth(synth_), 304 time(time_), 305 sync(sync_), 306 gzip_compression(gzip_compression), 307 interpolation(interpolation) 308 { 309 loaded_file[0] = '\0'; 310 311 if(prefix_) 312 fast_strcpy(prefix, prefix_, sizeof(prefix)); 313 else 314 memset(prefix, 0, sizeof(prefix)); 315 316 monomemClear(); 317 318 for(int n = 0; n < NUM_KIT_ITEMS; ++n) { 319 kit[n].parent = this; 320 kit[n].Pname = new char [PART_MAX_NAME_LEN]; 321 kit[n].adpars = nullptr; 322 kit[n].subpars = nullptr; 323 kit[n].padpars = nullptr; 324 } 325 326 kit[0].adpars = new ADnoteParameters(synth, fft, &time); 327 328 //Part's Insertion Effects init 329 for(int nefx = 0; nefx < NUM_PART_EFX; ++nefx) { 330 partefx[nefx] = new EffectMgr(memory, synth, 1, &time, sync); 331 Pefxbypass[nefx] = false; 332 } 333 assert(partefx[0]); 334 335 for(int n = 0; n < NUM_PART_EFX + 1; ++n) { 336 partfxinputl[n] = new float [synth.buffersize]; 337 partfxinputr[n] = new float [synth.buffersize]; 338 } 339 340 killallnotes = false; 341 silent = false; 342 oldfreq_log2 = -1.0f; 343 oldportamento = NULL; 344 legatoportamento = NULL; 345 346 cleanup(); 347 348 Pname = new char[PART_MAX_NAME_LEN]; 349 350 lastnote = -1; 351 352 defaults(); 353 assert(partefx[0]); 354 } 355 356 Part::Kit::Kit(void) 357 :parent(nullptr), 358 Penabled(false), Pmuted(false), 359 Pminkey(0), Pmaxkey(127), 360 Pname(nullptr), 361 Padenabled(false), Psubenabled(false), 362 Ppadenabled(false), Psendtoparteffect(0), 363 adpars(nullptr), subpars(nullptr), padpars(nullptr) 364 { 365 } 366 367 void Part::cloneTraits(Part &p) const 368 { 369 #define CLONE(x) p.x = this->x 370 CLONE(Penabled); 371 372 p.setVolumedB(this->Volume); 373 p.setPpanning(this->Ppanning); 374 375 CLONE(Pminkey); 376 CLONE(Pmaxkey); 377 CLONE(Pkeyshift); 378 CLONE(Prcvchn); 379 380 CLONE(Pvelsns); 381 CLONE(Pveloffs); 382 383 CLONE(Pnoteon); 384 CLONE(Ppolymode); 385 CLONE(Plegatomode); 386 CLONE(Pkeylimit); 387 CLONE(Pvoicelimit); 388 389 // Controller has a reference, so it can not be re-assigned 390 // So, destroy and reconstruct it. 391 p.ctl.~Controller(); new (&p.ctl) Controller(this->ctl); 392 } 393 394 void Part::defaults() 395 { 396 Penabled = 0; 397 Pminkey = 0; 398 Pmaxkey = 127; 399 Pnoteon = 1; 400 Ppolymode = 1; 401 Plegatomode = 0; 402 setVolumedB(0.0); 403 Pkeyshift = 64; 404 Prcvchn = 0; 405 setPpanning(64); 406 Pvelsns = 64; 407 Pveloffs = 64; 408 Pkeylimit = 15; 409 Pvoicelimit = 0; 410 defaultsinstrument(); 411 ctl.defaults(); 412 } 413 414 void Part::defaultsinstrument() 415 { 416 ZERO(Pname, PART_MAX_NAME_LEN); 417 418 info.Ptype = 0; 419 ZERO(info.Pauthor, MAX_INFO_TEXT_SIZE + 1); 420 ZERO(info.Pcomments, MAX_INFO_TEXT_SIZE + 1); 421 422 Pkitmode = 0; 423 Pdrummode = 0; 424 425 for(int n = 0; n < NUM_KIT_ITEMS; ++n) { 426 //kit[n].Penabled = false; 427 kit[n].firstkit = false; 428 kit[n].Pmuted = false; 429 kit[n].Pminkey = 0; 430 kit[n].Pmaxkey = 127; 431 kit[n].Padenabled = false; 432 kit[n].Psubenabled = false; 433 kit[n].Ppadenabled = false; 434 ZERO(kit[n].Pname, PART_MAX_NAME_LEN); 435 kit[n].Psendtoparteffect = 0; 436 if(n != 0) 437 setkititemstatus(n, 0); 438 } 439 kit[0].firstkit = true; 440 kit[0].Penabled = 1; 441 kit[0].Padenabled = 1; 442 kit[0].adpars->defaults(); 443 444 for(int nefx = 0; nefx < NUM_PART_EFX; ++nefx) { 445 partefx[nefx]->defaults(); 446 Pefxroute[nefx] = 0; //route to next effect 447 } 448 } 449 450 451 452 /* 453 * Cleanup the part 454 */ 455 void Part::cleanup(bool final_) 456 { 457 notePool.killAllNotes(); 458 for(int i = 0; i < synth.buffersize; ++i) { 459 partoutl[i] = final_ ? 0.0f : synth.denormalkillbuf[i]; 460 partoutr[i] = final_ ? 0.0f : synth.denormalkillbuf[i]; 461 } 462 ctl.resetall(); 463 for(int nefx = 0; nefx < NUM_PART_EFX; ++nefx) 464 partefx[nefx]->cleanup(); 465 for(int n = 0; n < NUM_PART_EFX + 1; ++n) 466 for(int i = 0; i < synth.buffersize; ++i) { 467 partfxinputl[n][i] = final_ ? 0.0f : synth.denormalkillbuf[i]; 468 partfxinputr[n][i] = final_ ? 0.0f : synth.denormalkillbuf[i]; 469 } 470 } 471 472 Part::~Part() 473 { 474 cleanup(true); 475 for(int n = 0; n < NUM_KIT_ITEMS; ++n) { 476 delete kit[n].adpars; 477 delete kit[n].subpars; 478 delete kit[n].padpars; 479 delete [] kit[n].Pname; 480 } 481 482 delete [] Pname; 483 delete [] partoutl; 484 delete [] partoutr; 485 for(int nefx = 0; nefx < NUM_PART_EFX; ++nefx) 486 delete partefx[nefx]; 487 for(int n = 0; n < NUM_PART_EFX + 1; ++n) { 488 delete [] partfxinputl[n]; 489 delete [] partfxinputr[n]; 490 } 491 } 492 493 static void assert_kit_sanity(const Part::Kit *kits) 494 { 495 for(int i=0; i<NUM_KIT_ITEMS; ++i) { 496 //an enabled kit must have a corresponding parameter object 497 assert(!kits[i].Padenabled || kits[i].adpars); 498 assert(!kits[i].Ppadenabled || kits[i].padpars); 499 assert(!kits[i].Psubenabled || kits[i].subpars); 500 } 501 } 502 503 static int kit_usage(const Part::Kit *kits, int note, int mode) 504 { 505 const bool non_kit = mode == 0; 506 const bool singl_kit = mode == 2; 507 int synth_usage = 0; 508 509 for(uint8_t i = 0; i < NUM_KIT_ITEMS; ++i) { 510 const auto &item = kits[i]; 511 if(!non_kit && !item.validNote(note)) 512 continue; 513 514 synth_usage += item.Padenabled; 515 synth_usage += item.Psubenabled; 516 synth_usage += item.Ppadenabled; 517 518 //Partial Kit Use 519 if(non_kit || (singl_kit && item.active())) 520 break; 521 } 522 523 return synth_usage; 524 } 525 526 /* 527 * Note On Messages 528 */ 529 bool Part::NoteOnInternal(note_t note, 530 unsigned char velocity, 531 float note_log2_freq) 532 { 533 //Verify Basic Mode and sanity 534 const bool isRunningNote = notePool.existsRunningNote(); 535 const bool doingLegato = isRunningNote && isLegatoMode() && 536 lastlegatomodevalid; 537 538 if(!Pnoteon || !inRange(note, Pminkey, Pmaxkey) || notePool.full() || 539 notePool.synthFull(kit_usage(kit, note, Pkitmode))) 540 return false; 541 542 verifyKeyMode(); 543 assert_kit_sanity(kit); 544 545 //Preserve Note Stack 546 if(isMonoMode() || isLegatoMode()) { 547 monomemPush(note); 548 monomem[note].velocity = velocity; 549 monomem[note].note_log2_freq = note_log2_freq; 550 551 } else if(!monomemEmpty()) 552 monomemClear(); 553 554 //Mono/Legato Release old notes 555 if(isMonoMode() || (isLegatoMode() && !doingLegato)) 556 notePool.releasePlayingNotes(); 557 558 lastlegatomodevalid = isLegatoMode(); 559 560 //Compute Note Parameters 561 const float vel = getVelocity(velocity, Pvelsns, Pveloffs); 562 563 //Portamento 564 lastnote = note; 565 566 /* check if first note is played */ 567 if(oldfreq_log2 < 0.0f) 568 oldfreq_log2 = note_log2_freq; 569 570 // For Mono/Legato: Force Portamento Off on first 571 // notes. That means it is required that the previous note is 572 // still held down or sustained for the Portamento to activate 573 // (that's like Legato). 574 PortamentoRealtime *portamento_realtime = NULL; 575 // If there is a currently ongoing glide, shift the starting point 576 // for any new portamento to where the current glide is right now 577 if (oldportamento && oldportamento->portamento.active) 578 oldportamentofreq_log2 += oldportamento->portamento.freqdelta_log2; 579 // Non-portamento settings and conditions say the note may have 580 // portamento, but it remains for Portamento.init to make the 581 // final decision depending on the portamento enable, threshold and 582 // other parameters. 583 Portamento portamento(ctl, synth, isRunningNote, oldfreq_log2, oldportamentofreq_log2, note_log2_freq); 584 if(portamento.active) { 585 // If we're doing legato and we already have a portamento structure, 586 // reuse it. 587 if (doingLegato && legatoportamento) { 588 portamento_realtime = legatoportamento; 589 portamento_realtime->portamento = portamento; 590 } else { 591 // Create new one if we don't already have one, or for each 592 // note in poly/mono mode 593 portamento_realtime = memory.alloc<PortamentoRealtime> 594 (this, 595 memory, 596 // Cleanup function: Destroy any references we might 597 // have to the current realtime pointer so that it 598 // can not be (re)used, with disastrous results. 599 [](PortamentoRealtime *realtime) 600 { 601 assert(realtime); 602 Part *part = static_cast<Part *>(realtime->handle); 603 assert(part); 604 if (realtime == part->oldportamento) { 605 // Since the last note is going away, capture 606 // the portamento:ed pitch offset to our saved 607 // previous note. This will be our starting 608 // point for the next portamento glide. 609 if (realtime->portamento.active) 610 part->oldportamentofreq_log2 += 611 realtime->portamento.freqdelta_log2; 612 part->oldportamento = NULL; 613 } 614 if (realtime == part->legatoportamento) 615 part->legatoportamento = NULL; 616 }, 617 portamento 618 ); 619 if (doingLegato) 620 legatoportamento = portamento_realtime; 621 } 622 } 623 624 // Create the portamento pointer that we distribute to the synth notes 625 Portamento *portamentoptr = NULL; 626 if(portamento_realtime) 627 portamentoptr = &portamento_realtime->portamento; 628 629 // Save note freq and pointer to portamento state for next note 630 oldfreq_log2 = note_log2_freq; 631 oldportamentofreq_log2 = oldfreq_log2; 632 oldportamento = portamento_realtime; 633 634 //Adjust Existing Notes 635 if(doingLegato) { 636 LegatoParams pars = {vel, portamentoptr, note_log2_freq, true, prng()}; 637 notePool.applyLegato(note, pars, portamento_realtime); 638 return true; 639 } 640 641 // We know now that we are not doing legato, so we destroy the reference 642 // to the previous legato portamento info so we don't try to reuse it 643 legatoportamento = NULL; 644 645 if(Ppolymode) 646 notePool.makeUnsustainable(note); 647 648 // in latch mode release latched notes before creating the new one 649 if(Platchmode) 650 notePool.releaseLatched(); 651 652 //Create New Notes 653 for(uint8_t i = 0; i < NUM_KIT_ITEMS; ++i) { 654 ScratchString pre = prefix; 655 auto &item = kit[i]; 656 if(Pkitmode != 0 && !item.validNote(note)) 657 continue; 658 659 SynthParams pars{memory, ctl, synth, time, vel, 660 portamentoptr, note_log2_freq, false, prng()}; 661 const int sendto = Pkitmode ? item.sendto() : 0; 662 663 // Enforce voice limit, before we trigger new note 664 limit_voices(note); 665 666 try { 667 if(item.Padenabled) 668 notePool.insertNote(note, sendto, 669 {memory.alloc<ADnote>(kit[i].adpars, pars, 670 wm, (pre+"kit"+i+"/adpars/").c_str), 0, i}, 671 portamento_realtime); 672 if(item.Psubenabled) 673 notePool.insertNote(note, sendto, 674 {memory.alloc<SUBnote>(kit[i].subpars, pars, wm, (pre+"kit"+i+"/subpars/").c_str), 1, i}, 675 portamento_realtime); 676 if(item.Ppadenabled) 677 notePool.insertNote(note, sendto, 678 {memory.alloc<PADnote>(kit[i].padpars, pars, interpolation, wm, 679 (pre+"kit"+i+"/padpars/").c_str), 2, i}, 680 portamento_realtime); 681 } catch (std::bad_alloc & ba) { 682 std::cerr << "dropped new note: " << ba.what() << std::endl; 683 } 684 685 //Partial Kit Use 686 if(isNonKit() || (isSingleKit() && item.active())) 687 break; 688 } 689 690 if(isLegatoMode()) 691 notePool.upgradeToLegato(); 692 693 //Enforce the key limit 694 setkeylimit(Pkeylimit); 695 return true; 696 } 697 698 /* 699 * Note Off Messages 700 */ 701 void Part::NoteOff(note_t note) //release the key 702 { 703 // This note is released, so we remove it from the list. 704 if(!monomemEmpty()) 705 monomemPop(note); 706 707 for(auto &desc:notePool.activeDesc()) { 708 if(desc.note != note || !desc.playing()) 709 continue; 710 // if latch is on we ignore noteoff, but set the state to latched 711 if(Platchmode) { 712 notePool.latch(desc); 713 } else if(!ctl.sustain.sustain) { //the sustain pedal is not pushed 714 if((isMonoMode() || isLegatoMode()) && !monomemEmpty()) 715 MonoMemRenote();//Play most recent still active note 716 else 717 notePool.release(desc); 718 } 719 else { //the sustain pedal is pushed 720 if(desc.canSustain()) 721 desc.doSustain(); 722 else { 723 notePool.release(desc); 724 } 725 } 726 } 727 } 728 729 /* 730 * This handles the MIDI All Notes Off message (the 'notes off' in 'all notes 731 * off' refers to note off events, not actually silencing all playing 732 * voices). 733 */ 734 void Part::ReleaseAllKeys(void) 735 { 736 // Clear all notes from list. 737 monomemClear(); 738 739 for(auto &desc:notePool.activeDesc()) { 740 if(!desc.playing()) 741 continue; 742 // if latch is on we ignore noteoff, but set the state to latched 743 if(Platchmode) { 744 notePool.latch(desc); 745 } else if(!ctl.sustain.sustain) { //the sustain pedal is not pushed 746 notePool.release(desc); 747 } else { //the sustain pedal is pushed 748 if(desc.canSustain()) 749 desc.doSustain(); 750 else 751 notePool.release(desc); 752 } 753 } 754 } 755 756 void Part::PolyphonicAftertouch(note_t note, 757 unsigned char velocity) 758 { 759 if(!Pnoteon || !inRange(note, Pminkey, Pmaxkey) || Pdrummode) 760 return; 761 762 /* 763 * Don't allow the velocity to reach zero. 764 * Keep it alive until note off. 765 */ 766 if(velocity == 0) 767 velocity = 1; 768 769 // MonoMem stuff: 770 if(!Ppolymode) // if Poly is off 771 monomem[note].velocity = velocity; // Store this note's velocity. 772 773 const float vel = getVelocity(velocity, Pvelsns, Pveloffs); 774 for(auto &d:notePool.activeDesc()) { 775 if(d.note == note && d.playing()) 776 for(auto &s:notePool.activeNotes(d)) 777 s.note->setVelocity(vel); 778 } 779 } 780 781 /* 782 * Controllers 783 */ 784 void Part::SetController(unsigned int type, int par) 785 { 786 switch(type) { 787 case C_pitchwheel: 788 ctl.setpitchwheel(par); 789 break; 790 case C_expression: 791 ctl.setexpression(par); 792 setVolumedB(Volume); //update the volume 793 break; 794 case C_portamento: 795 ctl.setportamento(par); 796 break; 797 case C_panning: 798 ctl.setpanning(par); 799 setPpanning(Ppanning); //update the panning 800 break; 801 case C_filtercutoff: 802 ctl.setfiltercutoff(par); 803 break; 804 case C_filterq: 805 ctl.setfilterq(par); 806 break; 807 case C_bandwidth: 808 ctl.setbandwidth(par); 809 break; 810 case C_modwheel: 811 ctl.setmodwheel(par); 812 break; 813 case C_fmamp: 814 ctl.setfmamp(par); 815 break; 816 case C_volume: 817 ctl.setvolume(par); 818 if(ctl.volume.receive != 0) 819 setVolumedB(volume127TodB( ctl.volume.volume * 127.0f ) ); 820 else 821 /* FIXME: why do this? */ 822 setVolumedB(Volume); 823 break; 824 case C_sustain: 825 ctl.setsustain(par); 826 if(ctl.sustain.sustain == 0) 827 ReleaseSustainedKeys(); 828 break; 829 case C_allsoundsoff: 830 AllNotesOff(); //Panic 831 break; 832 case C_resetallcontrollers: 833 ctl.resetall(); 834 ReleaseSustainedKeys(); 835 if(ctl.volume.receive != 0) 836 setVolumedB(volume127TodB( ctl.volume.volume * 127.0f ) ); 837 else 838 setVolumedB(Volume); 839 setPpanning(Ppanning); //update the panning 840 841 for(int item = 0; item < NUM_KIT_ITEMS; ++item) { 842 if(kit[item].adpars == NULL) 843 continue; 844 kit[item].adpars->GlobalPar.Reson-> 845 sendcontroller(C_resonance_center, 1.0f); 846 847 kit[item].adpars->GlobalPar.Reson-> 848 sendcontroller(C_resonance_bandwidth, 1.0f); 849 } 850 //more update to add here if I add controllers 851 break; 852 case C_allnotesoff: 853 ReleaseAllKeys(); 854 break; 855 case C_resonance_center: 856 ctl.setresonancecenter(par); 857 for(int item = 0; item < NUM_KIT_ITEMS; ++item) { 858 if(kit[item].adpars == NULL) 859 continue; 860 kit[item].adpars->GlobalPar.Reson-> 861 sendcontroller(C_resonance_center, 862 ctl.resonancecenter.relcenter); 863 } 864 break; 865 case C_resonance_bandwidth: 866 ctl.setresonancebw(par); 867 for(int item = 0; item < NUM_KIT_ITEMS; ++item) { 868 if(kit[item].adpars == NULL) 869 continue; 870 kit[item].adpars->GlobalPar.Reson-> 871 sendcontroller(C_resonance_bandwidth, 872 ctl.resonancebandwidth.relbw); 873 } 874 break; 875 } 876 } 877 878 /* 879 * Per note controllers. 880 */ 881 void Part::SetController(unsigned int type, note_t note, float value, 882 int masterkeyshift) 883 { 884 if(!Pnoteon || !inRange(note, Pminkey, Pmaxkey) || Pdrummode) 885 return; 886 887 switch (type) { 888 case C_aftertouch: 889 PolyphonicAftertouch(note, floorf(value)); 890 break; 891 case C_pitch: { 892 if (getNoteLog2Freq(masterkeyshift, value) == false) 893 break; 894 895 /* Make sure MonoMem's frequency information is kept up to date */ 896 if(!Ppolymode) 897 monomem[note].note_log2_freq = value; 898 899 for(auto &d:notePool.activeDesc()) { 900 if(d.note == note && d.playing()) 901 for(auto &s:notePool.activeNotes(d)) 902 s.note->setPitch(value); 903 } 904 break; 905 } 906 case C_filtercutoff: 907 for(auto &d:notePool.activeDesc()) { 908 if(d.note == note && d.playing()) 909 for(auto &s:notePool.activeNotes(d)) 910 s.note->setFilterCutoff(value); 911 } 912 break; 913 default: 914 break; 915 } 916 } 917 918 /* 919 * Release the sustained keys 920 */ 921 922 void Part::ReleaseSustainedKeys() 923 { 924 // Let's call MonoMemRenote() on some conditions: 925 if((isMonoMode() || isLegatoMode()) && !monomemEmpty()) 926 if(monomemBack() != lastnote) // Sustain controller manipulation would cause repeated same note respawn without this check. 927 MonoMemRenote(); // To play most recent still held note. 928 929 notePool.releaseSustainingNotes(); 930 } 931 932 // Call NoteOn(...) with the most recent still held key as new note 933 // (Made for Mono/Legato). 934 void Part::MonoMemRenote() 935 { 936 note_t mmrtempnote = monomemBack(); // Last list element. 937 monomemPop(mmrtempnote); // We remove it, will be added again in NoteOn(...). 938 NoteOnInternal(mmrtempnote, 939 monomem[mmrtempnote].velocity, 940 monomem[mmrtempnote].note_log2_freq); 941 } 942 943 bool Part::getNoteLog2Freq(int masterkeyshift, float ¬e_log2_freq) 944 { 945 if(Pdrummode) { 946 note_log2_freq += log2f(440.0f) - 69.0f / 12.0f; 947 return true; 948 } 949 return microtonal->updatenotefreq_log2(note_log2_freq, 950 (int)Pkeyshift - 64 + masterkeyshift); 951 } 952 953 float Part::getVelocity(uint8_t velocity, uint8_t velocity_sense, 954 uint8_t velocity_offset) const 955 { 956 //compute sense function 957 const float vel = VelF(velocity / 127.0f, velocity_sense); 958 959 //compute the velocity offset 960 return limit(vel + (velocity_offset - 64.0f) / 64.0f, 0.0f, 1.0f); 961 } 962 963 void Part::verifyKeyMode(void) 964 { 965 if(Plegatomode && !Pdrummode && Ppolymode) { 966 fprintf(stderr, 967 "WARNING: Poly & Legato modes are On, that shouldn't happen\n" 968 "Disabling Legato mode...\n" 969 "(Part.cpp::NoteOn(..))\n"); 970 Plegatomode = 0; 971 } 972 } 973 974 975 /* 976 * Set Part's key limit 977 */ 978 void Part::setkeylimit(unsigned char Pkeylimit_) 979 { 980 Pkeylimit = Pkeylimit_; 981 int keylimit = Pkeylimit; 982 if(keylimit == 0) 983 keylimit = POLYPHONY - 5; 984 985 if(notePool.getRunningNotes() >= keylimit) 986 notePool.enforceKeyLimit(keylimit); 987 } 988 989 /* 990 * Enforce voice limit 991 */ 992 void Part::limit_voices(int new_note) 993 { 994 int voicelimit = Pvoicelimit; 995 if(voicelimit == 0) /* voice limit disabled */ 996 return; 997 998 /* If we're called because a new note is imminent, we need to enforce 999 * one less note than the limit, so we don't go above the limit when the 1000 * new note is triggered. 1001 */ 1002 if (new_note >= 0) 1003 voicelimit--; 1004 1005 int running_voices = notePool.getRunningVoices(); 1006 if(running_voices >= voicelimit) 1007 notePool.enforceVoiceLimit(voicelimit, new_note); 1008 } 1009 1010 /* 1011 * Set Part's voice limit 1012 */ 1013 void Part::setvoicelimit(unsigned char Pvoicelimit_) 1014 { 1015 Pvoicelimit = Pvoicelimit_; 1016 1017 limit_voices(-1); 1018 } 1019 1020 /* 1021 * Prepare all notes to be turned off 1022 */ 1023 void Part::AllNotesOff() 1024 { 1025 killallnotes = true; 1026 } 1027 1028 /* 1029 * Compute Part samples and store them in the partoutl[] and partoutr[] 1030 */ 1031 void Part::ComputePartSmps() 1032 { 1033 /* When we are in the process of being disabled (Penabled set to false), 1034 * AllNotesOff will be called, setting killallnotes, which causes all 1035 * playing voices to terminate and the signal level being graciously 1036 * muted during the course of the current buffer. After that, all 1037 * subsequent output buffers will be set to 0 until we are enabled again. 1038 */ 1039 if (!Penabled && !killallnotes) { 1040 /* We only need to clear the output buffer once when disabled; since 1041 * it's static within the part it's wasteful to do it every time. */ 1042 if (!silent) { 1043 memset(partoutl, 0, synth.bufferbytes); 1044 memset(partoutr, 0, synth.bufferbytes); 1045 silent = true; 1046 } 1047 return; 1048 } 1049 silent = false; 1050 1051 assert(partefx[0]); 1052 for(unsigned nefx = 0; nefx < NUM_PART_EFX + 1; ++nefx) { 1053 memset(partfxinputl[nefx], 0, synth.bufferbytes); 1054 memset(partfxinputr[nefx], 0, synth.bufferbytes); 1055 } 1056 1057 for(auto &d:notePool.activeDesc()) { 1058 d.age++; 1059 for(auto &s:notePool.activeNotes(d)) { 1060 float tmpoutr[synth.buffersize]; 1061 float tmpoutl[synth.buffersize]; 1062 auto ¬e = *s.note; 1063 note.noteout(&tmpoutl[0], &tmpoutr[0]); 1064 1065 for(int i = 0; i < synth.buffersize; ++i) { //add the note to part(mix) 1066 partfxinputl[d.sendto][i] += tmpoutl[i]; 1067 partfxinputr[d.sendto][i] += tmpoutr[i]; 1068 } 1069 1070 if(note.finished()) 1071 notePool.kill(s); 1072 } 1073 if (d.portamentoRealtime) 1074 d.portamentoRealtime->portamento.update(); 1075 } 1076 1077 //Apply part's effects and mix them 1078 for(int nefx = 0; nefx < NUM_PART_EFX; ++nefx) { 1079 if(!Pefxbypass[nefx]) { 1080 partefx[nefx]->out(partfxinputl[nefx], partfxinputr[nefx]); 1081 if(Pefxroute[nefx] == 2) 1082 for(int i = 0; i < synth.buffersize; ++i) { 1083 partfxinputl[nefx + 1][i] += partefx[nefx]->efxoutl[i]; 1084 partfxinputr[nefx + 1][i] += partefx[nefx]->efxoutr[i]; 1085 } 1086 } 1087 int routeto = ((Pefxroute[nefx] == 0) ? nefx + 1 : NUM_PART_EFX); 1088 for(int i = 0; i < synth.buffersize; ++i) { 1089 partfxinputl[routeto][i] += partfxinputl[nefx][i]; 1090 partfxinputr[routeto][i] += partfxinputr[nefx][i]; 1091 } 1092 } 1093 for(int i = 0; i < synth.buffersize; ++i) { 1094 partoutl[i] = partfxinputl[NUM_PART_EFX][i]; 1095 partoutr[i] = partfxinputr[NUM_PART_EFX][i]; 1096 } 1097 1098 if(killallnotes) { 1099 for(int i = 0; i < synth.buffersize; ++i) { 1100 float tmp = (synth.buffersize_f - i) / synth.buffersize_f; 1101 partoutl[i] *= tmp; 1102 partoutr[i] *= tmp; 1103 } 1104 notePool.killAllNotes(); 1105 monomemClear(); 1106 killallnotes = false; 1107 for(int nefx = 0; nefx < NUM_PART_EFX; ++nefx) 1108 partefx[nefx]->cleanup(); 1109 } 1110 } 1111 1112 /* 1113 * Parameter control 1114 */ 1115 1116 float Part::volume127TodB(unsigned char volume_) 1117 { 1118 assert( volume_ <= 127 ); 1119 return (volume_ - 96.0f) / 96.0f * 40.0; 1120 } 1121 1122 void Part::setVolumedB(float Volume_) 1123 { 1124 //Fixes bug with invalid loading 1125 if(fabs(Volume_ - 50.0f) < 0.001) 1126 Volume_ = 0.0f; 1127 1128 Volume_ = limit(Volume_, -40.0f, 13.333f); 1129 1130 assert(Volume_ < 14.0); 1131 Volume = Volume_; 1132 1133 float volume = dB2rap( Volume_ ); 1134 1135 /* printf( "Volume: %f, Expression %f\n", volume, ctl.expression.relvolume ); */ 1136 1137 assert( volume <= dB2rap(14.0f) ); 1138 1139 gain = volume * ctl.expression.relvolume; 1140 } 1141 1142 void Part::setPpanning(char Ppanning_) 1143 { 1144 Ppanning = Ppanning_; 1145 panning = limit(Ppanning / 127.0f + ctl.panning.pan, 0.0f, 1.0f); 1146 } 1147 1148 /* 1149 * Enable or disable a kit item 1150 */ 1151 void Part::setkititemstatus(unsigned kititem, bool Penabled_) 1152 { 1153 //nonexistent kit item and the first kit item is always enabled 1154 if((kititem == 0) || (kititem >= NUM_KIT_ITEMS)) 1155 return; 1156 1157 Kit &kkit = kit[kititem]; 1158 1159 //no need to update if 1160 if(kkit.Penabled == Penabled_) 1161 return; 1162 kkit.Penabled = Penabled_; 1163 1164 if(!Penabled_) { 1165 delete kkit.adpars; 1166 delete kkit.subpars; 1167 delete kkit.padpars; 1168 kkit.adpars = nullptr; 1169 kkit.subpars = nullptr; 1170 kkit.padpars = nullptr; 1171 kkit.Pname[0] = '\0'; 1172 1173 notePool.killAllNotes(); 1174 } 1175 else { 1176 //All parameters must be NULL in this case 1177 assert(!(kkit.adpars || kkit.subpars || kkit.padpars)); 1178 kkit.adpars = new ADnoteParameters(synth, fft, &time); 1179 kkit.subpars = new SUBnoteParameters(&time); 1180 kkit.padpars = new PADnoteParameters(synth, fft, &time); 1181 } 1182 } 1183 1184 void Part::add2XMLinstrument(XMLwrapper& xml) 1185 { 1186 xml.beginbranch("INFO"); 1187 xml.addparstr("name", (char *)Pname); 1188 xml.addparstr("author", (char *)info.Pauthor); 1189 xml.addparstr("comments", (char *)info.Pcomments); 1190 xml.addpar("type", info.Ptype); 1191 xml.endbranch(); 1192 1193 1194 xml.beginbranch("INSTRUMENT_KIT"); 1195 xml.addpar("kit_mode", Pkitmode); 1196 xml.addparbool("drum_mode", Pdrummode); 1197 1198 for(int i = 0; i < NUM_KIT_ITEMS; ++i) { 1199 xml.beginbranch("INSTRUMENT_KIT_ITEM", i); 1200 xml.addparbool("enabled", kit[i].Penabled); 1201 if(kit[i].Penabled != 0 || xml.SaveFullXml) { 1202 xml.addparstr("name", (char *)kit[i].Pname); 1203 1204 xml.addparbool("muted", kit[i].Pmuted); 1205 xml.addpar("min_key", kit[i].Pminkey); 1206 xml.addpar("max_key", kit[i].Pmaxkey); 1207 1208 xml.addpar("send_to_instrument_effect", kit[i].Psendtoparteffect); 1209 1210 xml.addparbool("add_enabled", kit[i].Padenabled); 1211 if((kit[i].Padenabled || xml.SaveFullXml) && kit[i].adpars) { 1212 xml.beginbranch("ADD_SYNTH_PARAMETERS"); 1213 kit[i].adpars->add2XML(xml); 1214 xml.endbranch(); 1215 } 1216 1217 xml.addparbool("sub_enabled", kit[i].Psubenabled); 1218 if((kit[i].Psubenabled || xml.SaveFullXml) && kit[i].subpars) { 1219 xml.beginbranch("SUB_SYNTH_PARAMETERS"); 1220 kit[i].subpars->add2XML(xml); 1221 xml.endbranch(); 1222 } 1223 1224 xml.addparbool("pad_enabled", kit[i].Ppadenabled); 1225 if((kit[i].Ppadenabled || xml.SaveFullXml) && kit[i].padpars) { 1226 xml.beginbranch("PAD_SYNTH_PARAMETERS"); 1227 kit[i].padpars->add2XML(xml); 1228 xml.endbranch(); 1229 } 1230 } 1231 xml.endbranch(); 1232 } 1233 xml.endbranch(); 1234 1235 xml.beginbranch("INSTRUMENT_EFFECTS"); 1236 for(int nefx = 0; nefx < NUM_PART_EFX; ++nefx) { 1237 xml.beginbranch("INSTRUMENT_EFFECT", nefx); 1238 xml.beginbranch("EFFECT"); 1239 partefx[nefx]->add2XML(xml); 1240 xml.endbranch(); 1241 1242 xml.addpar("route", Pefxroute[nefx]); 1243 partefx[nefx]->setdryonly(Pefxroute[nefx] == 2); 1244 xml.addparbool("bypass", Pefxbypass[nefx]); 1245 xml.endbranch(); 1246 } 1247 xml.endbranch(); 1248 } 1249 1250 void Part::add2XML(XMLwrapper& xml) 1251 { 1252 //parameters 1253 xml.addparbool("enabled", Penabled); 1254 if((Penabled == 0) && (xml.minimal)) 1255 return; 1256 1257 xml.addparreal("volume", Volume); 1258 xml.addpar("panning", Ppanning); 1259 1260 xml.addpar("min_key", Pminkey); 1261 xml.addpar("max_key", Pmaxkey); 1262 xml.addpar("key_shift", Pkeyshift); 1263 xml.addpar("rcv_chn", Prcvchn); 1264 1265 xml.addpar("velocity_sensing", Pvelsns); 1266 xml.addpar("velocity_offset", Pveloffs); 1267 1268 xml.addparbool("note_on", Pnoteon); 1269 xml.addparbool("poly_mode", Ppolymode); 1270 xml.addpar("legato_mode", Plegatomode); 1271 xml.addpar("key_limit", Pkeylimit); 1272 xml.addpar("voice_limit", Pvoicelimit); 1273 1274 xml.beginbranch("INSTRUMENT"); 1275 add2XMLinstrument(xml); 1276 xml.endbranch(); 1277 1278 xml.beginbranch("CONTROLLER"); 1279 ctl.add2XML(xml); 1280 xml.endbranch(); 1281 } 1282 1283 int Part::saveXML(const char *filename) 1284 { 1285 XMLwrapper xml; 1286 1287 xml.beginbranch("INSTRUMENT"); 1288 add2XMLinstrument(xml); 1289 xml.endbranch(); 1290 1291 int result = xml.saveXMLfile(filename, gzip_compression); 1292 return result; 1293 } 1294 1295 int Part::loadXMLinstrument(const char *filename) 1296 { 1297 XMLwrapper xml; 1298 if(xml.loadXMLfile(filename) < 0) { 1299 return -1; 1300 } 1301 1302 if(xml.enterbranch("INSTRUMENT") == 0) 1303 return -10; 1304 1305 // store filename in member variable 1306 int length = sizeof(loaded_file)-1; 1307 strncpy(loaded_file, filename, length); 1308 // set last element to \0 in case filename is too long or not terminated 1309 loaded_file[length]='\0'; 1310 1311 getfromXMLinstrument(xml); 1312 xml.exitbranch(); 1313 1314 return 0; 1315 } 1316 1317 void Part::applyparameters(void) 1318 { 1319 applyparameters([]{return false;}); 1320 } 1321 1322 void Part::applyparameters(std::function<bool()> do_abort) 1323 { 1324 for(int n = 0; n < NUM_KIT_ITEMS; ++n) 1325 if(kit[n].Ppadenabled && kit[n].padpars) 1326 kit[n].padpars->applyparameters(do_abort); 1327 } 1328 1329 void Part::initialize_rt(void) 1330 { 1331 for(int i=0; i<NUM_PART_EFX; ++i) 1332 partefx[i]->init(); 1333 } 1334 1335 void Part::kill_rt(void) 1336 { 1337 for(int i=0; i<NUM_PART_EFX; ++i) 1338 partefx[i]->kill(); 1339 notePool.killAllNotes(); 1340 } 1341 1342 void Part::monomemPush(note_t note) 1343 { 1344 for(int i=0; i<256; ++i) 1345 if(monomemnotes[i]==note) 1346 return; 1347 1348 for(int i=254;i>=0; --i) 1349 monomemnotes[i+1] = monomemnotes[i]; 1350 monomemnotes[0] = note; 1351 } 1352 1353 void Part::monomemPop(note_t note) 1354 { 1355 int note_pos=-1; 1356 for(int i=0; i<256; ++i) 1357 if(monomemnotes[i]==note) 1358 note_pos = i; 1359 if(note_pos != -1) { 1360 for(int i=note_pos; i<256; ++i) 1361 monomemnotes[i] = monomemnotes[i+1]; 1362 monomemnotes[255] = -1; 1363 } 1364 } 1365 1366 note_t Part::monomemBack(void) const 1367 { 1368 return monomemnotes[0]; 1369 } 1370 1371 bool Part::monomemEmpty(void) const 1372 { 1373 return monomemnotes[0] == -1; 1374 } 1375 1376 void Part::monomemClear(void) 1377 { 1378 for(int i=0; i<256; ++i) 1379 monomemnotes[i] = -1; 1380 } 1381 1382 void Part::getfromXMLinstrument(XMLwrapper& xml) 1383 { 1384 if(xml.enterbranch("INFO")) { 1385 xml.getparstr("name", (char *)Pname, PART_MAX_NAME_LEN); 1386 xml.getparstr("author", (char *)info.Pauthor, MAX_INFO_TEXT_SIZE); 1387 xml.getparstr("comments", (char *)info.Pcomments, MAX_INFO_TEXT_SIZE); 1388 info.Ptype = xml.getpar("type", info.Ptype, 0, 16); 1389 1390 xml.exitbranch(); 1391 } 1392 1393 if(xml.enterbranch("INSTRUMENT_KIT")) { 1394 Pkitmode = xml.getpar127("kit_mode", Pkitmode); 1395 Pdrummode = xml.getparbool("drum_mode", Pdrummode); 1396 1397 setkititemstatus(0, 0); 1398 for(int i = 0; i < NUM_KIT_ITEMS; ++i) { 1399 if(xml.enterbranch("INSTRUMENT_KIT_ITEM", i) == 0) 1400 continue; 1401 setkititemstatus(i, xml.getparbool("enabled", kit[i].Penabled)); 1402 // if(kit[i].Penabled == 0) { // Remove this as it loses data that may be in the xml file but disabled! 1403 // xml.exitbranch(); 1404 // continue; 1405 // } 1406 1407 xml.getparstr("name", (char *)kit[i].Pname, PART_MAX_NAME_LEN); 1408 1409 kit[i].Pmuted = xml.getparbool("muted", kit[i].Pmuted); 1410 kit[i].Pminkey = xml.getpar127("min_key", kit[i].Pminkey); 1411 kit[i].Pmaxkey = xml.getpar127("max_key", kit[i].Pmaxkey); 1412 1413 kit[i].Psendtoparteffect = xml.getpar127( 1414 "send_to_instrument_effect", 1415 kit[i].Psendtoparteffect); 1416 1417 kit[i].Padenabled = xml.getparbool("add_enabled", 1418 kit[i].Padenabled); 1419 if(xml.enterbranch("ADD_SYNTH_PARAMETERS")) { 1420 if(!kit[i].adpars) 1421 kit[i].adpars = new ADnoteParameters(synth, fft, &time); 1422 kit[i].adpars->getfromXML(xml); 1423 xml.exitbranch(); 1424 } 1425 1426 kit[i].Psubenabled = xml.getparbool("sub_enabled", 1427 kit[i].Psubenabled); 1428 if(xml.enterbranch("SUB_SYNTH_PARAMETERS")) { 1429 if(!kit[i].subpars) 1430 kit[i].subpars = new SUBnoteParameters(&time); 1431 kit[i].subpars->getfromXML(xml); 1432 xml.exitbranch(); 1433 } 1434 1435 kit[i].Ppadenabled = xml.getparbool("pad_enabled", 1436 kit[i].Ppadenabled); 1437 if(xml.enterbranch("PAD_SYNTH_PARAMETERS")) { 1438 if(!kit[i].padpars) 1439 kit[i].padpars = new PADnoteParameters(synth, fft, &time); 1440 kit[i].padpars->getfromXML(xml); 1441 xml.exitbranch(); 1442 } 1443 1444 xml.exitbranch(); 1445 } 1446 1447 xml.exitbranch(); 1448 } 1449 1450 1451 if(xml.enterbranch("INSTRUMENT_EFFECTS")) { 1452 for(int nefx = 0; nefx < NUM_PART_EFX; ++nefx) { 1453 if(xml.enterbranch("INSTRUMENT_EFFECT", nefx) == 0) 1454 continue; 1455 if(xml.enterbranch("EFFECT")) { 1456 partefx[nefx]->getfromXML(xml); 1457 xml.exitbranch(); 1458 } 1459 1460 Pefxroute[nefx] = xml.getpar("route", 1461 Pefxroute[nefx], 1462 0, 1463 NUM_PART_EFX); 1464 if(Pefxroute[nefx]>2) // fix for broken savefiles 1465 Pefxroute[nefx]=2; 1466 partefx[nefx]->setdryonly(Pefxroute[nefx] == 2); 1467 Pefxbypass[nefx] = xml.getparbool("bypass", Pefxbypass[nefx]); 1468 xml.exitbranch(); 1469 } 1470 xml.exitbranch(); 1471 } 1472 } 1473 1474 void Part::getfromXML(XMLwrapper& xml) 1475 { 1476 Penabled = xml.getparbool("enabled", Penabled); 1477 if (xml.hasparreal("volume")) { 1478 setVolumedB(xml.getparreal("volume", Volume)); 1479 } else { 1480 setVolumedB(volume127TodB( xml.getpar127("volume", 96))); 1481 } 1482 setPpanning(xml.getpar127("panning", Ppanning)); 1483 1484 Pminkey = xml.getpar127("min_key", Pminkey); 1485 Pmaxkey = xml.getpar127("max_key", Pmaxkey); 1486 Pkeyshift = xml.getpar127("key_shift", Pkeyshift); 1487 Prcvchn = xml.getpar127("rcv_chn", Prcvchn); 1488 1489 Pvelsns = xml.getpar127("velocity_sensing", Pvelsns); 1490 Pveloffs = xml.getpar127("velocity_offset", Pveloffs); 1491 1492 Pnoteon = xml.getparbool("note_on", Pnoteon); 1493 Ppolymode = xml.getparbool("poly_mode", Ppolymode); 1494 Plegatomode = xml.getparbool("legato_mode", Plegatomode); //older versions 1495 if(!Plegatomode) 1496 Plegatomode = xml.getpar127("legato_mode", Plegatomode); 1497 int keylimit_max = std::atoi(ports["Pkeylimit"]->meta()["max"]); 1498 Pkeylimit = std::min(keylimit_max, xml.getpar127("key_limit", Pkeylimit)); 1499 Pvoicelimit = xml.getpar127("voice_limit", Pvoicelimit); 1500 1501 1502 if(xml.enterbranch("INSTRUMENT")) { 1503 getfromXMLinstrument(xml); 1504 xml.exitbranch(); 1505 } 1506 1507 if(xml.enterbranch("CONTROLLER")) { 1508 const bool upgrade_3_0_7 = (xml.fileversion() < version_type(3,0,7)); 1509 1510 ctl.getfromXML(xml); 1511 // Before version 3.0.7, mono and legato modes always had auto 1512 // portamento (and poly mode never did, but in that case 1513 // portamento.automode will default to off, so no need to do anything 1514 // here). 1515 if (upgrade_3_0_7 && !Ppolymode) 1516 ctl.portamento.automode = 1; 1517 xml.exitbranch(); 1518 } 1519 } 1520 1521 bool Part::Kit::active(void) const 1522 { 1523 return Padenabled || Psubenabled || Ppadenabled; 1524 } 1525 1526 uint8_t Part::Kit::sendto(void) const 1527 { 1528 return limit((int)Psendtoparteffect, 0, NUM_PART_EFX); 1529 1530 } 1531 1532 bool Part::Kit::validNote(char note) const 1533 { 1534 return !Pmuted && Penabled && inRange((uint8_t)note, Pminkey, Pmaxkey); 1535 } 1536 1537 }