ADnote.cpp (75572B)
1 /* 2 ZynAddSubFX - a software synthesizer 3 4 ADnote.cpp - The "additive" synthesizer 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 <cmath> 15 #include <cstdlib> 16 #include <cstdio> 17 #include <cstring> 18 #include <cassert> 19 #include <stdint.h> 20 21 #include "../globals.h" 22 #include "../Misc/Util.h" 23 #include "../Misc/Allocator.h" 24 #include "../Params/ADnoteParameters.h" 25 #include "../Containers/ScratchString.h" 26 #include "../Containers/NotePool.h" 27 #include "ModFilter.h" 28 #include "OscilGen.h" 29 #include "ADnote.h" 30 31 #define LENGTHOF(x) ((int)(sizeof(x)/sizeof(x[0]))) 32 33 namespace zyn { 34 ADnote::ADnote(ADnoteParameters *pars_, const SynthParams &spars, 35 WatchManager *wm, const char *prefix) 36 :SynthNote(spars), watch_be4_add(wm, prefix, "noteout/be4_mix"), watch_after_add(wm,prefix,"noteout/after_mix"), 37 watch_punch(wm, prefix, "noteout/punch"), watch_legato(wm, prefix, "noteout/legato"), pars(*pars_) 38 { 39 memory.beginTransaction(); 40 tmpwavel = memory.valloc<float>(synth.buffersize); 41 tmpwaver = memory.valloc<float>(synth.buffersize); 42 bypassl = memory.valloc<float>(synth.buffersize); 43 bypassr = memory.valloc<float>(synth.buffersize); 44 45 ADnoteParameters &pars = *pars_; 46 portamento = spars.portamento; 47 note_log2_freq = spars.note_log2_freq; 48 NoteEnabled = ON; 49 velocity = spars.velocity; 50 initial_seed = spars.seed; 51 current_prng_state = spars.seed; 52 stereo = pars.GlobalPar.PStereo; 53 54 NoteGlobalPar.Detune = getdetune(pars.GlobalPar.PDetuneType, 55 pars.GlobalPar.PCoarseDetune, 56 pars.GlobalPar.PDetune); 57 bandwidthDetuneMultiplier = pars.getBandwidthDetuneMultiplier(); 58 59 if(pars.GlobalPar.PPanning == 0) 60 NoteGlobalPar.Panning = getRandomFloat(); 61 else 62 NoteGlobalPar.Panning = pars.GlobalPar.PPanning / 128.0f; 63 64 NoteGlobalPar.Fadein_adjustment = 65 pars.GlobalPar.Fadein_adjustment / (float)FADEIN_ADJUSTMENT_SCALE; 66 NoteGlobalPar.Fadein_adjustment *= NoteGlobalPar.Fadein_adjustment; 67 if(pars.GlobalPar.PPunchStrength != 0) { 68 NoteGlobalPar.Punch.Enabled = 1; 69 NoteGlobalPar.Punch.t = 1.0f; //start from 1.0f and to 0.0f 70 NoteGlobalPar.Punch.initialvalue = 71 ((powf(10, 1.5f * pars.GlobalPar.PPunchStrength / 127.0f) - 1.0f) 72 * VelF(velocity, 73 pars.GlobalPar.PPunchVelocitySensing)); 74 const float time = 75 powf(10, 3.0f * pars.GlobalPar.PPunchTime / 127.0f) / 10000.0f; //0.1f .. 100 ms 76 const float stretch = powf(440.0f / powf(2.0f, spars.note_log2_freq), 77 pars.GlobalPar.PPunchStretch / 64.0f); 78 NoteGlobalPar.Punch.dt = 1.0f / (time * synth.samplerate_f * stretch); 79 } 80 else 81 NoteGlobalPar.Punch.Enabled = 0; 82 83 for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice) 84 setupVoice(nvoice); 85 86 max_unison = 1; 87 for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice) 88 if(NoteVoicePar[nvoice].unison_size > max_unison) 89 max_unison = NoteVoicePar[nvoice].unison_size; 90 91 92 tmpwave_unison = memory.valloc<float*>(max_unison); 93 for(int k = 0; k < max_unison; ++k) { 94 tmpwave_unison[k] = memory.valloc<float>(synth.buffersize); 95 memset(tmpwave_unison[k], 0, synth.bufferbytes); 96 } 97 98 initparameters(wm, prefix); 99 memory.endTransaction(); 100 } 101 102 void ADnote::setupVoice(int nvoice) 103 { 104 auto ¶m = pars.VoicePar[nvoice]; 105 auto &voice = NoteVoicePar[nvoice]; 106 107 108 for (int i = 0; i < 14; i++) 109 voice.pinking[i] = 0.0; 110 111 param.OscilGn->newrandseed(prng()); 112 voice.OscilSmp = NULL; 113 voice.FMSmp = NULL; 114 voice.VoiceOut = NULL; 115 116 voice.FMVoice = -1; 117 voice.unison_size = 1; 118 119 if(!pars.VoicePar[nvoice].Enabled) { 120 voice.Enabled = OFF; 121 return; //the voice is disabled 122 } 123 NoteVoicePar[nvoice].AAEnabled = 124 pars.VoicePar[nvoice].PAAEnabled; 125 126 const int BendAdj = pars.VoicePar[nvoice].PBendAdjust - 64; 127 if (BendAdj % 24 == 0) 128 voice.BendAdjust = BendAdj / 24; 129 else 130 voice.BendAdjust = BendAdj / 24.0f; 131 132 const float offset_val = (param.POffsetHz - 64)/64.0f; 133 voice.OffsetHz = 15.0f*(offset_val * sqrtf(fabsf(offset_val))); 134 135 voice.unison_stereo_spread = 136 pars.VoicePar[nvoice].Unison_stereo_spread / 127.0f; 137 138 int unison = setupVoiceUnison(nvoice); 139 140 141 voice.oscfreqhi = memory.valloc<int>(unison); 142 voice.oscfreqlo = memory.valloc<float>(unison); 143 144 voice.oscfreqhiFM = memory.valloc<unsigned int>(unison); 145 voice.oscfreqloFM = memory.valloc<float>(unison); 146 voice.oscposhi = memory.valloc<int>(unison); 147 voice.oscposlo = memory.valloc<float>(unison); 148 voice.oscposhiFM = memory.valloc<unsigned int>(unison); 149 voice.oscposloFM = memory.valloc<float>(unison); 150 151 voice.Enabled = ON; 152 voice.fixedfreq = pars.VoicePar[nvoice].Pfixedfreq; 153 voice.fixedfreqET = pars.VoicePar[nvoice].PfixedfreqET; 154 155 setupVoiceDetune(nvoice); 156 157 for(int k = 0; k < unison; ++k) { 158 voice.oscposhi[k] = 0; 159 voice.oscposlo[k] = 0.0f; 160 voice.oscposhiFM[k] = 0; 161 voice.oscposloFM[k] = 0.0f; 162 } 163 164 //the extra points contains the first point 165 voice.OscilSmp = 166 memory.valloc<float>(synth.oscilsize + OSCIL_SMP_EXTRA_SAMPLES); 167 168 //Get the voice's oscil or external's voice oscil 169 int vc = nvoice; 170 if(pars.VoicePar[nvoice].Pextoscil != -1) 171 vc = pars.VoicePar[nvoice].Pextoscil; 172 if(!pars.GlobalPar.Hrandgrouping) 173 pars.VoicePar[vc].OscilGn->newrandseed(prng()); 174 int oscposhi_start = 175 pars.VoicePar[vc].OscilGn->get(NoteVoicePar[nvoice].OscilSmp, 176 getvoicebasefreq(nvoice), 177 pars.VoicePar[nvoice].Presonance); 178 179 // This code was planned for biasing the carrier in MOD_RING 180 // but that's on hold for the moment. Disabled 'cos small 181 // machines run this stuff too. 182 // 183 // //Find range of generated wave 184 // float min = NoteVoicePar[nvoice].OscilSmp[0]; 185 // float max = min; 186 // float *smpls = &(NoteVoicePar[nvoice].OscilSmp[1]); 187 // for (int i = synth.oscilsize-1; i--; smpls++) 188 // if (*smpls > max) 189 // max = *smpls; 190 // else if (*smpls < min) 191 // min = *smpls; 192 // NoteVoicePar[nvoice].OscilSmpMin = min; 193 // NoteVoicePar[nvoice].OscilSmpMax = max; 194 195 //I store the first elements to the last position for speedups 196 for(int i = 0; i < OSCIL_SMP_EXTRA_SAMPLES; ++i) 197 voice.OscilSmp[synth.oscilsize + i] = voice.OscilSmp[i]; 198 199 voice.phase_offset = (int)((pars.VoicePar[nvoice].Poscilphase 200 - 64.0f) / 128.0f * synth.oscilsize + synth.oscilsize * 4); 201 oscposhi_start += NoteVoicePar[nvoice].phase_offset; 202 203 int kth_start = oscposhi_start; 204 for(int k = 0; k < unison; ++k) { 205 voice.oscposhi[k] = kth_start % synth.oscilsize; 206 //put random starting point for other subvoices 207 kth_start = oscposhi_start + 208 (int)(RND * pars.VoicePar[nvoice].Unison_phase_randomness / 209 127.0f * (synth.oscilsize - 1)); 210 } 211 212 voice.FreqLfo = NULL; 213 voice.FreqEnvelope = NULL; 214 215 voice.AmpLfo = NULL; 216 voice.AmpEnvelope = NULL; 217 218 voice.Filter = NULL; 219 voice.FilterEnvelope = NULL; 220 voice.FilterLfo = NULL; 221 222 voice.filterbypass = param.Pfilterbypass; 223 voice.filterFcCtlBypass = param.PfilterFcCtlBypass; 224 225 setupVoiceMod(nvoice); 226 227 voice.FMVoice = param.PFMVoice; 228 voice.FMFreqEnvelope = NULL; 229 voice.FMAmpEnvelope = NULL; 230 231 voice.FMoldsmp = memory.valloc<float>(unison); 232 for(int k = 0; k < unison; ++k) 233 voice.FMoldsmp[k] = 0.0f; //this is for FM (integration) 234 235 voice.firsttick = 1; 236 voice.DelayTicks = 237 (int)((expf(param.PDelay / 127.0f * logf(50.0f)) 238 - 1.0f) / synth.buffersize_f / 10.0f * synth.samplerate_f); 239 } 240 241 int ADnote::setupVoiceUnison(int nvoice) 242 { 243 auto &voice = NoteVoicePar[nvoice]; 244 245 int unison = pars.VoicePar[nvoice].Unison_size; 246 if(unison < 1) 247 unison = 1; 248 249 bool is_pwm = pars.VoicePar[nvoice].PFMEnabled == FMTYPE::PW_MOD; 250 251 if (pars.VoicePar[nvoice].Type != 0) { 252 // Since noise unison of greater than two is touch goofy... 253 if (unison > 2) 254 unison = 2; 255 } else if (is_pwm) { 256 /* Pulse width mod uses pairs of subvoices. */ 257 unison *= 2; 258 // This many is likely to sound like noise anyhow. 259 if (unison > 64) 260 unison = 64; 261 } 262 263 //compute unison 264 voice.unison_size = unison; 265 266 voice.unison_base_freq_rap = memory.valloc<float>(unison); 267 voice.unison_freq_rap = memory.valloc<float>(unison); 268 voice.unison_invert_phase = memory.valloc<bool>(unison); 269 const float unison_spread = 270 pars.getUnisonFrequencySpreadCents(nvoice); 271 const float unison_real_spread = powf(2.0f, (unison_spread * 0.5f) / 1200.0f); 272 const float unison_vibratto_a = 273 pars.VoicePar[nvoice].Unison_vibratto / 127.0f; //0.0f .. 1.0f 274 275 const int true_unison = unison / (is_pwm ? 2 : 1); 276 switch(true_unison) { 277 case 1: 278 voice.unison_base_freq_rap[0] = 1.0f; //if the unison is not used, always make the only subvoice to have the default note 279 break; 280 case 2: //unison for 2 subvoices 281 voice.unison_base_freq_rap[0] = 1.0f / unison_real_spread; 282 voice.unison_base_freq_rap[1] = unison_real_spread; 283 break; 284 default: //unison for more than 2 subvoices 285 { 286 float unison_values[true_unison]; 287 float min = -1e-6f, max = 1e-6f; 288 for(int k = 0; k < true_unison; ++k) { 289 const float step = (k / (float) (true_unison - 1)) * 2.0f - 1.0f; //this makes the unison spread more uniform 290 const float val = step + (RND * 2.0f - 1.0f) / (true_unison - 1); 291 unison_values[k] = val; 292 if (min > val) { 293 min = val; 294 } 295 if (max < val) { 296 max = val; 297 } 298 } 299 const float diff = max - min; 300 for(int k = 0; k < true_unison; ++k) { 301 unison_values[k] = 302 (unison_values[k] - (max + min) * 0.5f) / diff; //the lowest value will be -1 and the highest will be 1 303 voice.unison_base_freq_rap[k] = 304 powf(2.0f, (unison_spread * unison_values[k]) / 1200); 305 } 306 } 307 } 308 if (is_pwm) 309 for (int i = true_unison - 1; i >= 0; i--) { 310 voice.unison_base_freq_rap[2*i + 1] = 311 voice.unison_base_freq_rap[i]; 312 voice.unison_base_freq_rap[2*i] = 313 voice.unison_base_freq_rap[i]; 314 } 315 316 //unison vibrattos 317 if(unison > 2 || (!is_pwm && unison > 1)) 318 for(int k = 0; k < unison; ++k) //reduce the frequency difference for larger vibrattos 319 voice.unison_base_freq_rap[k] = 1.0f 320 + (voice.unison_base_freq_rap[k] - 1.0f) 321 * (1.0f - unison_vibratto_a); 322 voice.unison_vibratto.step = memory.valloc<float>(unison); 323 voice.unison_vibratto.position = memory.valloc<float>(unison); 324 voice.unison_vibratto.amplitude = 325 (unison_real_spread - 1.0f) * unison_vibratto_a; 326 327 const float increments_per_second = synth.samplerate_f / synth.buffersize_f; 328 const float vib_speed = pars.VoicePar[nvoice].Unison_vibratto_speed / 127.0f; 329 const float vibratto_base_period = 0.25f * powf(2.0f, (1.0f - vib_speed) * 4.0f); 330 for(int k = 0; k < unison; ++k) { 331 voice.unison_vibratto.position[k] = RND * 1.8f - 0.9f; 332 //make period to vary randomly from 50% to 200% vibratto base period 333 const float vibratto_period = vibratto_base_period 334 * powf(2.0f, RND * 2.0f - 1.0f); 335 336 const float m = (RND < 0.5f ? -1.0f : 1.0f) * 337 4.0f / (vibratto_period * increments_per_second); 338 voice.unison_vibratto.step[k] = m; 339 340 // Ugly, but the alternative is likely uglier. 341 if (is_pwm) 342 for (int i = 0; i < unison; i += 2) { 343 voice.unison_vibratto.step[i+1] = 344 voice.unison_vibratto.step[i]; 345 voice.unison_vibratto.position[i+1] = 346 voice.unison_vibratto.position[i]; 347 } 348 } 349 350 if(unison <= 2) { //no vibratto for a single voice 351 if (is_pwm) { 352 voice.unison_vibratto.step[1] = 0.0f; 353 voice.unison_vibratto.position[1] = 0.0f; 354 } 355 if (is_pwm || unison == 1) { 356 voice.unison_vibratto.step[0] = 0.0f; 357 voice.unison_vibratto.position[0] = 0.0f; 358 voice.unison_vibratto.amplitude = 0.0f; 359 } 360 } 361 362 //phase invert for unison 363 voice.unison_invert_phase[0] = false; 364 if(unison != 1) { 365 int inv = pars.VoicePar[nvoice].Unison_invert_phase; 366 switch(inv) { 367 case 0: 368 for(int k = 0; k < unison; ++k) 369 voice.unison_invert_phase[k] = false; 370 break; 371 case 1: 372 for(int k = 0; k < unison; ++k) 373 voice.unison_invert_phase[k] = (RND > 0.5f); 374 break; 375 default: 376 for(int k = 0; k < unison; ++k) 377 voice.unison_invert_phase[k] = 378 (k % inv == 0) ? true : false; 379 break; 380 } 381 } 382 return unison; 383 } 384 385 void ADnote::setupVoiceDetune(int nvoice) 386 { 387 //use the Globalpars.detunetype if the detunetype is 0 388 if(pars.VoicePar[nvoice].PDetuneType != 0) { 389 NoteVoicePar[nvoice].Detune = getdetune( 390 pars.VoicePar[nvoice].PDetuneType, 391 pars.VoicePar[nvoice]. 392 PCoarseDetune, 393 8192); //coarse detune 394 NoteVoicePar[nvoice].FineDetune = getdetune( 395 pars.VoicePar[nvoice].PDetuneType, 396 0, 397 pars.VoicePar[nvoice].PDetune); //fine detune 398 } 399 else { 400 NoteVoicePar[nvoice].Detune = getdetune( 401 pars.GlobalPar.PDetuneType, 402 pars.VoicePar[nvoice]. 403 PCoarseDetune, 404 8192); //coarse detune 405 NoteVoicePar[nvoice].FineDetune = getdetune( 406 pars.GlobalPar.PDetuneType, 407 0, 408 pars.VoicePar[nvoice].PDetune); //fine detune 409 } 410 if(pars.VoicePar[nvoice].PFMDetuneType != 0) 411 NoteVoicePar[nvoice].FMDetune = getdetune( 412 pars.VoicePar[nvoice].PFMDetuneType, 413 pars.VoicePar[nvoice]. 414 PFMCoarseDetune, 415 pars.VoicePar[nvoice].PFMDetune); 416 else 417 NoteVoicePar[nvoice].FMDetune = getdetune( 418 pars.GlobalPar.PDetuneType, 419 pars.VoicePar[nvoice]. 420 PFMCoarseDetune, 421 pars.VoicePar[nvoice].PFMDetune); 422 } 423 424 void ADnote::setupVoiceMod(int nvoice, bool first_run) 425 { 426 auto ¶m = pars.VoicePar[nvoice]; 427 auto &voice = NoteVoicePar[nvoice]; 428 float FMVolume; 429 430 if (param.Type != 0) 431 voice.FMEnabled = FMTYPE::NONE; 432 else 433 voice.FMEnabled = param.PFMEnabled; 434 435 voice.FMFreqFixed = param.PFMFixedFreq; 436 437 //Triggers when a user enables modulation on a running voice 438 if(!first_run && voice.FMEnabled != FMTYPE::NONE && voice.FMSmp == NULL && voice.FMVoice < 0) { 439 param.FmGn->newrandseed(prng()); 440 voice.FMSmp = memory.valloc<float>(synth.oscilsize + OSCIL_SMP_EXTRA_SAMPLES); 441 memset(voice.FMSmp, 0, sizeof(float)*(synth.oscilsize + OSCIL_SMP_EXTRA_SAMPLES)); 442 int vc = nvoice; 443 if(param.PextFMoscil != -1) 444 vc = param.PextFMoscil; 445 446 float tmp = 1.0f; 447 if((pars.VoicePar[vc].FmGn->Padaptiveharmonics != 0) 448 || (voice.FMEnabled == FMTYPE::MIX) 449 || (voice.FMEnabled == FMTYPE::RING_MOD)) 450 tmp = getFMvoicebasefreq(nvoice); 451 452 if(!pars.GlobalPar.Hrandgrouping) 453 pars.VoicePar[vc].FmGn->newrandseed(prng()); 454 455 for(int k = 0; k < voice.unison_size; ++k) 456 voice.oscposhiFM[k] = (voice.oscposhi[k] 457 + pars.VoicePar[vc].FmGn->get( 458 voice.FMSmp, tmp)) 459 % synth.oscilsize; 460 461 for(int i = 0; i < OSCIL_SMP_EXTRA_SAMPLES; ++i) 462 voice.FMSmp[synth.oscilsize + i] = voice.FMSmp[i]; 463 int oscposhiFM_add = 464 (int)((param.PFMoscilphase 465 - 64.0f) / 128.0f * synth.oscilsize 466 + synth.oscilsize * 4); 467 for(int k = 0; k < voice.unison_size; ++k) { 468 voice.oscposhiFM[k] += oscposhiFM_add; 469 voice.oscposhiFM[k] %= synth.oscilsize; 470 } 471 } 472 473 474 //Compute the Voice's modulator volume (incl. damping) 475 float fmvoldamp = powf(440.0f / getvoicebasefreq(nvoice), 476 param.PFMVolumeDamp / 64.0f - 1.0f); 477 const float fmvolume_ = param.FMvolume / 100.0f; 478 switch(voice.FMEnabled) { 479 case FMTYPE::PHASE_MOD: 480 case FMTYPE::PW_MOD: 481 fmvoldamp = powf(440.0f / getvoicebasefreq(nvoice), 482 param.PFMVolumeDamp / 64.0f); 483 FMVolume = (expf(fmvolume_ * FM_AMP_MULTIPLIER) - 1.0f) 484 * fmvoldamp * 4.0f; 485 break; 486 case FMTYPE::FREQ_MOD: 487 FMVolume = (expf(fmvolume_ * FM_AMP_MULTIPLIER) - 1.0f) 488 * fmvoldamp * 4.0f; 489 break; 490 default: 491 if(fmvoldamp > 1.0f) 492 fmvoldamp = 1.0f; 493 FMVolume = fmvolume_ * fmvoldamp; 494 break; 495 } 496 497 //Voice's modulator velocity sensing 498 voice.FMVolume = FMVolume * 499 VelF(velocity, pars.VoicePar[nvoice].PFMVelocityScaleFunction); 500 } 501 502 SynthNote *ADnote::cloneLegato(void) 503 { 504 SynthParams sp{memory, ctl, synth, time, velocity, 505 portamento, legato.param.note_log2_freq, true, 506 initial_seed }; 507 return memory.alloc<ADnote>(&pars, sp); 508 } 509 510 // ADlegatonote: This function is (mostly) a copy of ADnote(...) and 511 // initparameters() stuck together with some lines removed so that it 512 // only alter the already playing note (to perform legato). It is 513 // possible I left stuff that is not required for this. 514 void ADnote::legatonote(const LegatoParams &lpars) 515 { 516 //ADnoteParameters &pars = *partparams; 517 // Manage legato stuff 518 if(legato.update(lpars)) 519 return; 520 521 portamento = lpars.portamento; 522 note_log2_freq = lpars.note_log2_freq; 523 initial_seed = lpars.seed; 524 current_prng_state = lpars.seed; 525 526 if(lpars.velocity > 1.0f) 527 velocity = 1.0f; 528 else 529 velocity = lpars.velocity; 530 531 const float basefreq = powf(2.0f, note_log2_freq); 532 533 NoteGlobalPar.Detune = getdetune(pars.GlobalPar.PDetuneType, 534 pars.GlobalPar.PCoarseDetune, 535 pars.GlobalPar.PDetune); 536 bandwidthDetuneMultiplier = pars.getBandwidthDetuneMultiplier(); 537 538 if(pars.GlobalPar.PPanning) 539 NoteGlobalPar.Panning = pars.GlobalPar.PPanning / 128.0f; 540 541 NoteGlobalPar.Filter->updateSense(velocity, 542 pars.GlobalPar.PFilterVelocityScale, 543 pars.GlobalPar.PFilterVelocityScaleFunction); 544 545 546 for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice) { 547 auto &voice = NoteVoicePar[nvoice]; 548 float FMVolume; 549 550 if(voice.Enabled == OFF) 551 continue; //(gf) Stay the same as first note in legato. 552 553 voice.fixedfreq = pars.VoicePar[nvoice].Pfixedfreq; 554 voice.fixedfreqET = pars.VoicePar[nvoice].PfixedfreqET; 555 556 //use the Globalpars.detunetype if the detunetype is 0 557 if(pars.VoicePar[nvoice].PDetuneType != 0) { 558 voice.Detune = getdetune( 559 pars.VoicePar[nvoice].PDetuneType, 560 pars.VoicePar[nvoice].PCoarseDetune, 561 8192); //coarse detune 562 voice.FineDetune = getdetune( 563 pars.VoicePar[nvoice].PDetuneType, 564 0, 565 pars.VoicePar[nvoice].PDetune); //fine detune 566 } 567 else { 568 voice.Detune = getdetune( 569 pars.GlobalPar.PDetuneType, 570 pars.VoicePar[nvoice].PCoarseDetune, 571 8192); //coarse detune 572 voice.FineDetune = getdetune( 573 pars.GlobalPar.PDetuneType, 574 0, 575 pars.VoicePar[nvoice].PDetune); //fine detune 576 } 577 if(pars.VoicePar[nvoice].PFMDetuneType != 0) 578 voice.FMDetune = getdetune( 579 pars.VoicePar[nvoice].PFMDetuneType, 580 pars.VoicePar[nvoice].PFMCoarseDetune, 581 pars.VoicePar[nvoice].PFMDetune); 582 else 583 voice.FMDetune = getdetune( 584 pars.GlobalPar.PDetuneType, 585 pars.VoicePar[nvoice].PFMCoarseDetune, 586 pars.VoicePar[nvoice].PFMDetune); 587 588 auto &voiceFilter = voice.Filter; 589 if(voiceFilter) { 590 const auto &vce = pars.VoicePar[nvoice]; 591 voiceFilter->updateSense(velocity, vce.PFilterVelocityScale, 592 vce.PFilterVelocityScaleFunction); 593 } 594 595 voice.filterbypass = 596 pars.VoicePar[nvoice].Pfilterbypass; 597 voice.filterFcCtlBypass = 598 pars.VoicePar[nvoice].PfilterFcCtlBypass; 599 600 601 voice.FMVoice = pars.VoicePar[nvoice].PFMVoice; 602 603 //Compute the Voice's modulator volume (incl. damping) 604 float fmvoldamp = powf(440.0f / getvoicebasefreq(nvoice), 605 pars.VoicePar[nvoice].PFMVolumeDamp / 64.0f 606 - 1.0f); 607 608 switch(voice.FMEnabled) { 609 case FMTYPE::PHASE_MOD: 610 case FMTYPE::PW_MOD: 611 fmvoldamp = 612 powf(440.0f / getvoicebasefreq( 613 nvoice), pars.VoicePar[nvoice].PFMVolumeDamp 614 / 64.0f); 615 FMVolume = 616 (expf(pars.VoicePar[nvoice].FMvolume / 100.0f 617 * FM_AMP_MULTIPLIER) - 1.0f) * fmvoldamp * 4.0f; 618 break; 619 case FMTYPE::FREQ_MOD: 620 FMVolume = 621 (expf(pars.VoicePar[nvoice].FMvolume / 100.0f 622 * FM_AMP_MULTIPLIER) - 1.0f) * fmvoldamp * 4.0f; 623 break; 624 default: 625 if(fmvoldamp > 1.0f) 626 fmvoldamp = 1.0f; 627 FMVolume = 628 pars.VoicePar[nvoice].FMvolume 629 / 100.0f * fmvoldamp; 630 break; 631 } 632 633 //Voice's modulator velocity sensing 634 voice.FMVolume = FMVolume * 635 VelF(velocity, 636 pars.VoicePar[nvoice].PFMVelocityScaleFunction); 637 } 638 /// initparameters(); 639 640 /////////////// 641 // Altered content of initparameters(): 642 643 int tmp[NUM_VOICES]; 644 645 NoteGlobalPar.Volume = dB2rap(pars.GlobalPar.Volume) //-60 dB .. 20 dB 646 * VelF( 647 velocity, 648 pars.GlobalPar.PAmpVelocityScaleFunction); //velocity sensing 649 650 { 651 auto *filter = NoteGlobalPar.Filter; 652 filter->updateSense(velocity, pars.GlobalPar.PFilterVelocityScale, 653 pars.GlobalPar.PFilterVelocityScaleFunction); 654 filter->updateNoteFreq(basefreq); 655 } 656 657 // Forbids the Modulation Voice to be greater or equal than voice 658 for(int i = 0; i < NUM_VOICES; ++i) 659 if(NoteVoicePar[i].FMVoice >= i) 660 NoteVoicePar[i].FMVoice = -1; 661 662 // Voice Parameter init 663 for(unsigned nvoice = 0; nvoice < NUM_VOICES; ++nvoice) { 664 Voice& vce = NoteVoicePar[nvoice]; 665 if(NoteVoicePar[nvoice].Enabled == 0) 666 continue; 667 668 NoteVoicePar[nvoice].noisetype = pars.VoicePar[nvoice].Type; 669 /* Voice Amplitude Parameters Init */ 670 NoteVoicePar[nvoice].Volume = 671 dB2rap(pars.VoicePar[nvoice].volume) // -60 dB .. 0 dB 672 * VelF(velocity, 673 pars.VoicePar[nvoice].PAmpVelocityScaleFunction); //velocity 674 if(pars.VoicePar[nvoice].volume == -60.0) 675 NoteVoicePar[nvoice].Volume = 0; 676 677 if(pars.VoicePar[nvoice].PVolumeminus != 0) 678 NoteVoicePar[nvoice].Volume = -NoteVoicePar[nvoice].Volume; 679 680 NoteVoicePar[nvoice].AAEnabled = 681 pars.VoicePar[nvoice].PAAEnabled; 682 683 if(pars.VoicePar[nvoice].PPanning == 0) { 684 NoteVoicePar[nvoice].Panning = getRandomFloat(); 685 } else 686 NoteVoicePar[nvoice].Panning = 687 pars.VoicePar[nvoice].PPanning / 128.0f; 688 689 vce.newamplitude = 1.0f; 690 if(pars.VoicePar[nvoice].PAmpEnvelopeEnabled 691 && NoteVoicePar[nvoice].AmpEnvelope) 692 vce.newamplitude *= NoteVoicePar[nvoice].AmpEnvelope->envout_dB(); 693 694 695 if(pars.VoicePar[nvoice].PAmpLfoEnabled && NoteVoicePar[nvoice].AmpLfo) 696 vce.newamplitude *= NoteVoicePar[nvoice].AmpLfo->amplfoout(); 697 698 auto *voiceFilter = NoteVoicePar[nvoice].Filter; 699 if(voiceFilter) { 700 voiceFilter->updateSense(velocity, pars.VoicePar[nvoice].PFilterVelocityScale, 701 pars.VoicePar[nvoice].PFilterVelocityScaleFunction); 702 voiceFilter->updateNoteFreq(basefreq); 703 } 704 705 /* Voice Modulation Parameters Init */ 706 if((NoteVoicePar[nvoice].FMEnabled != FMTYPE::NONE) 707 && (NoteVoicePar[nvoice].FMVoice < 0)) { 708 pars.VoicePar[nvoice].FmGn->newrandseed(prng()); 709 710 //Perform Anti-aliasing only on MIX or RING MODULATION 711 712 int vc = nvoice; 713 if(pars.VoicePar[nvoice].PextFMoscil != -1) 714 vc = pars.VoicePar[nvoice].PextFMoscil; 715 716 if(!pars.GlobalPar.Hrandgrouping) 717 pars.VoicePar[vc].FmGn->newrandseed(prng()); 718 719 for(int i = 0; i < OSCIL_SMP_EXTRA_SAMPLES; ++i) 720 NoteVoicePar[nvoice].FMSmp[synth.oscilsize + i] = 721 NoteVoicePar[nvoice].FMSmp[i]; 722 } 723 724 vce.FMnewamplitude = NoteVoicePar[nvoice].FMVolume 725 * ctl.fmamp.relamp; 726 727 if(pars.VoicePar[nvoice].PFMAmpEnvelopeEnabled 728 && NoteVoicePar[nvoice].FMAmpEnvelope) 729 vce.FMnewamplitude *= 730 NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB(); 731 } 732 733 for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice) { 734 for(unsigned i = nvoice + 1; i < NUM_VOICES; ++i) 735 tmp[i] = 0; 736 for(unsigned i = nvoice + 1; i < NUM_VOICES; ++i) 737 if((NoteVoicePar[i].FMVoice == nvoice) && (tmp[i] == 0)) 738 tmp[i] = 1; 739 } 740 } 741 742 743 /* 744 * Kill a voice of ADnote 745 */ 746 void ADnote::KillVoice(int nvoice) 747 { 748 auto &voice = NoteVoicePar[nvoice]; 749 750 memory.devalloc(voice.oscfreqhi); 751 memory.devalloc(voice.oscfreqlo); 752 memory.devalloc(voice.oscfreqhiFM); 753 memory.devalloc(voice.oscfreqloFM); 754 memory.devalloc(voice.oscposhi); 755 memory.devalloc(voice.oscposlo); 756 memory.devalloc(voice.oscposhiFM); 757 memory.devalloc(voice.oscposloFM); 758 759 memory.devalloc(voice.unison_base_freq_rap); 760 memory.devalloc(voice.unison_freq_rap); 761 memory.devalloc(voice.unison_invert_phase); 762 memory.devalloc(voice.FMoldsmp); 763 memory.devalloc(voice.unison_vibratto.step); 764 memory.devalloc(voice.unison_vibratto.position); 765 766 NoteVoicePar[nvoice].kill(memory, synth); 767 } 768 769 /* 770 * Kill the note 771 */ 772 void ADnote::KillNote() 773 { 774 for(unsigned nvoice = 0; nvoice < NUM_VOICES; ++nvoice) { 775 if(NoteVoicePar[nvoice].Enabled == ON) 776 KillVoice(nvoice); 777 778 if(NoteVoicePar[nvoice].VoiceOut) 779 memory.dealloc(NoteVoicePar[nvoice].VoiceOut); 780 } 781 782 NoteGlobalPar.kill(memory); 783 784 NoteEnabled = OFF; 785 } 786 787 ADnote::~ADnote() 788 { 789 if(NoteEnabled == ON) 790 KillNote(); 791 memory.devalloc(tmpwavel); 792 memory.devalloc(tmpwaver); 793 memory.devalloc(bypassl); 794 memory.devalloc(bypassr); 795 for(int k = 0; k < max_unison; ++k) 796 memory.devalloc(tmpwave_unison[k]); 797 memory.devalloc(tmpwave_unison); 798 } 799 800 801 /* 802 * Init the parameters 803 */ 804 void ADnote::initparameters(WatchManager *wm, const char *prefix) 805 { 806 int tmp[NUM_VOICES]; 807 ScratchString pre = prefix; 808 const float basefreq = powf(2.0f, note_log2_freq); 809 810 // Global Parameters 811 NoteGlobalPar.initparameters(pars.GlobalPar, synth, 812 time, 813 memory, basefreq, velocity, 814 stereo, wm, prefix); 815 816 NoteGlobalPar.AmpEnvelope->envout_dB(); //discard the first envelope output 817 globalnewamplitude = NoteGlobalPar.Volume 818 * NoteGlobalPar.AmpEnvelope->envout_dB() 819 * NoteGlobalPar.AmpLfo->amplfoout(); 820 821 // Forbids the Modulation Voice to be greater or equal than voice 822 for(int i = 0; i < NUM_VOICES; ++i) 823 if(NoteVoicePar[i].FMVoice >= i) 824 NoteVoicePar[i].FMVoice = -1; 825 826 // Voice Parameter init 827 for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice) { 828 Voice &vce = NoteVoicePar[nvoice]; 829 ADnoteVoiceParam ¶m = pars.VoicePar[nvoice]; 830 831 if(vce.Enabled == 0) 832 continue; 833 834 vce.noisetype = param.Type; 835 /* Voice Amplitude Parameters Init */ 836 vce.Volume = dB2rap(param.volume) // -60dB..0dB 837 * VelF(velocity, param.PAmpVelocityScaleFunction); 838 if(param.volume == -60.0f) 839 vce.Volume = 0; 840 841 if(param.PVolumeminus) 842 vce.Volume = -vce.Volume; 843 844 if(param.PPanning == 0) { 845 vce.Panning = getRandomFloat(); 846 } else 847 vce.Panning = param.PPanning / 128.0f; 848 849 vce.newamplitude = 1.0f; 850 if(param.PAmpEnvelopeEnabled) { 851 vce.AmpEnvelope = memory.alloc<Envelope>(*param.AmpEnvelope, 852 basefreq, synth.dt(), wm, 853 (pre+"VoicePar"+nvoice+"/AmpEnvelope/").c_str); 854 vce.AmpEnvelope->envout_dB(); //discard the first envelope sample 855 vce.newamplitude *= vce.AmpEnvelope->envout_dB(); 856 } 857 858 if(param.PAmpLfoEnabled) { 859 vce.AmpLfo = memory.alloc<LFO>(*param.AmpLfo, basefreq, time, wm, 860 (pre+"VoicePar"+nvoice+"/AmpLfo/").c_str); 861 vce.newamplitude *= vce.AmpLfo->amplfoout(); 862 } 863 864 /* Voice Frequency Parameters Init */ 865 if(param.PFreqEnvelopeEnabled) 866 vce.FreqEnvelope = memory.alloc<Envelope>(*param.FreqEnvelope, 867 basefreq, synth.dt(), wm, 868 (pre+"VoicePar"+nvoice+"/FreqEnvelope/").c_str); 869 870 if(param.PFreqLfoEnabled) 871 vce.FreqLfo = memory.alloc<LFO>(*param.FreqLfo, basefreq, time, wm, 872 (pre+"VoicePar"+nvoice+"/FreqLfo/").c_str); 873 874 /* Voice Filter Parameters Init */ 875 if(param.PFilterEnabled) { 876 vce.Filter = memory.alloc<ModFilter>(*param.VoiceFilter, synth, time, memory, stereo, 877 basefreq); 878 vce.Filter->updateSense(velocity, param.PFilterVelocityScale, 879 param.PFilterVelocityScaleFunction); 880 881 882 if(param.PFilterEnvelopeEnabled) { 883 vce.FilterEnvelope = 884 memory.alloc<Envelope>(*param.FilterEnvelope, 885 basefreq, synth.dt(), wm, 886 (pre+"VoicePar"+nvoice+"/FilterEnvelope/").c_str); 887 vce.Filter->addMod(*vce.FilterEnvelope); 888 } 889 890 if(param.PFilterLfoEnabled) { 891 vce.FilterLfo = memory.alloc<LFO>(*param.FilterLfo, basefreq, time, wm, 892 (pre+"VoicePar"+nvoice+"/FilterLfo/").c_str); 893 vce.Filter->addMod(*vce.FilterLfo); 894 } 895 } 896 897 /* Voice Modulation Parameters Init */ 898 if((vce.FMEnabled != FMTYPE::NONE) && (vce.FMVoice < 0)) { 899 param.FmGn->newrandseed(prng()); 900 vce.FMSmp = memory.valloc<float>(synth.oscilsize + OSCIL_SMP_EXTRA_SAMPLES); 901 902 //Perform Anti-aliasing only on MIX or RING MODULATION 903 904 int vc = nvoice; 905 if(param.PextFMoscil != -1) 906 vc = param.PextFMoscil; 907 908 float tmp = 1.0f; 909 if((pars.VoicePar[vc].FmGn->Padaptiveharmonics != 0) 910 || (vce.FMEnabled == FMTYPE::MIX) 911 || (vce.FMEnabled == FMTYPE::RING_MOD)) 912 tmp = getFMvoicebasefreq(nvoice); 913 914 if(!pars.GlobalPar.Hrandgrouping) 915 pars.VoicePar[vc].FmGn->newrandseed(prng()); 916 917 for(int k = 0; k < vce.unison_size; ++k) 918 vce.oscposhiFM[k] = (vce.oscposhi[k] 919 + pars.VoicePar[vc].FmGn->get( 920 vce.FMSmp, tmp)) 921 % synth.oscilsize; 922 923 for(int i = 0; i < OSCIL_SMP_EXTRA_SAMPLES; ++i) 924 vce.FMSmp[synth.oscilsize + i] = vce.FMSmp[i]; 925 int oscposhiFM_add = 926 (int)((param.PFMoscilphase 927 - 64.0f) / 128.0f * synth.oscilsize 928 + synth.oscilsize * 4); 929 for(int k = 0; k < vce.unison_size; ++k) { 930 vce.oscposhiFM[k] += oscposhiFM_add; 931 vce.oscposhiFM[k] %= synth.oscilsize; 932 } 933 } 934 935 if(param.PFMFreqEnvelopeEnabled) 936 vce.FMFreqEnvelope = memory.alloc<Envelope>(*param.FMFreqEnvelope, 937 basefreq, synth.dt(), wm, 938 (pre+"VoicePar"+nvoice+"/FMFreqEnvelope/").c_str); 939 940 vce.FMnewamplitude = vce.FMVolume * ctl.fmamp.relamp; 941 942 if(param.PFMAmpEnvelopeEnabled) { 943 vce.FMAmpEnvelope = 944 memory.alloc<Envelope>(*param.FMAmpEnvelope, 945 basefreq, synth.dt(), wm, 946 (pre+"VoicePar"+nvoice+"/FMAmpEnvelope/").c_str); 947 vce.FMnewamplitude *= vce.FMAmpEnvelope->envout_dB(); 948 } 949 } 950 951 for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice) { 952 for(int i = nvoice + 1; i < NUM_VOICES; ++i) 953 tmp[i] = 0; 954 for(int i = nvoice + 1; i < NUM_VOICES; ++i) 955 if((NoteVoicePar[i].FMVoice == nvoice) && (tmp[i] == 0)) { 956 NoteVoicePar[nvoice].VoiceOut = 957 memory.valloc<float>(synth.buffersize); 958 tmp[i] = 1; 959 } 960 961 if(NoteVoicePar[nvoice].VoiceOut) 962 memset(NoteVoicePar[nvoice].VoiceOut, 0, synth.bufferbytes); 963 } 964 } 965 966 967 /* 968 * Computes the relative frequency of each unison voice and it's vibratto 969 * This must be called before setfreq* functions 970 */ 971 void ADnote::compute_unison_freq_rap(int nvoice) { 972 Voice &vce = NoteVoicePar[nvoice]; 973 if(vce.unison_size == 1) { //no unison 974 vce.unison_freq_rap[0] = 1.0f; 975 return; 976 } 977 const float relbw = ctl.bandwidth.relbw * bandwidthDetuneMultiplier; 978 for(int k = 0; k < vce.unison_size; ++k) { 979 float pos = vce.unison_vibratto.position[k]; 980 float step = vce.unison_vibratto.step[k]; 981 pos += step; 982 if(pos <= -1.0f) { 983 pos = -1.0f; 984 step = -step; 985 } 986 if(pos >= 1.0f) { 987 pos = 1.0f; 988 step = -step; 989 } 990 const float vibratto_val = (pos - 0.333333333f * pos * pos * pos) * 1.5f; //make the vibratto lfo smoother 991 vce.unison_freq_rap[k] = 1.0f 992 + ((vce.unison_base_freq_rap[k] 993 - 1.0f) + vibratto_val 994 * vce.unison_vibratto.amplitude) 995 * relbw; 996 997 vce.unison_vibratto.position[k] = pos; 998 step = vce.unison_vibratto.step[k] = step; 999 } 1000 } 1001 1002 1003 /* 1004 * Computes the frequency of an oscillator 1005 */ 1006 void ADnote::setfreq(int nvoice, float in_freq) 1007 { 1008 Voice &vce = NoteVoicePar[nvoice]; 1009 for(int k = 0; k < vce.unison_size; ++k) { 1010 float freq = fabsf(in_freq) * vce.unison_freq_rap[k]; 1011 float speed = freq * synth.oscilsize_f / synth.samplerate_f; 1012 if(speed > synth.oscilsize_f) 1013 speed = synth.oscilsize_f; 1014 1015 F2I(speed, vce.oscfreqhi[k]); 1016 vce.oscfreqlo[k] = speed - floorf(speed); 1017 1018 } 1019 } 1020 1021 /* 1022 * Computes the frequency of an modullator oscillator 1023 */ 1024 void ADnote::setfreqFM(int nvoice, float in_freq) 1025 { 1026 Voice &vce = NoteVoicePar[nvoice]; 1027 for(int k = 0; k < vce.unison_size; ++k) { 1028 float freq = fabsf(in_freq) * vce.unison_freq_rap[k]; 1029 float speed = freq * synth.oscilsize_f / synth.samplerate_f; 1030 if(speed > synth.samplerate_f) 1031 speed = synth.samplerate_f; 1032 1033 F2I(speed, vce.oscfreqhiFM[k]); 1034 vce.oscfreqloFM[k] = speed - floorf(speed); 1035 } 1036 } 1037 1038 /* 1039 * Get Voice base frequency 1040 */ 1041 float ADnote::getvoicebasefreq(int nvoice, float adjust_log2) const 1042 { 1043 const float detune = NoteVoicePar[nvoice].Detune / 100.0f 1044 + NoteVoicePar[nvoice].FineDetune / 100.0f 1045 * ctl.bandwidth.relbw * bandwidthDetuneMultiplier 1046 + NoteGlobalPar.Detune / 100.0f; 1047 1048 if(NoteVoicePar[nvoice].fixedfreq == 0) { 1049 return powf(2.0f, note_log2_freq + detune / 12.0f + adjust_log2); 1050 } 1051 else { //the fixed freq is enabled 1052 const int fixedfreqET = NoteVoicePar[nvoice].fixedfreqET; 1053 float fixedfreq_log2 = log2f(440.0f); 1054 1055 if(fixedfreqET != 0) { //if the frequency varies according the keyboard note 1056 float tmp_log2 = (note_log2_freq - fixedfreq_log2) * 1057 (powf(2.0f, (fixedfreqET - 1) / 63.0f) - 1.0f); 1058 if(fixedfreqET <= 64) 1059 fixedfreq_log2 += tmp_log2; 1060 else 1061 fixedfreq_log2 += tmp_log2 * log2f(3.0f); 1062 } 1063 return powf(2.0f, fixedfreq_log2 + detune / 12.0f + adjust_log2); 1064 } 1065 } 1066 1067 /* 1068 * Get Voice's Modullator base frequency 1069 */ 1070 float ADnote::getFMvoicebasefreq(int nvoice) const 1071 { 1072 return getvoicebasefreq(nvoice, NoteVoicePar[nvoice].FMDetune / 1200.0f); 1073 } 1074 1075 /* 1076 * Computes all the parameters for each tick 1077 */ 1078 void ADnote::computecurrentparameters() 1079 { 1080 const float relfreq = getFilterCutoffRelFreq(); 1081 int nvoice; 1082 float voicefreq, voicepitch, FMfreq, 1083 FMrelativepitch, globalpitch; 1084 1085 globalpitch = 0.01f * (NoteGlobalPar.FreqEnvelope->envout() 1086 + NoteGlobalPar.FreqLfo->lfoout() 1087 * ctl.modwheel.relmod); 1088 globaloldamplitude = globalnewamplitude; 1089 globalnewamplitude = NoteGlobalPar.Volume 1090 * NoteGlobalPar.AmpEnvelope->envout_dB() 1091 * NoteGlobalPar.AmpLfo->amplfoout(); 1092 1093 NoteGlobalPar.Filter->update(relfreq, ctl.filterq.relq); 1094 1095 //compute the portamento, if it is used by this note 1096 float portamentofreqdelta_log2 = 0.0f; 1097 if(portamento) { //this voice uses portamento 1098 portamentofreqdelta_log2 = portamento->freqdelta_log2; 1099 if(!portamento->active) //the portamento has finished 1100 portamento = NULL; //this note is no longer "portamented" 1101 } 1102 1103 //compute parameters for all voices 1104 for(nvoice = 0; nvoice < NUM_VOICES; ++nvoice) { 1105 Voice& vce = NoteVoicePar[nvoice]; 1106 if(NoteVoicePar[nvoice].Enabled != ON) 1107 continue; 1108 NoteVoicePar[nvoice].DelayTicks -= 1; 1109 if(NoteVoicePar[nvoice].DelayTicks > 0) 1110 continue; 1111 1112 compute_unison_freq_rap(nvoice); 1113 1114 /*******************/ 1115 /* Voice Amplitude */ 1116 /*******************/ 1117 vce.oldamplitude = vce.newamplitude; 1118 vce.newamplitude = 1.0f; 1119 1120 if(NoteVoicePar[nvoice].AmpEnvelope) 1121 vce.newamplitude *= NoteVoicePar[nvoice].AmpEnvelope->envout_dB(); 1122 1123 if(NoteVoicePar[nvoice].AmpLfo) 1124 vce.newamplitude *= NoteVoicePar[nvoice].AmpLfo->amplfoout(); 1125 1126 /****************/ 1127 /* Voice Filter */ 1128 /****************/ 1129 auto *voiceFilter = NoteVoicePar[nvoice].Filter; 1130 if(voiceFilter) { 1131 const float voicerelfreq = NoteVoicePar[nvoice].filterFcCtlBypass == 0 ? relfreq : 0.0f; 1132 voiceFilter->update(voicerelfreq, ctl.filterq.relq); 1133 } 1134 1135 if(NoteVoicePar[nvoice].noisetype == 0) { //compute only if the voice isn't noise 1136 /*******************/ 1137 /* Voice Frequency */ 1138 /*******************/ 1139 voicepitch = 0.0f; 1140 if(NoteVoicePar[nvoice].FreqLfo) 1141 voicepitch += NoteVoicePar[nvoice].FreqLfo->lfoout() / 100.0f 1142 * ctl.bandwidth.relbw; 1143 1144 if(NoteVoicePar[nvoice].FreqEnvelope) 1145 voicepitch += NoteVoicePar[nvoice].FreqEnvelope->envout() 1146 / 100.0f; 1147 voicefreq = getvoicebasefreq(nvoice, portamentofreqdelta_log2 + 1148 (voicepitch + globalpitch) / 12.0f); //Hz frequency 1149 voicefreq *= 1150 powf(ctl.pitchwheel.relfreq, NoteVoicePar[nvoice].BendAdjust); //change the frequency by the controller 1151 setfreq(nvoice, voicefreq + NoteVoicePar[nvoice].OffsetHz); 1152 1153 /***************/ 1154 /* Modulator */ 1155 /***************/ 1156 1157 1158 if(NoteVoicePar[nvoice].FMEnabled != FMTYPE::NONE) { 1159 FMrelativepitch = NoteVoicePar[nvoice].FMDetune / 100.0f; 1160 if(NoteVoicePar[nvoice].FMFreqEnvelope) 1161 FMrelativepitch += 1162 NoteVoicePar[nvoice].FMFreqEnvelope->envout() / 100.0f; 1163 if (NoteVoicePar[nvoice].FMFreqFixed) 1164 FMfreq = powf(2.0f, FMrelativepitch / 12.0f) * 440.0f; 1165 else 1166 FMfreq = powf(2.0f, FMrelativepitch / 12.0f) * voicefreq; 1167 setfreqFM(nvoice, FMfreq); 1168 1169 vce.FMoldamplitude = vce.FMnewamplitude; 1170 vce.FMnewamplitude = NoteVoicePar[nvoice].FMVolume 1171 * ctl.fmamp.relamp; 1172 if(NoteVoicePar[nvoice].FMAmpEnvelope) 1173 vce.FMnewamplitude *= 1174 NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB(); 1175 } 1176 } 1177 } 1178 } 1179 1180 1181 /* 1182 * Fadein in a way that removes clicks but keep sound "punchy" 1183 */ 1184 inline void ADnote::fadein(float *smps) const 1185 { 1186 int zerocrossings = 0; 1187 for(int i = 1; i < synth.buffersize; ++i) 1188 if((smps[i - 1] < 0.0f) && (smps[i] > 0.0f)) 1189 zerocrossings++; //this is only the positive crossings 1190 1191 float tmp = (synth.buffersize_f - 1.0f) / (zerocrossings + 1) / 3.0f; 1192 if(tmp < 8.0f) 1193 tmp = 8.0f; 1194 tmp *= NoteGlobalPar.Fadein_adjustment; 1195 1196 int n; 1197 F2I(tmp, n); //how many samples is the fade-in 1198 if(n > synth.buffersize) 1199 n = synth.buffersize; 1200 for(int i = 0; i < n; ++i) { //fade-in 1201 const float tmp = 0.5f - cosf((float)i / (float) n * PI) * 0.5f; 1202 smps[i] *= tmp; 1203 } 1204 } 1205 1206 /* 1207 * Computes the Oscillator (Without Modulation) - LinearInterpolation 1208 */ 1209 1210 /* As the code here is a bit odd due to optimization, here is what happens 1211 * First the current position and frequency are retrieved from the running 1212 * state. These are broken up into high and low portions to indicate how many 1213 * samples are skipped in one step and how many fractional samples are skipped. 1214 * Outside of this method the fractional samples are just handled with floating 1215 * point code, but that's a bit slower than it needs to be. In this code the low 1216 * portions are known to exist between 0.0 and 1.0 and it is known that they are 1217 * stored in single precision floating point IEEE numbers. This implies that 1218 * a maximum of 24 bits are significant. The below code does your standard 1219 * linear interpolation that you'll see throughout this codebase, but by 1220 * sticking to integers for tracking the overflow of the low portion, around 15% 1221 * of the execution time was shaved off in the ADnote test. 1222 */ 1223 inline void ADnote::ComputeVoiceOscillator_LinearInterpolation(int nvoice) 1224 { 1225 Voice& vce = NoteVoicePar[nvoice]; 1226 for(int k = 0; k < vce.unison_size; ++k) { 1227 int poshi = vce.oscposhi[k]; 1228 // convert floating point fractional part (sample interval phase) 1229 // with range [0.0 ... 1.0] to fixed point with 1 digit is 2^-24 1230 // by multiplying with precalculated 2^24 and casting to integer: 1231 int poslo = (int)(vce.oscposlo[k] * 16777216.0f); 1232 int freqhi = vce.oscfreqhi[k]; 1233 // same for phase increment: 1234 int freqlo = (int)(vce.oscfreqlo[k] * 16777216.0f); 1235 float *smps = NoteVoicePar[nvoice].OscilSmp; 1236 float *tw = tmpwave_unison[k]; 1237 assert(vce.oscfreqlo[k] < 1.0f); 1238 for(int i = 0; i < synth.buffersize; ++i) { 1239 tw[i] = (smps[poshi] * (0x01000000 - poslo) + smps[poshi + 1] * poslo)/(16777216.0f); 1240 poslo += freqlo; // increment fractional part (sample interval phase) 1241 poshi += freqhi + (poslo>>24); // add overflow over 24 bits in poslo to poshi 1242 poslo &= 0xffffff; // remove overflow from poslo 1243 poshi &= synth.oscilsize - 1; // remove overflow 1244 } 1245 vce.oscposhi[k] = poshi; 1246 vce.oscposlo[k] = poslo/(16777216.0f); 1247 } 1248 } 1249 1250 1251 /* 1252 * Computes the Oscillator (Without Modulation) - windowed sinc Interpolation 1253 */ 1254 1255 /* As the code here is a bit odd due to optimization, here is what happens 1256 * First the current position and frequency are retrieved from the running 1257 * state. These are broken up into high and low portions to indicate how many 1258 * samples are skipped in one step and how many fractional samples are skipped. 1259 * Outside of this method the fractional samples are just handled with floating 1260 * point code, but that's a bit slower than it needs to be. In this code the low 1261 * portions are known to exist between 0.0 and 1.0 and it is known that they are 1262 * stored in single precision floating point IEEE numbers. This implies that 1263 * a maximum of 24 bits are significant. The below code does your standard 1264 * linear interpolation that you'll see throughout this codebase, but by 1265 * sticking to integers for tracking the overflow of the low portion, around 15% 1266 * of the execution time was shaved off in the ADnote test. 1267 */ 1268 inline void ADnote::ComputeVoiceOscillator_SincInterpolation(int nvoice) 1269 { 1270 // windowed sinc kernel factor Fs*0.3, rejection 80dB 1271 const float_t kernel[] = { 1272 0.0010596256917418426f, 1273 0.004273442181254887f, 1274 0.0035466063043375785f, 1275 -0.014555483937137638f, 1276 -0.04789321342588484f, 1277 -0.050800020978553066f, 1278 0.04679847159974432f, 1279 0.2610646708018185f, 1280 0.4964802251145513f, 1281 0.6000513532962539f, 1282 0.4964802251145513f, 1283 0.2610646708018185f, 1284 0.04679847159974432f, 1285 -0.050800020978553066f, 1286 -0.04789321342588484f, 1287 -0.014555483937137638f, 1288 0.0035466063043375785f, 1289 0.004273442181254887f, 1290 0.0010596256917418426f 1291 }; 1292 1293 1294 1295 Voice& vce = NoteVoicePar[nvoice]; 1296 for(int k = 0; k < vce.unison_size; ++k) { 1297 int poshi = vce.oscposhi[k]; 1298 int poslo = (int)(vce.oscposlo[k] * (1<<24)); 1299 int freqhi = vce.oscfreqhi[k]; 1300 int freqlo = (int)(vce.oscfreqlo[k] * (1<<24)); 1301 int ovsmpfreqhi = vce.oscfreqhi[k] / 2; 1302 int ovsmpfreqlo = (int)((vce.oscfreqlo[k] / 2) * (1<<24)); 1303 1304 int ovsmpposlo; 1305 int ovsmpposhi; 1306 int uflow; 1307 float *smps = NoteVoicePar[nvoice].OscilSmp; 1308 float *tw = tmpwave_unison[k]; 1309 assert(vce.oscfreqlo[k] < 1.0f); 1310 float out = 0; 1311 1312 for(int i = 0; i < synth.buffersize; ++i) { 1313 ovsmpposlo = poslo - (LENGTHOF(kernel)-1)/2 * ovsmpfreqlo; 1314 uflow = ovsmpposlo>>24; 1315 ovsmpposhi = poshi - (LENGTHOF(kernel)-1)/2 * ovsmpfreqhi - ((0x00 - uflow) & 0xff); 1316 ovsmpposlo &= 0xffffff; 1317 ovsmpposhi &= synth.oscilsize - 1; 1318 out = 0; 1319 for (int l = 0; l<LENGTHOF(kernel); l++) { 1320 out += kernel[l] * ( 1321 smps[ovsmpposhi] * ((1<<24) - ovsmpposlo) + 1322 smps[ovsmpposhi + 1] * ovsmpposlo)/(1.0f*(1<<24)); 1323 // advance to next kernel sample 1324 ovsmpposlo += ovsmpfreqlo; 1325 ovsmpposhi += ovsmpfreqhi + (ovsmpposlo>>24); // add the 24-bit overflow 1326 ovsmpposlo &= 0xffffff; 1327 ovsmpposhi &= synth.oscilsize - 1; 1328 1329 } 1330 1331 // advance to next sample 1332 poslo += freqlo; 1333 poshi += freqhi + (poslo>>24); 1334 poslo &= 0xffffff; 1335 poshi &= synth.oscilsize - 1; 1336 1337 tw[i] = out; 1338 1339 } 1340 vce.oscposhi[k] = poshi; 1341 vce.oscposlo[k] = poslo/(1.0f*(1<<24)); 1342 } 1343 } 1344 1345 1346 /* 1347 * Computes the Oscillator (Mixing) 1348 */ 1349 inline void ADnote::ComputeVoiceOscillatorMix(int nvoice) 1350 { 1351 ComputeVoiceOscillator_LinearInterpolation(nvoice); 1352 1353 Voice& vce = NoteVoicePar[nvoice]; 1354 if(vce.FMnewamplitude > 1.0f) 1355 vce.FMnewamplitude = 1.0f; 1356 if(vce.FMoldamplitude > 1.0f) 1357 vce.FMoldamplitude = 1.0f; 1358 1359 if(NoteVoicePar[nvoice].FMVoice >= 0) { 1360 //if I use VoiceOut[] as modullator 1361 int FMVoice = NoteVoicePar[nvoice].FMVoice; 1362 for(int k = 0; k < vce.unison_size; ++k) { 1363 float *tw = tmpwave_unison[k]; 1364 for(int i = 0; i < synth.buffersize; ++i) { 1365 const float amp = INTERPOLATE_AMPLITUDE(vce.FMoldamplitude, 1366 vce.FMnewamplitude, 1367 i, 1368 synth.buffersize); 1369 tw[i] = tw[i] 1370 * (1.0f - amp) + amp * NoteVoicePar[FMVoice].VoiceOut[i]; 1371 } 1372 } 1373 } 1374 else 1375 for(int k = 0; k < vce.unison_size; ++k) { 1376 int poshiFM = vce.oscposhiFM[k]; 1377 float posloFM = vce.oscposloFM[k]; 1378 int freqhiFM = vce.oscfreqhiFM[k]; 1379 float freqloFM = vce.oscfreqloFM[k]; 1380 float *tw = tmpwave_unison[k]; 1381 1382 for(int i = 0; i < synth.buffersize; ++i) { 1383 const float amp = INTERPOLATE_AMPLITUDE(vce.FMoldamplitude, 1384 vce.FMnewamplitude, 1385 i, 1386 synth.buffersize); 1387 tw[i] = tw[i] * (1.0f - amp) + amp 1388 * (NoteVoicePar[nvoice].FMSmp[poshiFM] * (1 - posloFM) 1389 + NoteVoicePar[nvoice].FMSmp[poshiFM + 1] * posloFM); 1390 posloFM += freqloFM; 1391 if(posloFM >= 1.0f) { 1392 posloFM -= 1.0f; 1393 poshiFM++; 1394 } 1395 poshiFM += freqhiFM; 1396 poshiFM &= synth.oscilsize - 1; 1397 } 1398 vce.oscposhiFM[k] = poshiFM; 1399 vce.oscposloFM[k] = posloFM; 1400 } 1401 } 1402 1403 /* 1404 * Computes the Oscillator (Ring Modulation) 1405 */ 1406 inline void ADnote::ComputeVoiceOscillatorRingModulation(int nvoice) 1407 { 1408 ComputeVoiceOscillator_LinearInterpolation(nvoice); 1409 1410 Voice& vce = NoteVoicePar[nvoice]; 1411 if(vce.FMnewamplitude > 1.0f) 1412 vce.FMnewamplitude = 1.0f; 1413 if(vce.FMoldamplitude > 1.0f) 1414 vce.FMoldamplitude = 1.0f; 1415 if(NoteVoicePar[nvoice].FMVoice >= 0) 1416 // if I use VoiceOut[] as modullator 1417 for(int k = 0; k < vce.unison_size; ++k) { 1418 float *tw = tmpwave_unison[k]; 1419 for(int i = 0; i < synth.buffersize; ++i) { 1420 const float amp = INTERPOLATE_AMPLITUDE(vce.FMoldamplitude, 1421 vce.FMnewamplitude, 1422 i, 1423 synth.buffersize); 1424 int FMVoice = NoteVoicePar[nvoice].FMVoice; 1425 tw[i] *= (1.0f - amp) + amp * NoteVoicePar[FMVoice].VoiceOut[i]; 1426 } 1427 } 1428 else 1429 for(int k = 0; k < vce.unison_size; ++k) { 1430 int poshiFM = vce.oscposhiFM[k]; 1431 float posloFM = vce.oscposloFM[k]; 1432 int freqhiFM = vce.oscfreqhiFM[k]; 1433 float freqloFM = vce.oscfreqloFM[k]; 1434 float *tw = tmpwave_unison[k]; 1435 1436 for(int i = 0; i < synth.buffersize; ++i) { 1437 const float amp = INTERPOLATE_AMPLITUDE(vce.FMoldamplitude, 1438 vce.FMnewamplitude, 1439 i, 1440 synth.buffersize); 1441 tw[i] *= (NoteVoicePar[nvoice].FMSmp[poshiFM] * (1.0f - posloFM) 1442 + NoteVoicePar[nvoice].FMSmp[poshiFM 1443 + 1] * posloFM) * amp 1444 + (1.0f - amp); 1445 posloFM += freqloFM; 1446 if(posloFM >= 1.0f) { 1447 posloFM -= 1.0f; 1448 poshiFM++; 1449 } 1450 poshiFM += freqhiFM; 1451 poshiFM &= synth.oscilsize - 1; 1452 } 1453 vce.oscposhiFM[k] = poshiFM; 1454 vce.oscposloFM[k] = posloFM; 1455 } 1456 } 1457 1458 /* 1459 * Computes the Oscillator (Phase Modulation or Frequency Modulation) 1460 */ 1461 inline void ADnote::ComputeVoiceOscillatorFrequencyModulation(int nvoice, 1462 FMTYPE FMmode) 1463 { 1464 Voice& vce = NoteVoicePar[nvoice]; 1465 if(NoteVoicePar[nvoice].FMVoice >= 0) { 1466 //if I use VoiceOut[] as modulator 1467 for(int k = 0; k < vce.unison_size; ++k) { 1468 float *tw = tmpwave_unison[k]; 1469 const float *smps = NoteVoicePar[NoteVoicePar[nvoice].FMVoice].VoiceOut; 1470 if (FMmode == FMTYPE::PW_MOD && (k & 1)) 1471 for (int i = 0; i < synth.buffersize; ++i) 1472 tw[i] = -smps[i]; 1473 else 1474 memcpy(tw, smps, synth.bufferbytes); 1475 } 1476 } else { 1477 //Compute the modulator and store it in tmpwave_unison[][] 1478 for(int k = 0; k < vce.unison_size; ++k) { 1479 int poshiFM = vce.oscposhiFM[k]; 1480 int posloFM = (int)(vce.oscposloFM[k] * (1<<24)); 1481 int freqhiFM = vce.oscfreqhiFM[k]; 1482 int freqloFM = (int)(vce.oscfreqloFM[k] * (1<<24)); 1483 float *tw = tmpwave_unison[k]; 1484 const float *smps = NoteVoicePar[nvoice].FMSmp; 1485 1486 for(int i = 0; i < synth.buffersize; ++i) { 1487 tw[i] = (smps[poshiFM] * ((1<<24) - posloFM) 1488 + smps[poshiFM + 1] * posloFM) / (1.0f*(1<<24)); 1489 if (FMmode == FMTYPE::PW_MOD && (k & 1)) 1490 tw[i] = -tw[i]; 1491 1492 posloFM += freqloFM; 1493 if(posloFM >= (1<<24)) { 1494 posloFM &= 0xffffff;//fmod(posloFM, 1.0f); 1495 poshiFM++; 1496 } 1497 poshiFM += freqhiFM; 1498 poshiFM &= synth.oscilsize - 1; 1499 } 1500 vce.oscposhiFM[k] = poshiFM; 1501 vce.oscposloFM[k] = posloFM/((1<<24)*1.0f); 1502 } 1503 } 1504 // Amplitude interpolation 1505 if(ABOVE_AMPLITUDE_THRESHOLD(vce.FMoldamplitude, 1506 vce.FMnewamplitude)) { 1507 for(int k = 0; k < vce.unison_size; ++k) { 1508 float *tw = tmpwave_unison[k]; 1509 for(int i = 0; i < synth.buffersize; ++i) 1510 tw[i] *= INTERPOLATE_AMPLITUDE(vce.FMoldamplitude, 1511 vce.FMnewamplitude, 1512 i, 1513 synth.buffersize); 1514 } 1515 } else { 1516 for(int k = 0; k < vce.unison_size; ++k) { 1517 float *tw = tmpwave_unison[k]; 1518 for(int i = 0; i < synth.buffersize; ++i) 1519 tw[i] *= vce.FMnewamplitude; 1520 } 1521 } 1522 1523 1524 //normalize: makes all sample-rates, oscil_sizes to produce same sound 1525 if(FMmode == FMTYPE::FREQ_MOD) { //Frequency modulation 1526 const float normalize = synth.oscilsize_f / 262144.0f * 44100.0f 1527 / synth.samplerate_f; 1528 for(int k = 0; k < vce.unison_size; ++k) { 1529 float *tw = tmpwave_unison[k]; 1530 float fmold = vce.FMoldsmp[k]; 1531 for(int i = 0; i < synth.buffersize; ++i) { 1532 fmold = fmodf(fmold + tw[i] * normalize, synth.oscilsize); 1533 tw[i] = fmold; 1534 } 1535 vce.FMoldsmp[k] = fmold; 1536 } 1537 } 1538 else { //Phase or PWM modulation 1539 const float normalize = synth.oscilsize_f / 262144.0f; 1540 for(int k = 0; k < vce.unison_size; ++k) { 1541 float *tw = tmpwave_unison[k]; 1542 for(int i = 0; i < synth.buffersize; ++i) 1543 tw[i] *= normalize; 1544 } 1545 } 1546 1547 //do the modulation 1548 for(int k = 0; k < vce.unison_size; ++k) { 1549 float *smps = NoteVoicePar[nvoice].OscilSmp; 1550 float *tw = tmpwave_unison[k]; 1551 int poshi = vce.oscposhi[k]; 1552 int poslo = (int)(vce.oscposlo[k] * (1<<24)); 1553 int freqhi = vce.oscfreqhi[k]; 1554 int freqlo = (int)(vce.oscfreqlo[k] * (1<<24)); 1555 1556 for(int i = 0; i < synth.buffersize; ++i) { 1557 int FMmodfreqhi = 0; 1558 F2I(tw[i], FMmodfreqhi); 1559 float FMmodfreqlo = tw[i]-FMmodfreqhi;//fmod(tw[i] /*+ 0.0000000001f*/, 1.0f); 1560 if(FMmodfreqhi < 0) 1561 FMmodfreqlo++; 1562 1563 //carrier 1564 int carposhi = poshi + FMmodfreqhi; 1565 int carposlo = (int)(poslo + FMmodfreqlo); 1566 if (FMmode == FMTYPE::PW_MOD && (k & 1)) 1567 carposhi += NoteVoicePar[nvoice].phase_offset; 1568 1569 if(carposlo >= (1<<24)) { 1570 carposhi++; 1571 carposlo &= 0xffffff;//fmod(carposlo, 1.0f); 1572 } 1573 carposhi &= (synth.oscilsize - 1); 1574 1575 tw[i] = (smps[carposhi] * ((1<<24) - carposlo) 1576 + smps[carposhi + 1] * carposlo)/(1.0f*(1<<24)); 1577 1578 poslo += freqlo; 1579 if(poslo >= (1<<24)) { 1580 poslo &= 0xffffff;//fmod(poslo, 1.0f); 1581 poshi++; 1582 } 1583 1584 poshi += freqhi; 1585 poshi &= synth.oscilsize - 1; 1586 } 1587 vce.oscposhi[k] = poshi; 1588 vce.oscposlo[k] = (poslo)/((1<<24)*1.0f); 1589 } 1590 } 1591 1592 1593 /* 1594 * Computes the Noise 1595 */ 1596 inline void ADnote::ComputeVoiceWhiteNoise(int nvoice) 1597 { 1598 for(int k = 0; k < NoteVoicePar[nvoice].unison_size; ++k) { 1599 float *tw = tmpwave_unison[k]; 1600 for(int i = 0; i < synth.buffersize; ++i) 1601 tw[i] = RND * 2.0f - 1.0f; 1602 } 1603 } 1604 1605 inline void ADnote::ComputeVoicePinkNoise(int nvoice) 1606 { 1607 Voice& vce = NoteVoicePar[nvoice]; 1608 for(int k = 0; k < vce.unison_size; ++k) { 1609 float *tw = tmpwave_unison[k]; 1610 float *f = &vce.pinking[k > 0 ? 7 : 0]; 1611 for(int i = 0; i < synth.buffersize; ++i) { 1612 const float white = (RND-0.5f)/4.0f; 1613 f[0] = 0.99886f*f[0]+white*0.0555179f; 1614 f[1] = 0.99332f*f[1]+white*0.0750759f; 1615 f[2] = 0.96900f*f[2]+white*0.1538520f; 1616 f[3] = 0.86650f*f[3]+white*0.3104856f; 1617 f[4] = 0.55000f*f[4]+white*0.5329522f; 1618 f[5] = -0.7616f*f[5]-white*0.0168980f; 1619 tw[i] = f[0]+f[1]+f[2]+f[3]+f[4]+f[5]+f[6]+white*0.5362f; 1620 f[6] = white*0.115926f; 1621 } 1622 } 1623 } 1624 1625 inline void ADnote::ComputeVoiceDC(int nvoice) 1626 { 1627 for(int k = 0; k < NoteVoicePar[nvoice].unison_size; ++k) { 1628 float *tw = tmpwave_unison[k]; 1629 for(int i = 0; i < synth.buffersize; ++i) 1630 tw[i] = 1.0f; 1631 } 1632 } 1633 1634 1635 1636 /* 1637 * Compute the ADnote samples 1638 * Returns 0 if the note is finished 1639 */ 1640 int ADnote::noteout(float *outl, float *outr) 1641 { 1642 memcpy(outl, synth.denormalkillbuf, synth.bufferbytes); 1643 memcpy(outr, synth.denormalkillbuf, synth.bufferbytes); 1644 1645 if(NoteEnabled == OFF) 1646 return 0; 1647 1648 memset(bypassl, 0, synth.bufferbytes); 1649 memset(bypassr, 0, synth.bufferbytes); 1650 1651 //Update Changed Parameters From UI 1652 for(unsigned nvoice = 0; nvoice < NUM_VOICES; ++nvoice) { 1653 if((NoteVoicePar[nvoice].Enabled != ON) 1654 || (NoteVoicePar[nvoice].DelayTicks > 0)) 1655 continue; 1656 setupVoiceDetune(nvoice); 1657 setupVoiceMod(nvoice, false); 1658 } 1659 1660 computecurrentparameters(); 1661 1662 for(unsigned nvoice = 0; nvoice < NUM_VOICES; ++nvoice) { 1663 if((NoteVoicePar[nvoice].Enabled != ON) 1664 || (NoteVoicePar[nvoice].DelayTicks > 0)) 1665 continue; 1666 switch (NoteVoicePar[nvoice].noisetype) { 1667 case 0: //voice mode=sound 1668 switch(NoteVoicePar[nvoice].FMEnabled) { 1669 case FMTYPE::MIX: 1670 ComputeVoiceOscillatorMix(nvoice); 1671 break; 1672 case FMTYPE::RING_MOD: 1673 ComputeVoiceOscillatorRingModulation(nvoice); 1674 break; 1675 case FMTYPE::FREQ_MOD: 1676 case FMTYPE::PHASE_MOD: 1677 case FMTYPE::PW_MOD: 1678 ComputeVoiceOscillatorFrequencyModulation(nvoice, 1679 NoteVoicePar[nvoice].FMEnabled); 1680 break; 1681 default: 1682 if(NoteVoicePar[nvoice].AAEnabled) ComputeVoiceOscillator_SincInterpolation(nvoice); 1683 else ComputeVoiceOscillator_LinearInterpolation(nvoice); 1684 //if (config.cfg.Interpolation) ComputeVoiceOscillator_CubicInterpolation(nvoice); 1685 } 1686 break; 1687 case 1: 1688 ComputeVoiceWhiteNoise(nvoice); 1689 break; 1690 case 2: 1691 ComputeVoicePinkNoise(nvoice); 1692 break; 1693 default: 1694 ComputeVoiceDC(nvoice); 1695 break; 1696 } 1697 // Voice Processing 1698 1699 Voice& vce = NoteVoicePar[nvoice]; 1700 //mix subvoices into voice 1701 memset(tmpwavel, 0, synth.bufferbytes); 1702 if(stereo) 1703 memset(tmpwaver, 0, synth.bufferbytes); 1704 for(int k = 0; k < vce.unison_size; ++k) { 1705 float *tw = tmpwave_unison[k]; 1706 if(stereo) { 1707 float stereo_pos = 0; 1708 bool is_pwm = NoteVoicePar[nvoice].FMEnabled == FMTYPE::PW_MOD; 1709 if (is_pwm) { 1710 if(vce.unison_size > 2) 1711 stereo_pos = k/2 1712 / (float)(vce.unison_size/2 1713 - 1) * 2.0f - 1.0f; 1714 } else if(vce.unison_size > 1) { 1715 stereo_pos = k 1716 / (float)(vce.unison_size 1717 - 1) * 2.0f - 1.0f; 1718 } 1719 float stereo_spread = vce.unison_stereo_spread * 2.0f; //between 0 and 2.0f 1720 if(stereo_spread > 1.0f) { 1721 float stereo_pos_1 = (stereo_pos >= 0.0f) ? 1.0f : -1.0f; 1722 stereo_pos = 1723 (2.0f 1724 - stereo_spread) * stereo_pos 1725 + (stereo_spread - 1.0f) * stereo_pos_1; 1726 } 1727 else 1728 stereo_pos *= stereo_spread; 1729 1730 if(vce.unison_size == 1 || 1731 (is_pwm && vce.unison_size == 2)) 1732 stereo_pos = 0.0f; 1733 float panning = (stereo_pos + 1.0f) * 0.5f; 1734 1735 1736 float lvol = (1.0f - panning) * 2.0f; 1737 if(lvol > 1.0f) 1738 lvol = 1.0f; 1739 1740 float rvol = panning * 2.0f; 1741 if(rvol > 1.0f) 1742 rvol = 1.0f; 1743 1744 if(vce.unison_invert_phase[k]) { 1745 lvol = -lvol; 1746 rvol = -rvol; 1747 } 1748 1749 for(int i = 0; i < synth.buffersize; ++i) 1750 tmpwavel[i] += tw[i] * lvol; 1751 for(int i = 0; i < synth.buffersize; ++i) 1752 tmpwaver[i] += tw[i] * rvol; 1753 } 1754 else 1755 for(int i = 0; i < synth.buffersize; ++i) 1756 tmpwavel[i] += tw[i]; 1757 if(nvoice == 0) 1758 watch_be4_add(tmpwavel,synth.buffersize); 1759 } 1760 1761 float unison_amplitude = 1.0f / sqrtf(vce.unison_size); //reduce the amplitude for large unison sizes 1762 // Amplitude 1763 float oldam = vce.oldamplitude * unison_amplitude; 1764 float newam = vce.newamplitude * unison_amplitude; 1765 1766 if(ABOVE_AMPLITUDE_THRESHOLD(oldam, newam)) { 1767 int rest = synth.buffersize; 1768 //test if the amplitude if raising and the difference is high 1769 if((newam > oldam) && ((newam - oldam) > 0.25f)) { 1770 rest = 10; 1771 if(rest > synth.buffersize) 1772 rest = synth.buffersize; 1773 for(int i = 0; i < synth.buffersize - rest; ++i) 1774 tmpwavel[i] *= oldam; 1775 if(stereo) 1776 for(int i = 0; i < synth.buffersize - rest; ++i) 1777 tmpwaver[i] *= oldam; 1778 } 1779 // Amplitude interpolation 1780 for(int i = 0; i < rest; ++i) { 1781 float amp = INTERPOLATE_AMPLITUDE(oldam, newam, i, rest); 1782 tmpwavel[i + (synth.buffersize - rest)] *= amp; 1783 if(stereo) 1784 tmpwaver[i + (synth.buffersize - rest)] *= amp; 1785 } 1786 } 1787 else { 1788 for(int i = 0; i < synth.buffersize; ++i) 1789 tmpwavel[i] *= newam; 1790 if(stereo) 1791 for(int i = 0; i < synth.buffersize; ++i) 1792 tmpwaver[i] *= newam; 1793 } 1794 1795 // Fade in 1796 if(vce.firsttick != 0) { 1797 fadein(&tmpwavel[0]); 1798 if(stereo) 1799 fadein(&tmpwaver[0]); 1800 vce.firsttick = 0; 1801 } 1802 1803 // Filter 1804 if(NoteVoicePar[nvoice].Filter) { 1805 if(stereo) 1806 NoteVoicePar[nvoice].Filter->filter(tmpwavel, tmpwaver); 1807 else 1808 NoteVoicePar[nvoice].Filter->filter(tmpwavel, 0); 1809 } 1810 1811 //check if the amplitude envelope is finished, if yes, the voice will be fadeout 1812 if(NoteVoicePar[nvoice].AmpEnvelope) 1813 if(NoteVoicePar[nvoice].AmpEnvelope->finished()) { 1814 for(int i = 0; i < synth.buffersize; ++i) 1815 tmpwavel[i] *= 1.0f - (float)i / synth.buffersize_f; 1816 if(stereo) 1817 for(int i = 0; i < synth.buffersize; ++i) 1818 tmpwaver[i] *= 1.0f - (float)i / synth.buffersize_f; 1819 } 1820 //the voice is killed later 1821 1822 1823 // Put the ADnote samples in VoiceOut (without applying Global volume, because I wish to use this voice as a modullator) 1824 if(NoteVoicePar[nvoice].VoiceOut) { 1825 if(stereo) 1826 for(int i = 0; i < synth.buffersize; ++i) 1827 NoteVoicePar[nvoice].VoiceOut[i] = tmpwavel[i] 1828 + tmpwaver[i]; 1829 else //mono 1830 for(int i = 0; i < synth.buffersize; ++i) 1831 NoteVoicePar[nvoice].VoiceOut[i] = tmpwavel[i]; 1832 } 1833 1834 1835 // Add the voice that do not bypass the filter to out 1836 if(NoteVoicePar[nvoice].filterbypass == 0) { //no bypass 1837 if(stereo) 1838 for(int i = 0; i < synth.buffersize; ++i) { //stereo 1839 outl[i] += tmpwavel[i] * NoteVoicePar[nvoice].Volume 1840 * (1.0f - NoteVoicePar[nvoice].Panning) * 2.0f; 1841 outr[i] += tmpwaver[i] * NoteVoicePar[nvoice].Volume 1842 * NoteVoicePar[nvoice].Panning * 2.0f; 1843 } 1844 else 1845 for(int i = 0; i < synth.buffersize; ++i) //mono 1846 outl[i] += tmpwavel[i] * NoteVoicePar[nvoice].Volume; 1847 } 1848 else { //bypass the filter 1849 if(stereo) 1850 for(int i = 0; i < synth.buffersize; ++i) { //stereo 1851 bypassl[i] += tmpwavel[i] * NoteVoicePar[nvoice].Volume 1852 * (1.0f 1853 - NoteVoicePar[nvoice].Panning) * 2.0f; 1854 bypassr[i] += tmpwaver[i] * NoteVoicePar[nvoice].Volume 1855 * NoteVoicePar[nvoice].Panning * 2.0f; 1856 } 1857 else 1858 for(int i = 0; i < synth.buffersize; ++i) //mono 1859 bypassl[i] += tmpwavel[i] * NoteVoicePar[nvoice].Volume; 1860 } 1861 // check if there is necessary to process the voice longer (if the Amplitude envelope isn't finished) 1862 if(NoteVoicePar[nvoice].AmpEnvelope) 1863 if(NoteVoicePar[nvoice].AmpEnvelope->finished()) 1864 KillVoice(nvoice); 1865 } 1866 1867 //Processing Global parameters 1868 if(stereo) { 1869 NoteGlobalPar.Filter->filter(outl, outr); 1870 } else { //set the right channel=left channel 1871 NoteGlobalPar.Filter->filter(outl, 0); 1872 memcpy(outr, outl, synth.bufferbytes); 1873 memcpy(bypassr, bypassl, synth.bufferbytes); 1874 } 1875 1876 for(int i = 0; i < synth.buffersize; ++i) { 1877 outl[i] += bypassl[i]; 1878 outr[i] += bypassr[i]; 1879 } 1880 1881 if(ABOVE_AMPLITUDE_THRESHOLD(globaloldamplitude, globalnewamplitude)) 1882 // Amplitude Interpolation 1883 for(int i = 0; i < synth.buffersize; ++i) { 1884 float tmpvol = INTERPOLATE_AMPLITUDE(globaloldamplitude, 1885 globalnewamplitude, 1886 i, 1887 synth.buffersize); 1888 outl[i] *= tmpvol * (1.0f - NoteGlobalPar.Panning); 1889 outr[i] *= tmpvol * NoteGlobalPar.Panning; 1890 } 1891 else 1892 for(int i = 0; i < synth.buffersize; ++i) { 1893 outl[i] *= globalnewamplitude * (1.0f - NoteGlobalPar.Panning); 1894 outr[i] *= globalnewamplitude * NoteGlobalPar.Panning; 1895 } 1896 1897 //Apply the punch 1898 if(NoteGlobalPar.Punch.Enabled != 0) 1899 for(int i = 0; i < synth.buffersize; ++i) { 1900 float punchamp = NoteGlobalPar.Punch.initialvalue 1901 * NoteGlobalPar.Punch.t + 1.0f; 1902 outl[i] *= punchamp; 1903 outr[i] *= punchamp; 1904 NoteGlobalPar.Punch.t -= NoteGlobalPar.Punch.dt; 1905 if(NoteGlobalPar.Punch.t < 0.0f) { 1906 NoteGlobalPar.Punch.Enabled = 0; 1907 break; 1908 } 1909 } 1910 1911 watch_punch(outl, synth.buffersize); 1912 watch_after_add(outl,synth.buffersize); 1913 1914 // Apply legato-specific sound signal modifications 1915 legato.apply(*this, outl, outr); 1916 1917 watch_legato(outl, synth.buffersize); 1918 1919 // Check if the global amplitude is finished. 1920 // If it does, disable the note 1921 if(NoteGlobalPar.AmpEnvelope->finished()) { 1922 for(int i = 0; i < synth.buffersize; ++i) { //fade-out 1923 float tmp = 1.0f - (float)i / synth.buffersize_f; 1924 outl[i] *= tmp; 1925 outr[i] *= tmp; 1926 } 1927 KillNote(); 1928 } 1929 return 1; 1930 } 1931 1932 1933 /* 1934 * Release the key (NoteOff) 1935 */ 1936 void ADnote::releasekey() 1937 { 1938 for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice) 1939 NoteVoicePar[nvoice].releasekey(); 1940 NoteGlobalPar.FreqEnvelope->releasekey(); 1941 NoteGlobalPar.FilterEnvelope->releasekey(); 1942 NoteGlobalPar.AmpEnvelope->releasekey(); 1943 NoteGlobalPar.FreqLfo->releasekey(); 1944 NoteGlobalPar.FilterLfo->releasekey(); 1945 NoteGlobalPar.AmpLfo->releasekey(); 1946 } 1947 1948 /* 1949 * Check if the note is finished 1950 */ 1951 bool ADnote::finished() const 1952 { 1953 if(NoteEnabled == ON) 1954 return 0; 1955 else 1956 return 1; 1957 } 1958 1959 void ADnote::entomb(void) 1960 { 1961 NoteGlobalPar.AmpEnvelope->forceFinish(); 1962 } 1963 1964 void ADnote::Voice::releasekey() 1965 { 1966 if(!Enabled) 1967 return; 1968 if(AmpEnvelope) 1969 AmpEnvelope->releasekey(); 1970 if(FreqEnvelope) 1971 FreqEnvelope->releasekey(); 1972 if(FilterEnvelope) 1973 FilterEnvelope->releasekey(); 1974 if(FMFreqEnvelope) 1975 FMFreqEnvelope->releasekey(); 1976 if(FMAmpEnvelope) 1977 FMAmpEnvelope->releasekey(); 1978 } 1979 1980 void ADnote::Voice::kill(Allocator &memory, const SYNTH_T &synth) 1981 { 1982 memory.devalloc(OscilSmp); 1983 memory.dealloc(FreqEnvelope); 1984 memory.dealloc(FreqLfo); 1985 memory.dealloc(AmpEnvelope); 1986 memory.dealloc(AmpLfo); 1987 memory.dealloc(Filter); 1988 memory.dealloc(FilterEnvelope); 1989 memory.dealloc(FilterLfo); 1990 memory.dealloc(FMFreqEnvelope); 1991 memory.dealloc(FMAmpEnvelope); 1992 1993 if((FMEnabled != FMTYPE::NONE) && (FMVoice < 0)) 1994 memory.devalloc(FMSmp); 1995 1996 if(VoiceOut) 1997 memset(VoiceOut, 0, synth.bufferbytes); 1998 //the buffer can't be safely deleted as it may be 1999 //an input to another voice 2000 2001 Enabled = OFF; 2002 } 2003 2004 void ADnote::Global::kill(Allocator &memory) 2005 { 2006 memory.dealloc(FreqEnvelope); 2007 memory.dealloc(FreqLfo); 2008 memory.dealloc(AmpEnvelope); 2009 memory.dealloc(AmpLfo); 2010 memory.dealloc(Filter); 2011 memory.dealloc(FilterEnvelope); 2012 memory.dealloc(FilterLfo); 2013 } 2014 2015 void ADnote::Global::initparameters(const ADnoteGlobalParam ¶m, 2016 const SYNTH_T &synth, 2017 const AbsTime &time, 2018 class Allocator &memory, 2019 float basefreq, float velocity, 2020 bool stereo, 2021 WatchManager *wm, 2022 const char *prefix) 2023 { 2024 ScratchString pre = prefix; 2025 FreqEnvelope = memory.alloc<Envelope>(*param.FreqEnvelope, basefreq, 2026 synth.dt(), wm, (pre+"GlobalPar/FreqEnvelope/").c_str); 2027 FreqLfo = memory.alloc<LFO>(*param.FreqLfo, basefreq, time, wm, 2028 (pre+"GlobalPar/FreqLfo/").c_str); 2029 2030 AmpEnvelope = memory.alloc<Envelope>(*param.AmpEnvelope, basefreq, 2031 synth.dt(), wm, (pre+"GlobalPar/AmpEnvelope/").c_str); 2032 AmpLfo = memory.alloc<LFO>(*param.AmpLfo, basefreq, time, wm, 2033 (pre+"GlobalPar/AmpLfo/").c_str); 2034 2035 Volume = dB2rap(param.Volume) 2036 * VelF(velocity, param.PAmpVelocityScaleFunction); //sensing 2037 2038 Filter = memory.alloc<ModFilter>(*param.GlobalFilter, synth, time, memory, 2039 stereo, basefreq); 2040 2041 FilterEnvelope = memory.alloc<Envelope>(*param.FilterEnvelope, basefreq, 2042 synth.dt(), wm, (pre+"GlobalPar/FilterEnvelope/").c_str); 2043 FilterLfo = memory.alloc<LFO>(*param.FilterLfo, basefreq, time, wm, 2044 (pre+"GlobalPar/FilterLfo/").c_str); 2045 2046 Filter->addMod(*FilterEnvelope); 2047 Filter->addMod(*FilterLfo); 2048 2049 { 2050 Filter->updateSense(velocity, param.PFilterVelocityScale, 2051 param.PFilterVelocityScaleFunction); 2052 } 2053 } 2054 2055 }