PADnoteParameters.cpp (45779B)
1 /* 2 ZynAddSubFX - a software synthesizer 3 4 PADnoteParameters.cpp - Parameters for PADnote (PADsynth) 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 #include <limits> 14 #include <cmath> 15 #include "PADnoteParameters.h" 16 #include "FilterParams.h" 17 #include "EnvelopeParams.h" 18 #include "LFOParams.h" 19 #include "../Synth/Resonance.h" 20 #include "../Synth/OscilGen.h" 21 #include "../Misc/WavFile.h" 22 #include "../Misc/Time.h" 23 #include <cstdio> 24 #include <thread> 25 26 #include <rtosc/ports.h> 27 #include <rtosc/port-sugar.h> 28 using namespace rtosc; 29 30 namespace zyn { 31 32 #define rObject PADnoteParameters 33 #undef rChangeCb 34 #define rChangeCb if (obj->time) { obj->last_update_timestamp = obj->time->time(); } 35 static const rtosc::Ports realtime_ports = 36 { 37 rRecurp(FreqLfo, "Frequency LFO"), 38 rRecurp(AmpLfo, "Amplitude LFO"), 39 rRecurp(FilterLfo, "Filter LFO"), 40 rRecurp(FreqEnvelope, "Frequency Envelope"), 41 rRecurp(AmpEnvelope, "Amplitude Envelope"), 42 rRecurp(FilterEnvelope, "Filter Envelope"), 43 rRecurp(GlobalFilter, "Post Filter"), 44 45 //Volume 46 rToggle(PStereo, rShort("stereo"), rDefault(true), "Stereo/Mono Mode"), 47 rParamZyn(PPanning, rShort("panning"), rDefault(64), "Left Right Panning"), 48 rParamZyn(PVolume, rShort("vol"), rDefault(90), "Synth Volume"), 49 rParamZyn(PAmpVelocityScaleFunction, rShort("sense"), rDefault(64), 50 "Amplitude Velocity Sensing function"), 51 52 rParamZyn(Fadein_adjustment, rShort("a.pop."), 53 rDefault(FADEIN_ADJUSTMENT_SCALE), "Adjustment for anti-pop strategy."), 54 55 //Punch 56 rParamZyn(PPunchStrength, rShort("strength"), rDefault(0), 57 "Punch Strength"), 58 rParamZyn(PPunchTime, rShort("time"), rDefault(60), 59 "Length of punch"), 60 rParamZyn(PPunchStretch, rShort("stretch"), rDefault(64), 61 "How Punch changes with note frequency"), 62 rParamZyn(PPunchVelocitySensing, rShort("sense"), rDefault(72), 63 "Punch Velocity control"), 64 65 //Filter 66 rParamZyn(PFilterVelocityScale, rShort("scale"), rDefault(0), 67 "Filter Velocity Magnitude"), 68 rParamZyn(PFilterVelocityScaleFunction, rShort("sense"), rDefault(64), 69 "Filter Velocity Function Shape"), 70 71 //Freq 72 rToggle(Pfixedfreq, rShort("fixed"), rDefault(false), 73 "Base frequency fixed frequency enable"), 74 rParamZyn(PfixedfreqET, rShort("f.ET"), rDefault(0), 75 "Equal temeperate control for fixed frequency operation"), 76 rParamZyn(PBendAdjust, rDefault(88), 77 "Pitch bend adjustment"), 78 rParamZyn(POffsetHz, rShort("offset"), rDefault(64), 79 "Voice constant offset"), 80 rParamI(PDetune, rShort("fine"), rLinear(0, 16383), rDefault(8192), 81 "Fine Detune"), 82 rParamI(PCoarseDetune, rShort("coarse"), rDefault(0), "Coarse Detune"), 83 rOption(PDetuneType, rShort("type"), 84 rOptions(L35cents, L10cents, E100cents, E1200cents), 85 rDefault(L10cents), "Magnitude of Detune"), 86 87 {"sample#64:ifb", rProp(internal) rDoc("Nothing to see here"), 0, 88 [](const char *m, rtosc::RtData &d) 89 { 90 // MiddleWare calls this to send the generated sample buffers to us 91 assert(rtosc_argument(m,2).b.len == sizeof(void*)); 92 PADnoteParameters *p = (PADnoteParameters*)d.obj; 93 const char *mm = m; 94 while(!isdigit(*mm))++mm; 95 int n = atoi(mm); 96 float *oldsmp = p->sample[n].smp; 97 p->sample[n].size = rtosc_argument(m,0).i; 98 p->sample[n].basefreq = rtosc_argument(m,1).f; 99 p->sample[n].smp = *(float**)rtosc_argument(m,2).b.data; 100 if (oldsmp) 101 d.reply("/free", "sb", "PADsample", sizeof(void*), &oldsmp); 102 }}, 103 //weird stuff for PCoarseDetune 104 {"detunevalue:", rMap(unit,cents) rDoc("Get detune value"), NULL, 105 [](const char *, RtData &d) 106 { 107 PADnoteParameters *obj = (PADnoteParameters *)d.obj; 108 d.reply(d.loc, "f", getdetune(obj->PDetuneType, 0, obj->PDetune)); 109 }}, 110 {"octave::c:i", rProp(parameter) rShort("octave") rLinear(-8,7) 111 rDoc("Octave note offset"), NULL, 112 [](const char *msg, RtData &d) 113 { 114 PADnoteParameters *obj = (PADnoteParameters *)d.obj; 115 auto get_octave = [&obj](){ 116 int k=obj->PCoarseDetune/1024; 117 if (k>=8) k-=16; 118 return k; 119 }; 120 if(!rtosc_narguments(msg)) { 121 d.reply(d.loc, "i", get_octave()); 122 } else { 123 int k=(int) rtosc_argument(msg, 0).i; 124 if (k<0) k+=16; 125 obj->PCoarseDetune = k*1024 + obj->PCoarseDetune%1024; 126 d.broadcast(d.loc, "i", get_octave()); 127 } 128 }}, 129 {"coarsedetune::c:i", rProp(parameter) rShort("coarse") rLinear(-64, 63) 130 rDoc("Coarse note detune"), NULL, 131 [](const char *msg, RtData &d) 132 { 133 PADnoteParameters *obj = (PADnoteParameters *)d.obj; 134 auto get_coarse = [&obj](){ 135 int k=obj->PCoarseDetune%1024; 136 if (k>=512) k-=1024; 137 return k; 138 }; 139 if(!rtosc_narguments(msg)) { 140 d.reply(d.loc, "i", get_coarse()); 141 } else { 142 int k=(int) rtosc_argument(msg, 0).i; 143 if (k<0) k+=1024; 144 obj->PCoarseDetune = k + (obj->PCoarseDetune/1024)*1024; 145 d.broadcast(d.loc, "i", get_coarse()); 146 } 147 }}, 148 {"paste:b", rProp(internal) rDoc("paste port"), 0, 149 [](const char *m, rtosc::RtData &d){ 150 rObject &paste = **(rObject **)rtosc_argument(m,0).b.data; 151 rObject &o = *(rObject*)d.obj; 152 o.pasteRT(paste); 153 rObject* ptr = &paste;\ 154 d.reply("/free", "sb", STRINGIFY(rObject), sizeof(rObject*), &ptr);}} 155 156 }; 157 static const rtosc::Ports non_realtime_ports = 158 { 159 rSelf(PADnoteParameters), 160 rPresetType, 161 #undef rDefaultProps 162 #define rDefaultProps rProp(non-realtime) 163 {"paste:b", rProp(internal) rDoc("paste port"), 0, 164 [](const char *m, rtosc::RtData &d){ 165 rObject &paste = **(rObject **)rtosc_argument(m,0).b.data; 166 rObject &o = *(rObject*)d.obj; 167 o.paste(paste); 168 //avoid the match to forward the request along 169 d.matches--; 170 // "/damage" is not replied here yet - this is handled later when 171 // pasting the realtime ports 172 }}, 173 //Harmonic Source Distribution 174 rRecurp(oscilgen, "Oscillator"), 175 rRecurp(resonance, "Resonance"), 176 177 //Harmonic Shape 178 rOption(Pmode, rMap(min, 0), rMap(max, 2), rShort("distribution"), 179 rOptions(bandwidth,discrete,continious), 180 rDefault(bandwidth), 181 "Harmonic Distribution Model"), 182 rOption(Php.base.type, rOptions(Gaussian, Rectangular, Double Exponential), 183 rShort("shape"), rDefault(Gaussian), 184 "Harmonic profile shape"), 185 rParamZyn(Php.base.par1, rShort("warp"), rDefault(80), 186 "Harmonic shape distribution parameter"), 187 rParamZyn(Php.freqmult, rShort("clone"), rDefault(0), 188 "Frequency multiplier on distribution"), 189 rParamZyn(Php.modulator.par1, rShort("p1"), rDefault(0), 190 "Distribution modulator parameter"), 191 rParamZyn(Php.modulator.freq, rShort("freq"), rDefault(30), 192 "Frequency of modulator parameter"), 193 rParamZyn(Php.width, rShort("bandwidth"), rDefault(127), 194 "Width of base harmonic"), 195 rOption(Php.amp.mode, rShort("mode"), 196 rOptions(Sum, Mult, Div1, Div2), rDefault(Sum), 197 "Amplitude harmonic multiplier type"), 198 199 //Harmonic Modulation 200 rOption(Php.amp.type, rShort("mult"), rOptions(Off, Gauss, Sine, Flat), 201 rDefault(Off), "Type of amplitude multiplier"), 202 rParamZyn(Php.amp.par1, rShort("p1"), rDefault(80), 203 "Amplitude multiplier parameter"), 204 rParamZyn(Php.amp.par2, rShort("p2"), rDefault(64), 205 "Amplitude multiplier parameter"), 206 rToggle(Php.autoscale, rShort("auto"), rDefault(true), 207 "Autoscaling Harmonics"), 208 rOption(Php.onehalf, rShort("side"), 209 rOptions(Full, Upper Half, Lower Half), rDefault(Full), 210 "Harmonic cutoff model"), 211 212 //Harmonic Bandwidth 213 rOption(Pbwscale, rShort("bw scale"), 214 rOptions(Normal, 215 EqualHz, Quarter, 216 Half, 75%, 150%, 217 Double, Inv. Half), 218 rDefault(Normal), 219 "Bandwidth scaling"), 220 221 //Harmonic Position Modulation 222 rOption(Phrpos.type, 223 rOptions(Harmonic, ShiftU, ShiftL, PowerU, PowerL, Sine, 224 Power, Shift), 225 rDefault(Harmonic), 226 "Harmonic Overtone shifting mode"), 227 rParamI(Phrpos.par1, rShort("p1"), rLinear(0,255), rDefault(0), 228 "Harmonic position parameter"), 229 rParamI(Phrpos.par2, rShort("p2"), rLinear(0,255), rDefault(0), 230 "Harmonic position parameter"), 231 rParamI(Phrpos.par3, rShort("force h."), rLinear(0,255), rDefault(0), 232 "Harmonic position parameter"), 233 234 //Quality 235 rOption(Pquality.samplesize, rShort("quality"), 236 rOptions(16k (Tiny), 32k, 64k (Small), 128k, 237 256k (Normal), 512k, 1M (Big)), 238 rDefaultId(128k), 239 "Size of each wavetable element"), 240 rOption(Pquality.basenote, rShort("basenote"), 241 rOptions(C-2, G-2, C-3, G-3, C-4, 242 G-4, C-5, G-5, G-6,), 243 rDefaultId(C-4), 244 "Base note for wavetable"), 245 rOption(Pquality.smpoct, rShort("smp/oct"), 246 rOptions(0.5, 1, 2, 3, 4, 6, 12), 247 rDefault(2), 248 "Samples per octave"), 249 rParamI(Pquality.oct, rShort("octaves"), rLinear(0,7), rDefault(3), 250 "Number of octaves to sample (above the first sample"), 251 #undef rDefaultProps 252 #define rDefaultProps 253 254 {"Pbandwidth::i", rShort("bandwidth") rProp(parameter) rProp(non-realtime) rLinear(0,1000) 255 rDefault(500) rDoc("Bandwidth Of Harmonics"), NULL, 256 [](const char *msg, rtosc::RtData &d) { 257 PADnoteParameters *p = ((PADnoteParameters*)d.obj); 258 if(rtosc_narguments(msg)) { 259 p->setPbandwidth(rtosc_argument(msg, 0).i); 260 d.broadcast(d.loc, "i", p->Pbandwidth); 261 } else { 262 d.reply(d.loc, "i", p->Pbandwidth); 263 }}}, 264 265 {"bandwidthvalue:", rProp(non-realtime) rMap(unit, cents) rDoc("Get Bandwidth"), NULL, 266 [](const char *, rtosc::RtData &d) { 267 PADnoteParameters *p = ((PADnoteParameters*)d.obj); 268 d.reply(d.loc, "f", p->setPbandwidth(p->Pbandwidth)); 269 }}, 270 271 272 {"nhr:", rProp(non-realtime) rDoc("Returns the harmonic shifts"), 273 NULL, [](const char *, rtosc::RtData &d) { 274 PADnoteParameters *p = ((PADnoteParameters*)d.obj); 275 const unsigned n = p->synth.oscilsize / 2; 276 float *tmp = new float[n]; 277 *tmp = 0; 278 for(unsigned i=1; i<n; ++i) 279 tmp[i] = p->getNhr(i); 280 d.reply(d.loc, "b", n*sizeof(float), tmp); 281 delete[] tmp;}}, 282 {"profile:i", rProp(non-realtime) rDoc("UI display of the harmonic profile"), 283 NULL, [](const char *m, rtosc::RtData &d) { 284 PADnoteParameters *p = ((PADnoteParameters*)d.obj); 285 const int n = rtosc_argument(m, 0).i; 286 if(n<=0) 287 return; 288 float *tmp = new float[n]; 289 float realbw = p->getprofile(tmp, n); 290 d.reply(d.loc, "b", n*sizeof(float), tmp); 291 d.reply(d.loc, "i", (int)realbw); 292 delete[] tmp;}}, 293 {"harmonic_profile:", rProp(non-realtime) rDoc("UI display of the harmonic profile"), 294 NULL, [](const char *, rtosc::RtData &d) { 295 PADnoteParameters *p = ((PADnoteParameters*)d.obj); 296 #define RES 512 297 char types[RES+2] = {}; 298 rtosc_arg_t args[RES+1]; 299 float tmp[RES]; 300 types[0] = 'f'; 301 args[0].f = p->getprofile(tmp, RES); 302 for(int i=0; i<RES; ++i) { 303 types[i+1] = 'f'; 304 args[i+1].f = tmp[i]; 305 } 306 d.replyArray(d.loc, types, args); 307 #undef RES 308 }}, 309 {"export2wav:s", rDoc("Export padsynth waveforms to .wav files"), 310 NULL, [](const char *m, rtosc::RtData&d) { 311 PADnoteParameters *p = ((PADnoteParameters*)d.obj); 312 p->export2wav(rtosc_argument(m, 0).s); 313 }}, 314 {"needPrepare:", rDoc("Unimplemented Stub"), 315 NULL, [](const char *, rtosc::RtData&) {}}, 316 }; 317 #undef rDefaultProps 318 #undef rChangeCb 319 320 const rtosc::Ports &PADnoteParameters::non_realtime_ports = zyn::non_realtime_ports; 321 const rtosc::Ports &PADnoteParameters::realtime_ports = zyn::realtime_ports; 322 323 324 const rtosc::MergePorts PADnoteParameters::ports = 325 { 326 &realtime_ports, 327 &non_realtime_ports 328 }; 329 330 331 PADnoteParameters::PADnoteParameters(const SYNTH_T &synth_, FFTwrapper *fft_, 332 const AbsTime *time_) 333 : Presets(), time(time_), last_update_timestamp(0), synth(synth_) 334 { 335 setpresettype("Ppadsynth"); 336 337 resonance = new Resonance(); 338 oscilgen = new OscilGen(synth, fft_, resonance); 339 oscilgen->ADvsPAD = true; 340 341 FreqEnvelope = new EnvelopeParams(0, 0, time_); 342 FreqEnvelope->init(ad_global_freq); 343 FreqLfo = new LFOParams(ad_global_freq, time_); 344 345 AmpEnvelope = new EnvelopeParams(64, 1, time_); 346 AmpEnvelope->init(ad_global_amp); 347 AmpLfo = new LFOParams(ad_global_amp, time_); 348 349 GlobalFilter = new FilterParams(ad_global_filter, time_); 350 FilterEnvelope = new EnvelopeParams(0, 1, time_); 351 FilterEnvelope->init(ad_global_filter); 352 FilterLfo = new LFOParams(ad_global_filter, time_); 353 354 for(int i = 0; i < PAD_MAX_SAMPLES; ++i) 355 sample[i].smp = NULL; 356 357 defaults(); 358 } 359 360 PADnoteParameters::~PADnoteParameters() 361 { 362 deletesamples(); 363 delete (oscilgen); 364 delete (resonance); 365 366 delete (FreqEnvelope); 367 delete (FreqLfo); 368 delete (AmpEnvelope); 369 delete (AmpLfo); 370 delete (GlobalFilter); 371 delete (FilterEnvelope); 372 delete (FilterLfo); 373 } 374 375 void PADnoteParameters::defaults() 376 { 377 Pmode = pad_mode::bandwidth; 378 Php.base.type = 0; 379 Php.base.par1 = 80; 380 Php.freqmult = 0; 381 Php.modulator.par1 = 0; 382 Php.modulator.freq = 30; 383 Php.width = 127; 384 Php.amp.type = 0; 385 Php.amp.mode = 0; 386 Php.amp.par1 = 80; 387 Php.amp.par2 = 64; 388 Php.autoscale = true; 389 Php.onehalf = 0; 390 391 setPbandwidth(500); 392 Pbwscale = 0; 393 394 resonance->defaults(); 395 oscilgen->defaults(); 396 397 Phrpos.type = 0; 398 Phrpos.par1 = 0; 399 Phrpos.par2 = 0; 400 Phrpos.par3 = 0; 401 402 Pquality.samplesize = 3; 403 Pquality.basenote = 4; 404 Pquality.oct = 3; 405 Pquality.smpoct = 2; 406 407 PStereo = 1; //stereo 408 /* Frequency Global Parameters */ 409 Pfixedfreq = 0; 410 PfixedfreqET = 0; 411 PBendAdjust = 88; // 64 + 24 412 POffsetHz = 64; 413 PDetune = 8192; //zero 414 PCoarseDetune = 0; 415 PDetuneType = 1; 416 FreqEnvelope->defaults(); 417 FreqLfo->defaults(); 418 419 /* Amplitude Global Parameters */ 420 PVolume = 90; 421 PPanning = 64; //center 422 PAmpVelocityScaleFunction = 64; 423 AmpEnvelope->defaults(); 424 AmpLfo->defaults(); 425 Fadein_adjustment = FADEIN_ADJUSTMENT_SCALE; 426 PPunchStrength = 0; 427 PPunchTime = 60; 428 PPunchStretch = 64; 429 PPunchVelocitySensing = 72; 430 431 /* Filter Global Parameters*/ 432 PFilterVelocityScale = 0; 433 PFilterVelocityScaleFunction = 64; 434 GlobalFilter->defaults(); 435 FilterEnvelope->defaults(); 436 FilterLfo->defaults(); 437 438 deletesamples(); 439 } 440 441 void PADnoteParameters::deletesample(int n) 442 { 443 if((n < 0) || (n >= PAD_MAX_SAMPLES)) 444 return; 445 446 delete[] sample[n].smp; 447 sample[n].smp = NULL; 448 sample[n].size = 0; 449 sample[n].basefreq = 440.0f; 450 } 451 452 void PADnoteParameters::deletesamples() 453 { 454 for(int i = 0; i < PAD_MAX_SAMPLES; ++i) 455 deletesample(i); 456 } 457 458 /* 459 * Get the harmonic profile (i.e. the frequency distributio of a single harmonic) 460 */ 461 float PADnoteParameters::getprofile(float *smp, int size) 462 { 463 for(int i = 0; i < size; ++i) 464 smp[i] = 0.0f; 465 const int supersample = 16; 466 float basepar = powf(2.0f, (1.0f - Php.base.par1 / 127.0f) * 12.0f); 467 float freqmult = floorf(powf(2.0f, 468 Php.freqmult / 127.0f 469 * 5.0f) + 0.000001f); 470 471 float modfreq = floorf(powf(2.0f, 472 Php.modulator.freq / 127.0f 473 * 5.0f) + 0.000001f); 474 float modpar1 = powf(Php.modulator.par1 / 127.0f, 4.0f) * 5.0f / sqrtf( 475 modfreq); 476 float amppar1 = 477 powf(2.0f, powf(Php.amp.par1 / 127.0f, 2.0f) * 10.0f) - 0.999f; 478 float amppar2 = (1.0f - Php.amp.par2 / 127.0f) * 0.998f + 0.001f; 479 float width = powf(150.0f / (Php.width + 22.0f), 2.0f); 480 481 for(int i = 0; i < size * supersample; ++i) { 482 bool makezero = false; 483 float x = i * 1.0f / (size * (float) supersample); 484 485 float origx = x; 486 487 //do the sizing (width) 488 x = (x - 0.5f) * width + 0.5f; 489 if(x < 0.0f) { 490 x = 0.0f; 491 makezero = true; 492 } 493 else 494 if(x > 1.0f) { 495 x = 1.0f; 496 makezero = true; 497 } 498 499 //compute the full profile or one half 500 switch(Php.onehalf) { 501 case 1: 502 x = x * 0.5f + 0.5f; 503 break; 504 case 2: 505 x = x * 0.5f; 506 break; 507 } 508 509 float x_before_freq_mult = x; 510 511 //do the frequency multiplier 512 x *= freqmult; 513 514 //do the modulation of the profile 515 x += sinf(x_before_freq_mult * 3.1415926f * modfreq) * modpar1; 516 x = fmodf(x + 1000.0f, 1.0f) * 2.0f - 1.0f; 517 518 519 //this is the base function of the profile 520 float f; 521 switch(Php.base.type) { 522 case 1: 523 f = expf(-(x * x) * basepar); 524 if(f < 0.4f) 525 f = 0.0f; 526 else 527 f = 1.0f; 528 break; 529 case 2: 530 f = expf(-(fabsf(x)) * sqrtf(basepar)); 531 break; 532 default: 533 f = expf(-(x * x) * basepar); 534 break; 535 } 536 if(makezero) 537 f = 0.0f; 538 539 float amp = 1.0f; 540 origx = origx * 2.0f - 1.0f; 541 542 //compute the amplitude multiplier 543 switch(Php.amp.type) { 544 case 1: 545 amp = expf(-(origx * origx) * 10.0f * amppar1); 546 break; 547 case 2: 548 amp = 0.5f 549 * (1.0f 550 + cosf(3.1415926f * origx * sqrtf(amppar1 * 4.0f + 1.0f))); 551 break; 552 case 3: 553 amp = 1.0f 554 / (powf(origx * (amppar1 * 2.0f + 0.8f), 14.0f) + 1.0f); 555 break; 556 } 557 558 //apply the amplitude multiplier 559 float finalsmp = f; 560 if(Php.amp.type != 0) { 561 switch(Php.amp.mode) { 562 case 0: 563 finalsmp = amp * (1.0f - amppar2) + finalsmp * amppar2; 564 break; 565 case 1: 566 finalsmp *= amp * (1.0f - amppar2) + amppar2; 567 break; 568 case 2: 569 finalsmp = finalsmp 570 / (amp + powf(amppar2, 4.0f) * 20.0f + 0.0001f); 571 break; 572 case 3: 573 finalsmp = amp 574 / (finalsmp 575 + powf(amppar2, 4.0f) * 20.0f + 0.0001f); 576 break; 577 } 578 } 579 580 smp[i / supersample] += finalsmp / supersample; 581 } 582 583 //normalize the profile (make the max. to be equal to 1.0f) 584 float max = 0.0f; 585 for(int i = 0; i < size; ++i) { 586 if(smp[i] < 0.0f) 587 smp[i] = 0.0f; 588 if(smp[i] > max) 589 max = smp[i]; 590 } 591 if(max < 0.00001f) 592 max = 1.0f; 593 for(int i = 0; i < size; ++i) 594 smp[i] /= max; 595 596 if(!Php.autoscale) 597 return 0.5f; 598 599 //compute the estimated perceived bandwidth 600 float sum = 0.0f; 601 int i; 602 for(i = 0; i < size / 2 - 2; ++i) { 603 sum += smp[i] * smp[i] + smp[size - i - 1] * smp[size - i - 1]; 604 if(sum >= 4.0f) 605 break; 606 } 607 608 float result = 1.0f - 2.0f * i / (float) size; 609 return result; 610 } 611 612 /* 613 * Compute the real bandwidth in cents and returns it 614 * Also, sets the bandwidth parameter 615 */ 616 float PADnoteParameters::setPbandwidth(int Pbandwidth) 617 { 618 this->Pbandwidth = Pbandwidth; 619 float result = powf(Pbandwidth / 1000.0f, 1.1f); 620 result = powf(10.0f, result * 4.0f) * 0.25f; 621 return result; 622 } 623 624 /* 625 * Get the harmonic(overtone) position 626 */ 627 float PADnoteParameters::getNhr(int n) const 628 { 629 float result = 1.0f; 630 const float par1 = powf(10.0f, -(1.0f - Phrpos.par1 / 255.0f) * 3.0f); 631 const float par2 = Phrpos.par2 / 255.0f; 632 633 const float n0 = n - 1.0f; 634 float tmp = 0.0f; 635 int thresh = 0; 636 switch(Phrpos.type) { 637 case 1: 638 thresh = (int)(par2 * par2 * 100.0f) + 1; 639 if(n < thresh) 640 result = n; 641 else 642 result = 1.0f + n0 + (n0 - thresh + 1.0f) * par1 * 8.0f; 643 break; 644 case 2: 645 thresh = (int)(par2 * par2 * 100.0f) + 1; 646 if(n < thresh) 647 result = n; 648 else 649 result = 1.0f + n0 - (n0 - thresh + 1.0f) * par1 * 0.90f; 650 break; 651 case 3: 652 tmp = par1 * 100.0f + 1.0f; 653 result = powf(n0 / tmp, 1.0f - par2 * 0.8f) * tmp + 1.0f; 654 break; 655 case 4: 656 result = n0 657 * (1.0f 658 - par1) 659 + powf(n0 * 0.1f, par2 * 3.0f 660 + 1.0f) * par1 * 10.0f + 1.0f; 661 break; 662 case 5: 663 result = n0 664 + sinf(n0 * par2 * par2 * PI 665 * 0.999f) * sqrtf(par1) * 2.0f + 1.0f; 666 break; 667 case 6: 668 tmp = powf(par2 * 2.0f, 2.0f) + 0.1f; 669 result = n0 * powf(1.0f + par1 * powf(n0 * 0.8f, tmp), tmp) + 1.0f; 670 break; 671 case 7: 672 result = (n + Phrpos.par1 / 255.0f) / (Phrpos.par1 / 255.0f + 1); 673 break; 674 default: 675 result = n; 676 break; 677 } 678 679 const float par3 = Phrpos.par3 / 255.0f; 680 681 const float iresult = floorf(result + 0.5f); 682 const float dresult = result - iresult; 683 684 return iresult + (1.0f - par3) * dresult; 685 } 686 687 //Transform non zero positive signals into ones with a max of one 688 static void normalize_max(float *f, size_t len) 689 { 690 float max = 0.0f; 691 for(unsigned i = 0; i < len; ++i) 692 if(f[i] > i) 693 max = f[i]; 694 if(max > 0.000001f) 695 for(unsigned i = 0; i < len; ++i) 696 f[i] /= max; 697 } 698 699 //Translate Bandwidth scale integer into floating point value 700 static float Pbwscale_translate(char Pbwscale) 701 { 702 switch(Pbwscale) { 703 case 0: return 1.0f; 704 case 1: return 0.0f; 705 case 2: return 0.25f; 706 case 3: return 0.5f; 707 case 4: return 0.75f; 708 case 5: return 1.5f; 709 case 6: return 2.0f; 710 case 7: return -0.5f; 711 default: return 1.0; 712 } 713 } 714 715 /* 716 * Generates the long spectrum for Bandwidth mode (only amplitudes are generated; phases will be random) 717 */ 718 719 //Requires 720 // - bandwidth scaling power 721 // - bandwidth 722 // - oscillator harmonics at various frequencies (oodles of data) 723 // - sampled resonance 724 void PADnoteParameters::generatespectrum_bandwidthMode(float *spectrum, 725 int size, 726 float basefreq, 727 const float *profile, 728 int profilesize, 729 float bwadjust) const 730 { 731 float harmonics[synth.oscilsize]; 732 memset(spectrum, 0, sizeof(float) * size); 733 memset(harmonics, 0, sizeof(float) * synth.oscilsize); 734 735 //get the harmonic structure from the oscillator (I am using the frequency amplitudes, only) 736 oscilgen->get(harmonics, basefreq, false); 737 738 //normalize 739 normalize_max(harmonics, synth.oscilsize / 2); 740 741 //Constants across harmonics 742 const float power = Pbwscale_translate(Pbwscale); 743 const float bandwidthcents = const_cast<PADnoteParameters*>(this)->setPbandwidth(Pbandwidth); 744 745 for(int nh = 1; nh < synth.oscilsize / 2; ++nh) { //for each harmonic 746 const float realfreq = getNhr(nh) * basefreq; 747 if(realfreq > synth.samplerate_f * 0.49999f) 748 break; 749 if(realfreq < 20.0f) 750 break; 751 if(harmonics[nh - 1] < 1e-4) 752 continue; 753 754 //compute the bandwidth of each harmonic 755 const float bw = 756 ((powf(2.0f, bandwidthcents / 1200.0f) - 1.0f) * basefreq / bwadjust) 757 * powf(realfreq / basefreq, power); 758 const int ibw = (int)((bw / (synth.samplerate_f * 0.5f) * size)) + 1; 759 760 float amp = harmonics[nh - 1]; 761 if(resonance->Penabled) 762 amp *= resonance->getfreqresponse(realfreq); 763 764 if(ibw > profilesize) { //if the bandwidth is larger than the profilesize 765 const float rap = sqrtf((float)profilesize / (float)ibw); 766 const int cfreq = 767 (int) (realfreq 768 / (synth.samplerate_f * 0.5f) * size) - ibw / 2; 769 for(int i = 0; i < ibw; ++i) { 770 const int src = (int)(i * rap * rap); 771 const int spfreq = i + cfreq; 772 if(spfreq < 0) 773 continue; 774 if(spfreq >= size) 775 break; 776 spectrum[spfreq] += amp * profile[src] * rap; 777 } 778 } 779 else { //if the bandwidth is smaller than the profilesize 780 const float rap = sqrtf((float)ibw / (float)profilesize); 781 const float ibasefreq = realfreq / (synth.samplerate_f * 0.5f) * size; 782 for(int i = 0; i < profilesize; ++i) { 783 const float idfreq = (i / (float)profilesize - 0.5f) * ibw; 784 const float freqsum = idfreq + ibasefreq; 785 const int spfreq = (int)freqsum; 786 const float fspfreq = freqsum - spfreq; 787 if(spfreq <= 0) 788 continue; 789 if(spfreq >= size - 1) 790 break; 791 spectrum[spfreq] += amp * profile[i] * rap 792 * (1.0f - fspfreq); 793 spectrum[spfreq + 1] += amp * profile[i] * rap * fspfreq; 794 } 795 } 796 } 797 } 798 799 /* 800 * Generates the long spectrum for non-Bandwidth modes (only amplitudes are generated; phases will be random) 801 */ 802 void PADnoteParameters::generatespectrum_otherModes(float *spectrum, 803 int size, 804 float basefreq) const 805 { 806 float harmonics[synth.oscilsize]; 807 memset(spectrum, 0, sizeof(float) * size); 808 memset(harmonics, 0, sizeof(float) * synth.oscilsize); 809 810 //get the harmonic structure from the oscillator (I am using the frequency amplitudes, only) 811 oscilgen->get(harmonics, basefreq, false); 812 813 //normalize 814 normalize_max(harmonics, synth.oscilsize / 2); 815 816 for(int nh = 1; nh < synth.oscilsize / 2; ++nh) { //for each harmonic 817 const float realfreq = getNhr(nh) * basefreq; 818 819 //take care of interpolation if frequency decreases 820 if(realfreq > synth.samplerate_f * 0.49999f) 821 break; 822 if(realfreq < 20.0f) 823 break; 824 825 826 float amp = harmonics[nh - 1]; 827 if(resonance->Penabled) 828 amp *= resonance->getfreqresponse(realfreq); 829 const int cfreq = (int)(realfreq / (synth.samplerate_f * 0.5f) * size); 830 831 spectrum[cfreq] = amp + (float)1e-9; 832 } 833 834 //In continous mode the spectrum gets additional interpolation between the 835 //spectral peaks 836 if(Pmode == pad_mode::continous) { //continous mode 837 int old = 0; 838 for(int k = 1; k < size; ++k) 839 if((spectrum[k] > 1e-10) || (k == (size - 1))) { 840 const int delta = k - old; 841 const float val1 = spectrum[old]; 842 const float val2 = spectrum[k]; 843 const float idelta = 1.0f / delta; 844 for(int i = 0; i < delta; ++i) { 845 const float x = idelta * i; 846 spectrum[old + i] = val1 * (1.0f - x) + val2 * x; 847 } 848 old = k; 849 } 850 } 851 } 852 853 /* 854 * Applies the parameters (i.e. computes all the samples, based on parameters); 855 */ 856 void PADnoteParameters::applyparameters() 857 { 858 applyparameters([]{return false;}); 859 } 860 861 void PADnoteParameters::applyparameters(std::function<bool()> do_abort, 862 unsigned max_threads) 863 { 864 if(do_abort()) 865 return; 866 unsigned num = sampleGenerator([this] 867 (unsigned N, PADnoteParameters::Sample&& smp) { 868 delete[] sample[N].smp; 869 sample[N] = std::move(smp); 870 }, 871 do_abort, max_threads); 872 873 //Delete remaining unused samples 874 for(unsigned i = num; i < PAD_MAX_SAMPLES; ++i) 875 deletesample(i); 876 } 877 878 //Requires 879 // - Pquality.samplesize 880 // - Pquality.basenote 881 // - Pquality.oct 882 // - Pquality.smpoct 883 // - spectrum at various frequencies (oodles of data) 884 int PADnoteParameters::sampleGenerator(PADnoteParameters::callback cb, 885 std::function<bool()> do_abort, 886 unsigned max_threads) 887 { 888 if(!max_threads) 889 max_threads = std::numeric_limits<unsigned>::max(); 890 891 const int samplesize = (((int) 1) << (Pquality.samplesize + 14)); 892 const int spectrumsize = samplesize / 2; 893 const int profilesize = 512; 894 895 float profile[profilesize]; 896 897 898 const float bwadjust = getprofile(profile, profilesize); 899 float basefreq = 65.406f * powf(2.0f, Pquality.basenote / 2); 900 if(Pquality.basenote % 2 == 1) 901 basefreq *= 1.5f; 902 903 int samplemax = Pquality.oct + 1; 904 int smpoct = Pquality.smpoct; 905 if(Pquality.smpoct == 5) 906 smpoct = 6; 907 if(Pquality.smpoct == 6) 908 smpoct = 12; 909 if(smpoct != 0) 910 samplemax *= smpoct; 911 else 912 samplemax = samplemax / 2 + 1; 913 if(samplemax == 0) 914 samplemax = 1; 915 916 if(samplemax > PAD_MAX_SAMPLES) 917 samplemax = PAD_MAX_SAMPLES; 918 919 //this is used to compute frequency relation to the base frequency 920 float adj[samplemax]; 921 for(int nsample = 0; nsample < samplemax; ++nsample) 922 adj[nsample] = (Pquality.oct + 1.0f) * (float)nsample / samplemax; 923 // QtCreator can't capture VLAs (QTCREATORBUG-23722), so this is 924 // a workaround to allow using the IDE 925 float * const adj_ptr = adj; 926 927 const PADnoteParameters* this_c = this; 928 929 auto thread_cb = [basefreq, bwadjust, &cb, do_abort, 930 samplesize, samplemax, spectrumsize, 931 adj_ptr, &profile, this_c]( 932 unsigned nthreads, unsigned threadno) 933 { 934 //prepare a BIG IFFT 935 FFTwrapper *fft = new FFTwrapper(samplesize); 936 FFTfreqBuffer fftfreqs = fft->allocFreqBuf(); 937 float *spectrum = new float[spectrumsize]; 938 939 for(int nsample = 0; nsample < samplemax; ++nsample) 940 if(nsample % nthreads == threadno) 941 { 942 if(do_abort()) 943 break; 944 const float basefreqadjust = 945 powf(2.0f, adj_ptr[nsample] - adj_ptr[samplemax - 1] * 0.5f); 946 947 if(this_c->Pmode == pad_mode::bandwidth) 948 this_c->generatespectrum_bandwidthMode(spectrum, 949 spectrumsize, 950 basefreq*basefreqadjust, 951 profile, 952 profilesize, 953 bwadjust); 954 else 955 this_c->generatespectrum_otherModes(spectrum, spectrumsize, 956 basefreq * basefreqadjust); 957 958 //the last samples contain the first samples 959 //(used for linear/cubic interpolation) 960 const int extra_samples = 5; 961 PADnoteParameters::Sample newsample; 962 newsample.smp = new float[samplesize + extra_samples]; 963 964 newsample.smp[0] = 0.0f; 965 fftfreqs[0] = fft_t(0, 0); 966 for(int i = 1; i < spectrumsize; ++i) //randomize the phases 967 fftfreqs[i] = FFTpolar(spectrum[i], (float)RND * 2 * PI); 968 //that's all; here is the only ifft for the whole sample; 969 //no windows are used ;-) 970 fft->freqs2smps_noconst_input(fftfreqs, fft->allocSampleBuf(newsample.smp)); 971 972 //normalize(rms) 973 float rms = 0.0f; 974 for(int i = 0; i < samplesize; ++i) 975 rms += newsample.smp[i] * newsample.smp[i]; 976 rms = sqrtf(rms); 977 if(rms < 0.000001f) 978 rms = 1.0f; 979 rms *= sqrtf(262144.0f / samplesize);//262144=2^18 980 for(int i = 0; i < samplesize; ++i) 981 newsample.smp[i] *= 1.0f / rms * 50.0f; 982 983 //prepare extra samples used by the linear or cubic interpolation 984 for(int i = 0; i < extra_samples; ++i) 985 newsample.smp[i + samplesize] = newsample.smp[i]; 986 987 //yield new sample 988 newsample.size = samplesize; 989 newsample.basefreq = basefreq * basefreqadjust; 990 cb(nsample, std::move(newsample)); 991 } 992 993 //Cleanup 994 delete (fft); 995 delete[] fftfreqs.data; 996 delete[] spectrum; 997 }; 998 999 if(oscilgen->needPrepare()) 1000 oscilgen->prepare(); 1001 1002 #ifdef WIN32 1003 //Temporarily disable multi-threading here as C++11 threads are broken on 1004 //mingw cross compilation 1005 thread_cb(1,0); 1006 #else 1007 unsigned nthreads = std::min(max_threads, 1008 std::thread::hardware_concurrency()); 1009 std::vector<std::thread> threads(nthreads); 1010 for(unsigned i = 0; i < nthreads; ++i) 1011 threads[i] = std::thread(thread_cb, nthreads, i); 1012 for(unsigned i = 0; i < nthreads; ++i) 1013 threads[i].join(); 1014 #endif 1015 1016 return samplemax; 1017 } 1018 1019 void PADnoteParameters::export2wav(std::string basefilename) 1020 { 1021 applyparameters(); 1022 basefilename += "_PADsynth_"; 1023 for(int k = 0; k < PAD_MAX_SAMPLES; ++k) { 1024 if(sample[k].smp == NULL) 1025 continue; 1026 char tmpstr[20]; 1027 snprintf(tmpstr, 20, "_%02d", k + 1); 1028 std::string filename = basefilename + std::string(tmpstr) + ".wav"; 1029 WavFile wav(filename, synth.samplerate, 1); 1030 if(wav.good()) { 1031 int nsmps = sample[k].size; 1032 short int *smps = new short int[nsmps]; 1033 for(int i = 0; i < nsmps; ++i) 1034 smps[i] = (short int)(sample[k].smp[i] * 32767.0f); 1035 wav.writeMonoSamples(nsmps, smps); 1036 } 1037 } 1038 } 1039 1040 void PADnoteParameters::add2XML(XMLwrapper& xml) 1041 { 1042 xml.setPadSynth(true); 1043 1044 xml.addparbool("stereo", PStereo); 1045 xml.addpar("mode", (int)Pmode); 1046 xml.addpar("bandwidth", Pbandwidth); 1047 xml.addpar("bandwidth_scale", Pbwscale); 1048 1049 xml.beginbranch("HARMONIC_PROFILE"); 1050 xml.addpar("base_type", Php.base.type); 1051 xml.addpar("base_par1", Php.base.par1); 1052 xml.addpar("frequency_multiplier", Php.freqmult); 1053 xml.addpar("modulator_par1", Php.modulator.par1); 1054 xml.addpar("modulator_frequency", Php.modulator.freq); 1055 xml.addpar("width", Php.width); 1056 xml.addpar("amplitude_multiplier_type", Php.amp.type); 1057 xml.addpar("amplitude_multiplier_mode", Php.amp.mode); 1058 xml.addpar("amplitude_multiplier_par1", Php.amp.par1); 1059 xml.addpar("amplitude_multiplier_par2", Php.amp.par2); 1060 xml.addparbool("autoscale", Php.autoscale); 1061 xml.addpar("one_half", Php.onehalf); 1062 xml.endbranch(); 1063 1064 xml.beginbranch("OSCIL"); 1065 oscilgen->add2XML(xml); 1066 xml.endbranch(); 1067 1068 xml.beginbranch("RESONANCE"); 1069 resonance->add2XML(xml); 1070 xml.endbranch(); 1071 1072 xml.beginbranch("HARMONIC_POSITION"); 1073 xml.addpar("type", Phrpos.type); 1074 xml.addpar("parameter1", Phrpos.par1); 1075 xml.addpar("parameter2", Phrpos.par2); 1076 xml.addpar("parameter3", Phrpos.par3); 1077 xml.endbranch(); 1078 1079 xml.beginbranch("SAMPLE_QUALITY"); 1080 xml.addpar("samplesize", Pquality.samplesize); 1081 xml.addpar("basenote", Pquality.basenote); 1082 xml.addpar("octaves", Pquality.oct); 1083 xml.addpar("samples_per_octave", Pquality.smpoct); 1084 xml.endbranch(); 1085 1086 xml.beginbranch("AMPLITUDE_PARAMETERS"); 1087 xml.addpar("volume", PVolume); 1088 xml.addpar("panning", PPanning); 1089 xml.addpar("velocity_sensing", PAmpVelocityScaleFunction); 1090 xml.addpar("fadein_adjustment", Fadein_adjustment); 1091 xml.addpar("punch_strength", PPunchStrength); 1092 xml.addpar("punch_time", PPunchTime); 1093 xml.addpar("punch_stretch", PPunchStretch); 1094 xml.addpar("punch_velocity_sensing", PPunchVelocitySensing); 1095 1096 xml.beginbranch("AMPLITUDE_ENVELOPE"); 1097 AmpEnvelope->add2XML(xml); 1098 xml.endbranch(); 1099 1100 xml.beginbranch("AMPLITUDE_LFO"); 1101 AmpLfo->add2XML(xml); 1102 xml.endbranch(); 1103 1104 xml.endbranch(); 1105 1106 xml.beginbranch("FREQUENCY_PARAMETERS"); 1107 xml.addpar("fixed_freq", Pfixedfreq); 1108 xml.addpar("fixed_freq_et", PfixedfreqET); 1109 xml.addpar("bend_adjust", PBendAdjust); 1110 xml.addpar("offset_hz", POffsetHz); 1111 xml.addpar("detune", PDetune); 1112 xml.addpar("coarse_detune", PCoarseDetune); 1113 xml.addpar("detune_type", PDetuneType); 1114 1115 xml.beginbranch("FREQUENCY_ENVELOPE"); 1116 FreqEnvelope->add2XML(xml); 1117 xml.endbranch(); 1118 1119 xml.beginbranch("FREQUENCY_LFO"); 1120 FreqLfo->add2XML(xml); 1121 xml.endbranch(); 1122 xml.endbranch(); 1123 1124 xml.beginbranch("FILTER_PARAMETERS"); 1125 xml.addpar("velocity_sensing_amplitude", PFilterVelocityScale); 1126 xml.addpar("velocity_sensing", PFilterVelocityScaleFunction); 1127 1128 xml.beginbranch("FILTER"); 1129 GlobalFilter->add2XML(xml); 1130 xml.endbranch(); 1131 1132 xml.beginbranch("FILTER_ENVELOPE"); 1133 FilterEnvelope->add2XML(xml); 1134 xml.endbranch(); 1135 1136 xml.beginbranch("FILTER_LFO"); 1137 FilterLfo->add2XML(xml); 1138 xml.endbranch(); 1139 xml.endbranch(); 1140 } 1141 1142 void PADnoteParameters::getfromXML(XMLwrapper& xml) 1143 { 1144 PStereo = xml.getparbool("stereo", PStereo); 1145 Pmode = (pad_mode)xml.getpar127("mode", 0); 1146 Pbandwidth = xml.getpar("bandwidth", Pbandwidth, 0, 1000); 1147 Pbwscale = xml.getpar127("bandwidth_scale", Pbwscale); 1148 1149 if(xml.enterbranch("HARMONIC_PROFILE")) { 1150 Php.base.type = xml.getpar127("base_type", Php.base.type); 1151 Php.base.par1 = xml.getpar127("base_par1", Php.base.par1); 1152 Php.freqmult = xml.getpar127("frequency_multiplier", 1153 Php.freqmult); 1154 Php.modulator.par1 = xml.getpar127("modulator_par1", 1155 Php.modulator.par1); 1156 Php.modulator.freq = xml.getpar127("modulator_frequency", 1157 Php.modulator.freq); 1158 Php.width = xml.getpar127("width", Php.width); 1159 Php.amp.type = xml.getpar127("amplitude_multiplier_type", 1160 Php.amp.type); 1161 Php.amp.mode = xml.getpar127("amplitude_multiplier_mode", 1162 Php.amp.mode); 1163 Php.amp.par1 = xml.getpar127("amplitude_multiplier_par1", 1164 Php.amp.par1); 1165 Php.amp.par2 = xml.getpar127("amplitude_multiplier_par2", 1166 Php.amp.par2); 1167 Php.autoscale = xml.getparbool("autoscale", Php.autoscale); 1168 Php.onehalf = xml.getpar127("one_half", Php.onehalf); 1169 xml.exitbranch(); 1170 } 1171 1172 if(xml.enterbranch("OSCIL")) { 1173 oscilgen->getfromXML(xml); 1174 xml.exitbranch(); 1175 } 1176 1177 if(xml.enterbranch("RESONANCE")) { 1178 resonance->getfromXML(xml); 1179 xml.exitbranch(); 1180 } 1181 1182 if(xml.enterbranch("HARMONIC_POSITION")) { 1183 Phrpos.type = xml.getpar127("type", Phrpos.type); 1184 Phrpos.par1 = xml.getpar("parameter1", Phrpos.par1, 0, 255); 1185 Phrpos.par2 = xml.getpar("parameter2", Phrpos.par2, 0, 255); 1186 Phrpos.par3 = xml.getpar("parameter3", Phrpos.par3, 0, 255); 1187 xml.exitbranch(); 1188 } 1189 1190 if(xml.enterbranch("SAMPLE_QUALITY")) { 1191 Pquality.samplesize = xml.getpar127("samplesize", Pquality.samplesize); 1192 Pquality.basenote = xml.getpar127("basenote", Pquality.basenote); 1193 Pquality.oct = xml.getpar127("octaves", Pquality.oct); 1194 Pquality.smpoct = xml.getpar127("samples_per_octave", 1195 Pquality.smpoct); 1196 xml.exitbranch(); 1197 } 1198 1199 if(xml.enterbranch("AMPLITUDE_PARAMETERS")) { 1200 PVolume = xml.getpar127("volume", PVolume); 1201 PPanning = xml.getpar127("panning", PPanning); 1202 PAmpVelocityScaleFunction = xml.getpar127("velocity_sensing", 1203 PAmpVelocityScaleFunction); 1204 Fadein_adjustment = xml.getpar127("fadein_adjustment", Fadein_adjustment); 1205 PPunchStrength = xml.getpar127("punch_strength", PPunchStrength); 1206 PPunchTime = xml.getpar127("punch_time", PPunchTime); 1207 PPunchStretch = xml.getpar127("punch_stretch", PPunchStretch); 1208 PPunchVelocitySensing = xml.getpar127("punch_velocity_sensing", 1209 PPunchVelocitySensing); 1210 1211 xml.enterbranch("AMPLITUDE_ENVELOPE"); 1212 AmpEnvelope->getfromXML(xml); 1213 xml.exitbranch(); 1214 1215 xml.enterbranch("AMPLITUDE_LFO"); 1216 AmpLfo->getfromXML(xml); 1217 xml.exitbranch(); 1218 1219 xml.exitbranch(); 1220 } 1221 1222 if(xml.enterbranch("FREQUENCY_PARAMETERS")) { 1223 Pfixedfreq = xml.getpar127("fixed_freq", Pfixedfreq); 1224 PfixedfreqET = xml.getpar127("fixed_freq_et", PfixedfreqET); 1225 PBendAdjust = xml.getpar127("bend_adjust", PBendAdjust); 1226 POffsetHz = xml.getpar127("offset_hz", POffsetHz); 1227 PDetune = xml.getpar("detune", PDetune, 0, 16383); 1228 PCoarseDetune = xml.getpar("coarse_detune", PCoarseDetune, 0, 16383); 1229 PDetuneType = xml.getpar127("detune_type", PDetuneType); 1230 1231 xml.enterbranch("FREQUENCY_ENVELOPE"); 1232 FreqEnvelope->getfromXML(xml); 1233 xml.exitbranch(); 1234 1235 xml.enterbranch("FREQUENCY_LFO"); 1236 FreqLfo->getfromXML(xml); 1237 xml.exitbranch(); 1238 xml.exitbranch(); 1239 } 1240 1241 if(xml.enterbranch("FILTER_PARAMETERS")) { 1242 PFilterVelocityScale = xml.getpar127("velocity_sensing_amplitude", 1243 PFilterVelocityScale); 1244 PFilterVelocityScaleFunction = xml.getpar127( 1245 "velocity_sensing", 1246 PFilterVelocityScaleFunction); 1247 1248 xml.enterbranch("FILTER"); 1249 GlobalFilter->getfromXML(xml); 1250 xml.exitbranch(); 1251 1252 xml.enterbranch("FILTER_ENVELOPE"); 1253 FilterEnvelope->getfromXML(xml); 1254 xml.exitbranch(); 1255 1256 xml.enterbranch("FILTER_LFO"); 1257 FilterLfo->getfromXML(xml); 1258 xml.exitbranch(); 1259 xml.exitbranch(); 1260 } 1261 } 1262 1263 #define COPY(y) this->y = x.y 1264 void PADnoteParameters::paste(PADnoteParameters &x) 1265 { 1266 COPY(Pmode); 1267 1268 COPY(Php.base.type); 1269 COPY(Php.base.par1); 1270 COPY(Php.freqmult); 1271 COPY(Php.modulator.par1); 1272 COPY(Php.modulator.freq); 1273 COPY(Php.width); 1274 COPY(Php.amp.mode); 1275 COPY(Php.amp.type); 1276 COPY(Php.amp.par1); 1277 COPY(Php.amp.par2); 1278 COPY(Php.autoscale); 1279 COPY(Php.onehalf); 1280 1281 COPY(Pbandwidth); 1282 COPY(Pbwscale); 1283 1284 COPY(Phrpos.type); 1285 COPY(Phrpos.par1); 1286 COPY(Phrpos.par2); 1287 COPY(Phrpos.par3); 1288 1289 COPY(Pquality.samplesize); 1290 COPY(Pquality.basenote); 1291 COPY(Pquality.oct); 1292 COPY(Pquality.smpoct); 1293 1294 oscilgen->paste(*x.oscilgen); 1295 resonance->paste(*x.resonance); 1296 1297 if ( time ) { 1298 last_update_timestamp = time->time(); 1299 } 1300 } 1301 1302 void PADnoteParameters::pasteRT(PADnoteParameters &x) 1303 { 1304 //Realtime stuff 1305 1306 COPY(Pfixedfreq); 1307 1308 COPY(PfixedfreqET); 1309 COPY(PBendAdjust); 1310 COPY(POffsetHz); 1311 COPY(PDetune); 1312 COPY(PCoarseDetune); 1313 COPY(PDetuneType); 1314 1315 FreqEnvelope->paste(*x.FreqEnvelope); 1316 FreqLfo->paste(*x.FreqLfo); 1317 1318 COPY(PStereo); 1319 COPY(PPanning); 1320 COPY(PVolume); 1321 COPY(PAmpVelocityScaleFunction); 1322 1323 AmpEnvelope->paste(*x.AmpEnvelope); 1324 AmpLfo->paste(*x.AmpLfo); 1325 1326 COPY(Fadein_adjustment); 1327 COPY(PPunchStrength); 1328 COPY(PPunchTime); 1329 COPY(PPunchStretch); 1330 COPY(PPunchVelocitySensing); 1331 1332 GlobalFilter->paste(*x.GlobalFilter); 1333 1334 COPY(PFilterVelocityScale); 1335 COPY(PFilterVelocityScaleFunction); 1336 1337 FilterEnvelope->paste(*x.FilterEnvelope); 1338 FilterLfo->paste(*x.FilterLfo); 1339 1340 if ( time ) { 1341 last_update_timestamp = time->time(); 1342 } 1343 } 1344 #undef COPY 1345 1346 }