1 module pixelperfectengine.audio.modules.qm816; 2 3 import pixelperfectengine.audio.base.modulebase; 4 import pixelperfectengine.audio.base.envgen; 5 import pixelperfectengine.audio.base.func; 6 7 import pixelperfectengine.system.etc : hashCalc; 8 9 import midi2.types.structs; 10 import midi2.types.enums; 11 12 import inteli.emmintrin; 13 14 import bitleveld.reinterpret; 15 16 import std.math; 17 18 /** 19 QM816 - implements a Quadrature-Amplitude synthesizer. This technique was used in early 20 digital FM synths, since it allowed allowed a cheap implementation of the same thing as 21 long as the modulator was a sinusoidal waveform. 22 23 It has 16 2 operator channels that can be individually paired-up for 4 operator channels, 24 for more complex sounds. Also all operators have the option for feedback, including 25 carriers. 2 operator channels have 2, 4 operator channels have 3*4 algorithms. 26 27 The audio module generates a few default waveforms upon startup, but further ones can be 28 supplied from files, or generated by code. Some waveform generation code is already 29 supplied with the synth's code. 30 */ 31 public class QM816 : AudioModule { 32 shared static this() { 33 34 for (int i ; i < 128 ; i++) { 35 ADSR_TIME_TABLE[i] = pow(i / 64.0, 1.8); 36 } 37 } 38 /** 39 Generates a waveform from a sinewave fragment (quarter). 40 41 q flags: 42 bit 0 = If set, then the sine fragment is present. If not, this portion will be replaced with all zeros instead. 43 bit 1-2 = Doubling mode: 44 0 = No doubling. 45 1 = Same cycle twice. 46 2 = Same cycle mirrored, effectively putting a half-sine into a quarter with the right settings. 47 3 = The second half is all zeros, the sine fragment is effectively "stuffed" into an eight of the waveform. 48 bit 3 = Horizontal mirroring of the cycle. 49 bit 4 = Vertical mirroring of the cycle. 50 bit 5 = Modifies the curve of the sinewave for a bit more square-ish shape. 51 */ 52 public static short[1024] generateSinewave(ubyte[4] q) @nogc @safe pure nothrow { 53 short sineWave(int i, bool shape) @nogc @safe pure nothrow { 54 real val = sin((PI_2 / 256) * i); 55 if (shape) { 56 if (val > 0) return cast(short)(sqrt(val) * short.max); 57 else if (val < 0) return cast(short)(sqrt(val * -1) * short.max * -1); 58 else return 0; 59 } else return cast(short)(val * short.max); 60 } 61 short[1024] result; 62 for (int j ; j < 4 ; j++) { 63 if (q[j] & 1) { 64 const int offset = 256 * j; 65 const int hMir = q[j] & 0x8 ? 256 : 0; 66 //int hBegin = q[j] & 0x8 ? 255 : 0; 67 //const int vOffset = q[j] & 0x10 ? -1 : 0; 68 const int vMir = q[j] & 0x10 ? 512 : 0; 69 const bool shape = q[j] & 0x20 ? true : false; 70 //const short[256] fragment = SINEWAVE_FRAGMENT; 71 switch (q[j]>>1 & 3) { 72 case 1: 73 for (int i ; i < 256 ; i++) { 74 result[offset + i] = sineWave(((i * 2) & 255) + hMir + vMir, shape); 75 } 76 break; 77 case 2: 78 for (int i ; i < 128 ; i++) { 79 result[offset + i] = sineWave(((i * 2) & 255) + hMir + vMir, shape); 80 } 81 for (int i ; i < 128 ; i++) { 82 result[offset + i + 128] = sineWave((((127 - i) * 2) & 255) + hMir + vMir, shape); 83 } 84 break; 85 case 3: 86 for (int i ; i < 128 ; i++) { 87 result[offset + i] = sineWave(((i * 2) & 255) + hMir + vMir, shape); 88 } 89 break; 90 default: 91 for (int i ; i < 256 ; i++) { 92 result[offset + i] = sineWave(i + hMir + vMir, shape); 93 } 94 break; 95 } 96 /+const int offset = 256 * j; 97 int hMir = q[j] & 0x8 ? -1 : 1; 98 int hBegin = q[j] & 0x8 ? 255 : 0; 99 const int vOffset = q[j] & 0x10 ? -1 : 0; 100 const int vMir = q[j] & 0x10 ? -1 : 1; 101 const short[256] fragment = SINEWAVE_FRAGMENT; 102 switch (q[j]>>1 & 3) { 103 case 1: 104 hMir *= 2; 105 for (int i ; i < 256 ; i++) { 106 result[offset + i] = cast(short)(fragment[(hBegin + hMir * i) & 255] * vMir + vOffset); 107 } 108 break; 109 case 2: 110 hMir *= 2; 111 for (int i ; i < 128 ; i++) { 112 result[offset + i] = cast(short)(fragment[(hBegin + hMir * i) & 255] * vMir + vOffset); 113 } 114 hMir *= -1; 115 hBegin = q[j] & 0x8 ? 0 : 255; 116 for (int i ; i < 128 ; i++) { 117 result[offset + i + 128] = cast(short)(fragment[(hBegin + hMir * i) & 255] * vMir + vOffset); 118 } 119 break; 120 case 3: 121 hMir *= 2; 122 for (int i ; i < 128 ; i++) { 123 result[offset + i] = cast(short)(fragment[(hBegin + hMir * i) & 255] * vMir + vOffset); 124 } 125 break; 126 default: 127 for (int i ; i < 256 ; i++) { 128 result[offset + i] = cast(short)(fragment[hBegin + hMir * i] * vMir + vOffset); 129 } 130 break; 131 }+/ 132 } 133 } 134 return result; 135 } 136 /** 137 Generates a pulse wave. 138 139 `width` controls the pulse width. 140 */ 141 public static short[1024] generatePulseWave(int width = 512) @nogc @safe pure nothrow { 142 short[1024] result; 143 for (int i ; i < 1024 ; i++) { 144 result[i] = i < width ? short.max : short.min; 145 } 146 return result; 147 } 148 /** 149 Generates a triangular waveform. 150 `shape` controls the shape of the triangular waveform, allowing it to be morphed between triangle, saw, and ramp. 151 `` 152 */ 153 public static short[1024] generateTriangularWave(int shape = 512) @nogc @safe pure nothrow { 154 import pixelperfectengine.system.etc : clamp; 155 short[1024] result; 156 int state; 157 const int upwardSlope = ushort.max / shape; 158 const int downwardSlope = ushort.max / (1024 - shape); 159 for (int i ; i < shape / 2 ; i++) { 160 state += upwardSlope; 161 clamp(state, short.min, short.max); 162 result[i] = cast(short)state; 163 } 164 for (int i = shape / 2 ; i < (shape / 2) + (1024 - shape) ; i++) { 165 state -= downwardSlope; 166 clamp(state, short.min, short.max); 167 result[i] = cast(short)state; 168 } 169 for (int i = (shape / 2) + (1024 - shape) ; i < 1024 ; i++) { 170 state += upwardSlope; 171 clamp(state, short.min, short.max); 172 result[i] = cast(short)state; 173 } 174 return result; 175 } 176 public static short[1024] integrateTriangularWave(short[1024] input) @nogc @safe pure nothrow { 177 import pixelperfectengine.system.etc : clamp; 178 short[1024] result; 179 for (int i ; i < input.length ; i++) { 180 result[i] = cast(short)((input[i] * input[i] * (input[i] < 0 ? -1 : 1))>>16); 181 } 182 return result; 183 } 184 /** 185 Contains a table to calculate Attack, Decay, and Release values. 186 187 All values are seconds with factions. Actual values are live-calculated depending on sustain-level and sampling 188 frequency. 189 190 Current formula for the ADSR time table: 191 192 yn = (x/64)^1.8 193 */ 194 public static immutable float[128] ADSR_TIME_TABLE; 195 /** 196 Contains a table to calculate Sustain control values. 197 198 All values are seconds with fractions. Actual values are live-calculated depending on sustain level and sampling 199 frequency. Please note that with certain levels of sustain, the actual max time might be altered. 200 */ 201 public static immutable float[63] SUSTAIN_CONTROL_TIME_TABLE = [ 202 // 0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |A |B |C |D |E |F 203 70.00, 60.00, 55.00, 50.00, 45.00, 42.50, 40.00, 38.50, 35.00, 32.50, 30.00, 27.50, 25.00, 24.00, 23.00, 22.00,//0 204 21.00, 20.00, 19.00, 18.00, 17.50, 17.00, 16.50, 16.00, 15.50, 15.00, 14.50, 14.00, 13.50, 13.00, 12.50, 12.25,//1 205 12.00, 11.75, 11.50, 11.25, 11.00, 10.75, 10.50, 10.25, 10.00, 9.750, 9.500, 9.250, 9.000, 8.750, 8.500, 8.250,//2 206 8.000, 7.750, 7.500, 7.250, 7.000, 6.750, 6.500, 6.250, 6.000, 5.750, 5.500, 5.250, 5.000, 4.750, 4.500 //3 207 ]; 208 /** 209 Used for quick resampling of the 55.5/60kHz output to 44.4/48kHz. 210 211 So far this has the best results. 212 */ 213 public static immutable __m128[2][4] RESAMPLING_TABLE = [ 214 [__m128([1.00, 1.00, 1.00, 1.00]), __m128([0.00, 0.00, 0.00, 0.00])], 215 [__m128([0.75, 0.75, 0.75, 0.75]), __m128([0.25, 0.25, 0.25, 0.25])], 216 [__m128([0.50, 0.50, 0.50, 0.50]), __m128([0.50, 0.50, 0.50, 0.50])], 217 [__m128([0.25, 0.25, 0.25, 0.25]), __m128([0.75, 0.75, 0.75, 0.75])], 218 ]; 219 /** 220 Defines operator parameter numbers, within the unregistered namespace. 221 */ 222 public enum OperatorParamNums { 223 //Unregistered 224 Level = 0, 225 Attack = 1, 226 Decay = 2, 227 SusLevel = 3, 228 SusCtrl = 4, 229 Release = 5, 230 Waveform = 6, 231 Feedback = 7, 232 TuneCor = 8, 233 TuneFine = 9, 234 ShpA = 10, 235 ShpR = 11, 236 VelToLevel = 12, 237 MWToLevel = 13, 238 LFOToLevel = 14, 239 OpCtrl = 15, 240 VelToFB = 16, 241 MWToFB = 17, 242 LFOToFB = 18, 243 EEGToFB = 19, 244 VelToShpA = 20, 245 VelToShpR = 21, 246 KSLBegin = 22, 247 KSLAttenOut = 23, 248 KSLAttenFB = 24, 249 KSLAttenADSR= 25, 250 } 251 /** 252 Defines channel parameter numbers, within the unregistered namespace. 253 */ 254 public enum ChannelParamNums { 255 MasterVol = 0, 256 Bal = 1, 257 AuxSLA = 2, 258 AuxSLB = 3, 259 EEGDetune = 4, 260 PLFO = 5, 261 Attack = 6, 262 Decay = 7, 263 SusLevel = 8, 264 SusCtrl = 9, 265 Release = 10, 266 ShpA = 11, 267 ShpR = 12, 268 GlobalFB = 13, 269 ChCtrl = 16, 270 EEGToLeft = 18, 271 EEGToRight = 19, 272 EEGToAuxA = 20, 273 EEGToAuxB = 21, 274 LFOToLeft = 22, 275 LFOToRight = 23, 276 LFOToAuxA = 24, 277 LFOToAuxB = 25, 278 MWToGFB = 26, 279 VelToGFB = 27, 280 } 281 /** 282 Defines channel parameters within the registered namespace 283 */ 284 public enum ChannelRegParams { 285 PitchBendSens, 286 TuneCor, 287 TuneFine, 288 } 289 /** 290 Defines global parameter nummbers, within the unregistered namespace 291 */ 292 public enum GlobalParamNums { 293 PLFORate = 0, 294 PLFOWF = 1, 295 ALFORate = 2, 296 ALFOWF = 3, 297 FilterLCFreq= 4, 298 FilterLCQ = 5, 299 FilterRCFreq= 6, 300 FilterRCQ = 7, 301 FilterACFreq= 8, 302 FilterACQ = 9, 303 FilterBCFreq= 10, 304 FilterBCQ = 11, 305 HPFLCFreq = 12, 306 HPFLCQ = 13, 307 HPFRCFreq = 14, 308 HPFRCQ = 15, 309 HPFACFreq = 16, 310 HPFACQ = 17, 311 HPFBCFreq = 18, 312 HPFBCQ = 19, 313 RingMod = 20, 314 } 315 enum TuneCtrlFlags : uint { 316 FineTuneMidPoint = 0x1_00_00_00, 317 CorTuneMidPoint = 36<<25, 318 FineTuneTest = 0x1_FF_FF_FF, 319 CorTuneTest = 0xFE_00_00_00, 320 } 321 ///Defines control values 322 enum OpCtrlFlags { 323 WavetableSelect = 127, ///Wavetable select flags 324 FBMode = 1 << 7, ///Feedback mode (L: After Envelop Generator, H: Before Envelop Generator) 325 FBNeg = 1 << 8, ///Feedback mode (L: Positive, H: Negative) 326 MWNeg = 1 << 9, ///Invert modulation wheel control 327 VelNeg = 1 << 10, ///Invert velocity control 328 EGRelAdaptive = 1 << 11, ///Adaptive release time based on current output level 329 FixedPitch = 1 << 12, ///Enables fixed pitch mode 330 EasyTune = 1 << 13, ///Enables easy tune mode 331 ContiTune = 1 << 14, ///Enables continuous tuning through the coarsetune parameter 332 ExprToMW = 1 << 15, ///Switches modwheel to auxilliary control on this operator 333 } 334 /** 335 Implements a single operator. 336 337 Contains an oscillator, an ADSR envelop generator, and locals. 338 */ 339 public struct Operator { 340 ///Local copy of operator preset data. 341 Preset.Op preset; 342 ///The envelop generator of the operator. 343 ADSREnvelopGenerator eg; 344 ///The current position of the oscillator, including fractions. 345 uint pos; 346 ///The amount the oscillator must be stepped forward each cycle, including fractions. 347 uint step; 348 ///Input register. 349 ///The amount which the oscillator will be offsetted. 350 int input; 351 ///Feedback register. Either out_0[n-1] or out[n-1] multiplied by feedback amount. 352 ///The amount which the oscillator will be offsetted. 353 ///Negative if inverted. 354 int feedback; 355 ///Output register. 356 ///Not affected by either level or EG 357 ///Might be used for ring modulation. 358 int output; 359 ///Output affected by EEG and level. 360 ///Either used for audible output, or to modulate other operators 361 int output_0; 362 ///Calculated output level containing KSL damping 363 float outL = 0; 364 ///Calculated feedback level containing KSL damping 365 float fbL = 0; 366 ///Live calculated out of shpA 367 float shpA0 = 0.0; 368 ///Live calculated out of shpR 369 float shpR0 = 0.0; 370 371 ///Sets the frequency of the operator 372 ///Also calculates KSL levels 373 void setFrequency(int slmpFreq, ubyte note, double pitchBend, double tuning) @nogc @safe pure nothrow { 374 double actualNote, oscFreq; 375 const int tuneAm = preset.opCtrl>>>25;//const int tuneAm = (preset.opCtrl>>>25) - 36; 376 if (preset.opCtrl & OpCtrlFlags.EasyTune) { 377 double ratio; 378 switch (tuneAm) { 379 case 0: 380 ratio = 1.0/8; 381 break; 382 case 1: .. case 5: 383 ratio = 1.0/6; 384 break; 385 case 6: .. case 8: 386 ratio = 1.0/5; 387 break; 388 case 9: .. case 12: 389 ratio = 1.0/4; 390 break; 391 case 13: .. case 18: 392 ratio = 1.0/3; 393 break; 394 case 19: .. case 24: 395 ratio = 1.0/2; 396 break; 397 case 25: .. case 42: 398 ratio = 1; 399 break; 400 case 43: .. case 47: 401 ratio = 1.5; 402 break; 403 case 48: .. case 54: 404 ratio = 2; 405 break; 406 case 55: .. case 59: 407 ratio = 3; 408 break; 409 case 60: .. case 63: 410 ratio = 4; 411 break; 412 case 64: .. case 66: 413 ratio = 5; 414 break; 415 case 67: .. case 69: 416 ratio = 6; 417 break; 418 case 70, 71: 419 ratio = 7; 420 break; 421 case 72, 73: 422 ratio = 8; 423 break; 424 case 74, 75: 425 ratio = 9; 426 break; 427 case 76, 77: 428 ratio = 10; 429 break; 430 case 78: 431 ratio = 11; 432 break; 433 case 79, 80: 434 ratio = 12; 435 break; 436 case 81: 437 ratio = 13; 438 break; 439 case 82: 440 ratio = 14; 441 break; 442 case 83: 443 ratio = 15; 444 break; 445 default: 446 ratio = 16; 447 break; 448 } 449 oscFreq = noteToFreq(note + pitchBend, tuning) * ratio; 450 } else if (preset.opCtrl & OpCtrlFlags.ContiTune) { 451 if (preset.opCtrl & OpCtrlFlags.FixedPitch) { 452 actualNote = preset.tune; 453 } else { 454 actualNote = note + pitchBend + preset.tune; 455 } 456 oscFreq = noteToFreq(actualNote, tuning); 457 } else { 458 const double tuneOffset = tuneAm + preset.tune; 459 if (!(preset.opCtrl & OpCtrlFlags.FixedPitch)) { 460 actualNote = note + pitchBend + tuneOffset; 461 } 462 oscFreq = noteToFreq(actualNote, tuning); 463 } 464 calculateKSL(note); 465 const double cycLen = oscFreq / ((slmpFreq + 1) / 1024.0); 466 //step = cast(uint)(cast(double)(1<<21) * cycLen); 467 step = cast(uint)(cast(double)(1<<22) * cycLen); 468 } 469 ///Calculates KSL values 470 void calculateKSL(ubyte note) @nogc @safe pure nothrow { 471 if (!(preset.opCtrl & OpCtrlFlags.FixedPitch) && preset.kslBegin < note) { 472 const double octaves = (note - preset.kslBegin) / 12.0; 473 outL = preset.outL * (1.0 - (octaves * ((preset.kslAttenOut / ubyte.max) * 0.75))); 474 fbL = (preset.opCtrl & OpCtrlFlags.FBNeg ? -1 : 1) * 475 preset.fbL * (1.0 - (octaves * ((preset.kslAttenFB / ubyte.max) * 0.75))); 476 } else { 477 outL = preset.outL; 478 fbL = (preset.opCtrl & OpCtrlFlags.FBNeg ? -1 : 1) * preset.fbL; 479 } 480 } 481 ///Sets the Envelop generator 482 void setEG(int sampleRate, ubyte note, float vel = 1.0) @nogc @safe pure nothrow { 483 const double timeAmount = (!(preset.opCtrl & OpCtrlFlags.FixedPitch) && preset.kslBegin < note) ? 484 1 - ((note - preset.kslBegin) * (0.1 * (preset.kslAttenADSR / 255))) : 1; 485 //Set attack phase 486 if (preset.atk) { 487 eg.attackRate = calculateRate(ADSR_TIME_TABLE[preset.atk] * timeAmount, sampleRate); 488 } else { 489 eg.attackRate = 1.0; 490 } 491 //Set decay phase 492 if (preset.dec) { 493 eg.decayRate = calculateRate(ADSR_TIME_TABLE[preset.dec] * 2 * timeAmount, sampleRate, 494 ADSREnvelopGenerator.maxOutput, eg.sustainLevel); 495 } else { 496 eg.decayRate = 1.0; 497 } 498 //Set sustain phase 499 if (preset.susCC) { 500 eg.isPercussive = false; 501 if (preset.susCC == 64) { 502 eg.sustainControl = 0.0; 503 } else if (preset.susCC < 64) { 504 eg.sustainControl = 505 calculateRate(SUSTAIN_CONTROL_TIME_TABLE[62 - (preset.susCC - 1)], sampleRate); 506 } else { 507 eg.sustainControl = -1.0 * 508 calculateRate(SUSTAIN_CONTROL_TIME_TABLE[preset.susCC - 64], sampleRate); 509 } 510 } else { 511 eg.isPercussive = true; 512 eg.sustainControl = 0.0; 513 } 514 //Set release phase 515 if (preset.rel) { 516 eg.releaseRate = calculateRate(ADSR_TIME_TABLE[preset.rel] * 2, sampleRate, eg.sustainLevel); 517 } else { 518 eg.releaseRate = 1.0; 519 } 520 setShpVals(vel); 521 } 522 ///Recalculates shape params. 523 void setShpVals(float vel = 1.0) @nogc @safe pure nothrow { 524 shpA0 = preset.shpA - (preset.shpA * preset.shpAVel) + (preset.shpA * preset.shpAVel * vel); 525 shpR0 = preset.shpR - (preset.shpR * preset.shpRVel) + (preset.shpR * preset.shpRVel * vel); 526 } 527 ///Sets the key to off on this channel. Also calculates adaptive release rates if needed. 528 void keyOff(int sampleRate) @nogc @safe pure nothrow { 529 eg.keyOff(); 530 if (preset.rel && (preset.opCtrl & OpCtrlFlags.EGRelAdaptive)) { 531 eg.releaseRate = calculateRate(ADSR_TIME_TABLE[preset.rel] * 2, sampleRate, eg.sustainLevel); 532 } 533 } 534 } 535 ///Defines channel control flags. 536 enum ChCtrlFlags { 537 ///Channel combination turned off, the channel pair is independent 538 ComboModeOff = 0b0000, 539 ///Channel combination mode 1: Secondary channel's output is fed into primary operator 0. 540 ComboMode1 = 0b0001, 541 ///Channel combination mode 2: Secondary channel's output is fed into primary operator 1 if primary 542 ///is in serial mode, or into both if primary is in parallel mode. 543 ComboMode2 = 0b0010, 544 ///Channel combination mode 3: Secondary channel's output is fed into main output, except if primary 545 ///channel set to parallel and secondary set to serial, then S1, P0, and P1 are connected to output, while 546 ///S0 is modulating all of them. 547 ComboMode3 = 0b0011, 548 ///Used for testing combo mode. 549 ComboModeTest = ComboMode3, 550 Algorithm = 1<<2, ///Channel algorithm (H: Parallel, L: Series) 551 IndivOutChLev = 1<<3, ///Enables the setting of individual output channel levels 552 LFOPan = 1<<4, ///Enables LFO Panning 553 EEGPan = 1<<5, ///Enables EEG Panning 554 MWToTrem = 1<<6, ///Assigns modwheel to amplitude LFO 555 MWToVibr = 1<<7, ///Assigns modwheel to pitch LFO 556 MWToAux = 1<<8, ///Assigns modwheel to aux levels 557 ResetOnKeyOn = 1<<9, ///Resets all operators and envelops belonging to this channel on key on event 558 ResetMode = 1<<10, ///If set, then reset only occurs of all envelops have reached `Off` state after a keyOff event 559 FBMode = 1<<11, ///Feedback mode (L: After Envelop Generator, H: Before Envelop Generator) 560 FBNeg = 1<<12, ///Feedback mode (L: Positive, H: Negative) 561 ResMode = 1<<13, ///Enables resonant mode if available for the given algorithm 562 ResSrc = 1<<14, ///Selects the source for the resonance if available for the given algorithm 563 } 564 /** 565 Defines channel common parameters. 566 */ 567 public struct Channel { 568 ///Copy of channel relevant preset data 569 Preset.Ch preset; 570 ///Extra envelop generator that can be assigned for multiple purpose. 571 ADSREnvelopGenerator eeg; 572 ///Calculated output level controls + aux send levels 573 ///Index notation: 0: Left channel 1: Right channel 2: Aux send A, 3: Aux send B 574 __m128 outLevels; 575 ///Sets the Extra Envelop generator 576 void setEEG(int sampleRate) @nogc @safe pure nothrow { 577 //Set attack phase 578 if (preset.atkX) { 579 eeg.attackRate = calculateRate(ADSR_TIME_TABLE[preset.atkX], sampleRate); 580 } else { 581 eeg.attackRate = 1.0; 582 } 583 //Set decay phase 584 if (preset.decX) { 585 eeg.decayRate = calculateRate(ADSR_TIME_TABLE[preset.decX] * 2, sampleRate, ADSREnvelopGenerator.maxOutput, 586 eeg.sustainLevel); 587 } else { 588 eeg.decayRate = 1.0; 589 } 590 //Set sustain phase 591 if (preset.susCCX) { 592 eeg.isPercussive = false; 593 if (preset.susCCX == 64) { 594 eeg.sustainControl = 0.0; 595 } else if (preset.susCCX < 64) { 596 eeg.sustainControl = 597 calculateRate(SUSTAIN_CONTROL_TIME_TABLE[62 - (preset.susCCX - 1)], sampleRate); 598 } else { 599 eeg.sustainControl = -1.0 * 600 calculateRate(SUSTAIN_CONTROL_TIME_TABLE[preset.susCCX - 64], sampleRate); 601 } 602 } else { 603 eeg.isPercussive = true; 604 eeg.sustainControl = 0.0; 605 } 606 //Set release phase 607 if (preset.relX) { 608 eeg.releaseRate = calculateRate(ADSR_TIME_TABLE[preset.relX] * 2, sampleRate, eeg.sustainLevel); 609 } else { 610 eeg.releaseRate = 1.0; 611 } 612 } 613 /** 614 * Recalculates the output levels for the channel. 615 */ 616 void recalculateOutLevels() @nogc @safe pure nothrow { 617 if (preset.chCtrl == ChCtrlFlags.IndivOutChLev) { 618 outLevels[0] = preset.masterVol; 619 outLevels[1] = preset.masterBal; 620 } else { 621 outLevels[0] = preset.masterVol * preset.masterBal; 622 outLevels[1] = preset.masterVol * (1 - preset.masterBal); 623 } 624 outLevels[2] = preset.auxSendA; 625 outLevels[3] = preset.auxSendB; 626 } 627 } 628 /** 629 Stores channel controller values (modwheel, velocity, etc.) 630 */ 631 public struct ChControllers { 632 ///Modulation wheel parameter, normalized between 0.0 and 1.0 633 float modwheel = 0; 634 ///Auxilliary controller parameter, normalized between 0.0 and 1.0 635 float auxCtrl = 0; 636 ///Velocity parameter, normalized between 0.0 and 1.0 637 float velocity = 0; 638 ///Pitch bend parameter, with the amount of pitch shifting in semitones + fractions 639 float pitchBend = 0; 640 ///The note that is currently being played 641 ubyte note; 642 } 643 /** 644 Defines a preset. 645 */ 646 public struct Preset { 647 ///Defines parameters of a single operator 648 public struct Op { 649 /+ ///Operator tuning 650 ///Bit 31-25: Coarse detuning (-36 to +91 seminotes) 651 ///Bit 24-0: Fine detuning (-100 to 100 cents), 0x1_00_00_00 is center 652 ///If fixed mode is being used, then top 7 bits are the note, the rest are fine tuning. 653 uint tune = TuneCtrlFlags.CorTuneMidPoint | TuneCtrlFlags.FineTuneMidPoint;+/ 654 ///Sets the fine detuning or the whole tuning of the operator depending on tuning mode. 655 float tune = 0.0; 656 ///Output level (between 0.0 and 1.0) 657 float outL = 0.50; 658 ///Feedback level (between 0.0 and 1.0) 659 float fbL = 0.0; 660 ///Control flags and Wavetable selector 661 uint opCtrl = OpCtrlFlags.EasyTune | TuneCtrlFlags.CorTuneMidPoint; 662 ///Output level controller assignment 663 ///Index notation: 0: velocity 1: modulation wheel 2: Amplitude LFO 3: unused 664 __m128 outLCtrl= [0,0,0,0]; 665 ///Feedback level controller assignment 666 ///Index notation: 0: velocity 1: modulation wheel 2: Amplitude LFO 3: Extra envelop generator 667 __m128 fbLCtrl = [0,0,0,0]; 668 ///Attack time control (between 0 and 127) 669 ubyte atk; 670 ///Decay time control (between 0 and 127) 671 ubyte dec; 672 ///Release time control (between 0 and 127) 673 ubyte rel = 1; 674 ///Sustain curve control (between 0 and 127) 675 ///0: Percussive mode 676 ///1 - 63: Descending over time 677 ///64: Constant 678 ///65 - 127: Ascending over time 679 ubyte susCC = 64; 680 ///Sustain level for the EG 681 float susLevel= 1.0; 682 ///ADSR shaping parameter (for the attack phase) 683 float shpA = 0.5; 684 ///ADSR shaping parameter (for the decay/release phase) 685 float shpR = 0.5; 686 ///Assigns velocity to shpA 687 float shpAVel = 0.0; 688 ///Assigns velocity to shpR 689 float shpRVel = 0.0; 690 ///Key Scale Level beginning point 691 ubyte kslBegin = ubyte.max; 692 ///Key Scale Level attenuation amount for output (0 = 0.0db/Oct ; 255 = 6.0db/Oct) 693 ubyte kslAttenOut; 694 ///Key Scale Level attenuation amount for feedback (0 = 0.0db/Oct ; 255 = 6.0db/Oct) 695 ubyte kslAttenFB; 696 ///Key Scale Level attenuation amount for attack/decay times (0 = 0%/Oct ; 255 = 10%/Oct) 697 ubyte kslAttenADSR; 698 } 699 ///Defines parameters of a single channel. 700 public struct Ch { 701 ///ADSR shaping parameter (for the attack phase) 702 float shpAX = 0.5; 703 ///ADSR shaping parameter (for the decay/release phase) 704 float shpRX = 0.5; 705 ///Pitch amount for EEG 706 float eegDetuneAm = 0; 707 ///Pitch bend sensitivity 708 ///Up to +/-2 octaves 709 float pitchBendSens = 2; 710 ///A-4 channel tuning in hertz. 711 float chnlTun = 440.0; 712 ///Stores channel control flags. 713 uint chCtrl = ChCtrlFlags.ResetMode; 714 ///Master volume (0.0 to 1.0) 715 float masterVol= 1; 716 ///Master balance (0.0 to 1.0) 717 float masterBal= 0.5;// 718 ///Aux send A 719 float auxSendA= 0; 720 ///Aux send B 721 float auxSendB= 0; 722 ///Modwheel to global feedback 723 float mwToGFB = 0; 724 ///Velocity to global feedback 725 float velToGFB= 0;// 726 ///EEG assign levels 727 ///Index notation: 0: Left channel 1: Right channel 2: Aux send A, 3: Aux send B 728 __m128 eegLevels= [0,0,0,0]; 729 ///Amplitude LFO assign levels 730 ///Index notation: 0: Left channel 1: Right channel 2: Aux send A, 3: Aux send B 731 __m128 aLFOlevels= [0,0,0,0]; 732 ///Global feedback 733 ///Only available on certain algorithms 734 float globalFb = 0; 735 ///Pitch LFO level 736 float pLFOlevel = 0; 737 ///Amplitude LFO to 738 ///Attack time control (between 0 and 127) 739 ubyte atkX; 740 ///Decay time control (between 0 and 127) 741 ubyte decX; 742 ///Release time control (between 0 and 127) 743 ubyte relX; 744 ///Sustain curve control (between 0 and 127) 745 ///0: Percussive mode 746 ///1 - 63: Descending over time 747 ///64: Constant 748 ///65 - 127: Ascending over time 749 ubyte susCCX = 64; 750 ///Sustain level 751 float susLevel = 1; 752 } 753 Op[2] operators; ///The operators belonging to this channel 754 Ch channel; ///Channel common values 755 } 756 ///Contains the wavetables for the operators and LFOs. 757 ///Value might be divided to limit the values between 2047 and -2048 via bitshifting, 758 ///otherwise the full range can be used for audio output, etc. 759 ///Loaded from a 16 bit wave file. 760 protected short[1024][128] wavetables; 761 ///Stores presets. 762 ///8 banks of 128 presets are available for a total of 1024. 763 ///If a channel combination is being used, then bank pairs (0-1, 2-3, etc) will store their primary and secondary 764 ///halves, and calling either will load both halves. 765 protected Preset[128][8] soundBank; 766 ///Operator data. 767 ///See rendering function on updating. 768 protected Operator[32] operators; 769 ///Channel data. 770 ///See rendering function on updating. 771 protected Channel[16] channels; 772 ///Channel control data. 773 protected ChControllers[16] chCtrls; 774 ///Preset numbers per channels. 775 protected ubyte[16] presetNum; 776 ///Bank numbers per channels. 777 protected ubyte[16] bankNum; 778 ///Keeps the registered/unregistered parameter positions (LSB = 1). 779 //protected ubyte[2] paramNum; 780 ///Stores LFO waveform selection. 0: Pitch; 1: Amplitude/Ringmod (if bit 7 is set) 781 protected ubyte[2] lfoWaveform; 782 ///Stores temporary parameter values 783 ///0: MSB of sel unregistered param 1: LSB of sel unregistered param 784 ///2: MSB of sel registered param 3: LSB of sel registered param 785 protected ubyte[4] paramTemp; 786 ///Stores ALFO position 787 protected uint aLFOPos; 788 ///Stores ALFO rate 789 protected uint aLFORate; 790 ///ALFO filter y[n-1] 791 protected float aLFO_y1; 792 ///ALFO filter factor 0 to 1 793 protected float aLFOff = 1; 794 ///ALFO frequency 795 protected float aLFOFreq = 6; 796 ///Stores output filter values. 797 ///0: a0; 1: a1; 2: a2; 3: b0; 4: b1; 5: b2; 6: x[n-1]; 7: x[n-2]; 8: y[n-1] 9: y[n-2] 798 protected __m128[10] filterVals; 799 ///Stores control values of the output values. 800 ///Layout: [LF, LQ, RF, RQ, AF, AQ, BF, BQ] 801 protected float[8] filterCtrl = [16_000, 0.707, 16_000, 0.707, 16_000, 0.707, 16_000, 0.707]; 802 ///Stores high-pass filter values. 803 ///0: a0; 1: a1; 2: a2; 3: b0; 4: b1; 5: b2; 6: y[n-1] 7: y[n-2] 804 protected __m128[8] hpfVals; 805 ///Stores high-pass filter control values 806 protected float[8] hpfCtrl = [32, 0.707, 32, 0.707, 32, 0.707, 32, 0.707]; 807 ///Initial mixing buffers 808 ///Output is directed there before filtering 809 ///Layout is: LRAB 810 protected __m128[] initBuffers; 811 ///Dummy buffer 812 ///Only used if one or more outputs haven't been defined 813 protected float[] dummyBuf; 814 ///Amplitude LFO buffer. Values are between 0.0 and 1.0 815 protected float[] aLFOBuf; 816 ///Pitch LFO output. Values are between -1.0 and 1.0 817 protected float pLFOOut = 0; 818 ///Stores PLFO position 819 protected uint pLFOPos; 820 ///Stores PLFO rate 821 protected uint pLFORate; 822 ///Current frequency of PLFO 823 protected float pLFOFreq = 6; 824 ///Mixdown value. 825 ///Used for final mixing. 826 protected float mixdownVal = short.max + 1; 827 ///Internal sampling frequency 828 protected int intSlmpRate; 829 ///Internal buffer sizes 830 protected size_t intBufSize; 831 alias ChFun = void delegate(int chNum, size_t length) @nogc pure nothrow; 832 ///Channel update delegates 833 protected ChFun[16] chDeleg; 834 ///Used as a keepsake for MIDI 1.0 control change values. 835 protected ubyte[64][16] ccLow; 836 protected ubyte[32] sysExBuf; ///SysEx command buffer [0-30] + length [31] 837 /** 838 Creates an instance of QM816 839 */ 840 public this() @trusted nothrow { 841 info.nOfAudioInput = 0; 842 info.nOfAudioOutput = 4; 843 info.outputChNames = ["mainL", "mainR", "auxSendA", "auxSendB"]; 844 info.isInstrument = true; 845 info.hasMidiIn = true; 846 info.hasMidiOut = true; 847 info.midiSendback = true; 848 try { 849 WaveFormat f = WaveFormat(0, 0, AudioFormat.PCM, 1, 0, 16); 850 short[1024] buffer = generateSinewave([0x01, 0x09, 0x11, 0x19]); 851 waveformDataReceive(0, reinterpretCast!ubyte(buffer), f); ///Sine (from OPL2) 852 buffer = generateSinewave([0x01, 0x09, 0x00, 0x00]); 853 waveformDataReceive(1, reinterpretCast!ubyte(buffer), f); ///Half-sine (from OPL2) 854 buffer = generateSinewave([0x01, 0x09, 0x01, 0x09]); 855 waveformDataReceive(2, reinterpretCast!ubyte(buffer), f); ///Full-sine (from OPL2) 856 buffer = generateSinewave([0x01, 0x00, 0x01, 0x00]); 857 waveformDataReceive(3, reinterpretCast!ubyte(buffer), f); ///Pulse-sine (from OPL2) 858 buffer = generateSinewave([0x01, 0x09, 0x11, 0x00]); 859 waveformDataReceive(4, reinterpretCast!ubyte(buffer), f); ///Pulse-sine 75% 860 buffer = generateSinewave([0x01, 0x00, 0x00, 0x00]); 861 waveformDataReceive(5, reinterpretCast!ubyte(buffer), f); ///Pulse-sine 25% 862 buffer = generateSinewave([0x01, 0x00, 0x11, 0x00]); 863 waveformDataReceive(6, reinterpretCast!ubyte(buffer), f); ///Alternating pulse-sine 864 buffer = generateSinewave([0x05, 0x00, 0x1d, 0x00]); 865 waveformDataReceive(7, reinterpretCast!ubyte(buffer), f); ///Alternating sine (from OPL3) 866 buffer = generateSinewave([0x05, 0x05, 0x1d, 0x1d]); 867 waveformDataReceive(8, reinterpretCast!ubyte(buffer), f); ///Camel sine (from OPL3) 868 buffer = generateSinewave([0x01, 0x09, 0x11, 0x1f]); 869 waveformDataReceive(9, reinterpretCast!ubyte(buffer), f); ///Variant sine 0 870 buffer = generateSinewave([0x01, 0x09, 0x1d, 0x1d]); 871 waveformDataReceive(10, reinterpretCast!ubyte(buffer), f); ///Variant sine 1 872 buffer = generateSinewave([0x01, 0x09, 0x0d, 0x0d]); 873 waveformDataReceive(11, reinterpretCast!ubyte(buffer), f); ///Variant sine 2 874 buffer = generateSinewave([0x01, 0x09, 0x00, 0x1d]); 875 waveformDataReceive(12, reinterpretCast!ubyte(buffer), f); ///Variant sine 3 876 buffer = generateSinewave([0x01, 0x09, 0x1d, 0x00]); 877 waveformDataReceive(13, reinterpretCast!ubyte(buffer), f); ///Variant sine 4 878 buffer = generateSinewave([0x01, 0x09, 0x00, 0x0d]); 879 waveformDataReceive(14, reinterpretCast!ubyte(buffer), f); ///Variant sine 5 880 buffer = generateSinewave([0x01, 0x09, 0x0d, 0x00]); 881 waveformDataReceive(15, reinterpretCast!ubyte(buffer), f); ///Variant sine 6 882 buffer = generateSinewave([0x01, 0x09, 0x1f, 0x1f]); 883 waveformDataReceive(16, reinterpretCast!ubyte(buffer), f); ///Variant sine 7 884 buffer = generatePulseWave(768); 885 waveformDataReceive(17, reinterpretCast!ubyte(buffer), f); ///Pulse wave 75% 886 buffer = generatePulseWave(512); 887 waveformDataReceive(18, reinterpretCast!ubyte(buffer), f); ///Pulse wave 50% 888 buffer = generatePulseWave(256); 889 waveformDataReceive(19, reinterpretCast!ubyte(buffer), f); ///Pulse wave 25% 890 buffer = generatePulseWave(128); 891 waveformDataReceive(20, reinterpretCast!ubyte(buffer), f); ///Pulse wave 12.5% 892 buffer = generatePulseWave(100); 893 waveformDataReceive(21, reinterpretCast!ubyte(buffer), f); ///Pulse wave 10% 894 buffer = generatePulseWave(50); 895 waveformDataReceive(22, reinterpretCast!ubyte(buffer), f); ///Pulse wave 5% 896 buffer = generateTriangularWave(1023); 897 waveformDataReceive(23, reinterpretCast!ubyte(buffer), f); ///Ramp wave 898 buffer = integrateTriangularWave(buffer); 899 waveformDataReceive(28, reinterpretCast!ubyte(buffer), f); ///Integrated Ramp wave 900 buffer = generateTriangularWave(768); 901 waveformDataReceive(24, reinterpretCast!ubyte(buffer), f); ///Morphed ramp 902 buffer = integrateTriangularWave(buffer); 903 waveformDataReceive(29, reinterpretCast!ubyte(buffer), f); ///Integrated Morphed ramp 904 buffer = generateTriangularWave(512); 905 waveformDataReceive(25, reinterpretCast!ubyte(buffer), f); ///Triangle wave 906 buffer = integrateTriangularWave(buffer); 907 waveformDataReceive(30, reinterpretCast!ubyte(buffer), f); ///Integrated triangle wave 908 buffer = generateTriangularWave(256); 909 waveformDataReceive(26, reinterpretCast!ubyte(buffer), f); ///Morphed saw 910 buffer = integrateTriangularWave(buffer); 911 waveformDataReceive(31, reinterpretCast!ubyte(buffer), f); ///Integrated Morphed saw 912 buffer = generateTriangularWave(2); 913 waveformDataReceive(27, reinterpretCast!ubyte(buffer), f); ///Saw wave 914 buffer = integrateTriangularWave(buffer); 915 waveformDataReceive(32, reinterpretCast!ubyte(buffer), f); ///Integrated Saw wave 916 } catch (Exception e) { 917 918 } 919 //Reset delegates 920 for (int i ; i < chDeleg.length ; i++) { 921 chDeleg[i] = &updateChannelM00; 922 } 923 } 924 /** 925 * Sets the module up. 926 * 927 * Can be overridden in child classes to allow resets. 928 */ 929 public override void moduleSetup(ubyte[] inputs, ubyte[] outputs, int sampleRate, size_t bufferSize, 930 ModuleManager handler) @safe nothrow { 931 // void test() @trusted nothrow { 932 // midiReceive(UMP(MessageType.MIDI2, 0x0, MIDI2_0Cmd.NoteOn, 0x0, 0x3f, 0x0)); 933 // } 934 enabledInputs = StreamIDSet(inputs); 935 enabledOutputs = StreamIDSet(outputs); 936 this.sampleRate = sampleRate; 937 this.bufferSize = bufferSize; 938 this.handler = handler; 939 //set up internal sample rate and buffer sizes 940 intBufSize = bufferSize + (bufferSize / 4); 941 intSlmpRate = sampleRate + (sampleRate / 4); 942 //set up and reset buffers 943 initBuffers.length = intBufSize; 944 resetBuffer(initBuffers); 945 dummyBuf.length = bufferSize; 946 resetBuffer(dummyBuf); 947 aLFOBuf.length = intBufSize; 948 resetBuffer(aLFOBuf); 949 //Reset filters 950 for (int i ; i < 4 ; i++) { 951 resetLPF(i); 952 resetHPF(i); 953 filterVals[6][i] = 0; 954 filterVals[7][i] = 0; 955 filterVals[8][i] = 0; 956 filterVals[9][i] = 0; 957 hpfVals[6][i] = 0; 958 hpfVals[7][i] = 0; 959 } 960 aLFO_y1 = 0; 961 setALFO(); 962 setPLFO(); 963 //Reset operator EGs 964 for (int i ; i < operators.length ; i++) { 965 operators[i].setEG(intSlmpRate, 40); 966 } 967 //Reset channel EGs 968 for (int i ; i < channels.length ; i++) { 969 channels[i].setEEG(intSlmpRate); 970 channels[i].recalculateOutLevels(); 971 } 972 //test(); 973 } 974 protected void resetLPF(int i) @nogc @safe pure nothrow { 975 BiquadFilterValues vals = createLPF(sampleRate, filterCtrl[i * 2], filterCtrl[(i * 2) + 1]); 976 filterVals[0][i] = vals.a0; 977 filterVals[1][i] = vals.a1; 978 filterVals[2][i] = vals.a2; 979 filterVals[3][i] = vals.b0; 980 filterVals[4][i] = vals.b1; 981 filterVals[5][i] = vals.b2; 982 //filterVals[6][i] = 0; 983 //filterVals[7][i] = 0; 984 //filterVals[8][i] = 0; 985 //filterVals[9][i] = 0; 986 } 987 protected void resetHPF(int i) @nogc @safe pure nothrow { 988 BiquadFilterValues hpf = createHPF(sampleRate, hpfCtrl[i * 2], hpfCtrl[(i * 2) + 1]); 989 hpfVals[0][i] = hpf.a0; 990 hpfVals[1][i] = hpf.a1; 991 hpfVals[2][i] = hpf.a2; 992 hpfVals[3][i] = hpf.b0; 993 hpfVals[4][i] = hpf.b1; 994 hpfVals[5][i] = hpf.b2; 995 //hpfVals[6][i] = 0; 996 //hpfVals[7][i] = 0; 997 } 998 /** 999 * Receives waveform data that has been loaded from disk for reading. Returns zero if successful, or a specific 1000 * errorcode. 1001 * 1002 * id: The ID of the waveform. 1003 * rawData: The data itself, in unprocessed form. 1004 * format: The format of the wave data, including the data type, bit depth, base sampling rate 1005 */ 1006 public override int waveformDataReceive(uint id, ubyte[] rawData, WaveFormat format) nothrow { 1007 int errorcode; 1008 if (format.channels != 1) errorcode |= SampleLoadErrorCode.ChNumNotSupported; 1009 if (format.bitsPerSample != 16) errorcode |= SampleLoadErrorCode.BitdepthNotSupported; 1010 if (format.format != AudioFormat.PCM) errorcode |= SampleLoadErrorCode.FormatNotSupported; 1011 if (rawData.length != 128 * 1024 * 2 && rawData.length != 1024 * 2) 1012 errorcode |= SampleLoadErrorCode.SampleLenghtNotSupported; 1013 if (errorcode) { 1014 return errorcode; 1015 } else { 1016 import core.stdc.string : memcpy; 1017 if (rawData.length == 128 * 1024 * 2) 1018 memcpy(wavetables.ptr, rawData.ptr, 128 * 1024 * 2); 1019 else 1020 memcpy(wavetables[id].ptr, rawData.ptr, 1024 * 2); 1021 return 0; 1022 } 1023 } 1024 /** 1025 * MIDI 2.0 data received here. 1026 * 1027 * data0: Header of the up to 128 bit MIDI 2.0 data. 1028 * data1-3: Other packets if needed. 1029 */ 1030 public override void midiReceive(UMP data0, uint data1 = 0, uint data2 = 0, uint data3 = 0) @nogc nothrow { 1031 //data0 = UMP(MessageType.MIDI2, 0x0, MIDI2_0Cmd.NoteOn, 0x0, 0x3f, 0x0); 1032 switch (data0.msgType) { 1033 case MessageType.SysCommMsg: //Process system common message 1034 break; 1035 case MessageType.MIDI1: //Process MIDI 1.0 messages 1036 ubyte ch = data0.channel; 1037 switch (data0.status) { 1038 case MIDI1_0Cmd.CtrlCh: //Process MIDI 1.0 control change messages 1039 switch (data0.note) { 1040 case 0, 32: //Bank select 1041 bankNum[data0.channel] = data0.value & 7; 1042 break; 1043 case 1, 33: //Modulation wheel 1044 ccLow[ch][data0.note] = data0.value; 1045 chCtrls[ch].modwheel = cast(double)((ccLow[ch][1]<<7) + ccLow[ch][33]) / (ushort.max>>2); 1046 break; 1047 case 2, 34: 1048 ccLow[ch][data0.note] = data0.value; 1049 chCtrls[ch].auxCtrl = cast(double)((ccLow[ch][2]<<7) + ccLow[ch][34]) / (ushort.max>>2); 1050 break; 1051 case 6, 38: //Data Entry 1052 ccLow[ch][data0.note] = data0.value; 1053 //paramTemp = [0xFF,0xFF,0xFF,0xFF]; 1054 setUnregisteredParam(convertM1CtrlValToM2(ccLow[ch][18], ccLow[ch][32+18]), [paramTemp[0], paramTemp[1]], ch); 1055 break; 1056 case 18, (32+18): 1057 ccLow[ch][data0.note] = data0.value; 1058 setUnregisteredParam(convertM1CtrlValToM2(ccLow[ch][18], ccLow[ch][32+18]), [0, 0], ch); 1059 break; 1060 case 19, (32+19): 1061 ccLow[ch][data0.note] = data0.value; 1062 setUnregisteredParam(convertM1CtrlValToM2(ccLow[ch][19], ccLow[ch][32+19]), [1, 0], ch); 1063 break; 1064 case 16, (32+16): 1065 ccLow[ch][data0.note] = data0.value; 1066 setUnregisteredParam(convertM1CtrlValToM2(ccLow[ch][16], ccLow[ch][32+16]), [0, 3], ch); 1067 break; 1068 case 17, (32+17): 1069 ccLow[ch][data0.note] = data0.value; 1070 setUnregisteredParam(convertM1CtrlValToM2(ccLow[ch][17], ccLow[ch][32+17]), [1, 3], ch); 1071 break; 1072 case 20, (32+20): 1073 ccLow[ch][data0.note] = data0.value; 1074 setUnregisteredParam(convertM1CtrlValToM2(ccLow[ch][20], ccLow[ch][32+20]), [0, 10], ch); 1075 break; 1076 case 22, (32+22): 1077 ccLow[ch][data0.note] = data0.value; 1078 setUnregisteredParam(convertM1CtrlValToM2(ccLow[ch][22], ccLow[ch][32+22]), [1, 10], ch); 1079 break; 1080 case 21, (32+21): 1081 ccLow[ch][data0.note] = data0.value; 1082 setUnregisteredParam(convertM1CtrlValToM2(ccLow[ch][21], ccLow[ch][32+21]), [0, 10], ch); 1083 break; 1084 case 23, (32+23): 1085 ccLow[ch][data0.note] = data0.value; 1086 setUnregisteredParam(convertM1CtrlValToM2(ccLow[ch][23], ccLow[ch][32+23]), [1, 10], ch); 1087 break; 1088 case 30, (32+30): 1089 ccLow[ch][data0.note] = data0.value; 1090 setUnregisteredParam(convertM1CtrlValToM2(ccLow[ch][30], ccLow[ch][32+30]), [0, 9], ch); 1091 break; 1092 case 31, (32+31): 1093 ccLow[ch][data0.note] = data0.value; 1094 setUnregisteredParam(convertM1CtrlValToM2(ccLow[ch][31], ccLow[ch][32+31]), [1, 9], ch); 1095 break; 1096 // 1097 case 73: 1098 setUnregisteredParam(data0.value<<25, [1, 1], data0.channel); 1099 break; 1100 case 78: 1101 setUnregisteredParam(data0.value<<25, [0, 1], data0.channel); 1102 break; 1103 case 74: 1104 setUnregisteredParam(data0.value<<25, [1, 2], data0.channel); 1105 break; 1106 case 79: 1107 setUnregisteredParam(data0.value<<25, [0, 2], data0.channel); 1108 break; 1109 case 85: 1110 setUnregisteredParam(data0.value<<25, [0, 4], data0.channel); 1111 break; 1112 case 86: 1113 setUnregisteredParam(data0.value<<25, [1, 4], data0.channel); 1114 break; 1115 case 87: 1116 setUnregisteredParam(data0.value<<25, [0, 8], data0.channel); 1117 break; 1118 case 88: 1119 setUnregisteredParam(data0.value<<25, [1, 8], data0.channel); 1120 break; 1121 case 72: 1122 setUnregisteredParam(data0.value<<25, [1, 5], data0.channel); 1123 break; 1124 case 77: 1125 setUnregisteredParam(data0.value<<25, [0, 5], data0.channel); 1126 break; 1127 case 70: 1128 setUnregisteredParam(data0.value<<25, [1, 6], data0.channel); 1129 break; 1130 case 75: 1131 setUnregisteredParam(data0.value<<25, [0, 6], data0.channel); 1132 break; 1133 case 71: 1134 setUnregisteredParam(data0.value<<25, [1, 7], data0.channel); 1135 break; 1136 case 76: 1137 setUnregisteredParam(data0.value<<25, [0, 7], data0.channel); 1138 break; 1139 // 1140 case 7, 32+7: 1141 ccLow[data0.note] = data0.value; 1142 setUnregisteredParam(convertM1CtrlValToM2(ccLow[ch][7], ccLow[ch][32+7]), [4, 0], data0.channel); 1143 break; 1144 case 8, 32+8: 1145 ccLow[data0.note] = data0.value; 1146 setUnregisteredParam(convertM1CtrlValToM2(ccLow[ch][8], ccLow[ch][32+8]), [4, 1], data0.channel); 1147 break; 1148 case 24, 32+24: 1149 ccLow[data0.note] = data0.value; 1150 setUnregisteredParam(convertM1CtrlValToM2(ccLow[ch][24], ccLow[ch][32+24]), [4, 11], data0.channel); 1151 break; 1152 case 25, 32+25: 1153 ccLow[data0.note] = data0.value; 1154 setUnregisteredParam(convertM1CtrlValToM2(ccLow[ch][25], ccLow[ch][32+25]), [4, 12], data0.channel); 1155 break; 1156 // 1157 case 91: 1158 setUnregisteredParam(data0.value<<25, [4, 2], data0.channel); 1159 break; 1160 case 92: 1161 setUnregisteredParam(data0.value<<25, [4, 3], data0.channel); 1162 break; 1163 case 93: 1164 setUnregisteredParam(data0.value<<25, [4, 4], data0.channel); 1165 break; 1166 case 94: 1167 setUnregisteredParam(data0.value<<25, [4, 5], data0.channel); 1168 break; 1169 case 102: 1170 setUnregisteredParam(data0.value<<25, [4, 6], data0.channel); 1171 break; 1172 case 103: 1173 setUnregisteredParam(data0.value<<25, [4, 7], data0.channel); 1174 break; 1175 case 104: 1176 setUnregisteredParam(data0.value<<25, [4, 8], data0.channel); 1177 break; 1178 case 105: 1179 setUnregisteredParam(data0.value<<25, [4, 9], data0.channel); 1180 break; 1181 case 106: 1182 setUnregisteredParam(data0.value<<25, [4, 10], data0.channel); 1183 break; 1184 case 107: 1185 setUnregisteredParam(data0.value<<25, [4, 13], data0.channel); 1186 break; 1187 // 1188 case 98: //Non Registered Parameter Number MSB (handle through MIDI 2.0) 1189 paramTemp[0] = data0.value; 1190 /* if (paramTemp[0] != 0xFF) 1191 setUnregisteredParam(convertM1CtrlValToM2(paramTemp[0], paramTemp[1]), [ccLow[ch][6], ccLow[ch][38]], data0.channel); */ 1192 break; 1193 case 99: //Non Registered Parameter Number LSB (handle through MIDI 2.0) 1194 //setUnregisteredParam(data0.value, paramNum, 0, data0.channel); 1195 paramTemp[1] = data0.value; 1196 /* if (paramTemp[0] != 0xFF) 1197 setUnregisteredParam(convertM1CtrlValToM2(paramTemp[0], paramTemp[1]), [ccLow[ch][6], ccLow[ch][38]], data0.channel); */ 1198 break; 1199 default: 1200 break; 1201 } 1202 break; 1203 case MIDI1_0Cmd.NoteOn: //Note on command 1204 keyOn(data0.note, data0.channel, data0.value/127.0); 1205 break; 1206 case MIDI1_0Cmd.NoteOff://Note off command 1207 keyOff(data0.note, data0.channel, data0.value/127.0); 1208 break; 1209 case MIDI1_0Cmd.ChAftrTch: 1210 chCtrls[data0.channel].velocity = cast(double)data0.note / cast(double)byte.max; 1211 break; 1212 case MIDI1_0Cmd.PolyAftrTch: 1213 chCtrls[data0.channel].velocity = cast(double)data0.velocity / cast(double)byte.max; 1214 break; 1215 case MIDI1_0Cmd.PrgCh: //Program change 1216 const uint chOffset = data0.channel; 1217 const uint chCtrl = soundBank[bankNum[chOffset] & 7][presetNum[chOffset]].channel.chCtrl; 1218 if (chCtrl & ChCtrlFlags.ComboModeTest) { 1219 const uint chX = chOffset & 7, bankX = bankNum[chOffset] & 7 & ~1; 1220 prgRecall(chX, presetNum[chX], bankX); 1221 prgRecall(chX + 8, presetNum[chX], bankX + 1); 1222 } else { 1223 prgRecall(chOffset, presetNum[chOffset], bankNum[chOffset]); 1224 } 1225 break; 1226 case MIDI1_0Cmd.PitchBend: 1227 //const uint ch = data0.channel; 1228 chCtrls[ch].pitchBend = channels[ch].preset.pitchBendSens * ((cast(double)data0.bend - 0x20_00) / 0x3F_FF); 1229 break; 1230 default: 1231 assert(0, "MIDI 1.0 data error!"); 1232 //break; 1233 } 1234 break; 1235 case MessageType.MIDI2: 1236 switch (data0.status) { 1237 case MIDI2_0Cmd.CtrlChOld: 1238 switch (data0.index) { 1239 case 1: 1240 chCtrls[data0.channel].modwheel = cast(double)data1 / uint.max; 1241 break; 1242 case 2: 1243 chCtrls[data0.channel].auxCtrl = cast(double)data1 / uint.max; 1244 break; 1245 default: 1246 break; 1247 } 1248 break; 1249 case MIDI2_0Cmd.CtrlCh: //Control change 1250 setUnregisteredParam(data1, [data0.index, data0.value], data0.channel); 1251 break; 1252 case MIDI2_0Cmd.CtrlChR://Registered control change 1253 //setRegisteredParam(data[1], [data0.index, data0.value], data0.channel); 1254 break; 1255 case MIDI2_0Cmd.PrgCh: //Program change 1256 const uint chOffset = data0.channel; 1257 //const uint prg = data[1]>>24, bank = data[1] & 7; 1258 presetNum[chOffset] = cast(ubyte)(data1>>24); 1259 if (data0.value & 1) bankNum[chOffset] = cast(ubyte)(data1 & 7); 1260 const uint chCtrl = soundBank[bankNum[chOffset] & 7][presetNum[chOffset]].channel.chCtrl; 1261 if (chCtrl & ChCtrlFlags.ComboModeTest) { 1262 const uint chX = chOffset & 7, bankX = bankNum[chOffset] & 7 & ~1; 1263 prgRecall(chX, presetNum[chX], bankX); 1264 prgRecall(chX + 8, presetNum[chX], bankX + 1); 1265 } else { 1266 prgRecall(chOffset, presetNum[chOffset], bankNum[chOffset]); 1267 } 1268 break; 1269 case MIDI2_0Cmd.NoteOn: 1270 NoteVals v = *cast(NoteVals*)(&data1); 1271 keyOn(data0.note, data0.channel, v.velocity/65_535.0); 1272 break; 1273 case MIDI2_0Cmd.NoteOff: 1274 NoteVals v = *cast(NoteVals*)(&data1); 1275 keyOff(data0.note, data0.channel, v.velocity/65_535.0); 1276 break; 1277 case MIDI2_0Cmd.PitchBend: 1278 const uint ch = data0.channel; 1279 /+const double pitchBendSens = (channels[ch].preset.pitchBendSens>>25) + 1280 (cast(double)(channels[ch].preset.pitchBendSens & 0x01_FF_FF_FF) / 0x01_FF_FF_FF);+/ 1281 chCtrls[ch].pitchBend = channels[ch].preset.pitchBendSens * ((cast(double)data1 - int.max) / (int.max)); 1282 break; 1283 default: 1284 assert(0, "MIDI 2.0 data error!"); 1285 //break; 1286 } 1287 break; 1288 case MessageType.Data64: 1289 if (data0.status == SysExSt.Start || data0.status == SysExSt.Complete) 1290 sysExBuf[31] = 0; 1291 ubyte[4] packet1 = [cast(ubyte)(data1>>24), cast(ubyte)(data1>>16), cast(ubyte)(data1>>8), cast(ubyte)data1]; 1292 int length = data0.channel; 1293 for (int i ; i < 2 && length - 4 > 0 ; i++, length--) { 1294 sysExBuf[sysExBuf[31]] = data0.bytes[i]; 1295 sysExBuf[31]++; 1296 if (sysExBuf[31] > 30) { 1297 length = 0; 1298 sysExBuf[31] = 0; 1299 } 1300 } 1301 for (int i ; i < 4 && length > 0 ; i++, length--) { 1302 sysExBuf[sysExBuf[31]] = packet1[i]; 1303 sysExBuf[31]++; 1304 if (sysExBuf[31] > 30) { 1305 length = 0; 1306 sysExBuf[31] = 0; 1307 } 1308 } 1309 if (data0.status == SysExSt.Complete || data0.status == SysExSt.End) 1310 sysExCmd(sysExBuf[0..sysExBuf[31]]); 1311 break; 1312 case MessageType.Data128: 1313 if (data0.status == SysExSt.Start || data0.status == SysExSt.Complete) 1314 sysExBuf[31] = 0; 1315 ubyte[13] data = [data0.value, 1316 cast(ubyte)(data1>>24), cast(ubyte)(data1>>16), cast(ubyte)(data1>>8), cast(ubyte)data1, 1317 cast(ubyte)(data2>>24), cast(ubyte)(data2>>16), cast(ubyte)(data2>>8), cast(ubyte)data2, 1318 cast(ubyte)(data3>>24), cast(ubyte)(data3>>16), cast(ubyte)(data3>>8), cast(ubyte)data3]; 1319 for (int i ; i < data0.channel ; i++, sysExBuf[31]++) { 1320 sysExBuf[sysExBuf[31]] = data[i]; 1321 if (sysExBuf[31] > 30) 1322 sysExBuf[31] = 0; 1323 } 1324 if (data0.status == SysExSt.Complete || data0.status == SysExSt.End) 1325 sysExCmd(sysExBuf[0..sysExBuf[31]]); 1326 break; 1327 default: 1328 //assert(0, "Something went really wrong!"); 1329 break; 1330 } 1331 } 1332 /** 1333 * Implements a key-on event. 1334 * Params: 1335 * note = identifies which key is being pressed. Affects KSL control parameters 1336 * ch = channel number 1337 * vel = key velocity 1338 * bend = amount of initial bend (MIDI 2.0 only) 1339 */ 1340 protected void keyOn(ubyte note, ubyte ch, float vel, float bend = float.nan) @nogc pure nothrow { 1341 void hardReset() @safe @nogc pure nothrow { 1342 channels[ch].eeg.keyOn(); 1343 operators[ch].eg.keyOn(); 1344 operators[ch + 1].eg.keyOn(); 1345 operators[ch].pos = 0; 1346 operators[ch + 1].pos = 0; 1347 } 1348 void softReset() @safe @nogc pure nothrow { 1349 channels[ch].eeg.keyOnNoReset(); 1350 operators[ch].eg.keyOnNoReset(); 1351 operators[ch + 1].eg.keyOnNoReset(); 1352 } 1353 void hardResetCmb() @safe @nogc pure nothrow { 1354 channels[ch + 8].eeg.keyOn(); 1355 operators[ch + 16].eg.keyOn(); 1356 operators[ch + 17].eg.keyOn(); 1357 operators[ch + 16].pos = 0; 1358 operators[ch + 17].pos = 0; 1359 } 1360 void softResetCmb() @safe @nogc pure nothrow { 1361 channels[ch + 8].eeg.keyOnNoReset(); 1362 operators[ch + 16].eg.keyOnNoReset(); 1363 operators[ch + 17].eg.keyOnNoReset(); 1364 } 1365 if ((channels[ch].preset.chCtrl & ChCtrlFlags.ComboModeTest) && ch > 7) return; 1366 chCtrls[ch].note = note; 1367 chCtrls[ch].velocity = vel; 1368 if (!isNaN(bend)) chCtrls[ch].pitchBend = bend; 1369 operators[ch].setFrequency(intSlmpRate, note, chCtrls[ch].pitchBend, channels[ch].preset.chnlTun); 1370 operators[ch].setEG(intSlmpRate, note, vel); 1371 operators[ch + 1].setFrequency(intSlmpRate, note, chCtrls[ch + 1].pitchBend, channels[ch].preset.chnlTun); 1372 operators[ch + 1].setEG(intSlmpRate, note, vel); 1373 if ((channels[ch].preset.chCtrl & ChCtrlFlags.ComboModeTest) && ch <= 7) { 1374 operators[ch + 16].setFrequency(intSlmpRate, note, chCtrls[ch].pitchBend, channels[ch].preset.chnlTun); 1375 operators[ch + 16].setEG(intSlmpRate, note, vel); 1376 operators[ch + 17].setFrequency(intSlmpRate, note, chCtrls[ch].pitchBend, channels[ch].preset.chnlTun); 1377 operators[ch + 17].setEG(intSlmpRate, note, vel); 1378 if (channels[ch].preset.chCtrl & ChCtrlFlags.ResetOnKeyOn) { 1379 hardReset(); 1380 hardResetCmb(); 1381 } else if (channels[ch].preset.chCtrl & ChCtrlFlags.ResetMode) { 1382 if ((channels[ch].eeg.position | channels[ch + 8].eeg.position | operators[ch].eg.position | 1383 operators[ch + 1].eg.position | operators[ch + 16].eg.position | operators[ch + 17].eg.position) == 1384 ADSREnvelopGenerator.Stage.Off) { 1385 hardReset(); 1386 hardResetCmb(); 1387 } else { 1388 softReset(); 1389 softResetCmb(); 1390 } 1391 } else { 1392 softReset(); 1393 softResetCmb(); 1394 } 1395 } else { 1396 if (channels[ch].preset.chCtrl & ChCtrlFlags.ResetOnKeyOn) { 1397 hardReset(); 1398 } else if (channels[ch].preset.chCtrl & ChCtrlFlags.ResetMode) { 1399 if ((channels[ch].eeg.position | operators[ch].eg.position | operators[ch + 1].eg.position) == 1400 ADSREnvelopGenerator.Stage.Off) { 1401 hardReset(); 1402 } else { 1403 softReset(); 1404 } 1405 } else { 1406 softReset(); 1407 } 1408 } 1409 } 1410 /** 1411 * Implements a key-off event. 1412 * Params: 1413 * note = 1414 * ch = 1415 * vel = 1416 */ 1417 protected void keyOff(ubyte note, ubyte ch, float vel, float bend = 0) @nogc pure nothrow { 1418 if ((channels[ch].preset.chCtrl & ChCtrlFlags.ComboModeTest) && ch > 7) return; 1419 chCtrls[ch].note = note; 1420 chCtrls[ch].velocity = vel; 1421 channels[ch].eeg.keyOff(); 1422 operators[ch].keyOff(intSlmpRate); 1423 operators[ch + 1].keyOff(intSlmpRate); 1424 if ((channels[ch].preset.chCtrl & ChCtrlFlags.ComboModeTest) && ch <= 7) { 1425 channels[ch + 8].eeg.keyOff(); 1426 operators[ch + 16].keyOff(intSlmpRate); 1427 operators[ch + 17].keyOff(intSlmpRate); 1428 } 1429 } 1430 protected void sysExCmd(ubyte[] msg) @nogc pure nothrow { 1431 //Check manufacturer ID (7D: internal use) 1432 if (msg[0] == 0x7D || msg[1] == 0x7D) { 1433 const int msgPos = msg[0] ? 1 : 2; 1434 switch (msg[msgPos]) { 1435 case 0x01: //Suspend channel 1436 if (msg[msgPos + 1] >= 16) return; 1437 chDeleg[msg[msgPos + 1]] = &updateChannelMD; 1438 break; 1439 case 0x02: //Resume channel 1440 if (msg[msgPos + 1] >= 16) return; 1441 ubyte ch = msg[msgPos + 1]; 1442 if (ch < 8) 1443 setChDeleg(channels[ch].preset.chCtrl, ch, channels[ch + 8].preset.chCtrl); 1444 else 1445 setChDeleg(channels[ch].preset.chCtrl, ch); 1446 break; 1447 case 0x03: //Overwrite preset 1448 if (msg[msgPos + 1] >= 16) return; 1449 ubyte ch = msg[msgPos + 1]; 1450 if (msg.length == msgPos + 5) { 1451 presetNum[ch] = msg[msgPos + 2]; 1452 if (channels[ch].preset.chCtrl & ChCtrlFlags.ComboModeTest) { 1453 bankNum[ch] = msg[msgPos + 4] & ~0x01; 1454 presetNum[ch + 8] = msg[msgPos + 2]; 1455 bankNum[ch + 8] = msg[msgPos + 4] | 0x01; 1456 } else 1457 bankNum[ch] = msg[msgPos + 4]; 1458 } 1459 soundBank[bankNum[ch]][presetNum[ch]] = Preset([operators[ch*2].preset, operators[(ch*2) + 1].preset], 1460 channels[ch].preset); 1461 if (ch < 8 && (channels[ch].preset.chCtrl & ChCtrlFlags.ComboModeTest)) { 1462 ch += 8; 1463 soundBank[bankNum[ch]][presetNum[ch]] = Preset([operators[ch*2].preset, operators[(ch*2) + 1].preset], 1464 channels[ch].preset); 1465 } 1466 break; 1467 default: 1468 break; 1469 } 1470 } 1471 } 1472 /** 1473 Sets the channel delegates 1474 */ 1475 protected void setChDeleg(uint chCtrl, uint chNum, uint chCtrl0 = 0) @nogc @safe pure nothrow { 1476 if (chCtrl & ChCtrlFlags.ComboModeTest) { //Test if channel is combined or not 1477 if (chNum < 8) { 1478 const uint algID = (chCtrl & (ChCtrlFlags.ComboModeTest | ChCtrlFlags.Algorithm)) | 1479 ((chCtrl0 & ChCtrlFlags.Algorithm)<<1); 1480 enum priChAlg = ChCtrlFlags.Algorithm; 1481 enum secChAlg = ChCtrlFlags.Algorithm<<1; 1482 switch (algID) { 1483 case ChCtrlFlags.ComboMode1: 1484 chDeleg[chNum] = &updateChannelM100; 1485 break; 1486 case ChCtrlFlags.ComboMode1 | secChAlg: 1487 chDeleg[chNum] = &updateChannelM110; 1488 break; 1489 case ChCtrlFlags.ComboMode1 | priChAlg: 1490 chDeleg[chNum] = &updateChannelM101; 1491 break; 1492 case ChCtrlFlags.ComboMode1 | secChAlg | priChAlg: 1493 chDeleg[chNum] = &updateChannelM111; 1494 break; 1495 case ChCtrlFlags.ComboMode2: 1496 chDeleg[chNum] = &updateChannelM200; 1497 break; 1498 case ChCtrlFlags.ComboMode2 | secChAlg: 1499 chDeleg[chNum] = &updateChannelM210; 1500 break; 1501 case ChCtrlFlags.ComboMode2 | priChAlg: 1502 chDeleg[chNum] = &updateChannelM201; 1503 break; 1504 case ChCtrlFlags.ComboMode2 | secChAlg | priChAlg: 1505 chDeleg[chNum] = &updateChannelM211; 1506 break; 1507 case ChCtrlFlags.ComboMode3: 1508 chDeleg[chNum] = &updateChannelM300; 1509 break; 1510 case ChCtrlFlags.ComboMode3 | secChAlg: 1511 chDeleg[chNum] = &updateChannelM310; 1512 break; 1513 case ChCtrlFlags.ComboMode3 | priChAlg: 1514 chDeleg[chNum] = &updateChannelM301; 1515 break; 1516 case ChCtrlFlags.ComboMode3 | secChAlg | priChAlg: 1517 chDeleg[chNum] = &updateChannelM311; 1518 break; 1519 default: 1520 chDeleg[chNum] = &updateChannelMD; 1521 break; 1522 } 1523 } else { 1524 chDeleg[chNum] = &updateChannelMD; 1525 } 1526 } else { 1527 if (chCtrl & ChCtrlFlags.Algorithm) 1528 chDeleg[chNum] = &updateChannelM01; 1529 else 1530 chDeleg[chNum] = &updateChannelM00; 1531 } 1532 } 1533 /** 1534 Recalls a program 1535 */ 1536 protected void prgRecall(ubyte ch, ubyte prg, ubyte bank) @nogc @safe pure nothrow { 1537 Preset p = soundBank[bank & 7][prg]; 1538 if (p.channel.chCtrl & ChCtrlFlags.ComboModeTest) { 1539 if (ch > 7) ch -= 8; 1540 operators[ch * 2].preset = p.operators[0]; 1541 operators[ch * 2].setEG(intSlmpRate, 40); 1542 operators[ch * 2 + 1].preset = p.operators[1]; 1543 operators[ch * 2 + 1].setEG(intSlmpRate, 40); 1544 channels[ch].preset = p.channel; 1545 channels[ch].setEEG(intSlmpRate); 1546 Preset upper = soundBank[(bank & 7) + 1][prg]; 1547 operators[ch * 2 + 16].preset = upper.operators[0]; 1548 operators[ch * 2 + 16].setEG(intSlmpRate, 40); 1549 operators[ch * 2 + 17].preset = upper.operators[1]; 1550 operators[ch * 2 + 17].setEG(intSlmpRate, 40); 1551 channels[ch + 8].preset = upper.channel; 1552 channels[ch + 8].setEEG(intSlmpRate); 1553 } else { 1554 operators[ch * 2].preset = p.operators[0]; 1555 operators[ch * 2].setEG(intSlmpRate, 40); 1556 operators[ch * 2 + 1].preset = p.operators[1]; 1557 operators[ch * 2 + 1].setEG(intSlmpRate, 40); 1558 channels[ch].preset = p.channel; 1559 channels[ch].setEEG(intSlmpRate); 1560 } 1561 if (ch <= 7) 1562 setChDeleg(channels[ch].preset.chCtrl, ch, channels[ch + 8].preset.chCtrl); 1563 else 1564 setChDeleg(channels[ch].preset.chCtrl, ch); 1565 } 1566 protected void setALFO() @nogc @safe pure nothrow { 1567 aLFOff = calculateLP6factor(intSlmpRate, aLFOFreq * 512); 1568 const double cycleLen = aLFOFreq / intSlmpRate / 1024; 1569 aLFORate = cast(uint)(cycleLen * (1<<22)); 1570 } 1571 protected void setPLFO() @nogc @safe pure nothrow { 1572 const double cycleLen = pLFOFreq / intSlmpRate / 1024; 1573 pLFORate = cast(uint)(cycleLen * (1<<22) * intBufSize); 1574 } 1575 /** 1576 Sets a registered parameter 1577 1578 If type is not zero, then the MSB is being set, otherwise the LSB will be used 1579 */ 1580 protected void setRegisteredParam(T)(T val, ubyte[2] paramNum, ubyte type, ubyte chNum) @nogc @safe pure nothrow { 1581 switch (paramNum[0]) { 1582 case ChannelRegParams.PitchBendSens: 1583 static if (is(T == uint)) { 1584 channels[chNum].pitchBendSens = (cast(double)val / (uint.max / 127.0)); 1585 } else static if (is(T == ubyte)) { 1586 const int whole = cast(int)(channels[chNum].pitchBendSens); 1587 if (type) { 1588 channels[chNum].pitchBendSens = whole + (val / byte.max); 1589 } else { 1590 channels[chNum].pitchBendSens = (channels[chNum].pitchBendSens - whole) * val; 1591 } 1592 } 1593 break; 1594 case ChannelRegParams.TuneFine: //Channel master tuning (fine) 1595 break; 1596 case ChannelRegParams.TuneCor: //Channel master tuning (coarse) 1597 break; 1598 default: break; 1599 } 1600 } 1601 /** 1602 Sets an unregistered parameter (MIDI 2.0) 1603 1604 If type is not zero, then the MSB is being set, otherwise the LSB will be used 1605 */ 1606 protected void setUnregisteredParam(uint val, ubyte[2] paramNum, ubyte chNum) @nogc @safe pure nothrow { 1607 void setOpParam(int opNum) { 1608 switch (paramNum[0]) { 1609 case OperatorParamNums.Attack: 1610 operators[opNum].preset.atk = cast(ubyte)(val >> 25); 1611 operators[opNum].setEG(intSlmpRate, chCtrls[chNum].note); 1612 break; 1613 case OperatorParamNums.Decay: 1614 operators[opNum].preset.dec = cast(ubyte)(val >> 25); 1615 operators[opNum].setEG(intSlmpRate, chCtrls[chNum].note); 1616 break; 1617 case OperatorParamNums.Feedback: 1618 const double valF = cast(double)val / uint.max; 1619 operators[opNum].preset.fbL = pow(valF, 2.5) * (operators[opNum].preset.opCtrl & OpCtrlFlags.FBNeg ? -1 : 1); 1620 break; 1621 case OperatorParamNums.Level: 1622 const double valF = cast(double)val / uint.max; 1623 operators[opNum].preset.outL = valF * valF; 1624 operators[opNum].calculateKSL(chCtrls[chNum].note); 1625 break; 1626 case OperatorParamNums.OpCtrl: 1627 operators[opNum].preset.opCtrl &= OpCtrlFlags.WavetableSelect; 1628 operators[opNum].preset.opCtrl |= val<<7; 1629 break; 1630 case OperatorParamNums.Release: 1631 operators[opNum].preset.rel = cast(ubyte)(val >> 25); 1632 operators[opNum].setEG(intSlmpRate, chCtrls[chNum].note); 1633 break; 1634 case OperatorParamNums.ShpA: 1635 operators[opNum].preset.shpA = cast(double)val / uint.max; 1636 operators[opNum].setShpVals(chCtrls[chNum].velocity); 1637 break; 1638 case OperatorParamNums.ShpR: 1639 operators[opNum].preset.shpR = cast(double)val / uint.max; 1640 operators[opNum].setShpVals(chCtrls[chNum].velocity); 1641 break; 1642 case OperatorParamNums.SusCtrl: 1643 operators[opNum].preset.susCC = cast(ubyte)(val >> 25); 1644 operators[opNum].setEG(intSlmpRate, chCtrls[chNum].note); 1645 break; 1646 case OperatorParamNums.SusLevel: 1647 operators[opNum].eg.sustainLevel = cast(double)val / uint.max; 1648 //Recalculate decay and release rates to new sustain levels 1649 if (operators[opNum].preset.dec) { 1650 operators[opNum].eg.decayRate = calculateRate(ADSR_TIME_TABLE[operators[opNum].preset.dec] * 2, intSlmpRate, 1651 ADSREnvelopGenerator.maxOutput, operators[opNum].eg.sustainLevel); 1652 } else { 1653 operators[opNum].eg.decayRate = 1.0; 1654 } 1655 if (operators[opNum].preset.rel) { 1656 operators[opNum].eg.releaseRate = calculateRate(ADSR_TIME_TABLE[operators[opNum].preset.rel] * 2, intSlmpRate, 1657 operators[opNum].eg.sustainLevel); 1658 } else { 1659 operators[opNum].eg.releaseRate = 1.0; 1660 } 1661 break; 1662 case OperatorParamNums.TuneCor: 1663 if (operators[opNum].preset.opCtrl & OpCtrlFlags.ContiTune) { 1664 operators[opNum].preset.tune = cast(double)val / 0x02_00_00_00; 1665 } else { 1666 operators[opNum].preset.opCtrl &= ~TuneCtrlFlags.CorTuneTest; 1667 operators[opNum].preset.opCtrl |= val & TuneCtrlFlags.CorTuneTest; 1668 } 1669 1670 break; 1671 case OperatorParamNums.TuneFine: 1672 if (!(operators[opNum].preset.opCtrl & OpCtrlFlags.ContiTune)) 1673 operators[opNum].preset.tune = (cast(double)val - int.min) / int.max; 1674 break; 1675 case OperatorParamNums.VelToLevel: 1676 operators[opNum].preset.outLCtrl[0] = cast(double)val / uint.max; 1677 break; 1678 case OperatorParamNums.MWToLevel: 1679 operators[opNum].preset.outLCtrl[1] = cast(double)val / uint.max; 1680 break; 1681 case OperatorParamNums.LFOToLevel: 1682 operators[opNum].preset.outLCtrl[2] = cast(double)val / uint.max; 1683 break; 1684 case OperatorParamNums.VelToFB: 1685 operators[opNum].preset.fbLCtrl[0] = cast(double)val / uint.max; 1686 break; 1687 case OperatorParamNums.MWToFB: 1688 operators[opNum].preset.fbLCtrl[1] = cast(double)val / uint.max; 1689 break; 1690 case OperatorParamNums.LFOToFB: 1691 operators[opNum].preset.fbLCtrl[2] = cast(double)val / uint.max; 1692 break; 1693 case OperatorParamNums.EEGToFB: 1694 operators[opNum].preset.fbLCtrl[3] = cast(double)val / uint.max; 1695 break; 1696 case OperatorParamNums.VelToShpA: 1697 operators[opNum].preset.shpAVel = cast(double)val / uint.max; 1698 break; 1699 case OperatorParamNums.VelToShpR: 1700 operators[opNum].preset.shpRVel = cast(double)val / uint.max; 1701 break; 1702 case OperatorParamNums.Waveform: 1703 operators[opNum].preset.opCtrl &= ~OpCtrlFlags.WavetableSelect; 1704 operators[opNum].preset.opCtrl |= cast(ubyte)(val >> 25); 1705 break; 1706 case OperatorParamNums.KSLBegin: 1707 const ubyte newval = cast(ubyte)(val>>25); 1708 if (newval == 127) 1709 operators[opNum].preset.kslBegin = ubyte.max; 1710 else 1711 operators[opNum].preset.kslBegin = newval; 1712 break; 1713 case OperatorParamNums.KSLAttenOut: 1714 operators[opNum].preset.kslAttenOut = cast(ubyte)(val>>24); 1715 break; 1716 case OperatorParamNums.KSLAttenFB: 1717 operators[opNum].preset.kslAttenFB = cast(ubyte)(val>>24); 1718 break; 1719 case OperatorParamNums.KSLAttenADSR: 1720 operators[opNum].preset.kslAttenADSR = cast(ubyte)(val>>24); 1721 break; 1722 default: break; 1723 } 1724 } 1725 void setOpFlag(int opNum){ 1726 if (val) 1727 operators[opNum].preset.opCtrl |= 1<<(paramNum[0] + 7); 1728 else 1729 operators[opNum].preset.opCtrl &= ~(1<<(paramNum[0] + 7)); 1730 } 1731 switch (paramNum[1]) { 1732 case 0: //Channel operator 0 1733 //chNum *= 2; 1734 setOpParam(chNum * 2); 1735 break; 1736 case 1: //Channel operator 1 1737 //chNum *= 2; 1738 setOpParam((chNum * 2) + 1); 1739 break; 1740 case 2: //Channel operator 0 flags 1741 setOpFlag(chNum * 2); 1742 break; 1743 case 3: //Channel operator 1 flags 1744 setOpFlag((chNum * 2) + 1); 1745 break; 1746 case 4: //Channel common values 1747 switch (paramNum[0]) { 1748 //case ChannelParamNums.ALFO: break; 1749 case ChannelParamNums.Attack: 1750 channels[chNum].preset.atkX = cast(ubyte)(val >> 25); 1751 if (channels[chNum].preset.atkX) { 1752 channels[chNum].eeg.attackRate = calculateRate(ADSR_TIME_TABLE[channels[chNum].preset.atkX], intSlmpRate); 1753 } else { 1754 channels[chNum].eeg.attackRate = 1.0; 1755 } 1756 break; 1757 case ChannelParamNums.AuxSLA: 1758 const double valF = cast(double)val / uint.max; 1759 channels[chNum].outLevels[2] = valF * valF; 1760 channels[chNum].preset.auxSendA = channels[chNum].outLevels[2]; 1761 break; 1762 case ChannelParamNums.AuxSLB: 1763 const double valF = cast(double)val / uint.max; 1764 channels[chNum].outLevels[2] = valF * valF; 1765 channels[chNum].preset.auxSendB = channels[chNum].outLevels[3]; 1766 break; 1767 case ChannelParamNums.Bal: 1768 channels[chNum].preset.masterBal = cast(double)val / uint.max; 1769 if (channels[chNum].preset.chCtrl & ChCtrlFlags.IndivOutChLev) { 1770 channels[chNum].outLevels[1] = channels[chNum].preset.masterBal * channels[chNum].preset.masterBal; 1771 } else { 1772 channels[chNum].outLevels[0] = channels[chNum].preset.masterVol - channels[chNum].preset.masterBal; 1773 channels[chNum].outLevels[1] = channels[chNum].preset.masterVol - (1.0 - channels[chNum].preset.masterBal); 1774 } 1775 break; 1776 case ChannelParamNums.ChCtrl: 1777 channels[chNum].preset.chCtrl = val; 1778 //mirror operator configuration parameters between paired channels 1779 if (chNum < 8) { 1780 channels[chNum + 8].preset.chCtrl &= ~ChCtrlFlags.ComboModeTest; 1781 channels[chNum + 8].preset.chCtrl |= ChCtrlFlags.ComboModeTest & channels[chNum].preset.chCtrl; 1782 } else { 1783 channels[chNum - 8].preset.chCtrl &= ~ChCtrlFlags.ComboModeTest; 1784 channels[chNum - 8].preset.chCtrl |= ChCtrlFlags.ComboModeTest & channels[chNum].preset.chCtrl; 1785 } 1786 break; 1787 //case ChannelParamNums.ChCtrlL: break; 1788 case ChannelParamNums.Decay: 1789 channels[chNum].preset.decX = cast(ubyte)(val >> 25); 1790 if (channels[chNum].preset.decX) { 1791 channels[chNum].eeg.decayRate = calculateRate(ADSR_TIME_TABLE[channels[chNum].preset.decX] * 2, intSlmpRate); 1792 } else { 1793 channels[chNum].eeg.decayRate = 1.0; 1794 } 1795 break; 1796 case ChannelParamNums.EEGDetune: 1797 channels[chNum].preset.eegDetuneAm = ((cast(double)(uint.max>>1) - cast(double)val) / (uint.max>>1)) * 24; 1798 break; 1799 case ChannelParamNums.MasterVol: 1800 const double valF = cast(double)val / uint.max; 1801 channels[chNum].outLevels[2] = valF * valF; 1802 if (channels[chNum].preset.chCtrl & ChCtrlFlags.IndivOutChLev) { 1803 channels[chNum].outLevels[1] = channels[chNum].preset.masterBal * channels[chNum].preset.masterBal; 1804 } else { 1805 channels[chNum].outLevels[0] = channels[chNum].preset.masterVol - channels[chNum].preset.masterBal; 1806 channels[chNum].outLevels[1] = channels[chNum].preset.masterVol - (1.0 - channels[chNum].preset.masterBal); 1807 } 1808 break; 1809 case ChannelParamNums.PLFO: 1810 channels[chNum].preset.pLFOlevel = cast(double)val / uint.max; 1811 break; 1812 case ChannelParamNums.Release: 1813 channels[chNum].preset.relX = cast(ubyte)(val >> 25); 1814 if (channels[chNum].preset.relX) { 1815 channels[chNum].eeg.releaseRate = calculateRate(ADSR_TIME_TABLE[channels[chNum].preset.relX] * 2, intSlmpRate); 1816 } else { 1817 channels[chNum].eeg.releaseRate = 1.0; 1818 } 1819 break; 1820 case ChannelParamNums.ShpA: 1821 channels[chNum].preset.shpAX = cast(double)val / uint.max; 1822 break; 1823 case ChannelParamNums.ShpR: 1824 channels[chNum].preset.shpRX = cast(double)val / uint.max; 1825 break; 1826 case ChannelParamNums.SusCtrl: 1827 channels[chNum].preset.susCCX = cast(ubyte)(val >> 25); 1828 if (channels[chNum].preset.susCCX) { 1829 channels[chNum].eeg.isPercussive = false; 1830 if (channels[chNum].preset.susCCX == 64) { 1831 channels[chNum].eeg.sustainControl = 0.0; 1832 } else if (channels[chNum].preset.susCCX < 64) { 1833 channels[chNum].eeg.sustainControl = -1.0 * 1834 calculateRate(SUSTAIN_CONTROL_TIME_TABLE[channels[chNum].preset.susCCX - 1], intSlmpRate); 1835 } else { 1836 channels[chNum].eeg.sustainControl = 1837 calculateRate(SUSTAIN_CONTROL_TIME_TABLE[channels[chNum].preset.susCCX - 64], intSlmpRate); 1838 } 1839 } else { 1840 channels[chNum].eeg.isPercussive = true; 1841 channels[chNum].eeg.sustainControl = 0.0; 1842 } 1843 break; 1844 case ChannelParamNums.SusLevel: 1845 channels[chNum].eeg.sustainLevel = cast(double)val / uint.max; 1846 channels[chNum].preset.susLevel = channels[chNum].eeg.sustainLevel; 1847 break; 1848 case ChannelParamNums.GlobalFB: 1849 const double valF = cast(double)val / uint.max; 1850 channels[chNum].preset.globalFb = valF * valF; 1851 break; 1852 case ChannelParamNums.EEGToLeft: 1853 const double valF = cast(double)val / uint.max; 1854 channels[chNum].preset.eegLevels[0] = valF * valF; 1855 break; 1856 case ChannelParamNums.EEGToRight: 1857 const double valF = cast(double)val / uint.max; 1858 channels[chNum].preset.eegLevels[1] = valF * valF; 1859 break; 1860 case ChannelParamNums.EEGToAuxA: 1861 const double valF = cast(double)val / uint.max; 1862 channels[chNum].preset.eegLevels[2] = valF * valF; 1863 break; 1864 case ChannelParamNums.EEGToAuxB: 1865 const double valF = cast(double)val / uint.max; 1866 channels[chNum].preset.eegLevels[3] = valF * valF; 1867 break; 1868 case ChannelParamNums.LFOToLeft: 1869 const double valF = cast(double)val / uint.max; 1870 channels[chNum].preset.aLFOlevels[0] = valF * valF; 1871 break; 1872 case ChannelParamNums.LFOToRight: 1873 const double valF = cast(double)val / uint.max; 1874 channels[chNum].preset.aLFOlevels[1] = valF * valF; 1875 break; 1876 case ChannelParamNums.LFOToAuxA: 1877 const double valF = cast(double)val / uint.max; 1878 channels[chNum].preset.aLFOlevels[2] = valF * valF; 1879 break; 1880 case ChannelParamNums.LFOToAuxB: 1881 const double valF = cast(double)val / uint.max; 1882 channels[chNum].preset.aLFOlevels[3] = valF * valF; 1883 break; 1884 case ChannelParamNums.MWToGFB: 1885 const double valF = cast(double)val / uint.max; 1886 channels[chNum].preset.mwToGFB = valF; 1887 break; 1888 case ChannelParamNums.VelToGFB: 1889 const double valF = cast(double)val / uint.max; 1890 channels[chNum].preset.velToGFB = valF; 1891 break; 1892 default: 1893 break; 1894 } 1895 break; 1896 case 5: //Channel common flags 1897 if (val) 1898 channels[chNum].preset.chCtrl |= 1<<paramNum[0]; 1899 else 1900 channels[chNum].preset.chCtrl &= ~(1<<paramNum[0]); 1901 if (chNum < 8) { 1902 channels[chNum + 8].preset.chCtrl &= ~ChCtrlFlags.ComboModeTest; 1903 channels[chNum + 8].preset.chCtrl |= ChCtrlFlags.ComboModeTest & channels[chNum].preset.chCtrl; 1904 setChDeleg(channels[chNum].preset.chCtrl, chNum, channels[chNum + 8].preset.chCtrl); 1905 setChDeleg(channels[chNum + 8].preset.chCtrl, chNum + 8); 1906 } else { 1907 channels[chNum - 8].preset.chCtrl &= ~ChCtrlFlags.ComboModeTest; 1908 channels[chNum - 8].preset.chCtrl |= ChCtrlFlags.ComboModeTest & channels[chNum].preset.chCtrl; 1909 setChDeleg(channels[chNum - 8].preset.chCtrl, chNum - 8, channels[chNum].preset.chCtrl); 1910 setChDeleg(channels[chNum].preset.chCtrl, chNum); 1911 } 1912 break; 1913 case 16: //LFO and master filter settings 1914 void setFilterFreq(int num) @nogc @safe pure nothrow { 1915 const double valF = cast(double)val / uint.max; 1916 filterCtrl[num] = valF * valF * 20_000; 1917 } 1918 1919 void setFilterQ(int num) @nogc @safe pure nothrow { 1920 const double valF = cast(double)val / uint.max; 1921 filterCtrl[num] = valF * 40; 1922 } 1923 1924 switch (paramNum[0]) { 1925 case GlobalParamNums.PLFORate: 1926 double valF; 1927 valF = cast(double)val / uint.max; 1928 valF *= 16; 1929 setPLFO(); 1930 break; 1931 case GlobalParamNums.PLFOWF: 1932 lfoWaveform[0] = cast(ubyte)(val >> 25); 1933 break; 1934 case GlobalParamNums.ALFORate: 1935 if (lfoWaveform[1 & 0x80]) { 1936 aLFOFreq = noteToFreq((cast(double)val) / 0x02_00_00_00, 440); 1937 } else { 1938 aLFOFreq = cast(double)val / uint.max; 1939 aLFOFreq *= 16; 1940 } 1941 setALFO(); 1942 break; 1943 case GlobalParamNums.ALFOWF: 1944 lfoWaveform[1] = cast(ubyte)(val >> 25); 1945 break; 1946 case GlobalParamNums.FilterLCFreq: 1947 const double valF = cast(double)val / uint.max; 1948 filterCtrl[0] = valF * valF * 20_000; 1949 resetLPF(0); 1950 break; 1951 case GlobalParamNums.FilterLCQ: 1952 const double valF = cast(double)val / uint.max; 1953 filterCtrl[1] = valF * 2; 1954 resetLPF(0); 1955 break; 1956 case GlobalParamNums.FilterRCFreq: 1957 const double valF = cast(double)val / uint.max; 1958 filterCtrl[2] = valF * valF * 20_000; 1959 resetLPF(1); 1960 break; 1961 case GlobalParamNums.FilterRCQ: 1962 const double valF = cast(double)val / uint.max; 1963 filterCtrl[3] = valF * 2; 1964 resetLPF(1); 1965 break; 1966 case GlobalParamNums.FilterACFreq: 1967 const double valF = cast(double)val / uint.max; 1968 filterCtrl[4] = valF * valF * 20_000; 1969 resetLPF(2); 1970 break; 1971 case GlobalParamNums.FilterACQ: 1972 const double valF = cast(double)val / uint.max; 1973 filterCtrl[5] = valF * 2; 1974 resetLPF(2); 1975 break; 1976 case GlobalParamNums.FilterBCFreq: 1977 const double valF = cast(double)val / uint.max; 1978 filterCtrl[6] = valF * valF * 20_000; 1979 resetLPF(3); 1980 break; 1981 case GlobalParamNums.FilterBCQ: 1982 const double valF = cast(double)val / uint.max; 1983 filterCtrl[7] = valF * 2; 1984 resetLPF(3); 1985 break; 1986 case GlobalParamNums.HPFLCFreq: 1987 const double valF = cast(double)val / uint.max; 1988 hpfCtrl[0] = valF * valF * 20_000; 1989 resetHPF(0); 1990 break; 1991 case GlobalParamNums.HPFLCQ: 1992 const double valF = cast(double)val / uint.max; 1993 hpfCtrl[1] = valF * 2; 1994 resetHPF(0); 1995 break; 1996 case GlobalParamNums.HPFRCFreq: 1997 const double valF = cast(double)val / uint.max; 1998 hpfCtrl[2] = valF * valF * 20_000; 1999 resetHPF(1); 2000 break; 2001 case GlobalParamNums.HPFRCQ: 2002 const double valF = cast(double)val / uint.max; 2003 hpfCtrl[3] = valF * 2; 2004 resetHPF(1); 2005 break; 2006 case GlobalParamNums.HPFACFreq: 2007 const double valF = cast(double)val / uint.max; 2008 hpfCtrl[4] = valF * valF * 20_000; 2009 resetHPF(2); 2010 break; 2011 case GlobalParamNums.HPFACQ: 2012 const double valF = cast(double)val / uint.max; 2013 hpfCtrl[5] = valF * 2; 2014 resetHPF(2); 2015 break; 2016 case GlobalParamNums.HPFBCFreq: 2017 const double valF = cast(double)val / uint.max; 2018 hpfCtrl[6] = valF * valF * 20_000; 2019 resetHPF(3); 2020 break; 2021 case GlobalParamNums.HPFBCQ: 2022 const double valF = cast(double)val / uint.max; 2023 hpfCtrl[7] = valF * 2; 2024 resetHPF(3); 2025 break; 2026 case GlobalParamNums.RingMod: 2027 if (val) 2028 lfoWaveform[1] |= 0b1000_0000; 2029 else 2030 lfoWaveform[1] &= 0b0111_1111; 2031 break; 2032 default: 2033 break; 2034 } 2035 break; 2036 default: break; 2037 } 2038 } 2039 /** 2040 * Renders the current audio frame. 2041 * 2042 * input: the input buffers if any, null if none. 2043 * output: the output buffers if any, null if none. 2044 * 2045 * NOTE: Buffers must have matching sizes. 2046 */ 2047 public override void renderFrame(float*[] input, float*[] output) @nogc nothrow { 2048 //Generate aLFO table with filtering 2049 for (int i ; i < intBufSize ; i++) { 2050 const float x = (wavetables[lfoWaveform[1] & byte.max][aLFOPos>>22] - short.min) * 2051 (1 / cast(float)(ushort.max)); 2052 const float y = aLFO_y1 + (x - aLFO_y1) * aLFOff; 2053 aLFOBuf[i] = y; 2054 aLFOPos += aLFORate; 2055 aLFO_y1 = y; 2056 } 2057 //Generate pLFO out 2058 { 2059 pLFOOut = (wavetables[lfoWaveform[0]][pLFOPos>>22]) * (1 / cast(float)(short.max)); 2060 pLFOPos += pLFORate; 2061 } 2062 //Render each channel 2063 foreach (size_t i, ChFun fun ; chDeleg) { 2064 2065 fun(cast(int)i, intBufSize); 2066 } 2067 //chDeleg[0](0, bufferSize); 2068 //Filter and mix outputs 2069 float*[4] outBuf; 2070 for (ubyte i, j ; i < 4 ; i++) { 2071 if (enabledOutputs.has(i)) { 2072 outBuf[i] = output[j]; 2073 j++; 2074 } else { 2075 outBuf[i] = dummyBuf.ptr; 2076 } 2077 } 2078 const __m128 b0_a0l = filterVals[3] / filterVals[0], b1_a0l = filterVals[4] / filterVals[0], 2079 b2_a0l = filterVals[5] / filterVals[0], a1_a0l = filterVals[1] / filterVals[0], 2080 a2_a0l = filterVals[2] / filterVals[0], 2081 b0_a0h = hpfVals[3] / hpfVals[0], b1_a0h = hpfVals[4] / hpfVals[0], b2_a0h = hpfVals[5] / hpfVals[0], 2082 a1_a0h = hpfVals[1] / hpfVals[0], a2_a0h = hpfVals[2] / hpfVals[0]; 2083 for (int i ; i < bufferSize ; i++) { 2084 const int intBufPos = (i>>2) * 5; 2085 const int intBP0 = intBufPos + (i & 3); 2086 __m128 input0 = (initBuffers[intBP0] * RESAMPLING_TABLE[i & 3][0]) + 2087 (initBuffers[intBP0 + 1] * RESAMPLING_TABLE[i & 3][1]); 2088 input0 /= __m128(mixdownVal); 2089 input0 = _mm_max_ps(input0, __m128(-1.0)); 2090 input0 = _mm_min_ps(input0, __m128(1.0)); 2091 __m128 output0 = b0_a0l * input0 + b1_a0l * filterVals[6] + b2_a0l * filterVals[7] - a1_a0l * filterVals[8] - 2092 a2_a0l * filterVals[9]; 2093 __m128 output1 = b0_a0h * output0 + b1_a0h * filterVals[8] + b2_a0h * filterVals[9] - a1_a0h * hpfVals[6] - 2094 a2_a0h * hpfVals[7]; 2095 for (int j ; j < 4 ; j++) 2096 outBuf[j][i] += output1[j]; 2097 // outBuf[j][i] += input0[j]; 2098 filterVals[7] = filterVals[6]; 2099 filterVals[6] = input0; 2100 filterVals[9] = filterVals[8]; 2101 filterVals[8] = output0; 2102 hpfVals[7] = hpfVals[6]; 2103 hpfVals[6] = output1; 2104 2105 } 2106 resetBuffer(initBuffers); 2107 } 2108 ///Updates an operator for a cycle 2109 ///chCtrl index notation: 0: velocity, 1: modulation wheel, 2: Amplitude LFO, 3: Extra Envelop Generator 2110 ///Returns the sum of the level control values for use with the resonant mode 2111 pragma(inline, true) 2112 protected double updateOperator(ref Operator op, __m128 chCtrl) @nogc @safe pure nothrow { 2113 op.output = wavetables 2114 [op.preset.opCtrl & OpCtrlFlags.WavetableSelect][(op.pos + (op.input<<20) + (op.feedback<<18))>>22 & 1023]; 2115 const double egOut = op.eg.shp(op.eg.position == ADSREnvelopGenerator.Stage.Attack ? op.shpA0 : op.shpR0); 2116 __m128 outCtrl = (__m128(1.0) - op.preset.outLCtrl) + (op.preset.outLCtrl * chCtrl); 2117 __m128 fbCtrl = (__m128(1.0) - op.preset.fbLCtrl) + (op.preset.fbLCtrl * chCtrl); 2118 2119 op.feedback = cast(int)((op.preset.opCtrl & OpCtrlFlags.FBMode ? op.output : op.output * egOut) * op.fbL * fbCtrl[0] * 2120 fbCtrl[1] * fbCtrl[2] * fbCtrl[3]); 2121 const double levelCtrl = egOut * op.outL * outCtrl[0] * outCtrl[1] * outCtrl[2]; 2122 op.output_0 = cast(int)(op.output * levelCtrl); 2123 op.pos += op.step; 2124 //op.input = 0; 2125 op.eg.advance(); 2126 return levelCtrl; 2127 } 2128 ///Updates automatic and manual pitchbend values (channel-assignable envelop, LFO, pitchbend CTRL) for 2 operators. 2129 pragma(inline, true) 2130 protected final void updatePitchbend2Op(ref Operator op0, ref Operator op1, ref Channel ch, ref ChControllers chCtrl) 2131 @nogc @safe pure nothrow { 2132 if (!isClose(ch.preset.eegDetuneAm, 0.0, 0.1) || !isClose(ch.preset.pLFOlevel, 0.0, 0.01) 2133 || !isClose(chCtrl.pitchBend, 0.0, 0.01)) { 2134 const float eegOut = ch.eeg.shp(ch.eeg.position == ADSREnvelopGenerator.Stage.Attack ? 2135 ch.preset.shpAX : ch.preset.shpRX); 2136 const float vibrAm = pLFOOut * ch.preset.pLFOlevel * 2137 (ch.preset.chCtrl & ChCtrlFlags.MWToVibr ? chCtrl.pitchBend : 1.0); 2138 op0.setFrequency(intSlmpRate, chCtrl.note, chCtrl.pitchBend + (ch.preset.eegDetuneAm * eegOut) * vibrAm, ch.preset.chnlTun); 2139 op1.setFrequency(intSlmpRate, chCtrl.note, chCtrl.pitchBend + (ch.preset.eegDetuneAm * eegOut) * vibrAm, ch.preset.chnlTun); 2140 } 2141 } 2142 ///Updates automatic and manual pitchbend values (channel-assignable envelop, LFO, pitchbend CTRL) for 4 operators. 2143 pragma(inline, true) 2144 protected final void updatePitchbend4Op(ref Operator op0, ref Operator op1, ref Operator op2, ref Operator op3, 2145 ref Channel ch, ref ChControllers chCtrl) @nogc @safe pure nothrow { 2146 if (!isClose(ch.preset.eegDetuneAm, 0.0, 0.1) || !isClose(ch.preset.pLFOlevel, 0.0, 0.01) 2147 || !isClose(chCtrl.pitchBend, 0.0, 0.01)) { 2148 const float eegOut = ch.eeg.shp(ch.eeg.position == ADSREnvelopGenerator.Stage.Attack ? 2149 ch.preset.shpAX : ch.preset.shpRX); 2150 const float vibrAm = pLFOOut * ch.preset.pLFOlevel * 2151 (ch.preset.chCtrl & ChCtrlFlags.MWToVibr ? chCtrl.pitchBend : 1.0); 2152 op0.setFrequency(intSlmpRate, chCtrl.note, chCtrl.pitchBend + (ch.preset.eegDetuneAm * eegOut) * vibrAm, ch.preset.chnlTun); 2153 op1.setFrequency(intSlmpRate, chCtrl.note, chCtrl.pitchBend + (ch.preset.eegDetuneAm * eegOut) * vibrAm, ch.preset.chnlTun); 2154 op2.setFrequency(intSlmpRate, chCtrl.note, chCtrl.pitchBend + (ch.preset.eegDetuneAm * eegOut) * vibrAm, ch.preset.chnlTun); 2155 op3.setFrequency(intSlmpRate, chCtrl.note, chCtrl.pitchBend + (ch.preset.eegDetuneAm * eegOut) * vibrAm, ch.preset.chnlTun); 2156 } 2157 } 2158 ///Macro for channel update constants that need to be calculated once per frame 2159 ///Kept in at one place to make updates easier and more consistent 2160 static immutable string CHNL_UPDATE_CONSTS = 2161 q{ 2162 const int opOffset = chNum * 2; 2163 __m128 aLFOOutMW = __m128(channels[chNum].preset.chCtrl & ChCtrlFlags.MWToTrem ? 2164 chCtrls[chNum].modwheel : 1.0); 2165 const float auxSendAmMW = (channels[chNum].preset.chCtrl & ChCtrlFlags.MWToAux ? 2166 chCtrls[chNum].modwheel : 1.0); 2167 __m128 opCtrl0, opCtrl1, mwAuxCtrl; 2168 opCtrl0[0] = operators[opOffset].preset.opCtrl & OpCtrlFlags.VelNeg ? 1 - chCtrls[chNum].velocity : 2169 chCtrls[chNum].velocity; 2170 opCtrl1[0] = operators[opOffset + 1].preset.opCtrl & OpCtrlFlags.VelNeg ? 1 - chCtrls[chNum].velocity : 2171 chCtrls[chNum].velocity; 2172 opCtrl0[1] = operators[opOffset].preset.opCtrl & OpCtrlFlags.ExprToMW ? chCtrls[chNum].auxCtrl : 2173 chCtrls[chNum].modwheel; 2174 opCtrl1[1] = operators[opOffset + 1].preset.opCtrl & OpCtrlFlags.ExprToMW ? chCtrls[chNum].auxCtrl : 2175 chCtrls[chNum].modwheel; 2176 opCtrl0[1] = operators[opOffset].preset.opCtrl & OpCtrlFlags.MWNeg ? 1 - opCtrl0[1] : opCtrl0[1]; 2177 opCtrl1[1] = operators[opOffset + 1].preset.opCtrl & OpCtrlFlags.MWNeg ? 1 - opCtrl0[1] : opCtrl0[1]; 2178 mwAuxCtrl[0] = 1.0; 2179 mwAuxCtrl[1] = 1.0; 2180 mwAuxCtrl[2] = auxSendAmMW; 2181 mwAuxCtrl[3] = auxSendAmMW; 2182 const float lfopan = (channels[chNum].preset.chCtrl & ChCtrlFlags.LFOPan ? 1.0 : 0); 2183 const float eegpan = (channels[chNum].preset.chCtrl & ChCtrlFlags.EEGPan ? 1.0 : 0); 2184 }; 2185 ///Macro for channel update constants that need to be calculated once per frame, for combined channels' second half 2186 ///Kept in at one place to make updates easier and more consistent 2187 static immutable string CHNL_UPDATE_CONSTS0 = 2188 q{ 2189 __m128 opCtrl2, opCtrl3; 2190 opCtrl2[0] = operators[opOffset + 16].preset.opCtrl & OpCtrlFlags.VelNeg ? 1 - chCtrls[chNum].velocity : 2191 chCtrls[chNum].velocity; 2192 opCtrl3[0] = operators[opOffset + 17].preset.opCtrl & OpCtrlFlags.VelNeg ? 1 - chCtrls[chNum].velocity : 2193 chCtrls[chNum].velocity; 2194 opCtrl2[1] = operators[opOffset + 16].preset.opCtrl & OpCtrlFlags.ExprToMW ? chCtrls[chNum].auxCtrl : 2195 chCtrls[chNum].modwheel; 2196 opCtrl3[1] = operators[opOffset + 17].preset.opCtrl & OpCtrlFlags.ExprToMW ? chCtrls[chNum].auxCtrl : 2197 chCtrls[chNum].modwheel; 2198 opCtrl2[1] = operators[opOffset + 16].preset.opCtrl & OpCtrlFlags.MWNeg ? 1 - opCtrl0[1] : opCtrl0[1]; 2199 opCtrl3[1] = operators[opOffset + 17].preset.opCtrl & OpCtrlFlags.MWNeg ? 1 - opCtrl0[1] : opCtrl0[1]; 2200 const float eegpan0 = (channels[chNum + 8].preset.chCtrl & ChCtrlFlags.EEGPan ? 1.0 : 0); 2201 }; 2202 ///Macro for channel update constants that need to be calculated for each cycle 2203 ///Kept in at one place to make updates easier and more consistent 2204 static immutable string CHNL_UPDATE_CONSTS_CYCL = 2205 q{ 2206 const float eegOut = channels[chNum].eeg.shp(channels[chNum].eeg.position == 2207 ADSREnvelopGenerator.Stage.Attack ? channels[chNum].preset.shpAX : channels[chNum].preset.shpRX); 2208 __m128 eegToMast = __m128(eegOut), lfoToMast = __m128(aLFOBuf[i]); 2209 eegToMast[0] = abs(eegpan - eegToMast[0]); 2210 lfoToMast[0] = abs(lfopan - lfoToMast[0]); 2211 opCtrl0[2] = aLFOBuf[i]; 2212 opCtrl1[2] = aLFOBuf[i]; 2213 opCtrl0[3] = eegOut; 2214 opCtrl1[3] = eegOut; 2215 }; 2216 2217 ///Macro for channel update constants that need to be calculated for each cycle for combined channels' second half 2218 ///Kept in at one place to make updates easier and more consistent 2219 static immutable string CHNL_UPDATE_CONSTS_CYCL0 = 2220 q{ 2221 const float eegOut0 = channels[chNum + 8].eeg.shp(channels[chNum + 8].eeg.position == 2222 ADSREnvelopGenerator.Stage.Attack ? channels[chNum + 8].preset.shpAX : 2223 channels[chNum + 8].preset.shpRX); 2224 __m128 eegToMast0 = __m128(eegOut0); 2225 eegToMast0[0] = abs(eegpan0 - eegToMast0[0]); 2226 opCtrl2[2] = aLFOBuf[i]; 2227 opCtrl3[2] = aLFOBuf[i]; 2228 opCtrl2[3] = eegOut0; 2229 opCtrl3[3] = eegOut0; 2230 }; 2231 2232 ///Macro for output mixing 2233 static immutable string CHNL_UPDATE_MIX = 2234 q{ 2235 __m128 outlevels = channels[chNum].outLevels * mwAuxCtrl; 2236 outlevels *= (channels[chNum].preset.eegLevels * eegToMast) + (__m128(1.0) - (__m128(1.0) * 2237 channels[chNum].preset.eegLevels)); 2238 outlevels *= (channels[chNum].preset.aLFOlevels * lfoToMast) + (__m128(1.0) - (__m128(1.0) * 2239 channels[chNum].preset.aLFOlevels)); 2240 initBuffers[i] += outlevels * outSum; 2241 }; 2242 ///Macro for output mixing in case of combo modes 2243 static immutable string CHNL_UPDATE_MIX0 = 2244 q{ 2245 __m128 outlevels = channels[chNum].outLevels * mwAuxCtrl; 2246 outlevels *= (channels[chNum].eegLevels * eegToMast) + (__m128(1.0) - (__m128(1.0) * 2247 channels[chNum].eegLevels)); 2248 outlevels *= (channels[chNum + 8].eegLevels * eegToMast0) + (__m128(1.0) - 2249 (__m128(1.0) * channels[chNum + 8].eegLevels)); 2250 outlevels *= (channels[chNum].aLFOlevels * lfoToMast) + (__m128(1.0) - (__m128(1.0) * 2251 channels[chNum].aLFOlevels)); 2252 initBuffers[i] += outlevels * outSum; 2253 }; 2254 2255 2256 ///Algorithm Mode 0/0 (Serial) 2257 protected void updateChannelM00(int chNum, size_t length) @nogc pure nothrow { 2258 mixin(CHNL_UPDATE_CONSTS); 2259 updatePitchbend2Op(operators[opOffset], operators[opOffset + 1], channels[chNum], chCtrls[chNum]); 2260 for (size_t i ; i < length ; i++) { 2261 mixin(CHNL_UPDATE_CONSTS_CYCL); 2262 updateOperator(operators[opOffset], opCtrl0); 2263 operators[opOffset + 1].input = operators[opOffset].output_0; 2264 updateOperator(operators[opOffset + 1], opCtrl1); 2265 operators[opOffset].feedback += 2266 cast(int)(operators[opOffset + 1].output_0 * channels[chNum].preset.globalFb * 2267 (channels[chNum].preset.chCtrl & ChCtrlFlags.FBMode ? eegOut : 1)); 2268 __m128 outSum = __m128(operators[opOffset + 1].output_0); 2269 mixin(CHNL_UPDATE_MIX); 2270 channels[chNum].eeg.advance(); 2271 } 2272 } 2273 ///Algorithm Mode0/1 (Parallel) 2274 protected void updateChannelM01(int chNum, size_t length) @nogc pure nothrow { 2275 mixin(CHNL_UPDATE_CONSTS); 2276 updatePitchbend2Op(operators[opOffset], operators[opOffset + 1], channels[chNum], chCtrls[chNum]); 2277 for (size_t i ; i < length ; i++) { 2278 mixin(CHNL_UPDATE_CONSTS_CYCL); 2279 updateOperator(operators[opOffset], opCtrl0); 2280 const double outCtrlOp1 = updateOperator(operators[opOffset + 1], opCtrl1); 2281 //const int outSum = operators[opOffset].output_0 + operators[opOffset + 1].output_0; 2282 const float outSum0 = operators[opOffset].output_0 + operators[opOffset + 1].output_0; 2283 const float outSum1 = ((cast(uint)(operators[opOffset].output - short.min) * 2284 cast(uint)(operators[opOffset + 1].output - short.min))>>16) * outCtrlOp1 + operators[opOffset].output_0; 2285 __m128 outSum = __m128((channels[chNum].preset.chCtrl & ChCtrlFlags.ResMode) ? outSum1 : outSum0); 2286 mixin(CHNL_UPDATE_MIX); 2287 channels[chNum].eeg.advance(); 2288 } 2289 } 2290 ///Algorithm Mode1/00 ([S0]->[S1]->[P0]->[P1]) 2291 protected void updateChannelM100(int chNum, size_t length) @nogc pure nothrow { 2292 mixin(CHNL_UPDATE_CONSTS); 2293 mixin(CHNL_UPDATE_CONSTS0); 2294 2295 for (size_t i ; i < length ; i++) { 2296 mixin(CHNL_UPDATE_CONSTS_CYCL); 2297 mixin(CHNL_UPDATE_CONSTS_CYCL0); 2298 updateOperator(operators[opOffset + 16], opCtrl2); //S0 2299 operators[opOffset + 17].input = operators[opOffset + 16].output_0; 2300 updateOperator(operators[opOffset + 17], opCtrl3); //S1 2301 operators[opOffset].input = operators[opOffset + 17].output_0; 2302 updateOperator(operators[opOffset], opCtrl0); //P0 2303 operators[opOffset + 1].input = operators[opOffset].output_0; 2304 updateOperator(operators[opOffset + 1], opCtrl1); //P1 2305 operators[opOffset + 16].feedback += 2306 cast(int)(operators[opOffset + 1].output_0 * channels[chNum].preset.globalFb * 2307 (channels[chNum].preset.chCtrl & ChCtrlFlags.FBMode ? eegOut : 1)); 2308 //const int outSum = operators[opOffset + 1].output_0; 2309 __m128 outSum = __m128(operators[opOffset + 1].output_0); 2310 mixin(CHNL_UPDATE_MIX); 2311 channels[chNum].eeg.advance(); 2312 channels[chNum + 8].eeg.advance(); 2313 } 2314 } 2315 ///Dummy algorithm for combined channels 2316 protected void updateChannelMD(int chNum, size_t length) @nogc pure nothrow { 2317 2318 } 2319 /** 2320 Algorithm Mode1/10 2321 [S0]\ 2322 ->[P0]->[P1]-> 2323 [S1]/ 2324 */ 2325 protected void updateChannelM110(int chNum, size_t length) @nogc pure nothrow { 2326 mixin(CHNL_UPDATE_CONSTS); 2327 mixin(CHNL_UPDATE_CONSTS0); 2328 for (size_t i ; i < length ; i++) { 2329 mixin(CHNL_UPDATE_CONSTS_CYCL); 2330 mixin(CHNL_UPDATE_CONSTS_CYCL0); 2331 updateOperator(operators[opOffset + 16], opCtrl2); //S0 2332 //operators[opOffset + 17].input = operators[opOffset + 16].output_0; 2333 updateOperator(operators[opOffset + 17], opCtrl3); //S1 2334 operators[opOffset].input = operators[opOffset + 17].output_0 + operators[opOffset + 16].output_0; 2335 updateOperator(operators[opOffset], opCtrl0); //P0 2336 operators[opOffset + 1].input = operators[opOffset].output_0; 2337 updateOperator(operators[opOffset + 1], opCtrl1); //P1 2338 operators[opOffset + 16].feedback += 2339 cast(int)(operators[opOffset + 1].output_0 * channels[chNum].preset.globalFb * 2340 (channels[chNum].preset.chCtrl & ChCtrlFlags.FBMode ? eegOut : 1)); 2341 //const int outSum = operators[opOffset + 1].output_0; 2342 __m128 outSum = __m128(operators[opOffset + 1].output_0); 2343 mixin(CHNL_UPDATE_MIX); 2344 channels[chNum].eeg.advance(); 2345 channels[chNum + 8].eeg.advance(); 2346 } 2347 } 2348 /** 2349 Algorithm Mode1/01 2350 [S0]->[S1]->[P0]-> 2351 [P1]-> 2352 */ 2353 protected void updateChannelM101(int chNum, size_t length) @nogc pure nothrow { 2354 mixin(CHNL_UPDATE_CONSTS); 2355 mixin(CHNL_UPDATE_CONSTS0); 2356 for (size_t i ; i < length ; i++) { 2357 mixin(CHNL_UPDATE_CONSTS_CYCL); 2358 mixin(CHNL_UPDATE_CONSTS_CYCL0); 2359 updateOperator(operators[opOffset + 16], opCtrl2); //S0 2360 operators[opOffset + 17].input = operators[opOffset + 16].output_0; 2361 updateOperator(operators[opOffset + 17], opCtrl3); //S1 2362 operators[opOffset].input = operators[opOffset + 17].output_0; 2363 updateOperator(operators[opOffset], opCtrl0); //P0 2364 //operators[opOffset + 1].input = operators[opOffset].output_0; 2365 const double outCtrlOp1 = updateOperator(operators[opOffset + 1], opCtrl1); //P1 2366 //const int outSum = operators[opOffset + 1].output_0; 2367 operators[opOffset + 16].feedback += 2368 cast(int)(operators[opOffset].output_0 * channels[chNum].preset.globalFb * 2369 (channels[chNum].preset.chCtrl & ChCtrlFlags.FBMode ? eegOut : 1)); 2370 const float outSum0 = operators[opOffset].output_0 + operators[opOffset + 1].output_0; 2371 const float outSum1 = ((cast(uint)(operators[opOffset].output - short.min) * 2372 cast(uint)(operators[opOffset + 1].output - short.min))>>16) * outCtrlOp1 + operators[opOffset].output_0; 2373 __m128 outSum = __m128((channels[chNum].preset.chCtrl & ChCtrlFlags.ResMode) ? outSum1 : outSum0); 2374 mixin(CHNL_UPDATE_MIX); 2375 channels[chNum].eeg.advance(); 2376 channels[chNum + 8].eeg.advance(); 2377 } 2378 } 2379 /** 2380 Algorithm Mode1/11 2381 [S0]\ 2382 ->[P0]-> 2383 [S1]/ [P1]-> 2384 */ 2385 protected void updateChannelM111(int chNum, size_t length) @nogc pure nothrow { 2386 mixin(CHNL_UPDATE_CONSTS); 2387 mixin(CHNL_UPDATE_CONSTS0); 2388 for (size_t i ; i < length ; i++) { 2389 mixin(CHNL_UPDATE_CONSTS_CYCL); 2390 mixin(CHNL_UPDATE_CONSTS_CYCL0); 2391 updateOperator(operators[opOffset + 16], opCtrl2); //S0 2392 //operators[opOffset + 17].input = operators[opOffset + 16].output_0; 2393 updateOperator(operators[opOffset + 17], opCtrl3); //S1 2394 operators[opOffset].input = operators[opOffset + 17].output_0 + operators[opOffset + 16].output_0; 2395 updateOperator(operators[opOffset], opCtrl0); //P0 2396 //operators[opOffset + 1].input = operators[opOffset].output_0; 2397 const double outCtrlOp1 = updateOperator(operators[opOffset + 1], opCtrl1); //P1 2398 //const int outSum = operators[opOffset + 1].output_0; 2399 operators[opOffset + 16].feedback += 2400 cast(int)(operators[opOffset].output_0 * channels[chNum].preset.globalFb * 2401 (channels[chNum].preset.chCtrl & ChCtrlFlags.FBMode ? eegOut : 1)); 2402 const float outSum0 = operators[opOffset].output_0 + operators[opOffset + 1].output_0; 2403 const float outSum1 = ((cast(uint)(operators[opOffset].output - short.min) * 2404 cast(uint)(operators[opOffset + 1].output - short.min))>>16) * outCtrlOp1 + operators[opOffset].output_0; 2405 __m128 outSum = __m128((channels[chNum].preset.chCtrl & ChCtrlFlags.ResMode) ? outSum1 : outSum0); 2406 mixin(CHNL_UPDATE_MIX); 2407 channels[chNum].eeg.advance(); 2408 channels[chNum + 8].eeg.advance(); 2409 } 2410 } 2411 /** 2412 Algorithm Mode2/00 2413 [S0]->[S1]\ 2414 ->[P1]-> 2415 [P0]/ 2416 */ 2417 protected void updateChannelM200(int chNum, size_t length) @nogc pure nothrow { 2418 mixin(CHNL_UPDATE_CONSTS); 2419 mixin(CHNL_UPDATE_CONSTS0); 2420 for (size_t i ; i < length ; i++) { 2421 mixin(CHNL_UPDATE_CONSTS_CYCL); 2422 mixin(CHNL_UPDATE_CONSTS_CYCL0); 2423 updateOperator(operators[opOffset + 16], opCtrl2); //S0 2424 operators[opOffset + 17].input = operators[opOffset + 16].output_0; 2425 updateOperator(operators[opOffset + 17], opCtrl3); //S1 2426 //operators[opOffset].input = operators[opOffset + 17].output_0; 2427 updateOperator(operators[opOffset], opCtrl0); //P0 2428 operators[opOffset + 1].input = operators[opOffset].output_0 + operators[opOffset + 17].output_0; 2429 updateOperator(operators[opOffset + 1], opCtrl1); //P1 2430 //const int outSum = operators[opOffset + 1].output_0; 2431 operators[opOffset + 16].feedback += 2432 cast(int)(operators[opOffset + 1].output_0 * channels[chNum].preset.globalFb * 2433 (channels[chNum].preset.chCtrl & ChCtrlFlags.FBMode ? eegOut : 1)); 2434 __m128 outSum = __m128(operators[opOffset + 1].output_0); 2435 mixin(CHNL_UPDATE_MIX); 2436 channels[chNum].eeg.advance(); 2437 channels[chNum + 8].eeg.advance(); 2438 } 2439 } 2440 /** 2441 Algorithm Mode2/10 2442 [S0]\ 2443 [S1]-->[P1]-> 2444 [P0]/ 2445 */ 2446 protected void updateChannelM210(int chNum, size_t length) @nogc pure nothrow { 2447 mixin(CHNL_UPDATE_CONSTS); 2448 mixin(CHNL_UPDATE_CONSTS0); 2449 for (size_t i ; i < length ; i++) { 2450 mixin(CHNL_UPDATE_CONSTS_CYCL); 2451 mixin(CHNL_UPDATE_CONSTS_CYCL0); 2452 updateOperator(operators[opOffset + 16], opCtrl2); //S0 2453 //operators[opOffset + 17].input = operators[opOffset + 16].output_0; 2454 updateOperator(operators[opOffset + 17], opCtrl3); //S1 2455 //operators[opOffset].input = operators[opOffset + 17].output_0; 2456 updateOperator(operators[opOffset], opCtrl0); //P0 2457 operators[opOffset + 1].input = operators[opOffset].output_0 + operators[opOffset + 17].output_0 + 2458 operators[opOffset + 16].output_0; 2459 const double outCtrlOp1 = updateOperator(operators[opOffset + 1], opCtrl1); //P1 2460 operators[opOffset + 16].feedback += 2461 cast(int)(operators[opOffset + 1].output_0 * channels[chNum].preset.globalFb * 2462 (channels[chNum].preset.chCtrl & ChCtrlFlags.FBMode ? eegOut : 1)); 2463 //const int outSum = operators[opOffset + 1].output_0; 2464 __m128 outSum = __m128(operators[opOffset + 1].output_0); 2465 mixin(CHNL_UPDATE_MIX); 2466 channels[chNum].eeg.advance(); 2467 channels[chNum + 8].eeg.advance(); 2468 } 2469 } 2470 /** 2471 Algorithm Mode2/01 2472 /[P0]-> 2473 [S0]->[S1] 2474 \[P1]-> 2475 */ 2476 protected void updateChannelM201(int chNum, size_t length) @nogc pure nothrow { 2477 mixin(CHNL_UPDATE_CONSTS); 2478 mixin(CHNL_UPDATE_CONSTS0); 2479 for (size_t i ; i < length ; i++) { 2480 mixin(CHNL_UPDATE_CONSTS_CYCL); 2481 mixin(CHNL_UPDATE_CONSTS_CYCL0); 2482 updateOperator(operators[opOffset + 16], opCtrl2); //S0 2483 operators[opOffset + 17].input = operators[opOffset + 16].output_0; 2484 updateOperator(operators[opOffset + 17], opCtrl3); //S1 2485 operators[opOffset].input = operators[opOffset + 17].output_0; 2486 updateOperator(operators[opOffset], opCtrl0); //P0 2487 operators[opOffset + 1].input = operators[opOffset + 17].output_0; 2488 updateOperator(operators[opOffset + 1], opCtrl1); //P1 2489 //const int outSum = operators[opOffset + 1].output_0; 2490 operators[opOffset + 16].feedback += 2491 cast(int)(operators[opOffset].output_0 * channels[chNum].preset.globalFb * 2492 (channels[chNum].preset.chCtrl & ChCtrlFlags.FBMode ? eegOut : 1)); 2493 __m128 outSum = __m128(operators[opOffset + 1].output_0 + operators[opOffset].output_0); 2494 mixin(CHNL_UPDATE_MIX); 2495 channels[chNum].eeg.advance(); 2496 channels[chNum + 8].eeg.advance(); 2497 } 2498 } 2499 /** 2500 Algorithm Mode2/11 2501 [S0]\ /[P0]-> 2502 - 2503 [S1]/ \[P1]-> 2504 */ 2505 protected void updateChannelM211(int chNum, size_t length) @nogc pure nothrow { 2506 mixin(CHNL_UPDATE_CONSTS); 2507 mixin(CHNL_UPDATE_CONSTS0); 2508 for (size_t i ; i < length ; i++) { 2509 mixin(CHNL_UPDATE_CONSTS_CYCL); 2510 mixin(CHNL_UPDATE_CONSTS_CYCL0); 2511 updateOperator(operators[opOffset + 16], opCtrl2); //S0 2512 //operators[opOffset + 17].input = operators[opOffset + 16].output_0; 2513 updateOperator(operators[opOffset + 17], opCtrl3); //S1 2514 operators[opOffset].input = operators[opOffset + 17].output_0 + operators[opOffset + 16].output_0; 2515 updateOperator(operators[opOffset], opCtrl0); //P0 2516 operators[opOffset + 1].input = operators[opOffset + 17].output_0 + operators[opOffset + 16].output_0; 2517 updateOperator(operators[opOffset + 1], opCtrl1); //P1 2518 //const int outSum = operators[opOffset + 1].output_0; 2519 operators[opOffset + 16].feedback += 2520 cast(int)(operators[opOffset].output_0 * channels[chNum].preset.globalFb * 2521 (channels[chNum].preset.chCtrl & ChCtrlFlags.FBMode ? eegOut : 1)); 2522 __m128 outSum = __m128(operators[opOffset + 1].output_0 + operators[opOffset].output_0); 2523 mixin(CHNL_UPDATE_MIX); 2524 channels[chNum].eeg.advance(); 2525 channels[chNum + 8].eeg.advance(); 2526 } 2527 } 2528 /** 2529 Algorithm Mode3/00 2530 [S0]->[S1]-> 2531 [P0]->[P1]-> 2532 */ 2533 protected void updateChannelM300(int chNum, size_t length) @nogc pure nothrow { 2534 mixin(CHNL_UPDATE_CONSTS); 2535 mixin(CHNL_UPDATE_CONSTS0); 2536 for (size_t i ; i < length ; i++) { 2537 mixin(CHNL_UPDATE_CONSTS_CYCL); 2538 mixin(CHNL_UPDATE_CONSTS_CYCL0); 2539 updateOperator(operators[opOffset + 16], opCtrl2); //S0 2540 operators[opOffset + 17].input = operators[opOffset + 16].output_0; 2541 updateOperator(operators[opOffset + 17], opCtrl3); //S1 2542 //operators[opOffset].input = operators[opOffset + 17].output_0; 2543 updateOperator(operators[opOffset], opCtrl0); //P0 2544 operators[opOffset + 1].input = operators[opOffset].output_0; 2545 updateOperator(operators[opOffset + 1], opCtrl1); //P1 2546 //const int outSum = operators[opOffset + 1].output_0; 2547 operators[opOffset + 16].feedback += 2548 cast(int)(operators[opOffset + 17].output_0 * channels[chNum].preset.globalFb * 2549 (channels[chNum].preset.chCtrl & ChCtrlFlags.FBMode ? eegOut : 1)); 2550 __m128 outSum = __m128(operators[opOffset + 1].output_0 + operators[opOffset + 17].output_0); 2551 mixin(CHNL_UPDATE_MIX); 2552 channels[chNum].eeg.advance(); 2553 channels[chNum + 8].eeg.advance(); 2554 } 2555 } 2556 /** 2557 Algorithm Mode3/10 2558 [S0]-> 2559 [S1]-> 2560 [P0]->[P1]-> 2561 */ 2562 protected void updateChannelM310(int chNum, size_t length) @nogc pure nothrow { 2563 mixin(CHNL_UPDATE_CONSTS); 2564 mixin(CHNL_UPDATE_CONSTS0); 2565 for (size_t i ; i < length ; i++) { 2566 mixin(CHNL_UPDATE_CONSTS_CYCL); 2567 mixin(CHNL_UPDATE_CONSTS_CYCL0); 2568 updateOperator(operators[opOffset + 16], opCtrl2); //S0 2569 //operators[opOffset + 17].input = operators[opOffset + 16].output_0; 2570 const double outCtrlOp1 = updateOperator(operators[opOffset + 17], opCtrl3); //S1 2571 //operators[opOffset].input = operators[opOffset + 17].output_0; 2572 updateOperator(operators[opOffset], opCtrl0); //P0 2573 operators[opOffset + 1].input = operators[opOffset].output_0; 2574 updateOperator(operators[opOffset + 1], opCtrl1); //P1 2575 //const int outSum = operators[opOffset + 1].output_0; 2576 operators[opOffset].feedback += 2577 cast(int)(operators[opOffset + 1].output_0 * channels[chNum].preset.globalFb * 2578 (channels[chNum].preset.chCtrl & ChCtrlFlags.FBMode ? eegOut : 1)); 2579 const float outSum0 = operators[opOffset + 1].output_0 + operators[opOffset + 17].output_0 + 2580 operators[opOffset + 16].output_0; 2581 const float outSum1 = ((cast(uint)(((channels[chNum].preset.chCtrl & ChCtrlFlags.ResSrc) ? operators[opOffset].output : 2582 operators[opOffset + 16].output) - short.min) * 2583 cast(uint)(operators[opOffset + 17].output - short.min))>>16) * outCtrlOp1 + 2584 operators[opOffset + 1].output_0 + operators[opOffset + 16].output_0; 2585 __m128 outSum = __m128((channels[chNum].preset.chCtrl & ChCtrlFlags.ResMode) ? outSum1 : outSum0); 2586 /* __m128 outSum = __m128i(operators[opOffset + 1].output_0 + operators[opOffset + 17].output_0 + 2587 operators[opOffset + 16].output_0); */ 2588 mixin(CHNL_UPDATE_MIX); 2589 channels[chNum].eeg.advance(); 2590 channels[chNum + 8].eeg.advance(); 2591 } 2592 } 2593 /** 2594 Algorithm Mode3/01 2595 />[S1]-> 2596 [S0]->[P0]-> 2597 \>[P1]-> 2598 */ 2599 protected void updateChannelM301(int chNum, size_t length) @nogc pure nothrow { 2600 mixin(CHNL_UPDATE_CONSTS); 2601 mixin(CHNL_UPDATE_CONSTS0); 2602 for (size_t i ; i < length ; i++) { 2603 mixin(CHNL_UPDATE_CONSTS_CYCL); 2604 mixin(CHNL_UPDATE_CONSTS_CYCL0); 2605 updateOperator(operators[opOffset + 16], opCtrl2); //S0 2606 operators[opOffset + 17].input = operators[opOffset + 16].output_0; 2607 updateOperator(operators[opOffset + 17], opCtrl3); //S1 2608 operators[opOffset].input = operators[opOffset + 16].output_0; 2609 updateOperator(operators[opOffset], opCtrl0); //P0 2610 operators[opOffset + 1].input = operators[opOffset + 16].output_0; 2611 updateOperator(operators[opOffset + 1], opCtrl1); //P1 2612 //const int outSum = operators[opOffset + 1].output_0; 2613 operators[opOffset + 16].feedback += 2614 cast(int)(operators[opOffset + 17].output_0 * channels[chNum].preset.globalFb * 2615 (channels[chNum].preset.chCtrl & ChCtrlFlags.FBMode ? eegOut : 1)); 2616 __m128 outSum = __m128(operators[opOffset].output_0 + operators[opOffset + 1].output_0 + 2617 operators[opOffset + 17].output_0); 2618 mixin(CHNL_UPDATE_MIX); 2619 channels[chNum].eeg.advance(); 2620 channels[chNum + 8].eeg.advance(); 2621 } 2622 } 2623 /** 2624 Algorithm Mode3/11 2625 [S0]-> 2626 [S1]-> 2627 [P0]-> 2628 [P1]-> 2629 */ 2630 protected void updateChannelM311(int chNum, size_t length) @nogc pure nothrow { 2631 mixin(CHNL_UPDATE_CONSTS); 2632 mixin(CHNL_UPDATE_CONSTS0); 2633 for (size_t i ; i < length ; i++) { 2634 mixin(CHNL_UPDATE_CONSTS_CYCL); 2635 mixin(CHNL_UPDATE_CONSTS_CYCL0); 2636 updateOperator(operators[opOffset + 16], opCtrl2); //S0 2637 //operators[opOffset + 17].input = operators[opOffset + 16].output_0; 2638 const double outCtrlOp1 = updateOperator(operators[opOffset + 17], opCtrl3); //S1 2639 //operators[opOffset].input = operators[opOffset + 17].output_0; 2640 updateOperator(operators[opOffset], opCtrl0); //P0 2641 //operators[opOffset + 1].input = operators[opOffset].output_0; 2642 updateOperator(operators[opOffset + 1], opCtrl1); //P1 2643 //const int outSum = operators[opOffset + 1].output_0; 2644 const float outSum0 = operators[opOffset].output_0 + operators[opOffset + 1].output_0 + 2645 operators[opOffset + 17].output_0 + operators[opOffset + 16].output_0; 2646 const float outSum1 = operators[opOffset].output_0 + operators[opOffset + 1].output_0 + 2647 ((cast(uint)(operators[opOffset + 16].output - short.min) * 2648 cast(uint)(operators[opOffset + 17].output - short.min))>>16) * outCtrlOp1 + 2649 operators[opOffset + 17].output_0; 2650 __m128 outSum = __m128((channels[chNum].preset.chCtrl & ChCtrlFlags.ResMode) ? outSum1 : outSum0); 2651 /* __m128i outSum = __m128i(operators[opOffset].output_0 + operators[opOffset].output_0 + 2652 operators[opOffset + 17].output_0 + operators[opOffset + 16].output_0); */ 2653 mixin(CHNL_UPDATE_MIX); 2654 channels[chNum].eeg.advance(); 2655 channels[chNum + 8].eeg.advance(); 2656 } 2657 } 2658 2659 /** 2660 * Restores a parameter to the given preset. 2661 * Returns an errorcode on failure. 2662 */ 2663 public override int writeParam_int(uint presetID, uint paramID, int value) nothrow { 2664 const ubyte bankNum = cast(ubyte)(presetID>>7), presetNum = cast(ubyte)(presetID & 127); 2665 switch (paramID) { 2666 //op0 begin 2667 case hashCalc(`op0_Attack`): 2668 if (value >=0 && value <= 127) { 2669 soundBank[bankNum][presetNum].operators[0].atk = cast(ubyte)value; 2670 return 0; 2671 } 2672 break; 2673 case hashCalc(`op0_Decay`): 2674 if (value >=0 && value <= 127) { 2675 soundBank[bankNum][presetNum].operators[0].dec = cast(ubyte)value; 2676 return 0; 2677 } 2678 break; 2679 case hashCalc(`op0_SusCtrl`): 2680 if (value >=0 && value <= 127) { 2681 soundBank[bankNum][presetNum].operators[0].susCC = cast(ubyte)value; 2682 return 0; 2683 } 2684 break; 2685 case hashCalc(`op0_Release`): 2686 if (value >=0 && value <= 127) { 2687 soundBank[bankNum][presetNum].operators[0].rel = cast(ubyte)value; 2688 return 0; 2689 } 2690 break; 2691 case hashCalc(`op0_Waveform`): 2692 if (value >=0 && value <= 127) { 2693 soundBank[bankNum][presetNum].operators[0].opCtrl &= ~OpCtrlFlags.WavetableSelect; 2694 soundBank[bankNum][presetNum].operators[0].opCtrl |= cast(ubyte)value; 2695 return 0; 2696 } 2697 break; 2698 case hashCalc(`op0_TuneCor`): 2699 if (value >=0 && value <= 127) { 2700 soundBank[bankNum][presetNum].operators[0].opCtrl &= ~TuneCtrlFlags.CorTuneTest; 2701 soundBank[bankNum][presetNum].operators[0].opCtrl |= (cast(ubyte)value)<<25; 2702 return 0; 2703 } 2704 break; 2705 case hashCalc(`op0_KSLBegin`): 2706 if (value >=0 && value <= 255) { 2707 soundBank[bankNum][presetNum].operators[0].kslBegin = cast(ubyte)value; 2708 return 0; 2709 } 2710 break; 2711 case hashCalc(`op0_KSLAttenOut`): 2712 if (value >=0 && value <= 255) { 2713 soundBank[bankNum][presetNum].operators[0].kslAttenOut = cast(ubyte)value; 2714 return 0; 2715 } 2716 break; 2717 case hashCalc(`op0_KSLAttenFB`): 2718 if (value >=0 && value <= 255) { 2719 soundBank[bankNum][presetNum].operators[1].kslAttenFB = cast(ubyte)value; 2720 return 0; 2721 } 2722 break; 2723 case hashCalc(`op0_KSLAttenADSR`): 2724 if (value >=0 && value <= 255) { 2725 soundBank[bankNum][presetNum].operators[1].kslAttenADSR = cast(ubyte)value; 2726 return 0; 2727 } 2728 break; 2729 //op0 end 2730 2731 //op1 begin 2732 case hashCalc(`op1_Attack`): 2733 if (value >=0 && value <= 127) { 2734 soundBank[bankNum][presetNum].operators[1].atk = cast(ubyte)value; 2735 return 0; 2736 } 2737 break; 2738 case hashCalc(`op1_Decay`): 2739 if (value >=0 && value <= 127) { 2740 soundBank[bankNum][presetNum].operators[1].dec = cast(ubyte)value; 2741 return 0; 2742 } 2743 break; 2744 case hashCalc(`op1_SusCtrl`): 2745 if (value >=0 && value <= 127) { 2746 soundBank[bankNum][presetNum].operators[1].susCC = cast(ubyte)value; 2747 return 0; 2748 } 2749 break; 2750 case hashCalc(`op1_Release`): 2751 if (value >=0 && value <= 127) { 2752 soundBank[bankNum][presetNum].operators[1].rel = cast(ubyte)value; 2753 return 0; 2754 } 2755 break; 2756 case hashCalc(`op1_Waveform`): 2757 if (value >=0 && value <= 127) { 2758 soundBank[bankNum][presetNum].operators[1].opCtrl &= ~OpCtrlFlags.WavetableSelect; 2759 soundBank[bankNum][presetNum].operators[1].opCtrl |= cast(ubyte)value; 2760 return 0; 2761 } 2762 break; 2763 case hashCalc(`op1_TuneCor`): 2764 if (value >=0 && value <= 127) { 2765 soundBank[bankNum][presetNum].operators[1].opCtrl &= ~TuneCtrlFlags.CorTuneTest; 2766 soundBank[bankNum][presetNum].operators[1].opCtrl |= (cast(ubyte)value)<<25; 2767 return 0; 2768 } 2769 break; 2770 case hashCalc(`op1_KSLBegin`): 2771 if (value >=0 && value <= 255) { 2772 soundBank[bankNum][presetNum].operators[1].kslBegin = cast(ubyte)value; 2773 return 0; 2774 } 2775 break; 2776 case hashCalc(`op1_KSLAttenOut`): 2777 if (value >=0 && value <= 255) { 2778 soundBank[bankNum][presetNum].operators[1].kslAttenOut = cast(ubyte)value; 2779 return 0; 2780 } 2781 break; 2782 case hashCalc(`op1_KSLAttenFB`): 2783 if (value >=0 && value <= 255) { 2784 soundBank[bankNum][presetNum].operators[1].kslAttenFB = cast(ubyte)value; 2785 return 0; 2786 } 2787 break; 2788 case hashCalc(`op1_KSLAttenADSR`): 2789 if (value >=0 && value <= 255) { 2790 soundBank[bankNum][presetNum].operators[1].kslAttenADSR = cast(ubyte)value; 2791 return 0; 2792 } 2793 break; 2794 //op1 end 2795 2796 //op0 flags begin 2797 case hashCalc(`op0f_FBMode`): 2798 if (value == 0) { 2799 soundBank[bankNum][presetNum].operators[0].opCtrl &= ~OpCtrlFlags.FBMode; 2800 } else { 2801 soundBank[bankNum][presetNum].operators[0].opCtrl |= OpCtrlFlags.FBMode; 2802 } 2803 return 0; 2804 case hashCalc(`op0f_FBNeg`): 2805 if (value == 0) { 2806 soundBank[bankNum][presetNum].operators[0].opCtrl &= ~OpCtrlFlags.FBNeg; 2807 } else { 2808 soundBank[bankNum][presetNum].operators[0].opCtrl |= OpCtrlFlags.FBNeg; 2809 } 2810 return 0; 2811 case hashCalc(`op0f_MWNeg`): 2812 if (value == 0) { 2813 soundBank[bankNum][presetNum].operators[0].opCtrl &= ~OpCtrlFlags.MWNeg; 2814 } else { 2815 soundBank[bankNum][presetNum].operators[0].opCtrl |= OpCtrlFlags.MWNeg; 2816 } 2817 return 0; 2818 case hashCalc(`op0f_VelNeg`): 2819 if (value == 0) { 2820 soundBank[bankNum][presetNum].operators[0].opCtrl &= ~OpCtrlFlags.VelNeg; 2821 } else { 2822 soundBank[bankNum][presetNum].operators[0].opCtrl |= OpCtrlFlags.VelNeg; 2823 } 2824 return 0; 2825 case hashCalc(`op0f_EGRelAdaptive`): 2826 if (value == 0) { 2827 soundBank[bankNum][presetNum].operators[0].opCtrl &= ~OpCtrlFlags.EGRelAdaptive; 2828 } else { 2829 soundBank[bankNum][presetNum].operators[0].opCtrl |= OpCtrlFlags.EGRelAdaptive; 2830 } 2831 return 0; 2832 case hashCalc(`op0f_FixedPitch`): 2833 if (value == 0) { 2834 soundBank[bankNum][presetNum].operators[0].opCtrl &= ~OpCtrlFlags.FixedPitch; 2835 } else { 2836 soundBank[bankNum][presetNum].operators[0].opCtrl |= OpCtrlFlags.FixedPitch; 2837 } 2838 return 0; 2839 case hashCalc(`op0f_EasyTune`): 2840 if (value == 0) { 2841 soundBank[bankNum][presetNum].operators[0].opCtrl &= ~OpCtrlFlags.EasyTune; 2842 } else { 2843 soundBank[bankNum][presetNum].operators[0].opCtrl |= OpCtrlFlags.EasyTune; 2844 } 2845 return 0; 2846 case hashCalc(`op0f_ContiTune`): 2847 if (value == 0) { 2848 soundBank[bankNum][presetNum].operators[0].opCtrl &= ~OpCtrlFlags.ContiTune; 2849 } else { 2850 soundBank[bankNum][presetNum].operators[0].opCtrl |= OpCtrlFlags.ContiTune; 2851 } 2852 return 0; 2853 case hashCalc(`op0f_ExprToMW`): 2854 if (value == 0) { 2855 soundBank[bankNum][presetNum].operators[0].opCtrl &= ~OpCtrlFlags.ExprToMW; 2856 } else { 2857 soundBank[bankNum][presetNum].operators[0].opCtrl |= OpCtrlFlags.ExprToMW; 2858 } 2859 return 0; 2860 //op0 flags end 2861 2862 //op1 flags begin 2863 case hashCalc(`op1f_FBMode`): 2864 if (value == 0) { 2865 soundBank[bankNum][presetNum].operators[1].opCtrl &= ~OpCtrlFlags.FBMode; 2866 } else { 2867 soundBank[bankNum][presetNum].operators[1].opCtrl |= OpCtrlFlags.FBMode; 2868 } 2869 return 0; 2870 case hashCalc(`op1f_FBNeg`): 2871 if (value == 0) { 2872 soundBank[bankNum][presetNum].operators[1].opCtrl &= ~OpCtrlFlags.FBNeg; 2873 } else { 2874 soundBank[bankNum][presetNum].operators[1].opCtrl |= OpCtrlFlags.FBNeg; 2875 } 2876 return 0; 2877 case hashCalc(`op1f_MWNeg`): 2878 if (value == 0) { 2879 soundBank[bankNum][presetNum].operators[1].opCtrl &= ~OpCtrlFlags.MWNeg; 2880 } else { 2881 soundBank[bankNum][presetNum].operators[1].opCtrl |= OpCtrlFlags.MWNeg; 2882 } 2883 return 0; 2884 case hashCalc(`op1f_VelNeg`): 2885 if (value == 0) { 2886 soundBank[bankNum][presetNum].operators[1].opCtrl &= ~OpCtrlFlags.VelNeg; 2887 } else { 2888 soundBank[bankNum][presetNum].operators[1].opCtrl |= OpCtrlFlags.VelNeg; 2889 } 2890 return 0; 2891 case hashCalc(`op1f_EGRelAdaptive`): 2892 if (value == 0) { 2893 soundBank[bankNum][presetNum].operators[1].opCtrl &= ~OpCtrlFlags.EGRelAdaptive; 2894 } else { 2895 soundBank[bankNum][presetNum].operators[1].opCtrl |= OpCtrlFlags.EGRelAdaptive; 2896 } 2897 return 0; 2898 case hashCalc(`op1f_FixedPitch`): 2899 if (value == 0) { 2900 soundBank[bankNum][presetNum].operators[1].opCtrl &= ~OpCtrlFlags.FixedPitch; 2901 } else { 2902 soundBank[bankNum][presetNum].operators[1].opCtrl |= OpCtrlFlags.FixedPitch; 2903 } 2904 return 0; 2905 case hashCalc(`op1f_EasyTune`): 2906 if (value == 0) { 2907 soundBank[bankNum][presetNum].operators[1].opCtrl &= ~OpCtrlFlags.EasyTune; 2908 } else { 2909 soundBank[bankNum][presetNum].operators[1].opCtrl |= OpCtrlFlags.EasyTune; 2910 } 2911 return 0; 2912 case hashCalc(`op1f_ContiTune`): 2913 if (value == 0) { 2914 soundBank[bankNum][presetNum].operators[1].opCtrl &= ~OpCtrlFlags.ContiTune; 2915 } else { 2916 soundBank[bankNum][presetNum].operators[1].opCtrl |= OpCtrlFlags.ContiTune; 2917 } 2918 return 0; 2919 case hashCalc(`op1f_ExprToMW`): 2920 if (value == 0) { 2921 soundBank[bankNum][presetNum].operators[1].opCtrl &= ~OpCtrlFlags.ExprToMW; 2922 } else { 2923 soundBank[bankNum][presetNum].operators[1].opCtrl |= OpCtrlFlags.ExprToMW; 2924 } 2925 return 0; 2926 //op1 flags end 2927 2928 //ch begin 2929 case hashCalc(`ch_Attack`): 2930 if (value >=0 && value <= 127) { 2931 soundBank[bankNum][presetNum].channel.atkX = cast(ubyte)value; 2932 return 0; 2933 } 2934 break; 2935 case hashCalc(`ch_Decay`): 2936 if (value >=0 && value <= 127) { 2937 soundBank[bankNum][presetNum].channel.decX = cast(ubyte)value; 2938 return 0; 2939 } 2940 break; 2941 case hashCalc(`ch_SusCtrl`): 2942 if (value >=0 && value <= 127) { 2943 soundBank[bankNum][presetNum].channel.susCCX = cast(ubyte)value; 2944 return 0; 2945 } 2946 break; 2947 case hashCalc(`ch_Release`): 2948 if (value >=0 && value <= 127) { 2949 soundBank[bankNum][presetNum].channel.relX = cast(ubyte)value; 2950 return 0; 2951 } 2952 break; 2953 //ch end 2954 2955 //ch flags begins 2956 case hashCalc(`chf_ComboMode`): 2957 if (value >= 0 && value <=3) { 2958 soundBank[bankNum][presetNum].channel.chCtrl &= ~ChCtrlFlags.ComboModeTest; 2959 soundBank[bankNum][presetNum].channel.chCtrl |= value; 2960 return 0; 2961 } 2962 break; 2963 case hashCalc(`chf_Algorithm`): 2964 if (value == 0) { 2965 soundBank[bankNum][presetNum].channel.chCtrl &= ~ChCtrlFlags.Algorithm; 2966 } else { 2967 soundBank[bankNum][presetNum].channel.chCtrl |= ChCtrlFlags.Algorithm; 2968 } 2969 return 0; 2970 case hashCalc(`chf_IndivOutChLev`): 2971 if (value == 0) { 2972 soundBank[bankNum][presetNum].channel.chCtrl &= ~ChCtrlFlags.IndivOutChLev; 2973 } else { 2974 soundBank[bankNum][presetNum].channel.chCtrl |= ChCtrlFlags.IndivOutChLev; 2975 } 2976 return 0; 2977 case hashCalc(`chf_LFOPan`): 2978 if (value == 0) { 2979 soundBank[bankNum][presetNum].channel.chCtrl &= ~ChCtrlFlags.LFOPan; 2980 } else { 2981 soundBank[bankNum][presetNum].channel.chCtrl |= ChCtrlFlags.LFOPan; 2982 } 2983 return 0; 2984 case hashCalc(`chf_EEGPan`): 2985 if (value == 0) { 2986 soundBank[bankNum][presetNum].channel.chCtrl &= ~ChCtrlFlags.EEGPan; 2987 } else { 2988 soundBank[bankNum][presetNum].channel.chCtrl |= ChCtrlFlags.EEGPan; 2989 } 2990 return 0; 2991 case hashCalc(`chf_MWToTrem`): 2992 if (value == 0) { 2993 soundBank[bankNum][presetNum].channel.chCtrl &= ~ChCtrlFlags.MWToTrem; 2994 } else { 2995 soundBank[bankNum][presetNum].channel.chCtrl |= ChCtrlFlags.MWToTrem; 2996 } 2997 return 0; 2998 case hashCalc(`chf_MWToVibr`): 2999 if (value == 0) { 3000 soundBank[bankNum][presetNum].channel.chCtrl &= ~ChCtrlFlags.MWToVibr; 3001 } else { 3002 soundBank[bankNum][presetNum].channel.chCtrl |= ChCtrlFlags.MWToVibr; 3003 } 3004 return 0; 3005 case hashCalc(`chf_MWToAux`): 3006 if (value == 0) { 3007 soundBank[bankNum][presetNum].channel.chCtrl &= ~ChCtrlFlags.MWToAux; 3008 } else { 3009 soundBank[bankNum][presetNum].channel.chCtrl |= ChCtrlFlags.MWToAux; 3010 } 3011 return 0; 3012 case hashCalc(`chf_ResetOnKeyOn`): 3013 if (value == 0) { 3014 soundBank[bankNum][presetNum].channel.chCtrl &= ~ChCtrlFlags.ResetOnKeyOn; 3015 } else { 3016 soundBank[bankNum][presetNum].channel.chCtrl |= ChCtrlFlags.ResetOnKeyOn; 3017 } 3018 return 0; 3019 case hashCalc(`chf_ResetMode`): 3020 if (value == 0) { 3021 soundBank[bankNum][presetNum].channel.chCtrl &= ~ChCtrlFlags.ResetMode; 3022 } else { 3023 soundBank[bankNum][presetNum].channel.chCtrl |= ChCtrlFlags.ResetMode; 3024 } 3025 return 0; 3026 case hashCalc(`chf_FBMode`): 3027 if (value == 0) { 3028 soundBank[bankNum][presetNum].channel.chCtrl &= ~ChCtrlFlags.FBMode; 3029 } else { 3030 soundBank[bankNum][presetNum].channel.chCtrl |= ChCtrlFlags.FBMode; 3031 } 3032 return 0; 3033 case hashCalc(`chf_FBNeg`): 3034 if (value == 0) { 3035 soundBank[bankNum][presetNum].channel.chCtrl &= ~ChCtrlFlags.FBNeg; 3036 } else { 3037 soundBank[bankNum][presetNum].channel.chCtrl |= ChCtrlFlags.FBNeg; 3038 } 3039 return 0; 3040 case hashCalc(`chf_ResMode`): 3041 if (value == 0) { 3042 soundBank[bankNum][presetNum].channel.chCtrl &= ~ChCtrlFlags.ResMode; 3043 } else { 3044 soundBank[bankNum][presetNum].channel.chCtrl |= ChCtrlFlags.ResMode; 3045 } 3046 return 0; 3047 case hashCalc(`chf_ResSrc`): 3048 if (value == 0) { 3049 soundBank[bankNum][presetNum].channel.chCtrl &= ~ChCtrlFlags.ResSrc; 3050 } else { 3051 soundBank[bankNum][presetNum].channel.chCtrl |= ChCtrlFlags.ResSrc; 3052 } 3053 return 0; 3054 //ch flags end 3055 3056 //common values begin 3057 case hashCalc(`_PLFOWF`): 3058 if (value >=0 && value <= 127){ 3059 lfoWaveform[0] = cast(ubyte)value; 3060 return 0; 3061 } 3062 break; 3063 case hashCalc(`_ALFOWF`): 3064 if (value >=0 && value <= 127) { 3065 lfoWaveform[1] &= 0b1000_0000; 3066 lfoWaveform[1] |= cast(ubyte)value; 3067 return 0; 3068 } 3069 break; 3070 case hashCalc(`_Ringmod`): 3071 if (value == 0) 3072 lfoWaveform[1] &= 0b0111_1111; 3073 else 3074 lfoWaveform[1] |= 0b1000_0000; 3075 return 0; 3076 //common values end 3077 default: 3078 return 1; 3079 } 3080 return 2; 3081 } 3082 /** 3083 * Restores a parameter to the given preset. 3084 * Returns an errorcode on failure. 3085 */ 3086 public override int writeParam_long(uint presetID, uint paramID, long value) nothrow { 3087 const ubyte bankNum = cast(ubyte)(presetID>>7), presetNum = cast(ubyte)(presetID & 127); 3088 switch (paramID) { 3089 //case hashCalc(`op0_Tune`):break; 3090 case hashCalc(`op0_OpCtrl`): 3091 soundBank[bankNum][presetNum].operators[0].opCtrl = cast(uint)value; 3092 break; 3093 3094 //case hashCalc(`op1_Tune`):break; 3095 case hashCalc(`op1_OpCtrl`): 3096 soundBank[bankNum][presetNum].operators[1].opCtrl = cast(uint)value; 3097 break; 3098 3099 case hashCalc(`ch_ChCtrl`): 3100 soundBank[bankNum][presetNum].channel.chCtrl = cast(uint)value; 3101 break; 3102 default: 3103 return 1; 3104 } 3105 return 0; 3106 } 3107 /** 3108 * Restores a parameter to the given preset. 3109 * Returns an errorcode on failure. 3110 */ 3111 public override int writeParam_double(uint presetID, uint paramID, double value) nothrow { 3112 const ubyte bankNum = cast(ubyte)(presetID>>7), presetNum = cast(ubyte)(presetID & 127); 3113 switch (paramID) { 3114 //op0 begin 3115 case hashCalc(`op0_Level`): 3116 if (value >= 0 && value <= 1) { 3117 soundBank[bankNum][presetNum].operators[0].outL = value; 3118 return 0; 3119 } 3120 break; 3121 case hashCalc(`op0_SusLevel`): 3122 if (value >= 0 && value <= 1) { 3123 soundBank[bankNum][presetNum].operators[0].susLevel = value; 3124 return 0; 3125 } 3126 break; 3127 case hashCalc(`op0_Feedback`): 3128 if (value >= 0 && value <= 1) { 3129 soundBank[bankNum][presetNum].operators[0].fbL = value; 3130 return 0; 3131 } 3132 break; 3133 case hashCalc(`op0_Tune`): 3134 soundBank[bankNum][presetNum].operators[0].tune = value; 3135 3136 return 0; 3137 //case hashCalc(`op0_FreqRate`):break; 3138 case hashCalc(`op0_ShpA`): 3139 if (value >= 0 && value <= 1) { 3140 soundBank[bankNum][presetNum].operators[0].shpA = value; 3141 return 0; 3142 } 3143 break; 3144 case hashCalc(`op0_ShpR`): 3145 if (value >= 0 && value <= 1) { 3146 soundBank[bankNum][presetNum].operators[0].shpR = value; 3147 return 0; 3148 } 3149 break; 3150 case hashCalc(`op0_VelToLevel`): 3151 if (value >= 0 && value <= 1) { 3152 soundBank[bankNum][presetNum].operators[0].outLCtrl[0] = value; 3153 return 0; 3154 } 3155 break; 3156 case hashCalc(`op0_MWToLevel`): 3157 if (value >= 0 && value <= 1) { 3158 soundBank[bankNum][presetNum].operators[0].outLCtrl[1] = value; 3159 return 0; 3160 } 3161 break; 3162 case hashCalc(`op0_LFOToLevel`): 3163 if (value >= 0 && value <= 1) { 3164 soundBank[bankNum][presetNum].operators[0].outLCtrl[2] = value; 3165 return 0; 3166 } 3167 break; 3168 case hashCalc(`op0_VelToFB`): 3169 if (value >= 0 && value <= 1) { 3170 soundBank[bankNum][presetNum].operators[0].fbLCtrl[0] = value; 3171 return 0; 3172 } 3173 break; 3174 case hashCalc(`op0_MWToFB`): 3175 if (value >= 0 && value <= 1) { 3176 soundBank[bankNum][presetNum].operators[0].fbLCtrl[1] = value; 3177 return 0; 3178 } 3179 break; 3180 case hashCalc(`op0_LFOToFB`): 3181 if (value >= 0 && value <= 1) { 3182 soundBank[bankNum][presetNum].operators[0].fbLCtrl[2] = value; 3183 return 0; 3184 } 3185 break; 3186 case hashCalc(`op0_EEGToFB`): 3187 if (value >= 0 && value <= 1) { 3188 soundBank[bankNum][presetNum].operators[0].fbLCtrl[3] = value; 3189 return 0; 3190 } 3191 break; 3192 case hashCalc(`op0_VelToShpA`): 3193 if (value >= 0 && value <= 1) { 3194 soundBank[bankNum][presetNum].operators[0].shpAVel = value; 3195 return 0; 3196 } 3197 break; 3198 case hashCalc(`op0_VelToShpR`): 3199 if (value >= 0 && value <= 1) { 3200 soundBank[bankNum][presetNum].operators[0].shpRVel = value; 3201 return 0; 3202 } 3203 break; 3204 //op0 end 3205 3206 //op1 begin 3207 case hashCalc(`op1_Level`): 3208 if (value >= 0 && value <= 1) { 3209 soundBank[bankNum][presetNum].operators[1].outL = value; 3210 return 0; 3211 } 3212 break; 3213 case hashCalc(`op1_SusLevel`): 3214 if (value >= 0 && value <= 1) { 3215 soundBank[bankNum][presetNum].operators[1].susLevel = value; 3216 return 0; 3217 } 3218 break; 3219 case hashCalc(`op1_Feedback`): 3220 if (value >= 0 && value <= 1) { 3221 soundBank[bankNum][presetNum].operators[1].fbL = value; 3222 return 0; 3223 } 3224 break; 3225 case hashCalc(`op1_Tune`): 3226 soundBank[bankNum][presetNum].operators[1].tune = value; 3227 3228 return 0; 3229 //case hashCalc(`op1_FreqRate`):break; 3230 case hashCalc(`op1_ShpA`): 3231 if (value >= 0 && value <= 1) { 3232 soundBank[bankNum][presetNum].operators[1].shpA = value; 3233 return 0; 3234 } 3235 break; 3236 case hashCalc(`op1_ShpR`): 3237 if (value >= 0 && value <= 1) { 3238 soundBank[bankNum][presetNum].operators[1].shpR = value; 3239 return 0; 3240 } 3241 break; 3242 case hashCalc(`op1_VelToLevel`): 3243 if (value >= 0 && value <= 1) { 3244 soundBank[bankNum][presetNum].operators[1].outLCtrl[0] = value; 3245 return 0; 3246 } 3247 break; 3248 case hashCalc(`op1_MWToLevel`): 3249 if (value >= 0 && value <= 1) { 3250 soundBank[bankNum][presetNum].operators[1].outLCtrl[1] = value; 3251 return 0; 3252 } 3253 break; 3254 case hashCalc(`op1_LFOToLevel`): 3255 if (value >= 0 && value <= 1) { 3256 soundBank[bankNum][presetNum].operators[1].outLCtrl[2] = value; 3257 return 0; 3258 } 3259 break; 3260 case hashCalc(`op1_VelToFB`): 3261 if (value >= 0 && value <= 1) { 3262 soundBank[bankNum][presetNum].operators[1].fbLCtrl[0] = value; 3263 return 0; 3264 } 3265 break; 3266 case hashCalc(`op1_MWToFB`): 3267 if (value >= 0 && value <= 1) { 3268 soundBank[bankNum][presetNum].operators[1].fbLCtrl[1] = value; 3269 return 0; 3270 } 3271 break; 3272 case hashCalc(`op1_LFOToFB`): 3273 if (value >= 0 && value <= 1) { 3274 soundBank[bankNum][presetNum].operators[1].fbLCtrl[2] = value; 3275 return 0; 3276 } 3277 break; 3278 case hashCalc(`op1_EEGToFB`): 3279 if (value >= 0 && value <= 1) { 3280 soundBank[bankNum][presetNum].operators[1].fbLCtrl[3] = value; 3281 return 0; 3282 } 3283 break; 3284 case hashCalc(`op1_VelToShpA`): 3285 if (value >= 0 && value <= 1) { 3286 soundBank[bankNum][presetNum].operators[1].shpAVel = value; 3287 return 0; 3288 } 3289 break; 3290 case hashCalc(`op1_VelToShpR`): 3291 if (value >= 0 && value <= 1) { 3292 soundBank[bankNum][presetNum].operators[1].shpRVel = value; 3293 return 0; 3294 } 3295 break; 3296 //op1 end 3297 3298 //ch begin 3299 case hashCalc(`ch_MasterVol`): 3300 if (value >= 0 && value <= 1) { 3301 soundBank[bankNum][presetNum].channel.masterVol = value; 3302 return 0; 3303 } 3304 break; 3305 case hashCalc(`ch_Bal`): 3306 if (value >= 0 && value <= 1) { 3307 soundBank[bankNum][presetNum].channel.masterBal = value; 3308 return 0; 3309 } 3310 break; 3311 case hashCalc(`ch_AuxSLA`): 3312 if (value >= 0 && value <= 1) { 3313 soundBank[bankNum][presetNum].channel.auxSendA = value; 3314 return 0; 3315 } 3316 break; 3317 case hashCalc(`ch_AuxSLB`): 3318 if (value >= 0 && value <= 1) { 3319 soundBank[bankNum][presetNum].channel.auxSendB = value; 3320 return 0; 3321 } 3322 break; 3323 case hashCalc(`ch_EEGDetune`): 3324 soundBank[bankNum][presetNum].channel.eegDetuneAm = value; 3325 return 0; 3326 case hashCalc(`ch_PitchBendSens`): 3327 soundBank[bankNum][presetNum].channel.pitchBendSens = value; 3328 return 0; 3329 case hashCalc(`ch_Tune`): 3330 soundBank[bankNum][presetNum].channel.chnlTun = value; 3331 return 0; 3332 case hashCalc(`ch_PLFO`): 3333 soundBank[bankNum][presetNum].channel.pLFOlevel = value; 3334 return 0; 3335 case hashCalc(`ch_SusLevel`): 3336 if (value >= 0 && value <= 1) { 3337 soundBank[bankNum][presetNum].channel.susLevel = value; 3338 return 0; 3339 } 3340 break; 3341 case hashCalc(`ch_ShpA`): 3342 if (value >= 0 && value <= 1) { 3343 soundBank[bankNum][presetNum].channel.shpAX = value; 3344 return 0; 3345 } 3346 break; 3347 case hashCalc(`ch_ShpR`): 3348 if (value >= 0 && value <= 1) { 3349 soundBank[bankNum][presetNum].channel.shpRX = value; 3350 return 0; 3351 } 3352 break; 3353 case hashCalc(`ch_GlobalFB`): 3354 if (value >= 0 && value <= 1) { 3355 soundBank[bankNum][presetNum].channel.globalFb = value; 3356 return 0; 3357 } 3358 break; 3359 case hashCalc(`ch_EEGToLeft`): 3360 if (value >= 0 && value <= 1) { 3361 soundBank[bankNum][presetNum].channel.eegLevels[0] = value; 3362 return 0; 3363 } 3364 break; 3365 case hashCalc(`ch_EEGToRight`): 3366 if (value >= 0 && value <= 1) { 3367 soundBank[bankNum][presetNum].channel.eegLevels[1] = value; 3368 return 0; 3369 } 3370 break; 3371 case hashCalc(`ch_EEGToAuxA`): 3372 if (value >= 0 && value <= 1) { 3373 soundBank[bankNum][presetNum].channel.eegLevels[2] = value; 3374 return 0; 3375 } 3376 break; 3377 case hashCalc(`ch_EEGToAuxB`): 3378 if (value >= 0 && value <= 1) { 3379 soundBank[bankNum][presetNum].channel.eegLevels[3] = value; 3380 return 0; 3381 } 3382 break; 3383 case hashCalc(`ch_LFOToLeft`): 3384 if (value >= 0 && value <= 1) { 3385 soundBank[bankNum][presetNum].channel.aLFOlevels[0] = value; 3386 return 0; 3387 } 3388 break; 3389 case hashCalc(`ch_LFOToRight`): 3390 if (value >= 0 && value <= 1) { 3391 soundBank[bankNum][presetNum].channel.aLFOlevels[1] = value; 3392 return 0; 3393 } 3394 break; 3395 case hashCalc(`ch_LFOToAuxA`): 3396 if (value >= 0 && value <= 1) { 3397 soundBank[bankNum][presetNum].channel.aLFOlevels[2] = value; 3398 return 0; 3399 } 3400 break; 3401 case hashCalc(`ch_LFOToAuxB`): 3402 if (value >= 0 && value <= 1) { 3403 soundBank[bankNum][presetNum].channel.aLFOlevels[3] = value; 3404 return 0; 3405 } 3406 break; 3407 case hashCalc(`ch_MWToGFB`): 3408 if (value >= 0 && value <= 1) { 3409 soundBank[bankNum][presetNum].channel.mwToGFB = value; 3410 return 0; 3411 } 3412 break; 3413 case hashCalc(`ch_VelToGFB`): 3414 if (value >= 0 && value <= 1) { 3415 soundBank[bankNum][presetNum].channel.velToGFB = value; 3416 return 0; 3417 } 3418 break; 3419 //ch end 3420 3421 //commons begin 3422 case hashCalc(`_PLFORate`): 3423 pLFOFreq = value; 3424 setPLFO(); 3425 return 0; 3426 case hashCalc(`_ALFORate`): 3427 aLFOFreq = value; 3428 setALFO(); 3429 return 0; 3430 case hashCalc(`_FilterLCFreq`): 3431 filterCtrl[0] = value; 3432 resetLPF(0); 3433 return 0; 3434 case hashCalc(`_FilterLCQ`): 3435 filterCtrl[1] = value; 3436 resetLPF(0); 3437 return 0; 3438 case hashCalc(`_FilterRCFreq`): 3439 filterCtrl[2] = value; 3440 resetLPF(1); 3441 return 0; 3442 case hashCalc(`_FilterRCQ`): 3443 filterCtrl[3] = value; 3444 resetLPF(1); 3445 return 0; 3446 case hashCalc(`_FilterACFreq`): 3447 filterCtrl[4] = value; 3448 resetLPF(2); 3449 return 0; 3450 case hashCalc(`_FilterACQ`): 3451 filterCtrl[5] = value; 3452 resetLPF(2); 3453 return 0; 3454 case hashCalc(`_FilterBCFreq`): 3455 filterCtrl[6] = value; 3456 resetLPF(3); 3457 return 0; 3458 case hashCalc(`_FilterBCQ`): 3459 filterCtrl[7] = value; 3460 resetLPF(3); 3461 return 0; 3462 case hashCalc(`_HPFLCFreq`): 3463 hpfCtrl[0] = value; 3464 resetHPF(0); 3465 return 0; 3466 case hashCalc(`_HPFLCQ`): 3467 hpfCtrl[1] = value; 3468 resetHPF(0); 3469 return 0; 3470 case hashCalc(`_HPFRCFreq`): 3471 hpfCtrl[2] = value; 3472 resetHPF(1); 3473 return 0; 3474 case hashCalc(`_HPFRCQ`): 3475 hpfCtrl[3] = value; 3476 resetHPF(1); 3477 return 0; 3478 case hashCalc(`_HPFACFreq`): 3479 hpfCtrl[4] = value; 3480 resetHPF(2); 3481 return 0; 3482 case hashCalc(`_HPFACQ`): 3483 hpfCtrl[5] = value; 3484 resetHPF(2); 3485 return 0; 3486 case hashCalc(`_HPFBCFreq`): 3487 hpfCtrl[6] = value; 3488 resetHPF(3); 3489 return 0; 3490 case hashCalc(`_HPFBCQ`): 3491 hpfCtrl[6] = value; 3492 resetHPF(3); 3493 return 0; 3494 //commons end 3495 default: 3496 return 1; 3497 } 3498 return 2; 3499 } 3500 /** 3501 * Restores a parameter to the given preset. 3502 * Returns an errorcode on failure. 3503 */ 3504 public override int writeParam_string(uint presetID, uint paramID, string value) nothrow { 3505 return 0; 3506 } 3507 /** 3508 * Returns all the possible parameters this module has. 3509 */ 3510 public override MValue[] getParameters() nothrow { 3511 return [ 3512 MValue(MValueType.Float,`op0_Level`), MValue(MValueType.Int32,`op0_Attack`), MValue(MValueType.Int32,`op0_Decay`), 3513 MValue(MValueType.Float,`op0_SusLevel`), MValue(MValueType.Int32,`op0_SusCtrl`), 3514 MValue(MValueType.Int32,`op0_Release`), MValue(MValueType.Int32,`op0_Waveform`), 3515 MValue(MValueType.Float,`op0_Feedback`), MValue(MValueType.Int32,`op0_TuneCor`), 3516 MValue(MValueType.Float,`op0_Tune`), MValue(MValueType.Float,`op0_ShpA`), 3517 MValue(MValueType.Float,`op0_ShpR`), MValue(MValueType.Float,`op0_VelToLevel`), 3518 MValue(MValueType.Float,`op0_MWToLevel`), MValue(MValueType.Float,`op0_LFOToLevel`), 3519 MValue(MValueType.Int64,`op0_OpCtrl`), MValue(MValueType.Float,`op0_VelToFB`), MValue(MValueType.Float,`op0_MWToFB`), 3520 MValue(MValueType.Float,`op0_LFOToFB`), MValue(MValueType.Float,`op0_EEGToFB`), 3521 MValue(MValueType.Float,`op0_VelToShpA`), MValue(MValueType.Float,`op0_VelToShpR`), 3522 MValue(MValueType.Int32,`op0_KSLBegin`), MValue(MValueType.Int32,`op0_KSLAttenOut`), 3523 MValue(MValueType.Int32,`op0_KSLAttenFB`), MValue(MValueType.Int32,`op0_KSLAttenADSR`), 3524 3525 MValue(MValueType.Boolean,`op0f_FBMode`), MValue(MValueType.Boolean,`op0f_FBNeg`), 3526 MValue(MValueType.Boolean,`op0f_MWNeg`), MValue(MValueType.Boolean,`op0f_VelNeg`), 3527 MValue(MValueType.Boolean,`op0f_EGRelAdaptive`), MValue(MValueType.Boolean,`op0f_FixedPitch`), 3528 MValue(MValueType.Boolean,`op0f_EasyTune`), MValue(MValueType.Boolean,`op0f_ContiTune`), 3529 MValue(MValueType.Boolean,`op0f_ExprToMW`), 3530 3531 MValue(MValueType.Float,`op1_Level`), MValue(MValueType.Int32,`op1_Attack`), MValue(MValueType.Int32,`op1_Decay`), 3532 MValue(MValueType.Float,`op1_SusLevel`), MValue(MValueType.Int32,`op1_SusCtrl`), 3533 MValue(MValueType.Int32,`op1_Release`), MValue(MValueType.Int32,`op1_Waveform`), 3534 MValue(MValueType.Float,`op1_Feedback`), MValue(MValueType.Int32,`op1_TuneCor`), 3535 MValue(MValueType.Float,`op1_Tune`), MValue(MValueType.Float,`op1_ShpA`), 3536 MValue(MValueType.Float,`op1_ShpR`), MValue(MValueType.Float,`op1_VelToLevel`), 3537 MValue(MValueType.Float,`op1_MWToLevel`), MValue(MValueType.Float,`op1_LFOToLevel`), 3538 MValue(MValueType.Int64,`op1_OpCtrl`), MValue(MValueType.Float,`op1_VelToFB`), MValue(MValueType.Float,`op1_MWToFB`), 3539 MValue(MValueType.Float,`op1_LFOToFB`), MValue(MValueType.Float,`op1_EEGToFB`), 3540 MValue(MValueType.Float,`op1_VelToShpA`), MValue(MValueType.Float,`op1_VelToShpR`), 3541 MValue(MValueType.Int32,`op1_KSLBegin`), MValue(MValueType.Int32,`op1_KSLAttenOut`), 3542 MValue(MValueType.Int32,`op1_KSLAttenFB`), MValue(MValueType.Int32,`op1_KSLAttenADSR`), 3543 3544 MValue(MValueType.Boolean,`op1f_FBMode`), MValue(MValueType.Boolean,`op1f_FBNeg`), 3545 MValue(MValueType.Boolean,`op1f_MWNeg`), MValue(MValueType.Boolean,`op1f_VelNeg`), 3546 MValue(MValueType.Boolean,`op1f_EGRelAdaptive`), MValue(MValueType.Boolean,`op1f_FixedPitch`), 3547 MValue(MValueType.Boolean,`op1f_EasyTune`), MValue(MValueType.Boolean,`op1f_ContiTune`), 3548 MValue(MValueType.Boolean,`op1f_ExprToMW`), 3549 3550 MValue(MValueType.Float,`ch_MasterVol`), MValue(MValueType.Float,`ch_Bal`), MValue(MValueType.Float,`ch_AuxSLA`), 3551 MValue(MValueType.Float,`ch_AuxSLB`), MValue(MValueType.Float,`ch_EEGDetune`), MValue(MValueType.Float,`ch_PLFO`), 3552 MValue(MValueType.Int32,`ch_Attack`), MValue(MValueType.Int32,`ch_Decay`), MValue(MValueType.Float,`ch_SusLevel`), 3553 MValue(MValueType.Int32,`ch_SusCtrl`), MValue(MValueType.Int32,`ch_Release`), MValue(MValueType.Float,`ch_ShpA`), 3554 MValue(MValueType.Float,`ch_ShpR`), MValue(MValueType.Float,`ch_GlobalFB`), MValue(MValueType.Int64,`ch_ChCtrl`), 3555 MValue(MValueType.Float,`ch_EEGToLeft`), MValue(MValueType.Float,`ch_EEGToRight`), 3556 MValue(MValueType.Float,`ch_EEGToAuxA`), MValue(MValueType.Float,`ch_EEGToAuxB`), 3557 MValue(MValueType.Float,`ch_LFOToLeft`), MValue(MValueType.Float,`ch_LFOToRight`), 3558 MValue(MValueType.Float,`ch_LFOToAuxA`), MValue(MValueType.Float,`ch_LFOToAuxB`), 3559 MValue(MValueType.Float,`ch_MWToGFB`), MValue(MValueType.Float,`ch_VelToGFB`), 3560 3561 MValue(MValueType.Int32,`chf_ComboMode`), MValue(MValueType.Boolean,`chf_Algorithm`), 3562 MValue(MValueType.Boolean,`chf_IndivOutChLev`), MValue(MValueType.Boolean,`chf_LFOPan`), 3563 MValue(MValueType.Boolean,`chf_EEGPan`), MValue(MValueType.Boolean,`chf_MWToTrem`), 3564 MValue(MValueType.Boolean,`chf_MWToVibr`), MValue(MValueType.Boolean,`chf_MWToAux`), 3565 MValue(MValueType.Boolean,`chf_ResetOnKeyOn`), MValue(MValueType.Boolean,`chf_ResetMode`), 3566 MValue(MValueType.Boolean,`chf_FBMode`), MValue(MValueType.Boolean,`chf_FBNeg`), 3567 MValue(MValueType.Boolean,`chf_ResMode`), MValue(MValueType.Boolean,`chf_ResSrc`), 3568 3569 MValue(MValueType.Float,`_PLFORate`), MValue(MValueType.Int32,`_PLFOWF`), 3570 MValue(MValueType.Float,`_ALFORate`), MValue(MValueType.Int32,`_ALFOWF`), 3571 MValue(MValueType.Float,`_FilterLCFreq`),MValue(MValueType.Float,`_FilterLCQ`), 3572 MValue(MValueType.Float,`_FilterRCFreq`),MValue(MValueType.Float,`_FilterRCQ`), 3573 MValue(MValueType.Float,`_FilterACFreq`),MValue(MValueType.Float,`_FilterACQ`), 3574 MValue(MValueType.Float,`_FilterBCFreq`),MValue(MValueType.Float,`_FilterBCQ`), 3575 MValue(MValueType.Float,`_HPFLCFreq`),MValue(MValueType.Float,`_HPFLCQ`), 3576 MValue(MValueType.Float,`_HPFRCFreq`),MValue(MValueType.Float,`_HPFRCQ`), 3577 MValue(MValueType.Float,`_HPFACFreq`),MValue(MValueType.Float,`_HPFACQ`), 3578 MValue(MValueType.Float,`_HPFBCFreq`),MValue(MValueType.Float,`_HPFBCQ`), 3579 MValue(MValueType.Boolean,`_Ringmod`), 3580 ]; 3581 } 3582 /** 3583 * Reads the given value (int). 3584 * Params: 3585 * presetID = The preset ID, or uint.max for global module values. 3586 * paramID = The parameter ID. 3587 * Returns: The value of the given preset and parameter 3588 */ 3589 public override int readParam_int(uint presetID, uint paramID) nothrow { 3590 const ubyte bankNum = cast(ubyte)(presetID>>7), presetNum = cast(ubyte)(presetID & 127); 3591 switch (paramID) { 3592 //op0 begin 3593 case hashCalc(`op0_Attack`): 3594 return soundBank[bankNum][presetNum].operators[0].atk; 3595 case hashCalc(`op0_Decay`): 3596 return soundBank[bankNum][presetNum].operators[0].dec; 3597 case hashCalc(`op0_SusCtrl`): 3598 return soundBank[bankNum][presetNum].operators[0].susCC; 3599 case hashCalc(`op0_Release`): 3600 return soundBank[bankNum][presetNum].operators[0].rel; 3601 case hashCalc(`op0_Waveform`): 3602 return soundBank[bankNum][presetNum].operators[0].opCtrl & OpCtrlFlags.WavetableSelect; 3603 case hashCalc(`op0_TuneCor`): 3604 return (soundBank[bankNum][presetNum].operators[0].opCtrl & TuneCtrlFlags.CorTuneTest)>>>25; 3605 case hashCalc(`op0_KSLBegin`): 3606 return soundBank[bankNum][presetNum].operators[0].kslBegin; 3607 case hashCalc(`op0_KSLAttenOut`): 3608 return soundBank[bankNum][presetNum].operators[0].kslAttenOut; 3609 case hashCalc(`op0_KSLAttenFB`): 3610 return soundBank[bankNum][presetNum].operators[1].kslAttenFB; 3611 case hashCalc(`op0_KSLAttenADSR`): 3612 return soundBank[bankNum][presetNum].operators[1].kslAttenADSR; 3613 //op0 end 3614 3615 //op1 begin 3616 case hashCalc(`op1_Attack`): 3617 return soundBank[bankNum][presetNum].operators[1].atk; 3618 case hashCalc(`op1_Decay`): 3619 return soundBank[bankNum][presetNum].operators[1].dec; 3620 case hashCalc(`op1_SusCtrl`): 3621 return soundBank[bankNum][presetNum].operators[1].susCC; 3622 case hashCalc(`op1_Release`): 3623 return soundBank[bankNum][presetNum].operators[1].rel; 3624 case hashCalc(`op1_Waveform`): 3625 return soundBank[bankNum][presetNum].operators[1].opCtrl & OpCtrlFlags.WavetableSelect; 3626 case hashCalc(`op1_TuneCor`): 3627 return (soundBank[bankNum][presetNum].operators[1].opCtrl & TuneCtrlFlags.CorTuneTest)>>25; 3628 case hashCalc(`op1_KSLBegin`): 3629 return soundBank[bankNum][presetNum].operators[1].kslBegin; 3630 case hashCalc(`op1_KSLAttenOut`): 3631 return soundBank[bankNum][presetNum].operators[1].kslAttenOut; 3632 case hashCalc(`op1_KSLAttenFB`): 3633 return soundBank[bankNum][presetNum].operators[1].kslAttenFB; 3634 case hashCalc(`op1_KSLAttenADSR`): 3635 return soundBank[bankNum][presetNum].operators[1].kslAttenADSR; 3636 //op1 end 3637 3638 //op0 flags begin 3639 case hashCalc(`op0f_FBMode`): 3640 return (soundBank[bankNum][presetNum].operators[0].opCtrl & OpCtrlFlags.FBMode) ? 1 : 0; 3641 case hashCalc(`op0f_FBNeg`): 3642 return (soundBank[bankNum][presetNum].operators[0].opCtrl & OpCtrlFlags.FBNeg) ? 1 : 0; 3643 case hashCalc(`op0f_MWNeg`): 3644 return (soundBank[bankNum][presetNum].operators[0].opCtrl & OpCtrlFlags.MWNeg) ? 1 : 0; 3645 case hashCalc(`op0f_VelNeg`): 3646 return (soundBank[bankNum][presetNum].operators[0].opCtrl & OpCtrlFlags.VelNeg) ? 1 : 0; 3647 case hashCalc(`op0f_EGRelAdaptive`): 3648 return (soundBank[bankNum][presetNum].operators[0].opCtrl & OpCtrlFlags.EGRelAdaptive) ? 1 : 0; 3649 case hashCalc(`op0f_FixedPitch`): 3650 return (soundBank[bankNum][presetNum].operators[0].opCtrl & OpCtrlFlags.FixedPitch) ? 1 : 0; 3651 case hashCalc(`op0f_EasyTune`): 3652 return (soundBank[bankNum][presetNum].operators[0].opCtrl & OpCtrlFlags.EasyTune) ? 1 : 0; 3653 case hashCalc(`op0f_ContiTune`): 3654 return (soundBank[bankNum][presetNum].operators[0].opCtrl & OpCtrlFlags.ContiTune) ? 1 : 0; 3655 case hashCalc(`op0f_ExprToMW`): 3656 return (soundBank[bankNum][presetNum].operators[0].opCtrl & OpCtrlFlags.ExprToMW) ? 1 : 0; 3657 //op0 flags end 3658 3659 //op1 flags begin 3660 case hashCalc(`op1f_FBMode`): 3661 return (soundBank[bankNum][presetNum].operators[1].opCtrl & OpCtrlFlags.FBMode) ? 1 : 0; 3662 case hashCalc(`op1f_FBNeg`): 3663 return (soundBank[bankNum][presetNum].operators[1].opCtrl & OpCtrlFlags.FBNeg) ? 1 : 0; 3664 case hashCalc(`op1f_MWNeg`): 3665 return (soundBank[bankNum][presetNum].operators[1].opCtrl & OpCtrlFlags.MWNeg) ? 1 : 0; 3666 case hashCalc(`op1f_VelNeg`): 3667 return (soundBank[bankNum][presetNum].operators[1].opCtrl & OpCtrlFlags.VelNeg) ? 1 : 0; 3668 case hashCalc(`op1f_EGRelAdaptive`): 3669 return (soundBank[bankNum][presetNum].operators[1].opCtrl & OpCtrlFlags.EGRelAdaptive) ? 1 : 0; 3670 case hashCalc(`op1f_FixedPitch`): 3671 return (soundBank[bankNum][presetNum].operators[1].opCtrl & OpCtrlFlags.FixedPitch) ? 1 : 0; 3672 case hashCalc(`op1f_EasyTune`): 3673 return (soundBank[bankNum][presetNum].operators[1].opCtrl & OpCtrlFlags.EasyTune) ? 1 : 0; 3674 case hashCalc(`op1f_ContiTune`): 3675 return (soundBank[bankNum][presetNum].operators[1].opCtrl & OpCtrlFlags.ContiTune) ? 1 : 0; 3676 case hashCalc(`op1f_ExprToMW`): 3677 return (soundBank[bankNum][presetNum].operators[1].opCtrl & OpCtrlFlags.ExprToMW) ? 1 : 0; 3678 //op1 flags end 3679 3680 //ch begin 3681 case hashCalc(`ch_Attack`): 3682 return soundBank[bankNum][presetNum].channel.atkX; 3683 case hashCalc(`ch_Decay`): 3684 return soundBank[bankNum][presetNum].channel.decX; 3685 case hashCalc(`ch_SusCtrl`): 3686 return soundBank[bankNum][presetNum].channel.susCCX; 3687 case hashCalc(`ch_Release`): 3688 return soundBank[bankNum][presetNum].channel.relX; 3689 //ch end 3690 3691 //ch flags begins 3692 case hashCalc(`chf_ComboMode`): 3693 return soundBank[bankNum][presetNum].channel.chCtrl & ChCtrlFlags.ComboModeTest; 3694 case hashCalc(`chf_Algorithm`): 3695 return (soundBank[bankNum][presetNum].channel.chCtrl & ChCtrlFlags.Algorithm) ? 1 : 0; 3696 case hashCalc(`chf_IndivOutChLev`): 3697 return (soundBank[bankNum][presetNum].channel.chCtrl & ChCtrlFlags.IndivOutChLev) ? 1 : 0; 3698 case hashCalc(`chf_LFOPan`): 3699 return (soundBank[bankNum][presetNum].channel.chCtrl & ChCtrlFlags.LFOPan) ? 1 : 0; 3700 case hashCalc(`chf_EEGPan`): 3701 return (soundBank[bankNum][presetNum].channel.chCtrl & ChCtrlFlags.EEGPan) ? 1 : 0; 3702 case hashCalc(`chf_MWToTrem`): 3703 return (soundBank[bankNum][presetNum].channel.chCtrl & ChCtrlFlags.MWToTrem) ? 1 : 0; 3704 case hashCalc(`chf_MWToVibr`): 3705 return (soundBank[bankNum][presetNum].channel.chCtrl & ChCtrlFlags.MWToVibr) ? 1 : 0; 3706 case hashCalc(`chf_MWToAux`): 3707 return (soundBank[bankNum][presetNum].channel.chCtrl & ChCtrlFlags.MWToAux) ? 1 : 0; 3708 case hashCalc(`chf_ResetOnKeyOn`): 3709 return (soundBank[bankNum][presetNum].channel.chCtrl & ChCtrlFlags.ResetOnKeyOn) ? 1 : 0; 3710 case hashCalc(`chf_ResetMode`): 3711 return (soundBank[bankNum][presetNum].channel.chCtrl & ChCtrlFlags.ResetMode) ? 1 : 0; 3712 case hashCalc(`chf_FBMode`): 3713 return (soundBank[bankNum][presetNum].channel.chCtrl & ChCtrlFlags.FBMode) ? 1 : 0; 3714 case hashCalc(`chf_FBNeg`): 3715 return (soundBank[bankNum][presetNum].channel.chCtrl & ChCtrlFlags.FBNeg) ? 1 : 0; 3716 case hashCalc(`chf_ResMode`): 3717 return (soundBank[bankNum][presetNum].channel.chCtrl & ChCtrlFlags.ResMode) ? 1 : 0; 3718 case hashCalc(`chf_ResSrc`): 3719 return (soundBank[bankNum][presetNum].channel.chCtrl & ChCtrlFlags.ResSrc) ? 1 : 0; 3720 //ch flags end 3721 3722 //common values begin 3723 case hashCalc(`_PLFOWF`): 3724 return lfoWaveform[0]; 3725 case hashCalc(`_ALFOWF`): 3726 return lfoWaveform[1] & 0b0111_1111; 3727 case hashCalc(`_Ringmod`): 3728 return (lfoWaveform[1] & 0b1000_0000) ? 1 : 0; 3729 //common values end 3730 default: 3731 return 0; 3732 } 3733 } 3734 /** 3735 * Reads the given value (int). 3736 * Params: 3737 * presetID = The preset ID, or uint.max for global module values. 3738 * paramID = The parameter ID. 3739 * Returns: The value of the given preset and parameter 3740 */ 3741 public override long readParam_long(uint presetID, uint paramID) nothrow { 3742 const ubyte bankNum = cast(ubyte)(presetID>>7), presetNum = cast(ubyte)(presetID & 127); 3743 switch (paramID) { 3744 //case hashCalc(`op0_Tune`):break; 3745 case hashCalc(`op0_OpCtrl`): 3746 return soundBank[bankNum][presetNum].operators[0].opCtrl; 3747 3748 //case hashCalc(`op1_Tune`):break; 3749 case hashCalc(`op1_OpCtrl`): 3750 return soundBank[bankNum][presetNum].operators[1].opCtrl; 3751 3752 case hashCalc(`ch_ChCtrl`): 3753 return soundBank[bankNum][presetNum].channel.chCtrl; 3754 default: 3755 return 0; 3756 } 3757 } 3758 /** 3759 * Reads the given value (int). 3760 * Params: 3761 * presetID = The preset ID, or uint.max for global module values. 3762 * paramID = The parameter ID. 3763 * Returns: The value of the given preset and parameter 3764 */ 3765 public override double readParam_double(uint presetID, uint paramID) nothrow { 3766 const ubyte bankNum = cast(ubyte)(presetID>>7), presetNum = cast(ubyte)(presetID & 127); 3767 switch (paramID) { 3768 //op0 begin 3769 case hashCalc(`op0_Level`): 3770 return soundBank[bankNum][presetNum].operators[0].outL; 3771 case hashCalc(`op0_SusLevel`): 3772 return soundBank[bankNum][presetNum].operators[0].susLevel; 3773 case hashCalc(`op0_Feedback`): 3774 return soundBank[bankNum][presetNum].operators[0].fbL; 3775 case hashCalc(`op0_Tune`): 3776 return soundBank[bankNum][presetNum].operators[0].tune; 3777 //case hashCalc(`op0_FreqRate`):break; 3778 case hashCalc(`op0_ShpA`): 3779 return soundBank[bankNum][presetNum].operators[0].shpA; 3780 case hashCalc(`op0_ShpR`): 3781 return soundBank[bankNum][presetNum].operators[0].shpR; 3782 case hashCalc(`op0_VelToLevel`): 3783 return soundBank[bankNum][presetNum].operators[0].outLCtrl[0]; 3784 case hashCalc(`op0_MWToLevel`): 3785 return soundBank[bankNum][presetNum].operators[0].outLCtrl[1]; 3786 case hashCalc(`op0_LFOToLevel`): 3787 return soundBank[bankNum][presetNum].operators[0].outLCtrl[2]; 3788 case hashCalc(`op0_VelToFB`): 3789 return soundBank[bankNum][presetNum].operators[0].fbLCtrl[0]; 3790 case hashCalc(`op0_MWToFB`): 3791 return soundBank[bankNum][presetNum].operators[0].fbLCtrl[1]; 3792 3793 case hashCalc(`op0_LFOToFB`): 3794 return soundBank[bankNum][presetNum].operators[0].fbLCtrl[2]; 3795 case hashCalc(`op0_EEGToFB`): 3796 return soundBank[bankNum][presetNum].operators[0].fbLCtrl[3]; 3797 case hashCalc(`op0_VelToShpA`): 3798 return soundBank[bankNum][presetNum].operators[0].shpAVel; 3799 case hashCalc(`op0_VelToShpR`): 3800 return soundBank[bankNum][presetNum].operators[0].shpRVel; 3801 //op0 end 3802 3803 //op1 begin 3804 case hashCalc(`op1_Level`): 3805 return soundBank[bankNum][presetNum].operators[1].outL; 3806 case hashCalc(`op1_SusLevel`): 3807 return soundBank[bankNum][presetNum].operators[1].susLevel; 3808 case hashCalc(`op1_Feedback`): 3809 return soundBank[bankNum][presetNum].operators[1].fbL; 3810 case hashCalc(`op1_Tune`): 3811 return soundBank[bankNum][presetNum].operators[1].tune; 3812 //case hashCalc(`op1_FreqRate`):break; 3813 case hashCalc(`op1_ShpA`): 3814 return soundBank[bankNum][presetNum].operators[1].shpA; 3815 case hashCalc(`op1_ShpR`): 3816 return soundBank[bankNum][presetNum].operators[1].shpR; 3817 case hashCalc(`op1_VelToLevel`): 3818 return soundBank[bankNum][presetNum].operators[1].outLCtrl[0]; 3819 case hashCalc(`op1_MWToLevel`): 3820 return soundBank[bankNum][presetNum].operators[1].outLCtrl[1]; 3821 case hashCalc(`op1_LFOToLevel`): 3822 return soundBank[bankNum][presetNum].operators[1].outLCtrl[2]; 3823 case hashCalc(`op1_VelToFB`): 3824 return soundBank[bankNum][presetNum].operators[1].fbLCtrl[0]; 3825 case hashCalc(`op1_MWToFB`): 3826 return soundBank[bankNum][presetNum].operators[1].fbLCtrl[1]; 3827 case hashCalc(`op1_LFOToFB`): 3828 return soundBank[bankNum][presetNum].operators[1].fbLCtrl[2]; 3829 case hashCalc(`op1_EEGToFB`): 3830 return soundBank[bankNum][presetNum].operators[1].fbLCtrl[3]; 3831 case hashCalc(`op1_VelToShpA`): 3832 return soundBank[bankNum][presetNum].operators[1].shpAVel; 3833 case hashCalc(`op1_VelToShpR`): 3834 return soundBank[bankNum][presetNum].operators[1].shpRVel; 3835 //op1 end 3836 3837 //ch begin 3838 case hashCalc(`ch_MasterVol`): 3839 return soundBank[bankNum][presetNum].channel.masterVol; 3840 case hashCalc(`ch_Bal`): 3841 return soundBank[bankNum][presetNum].channel.masterBal; 3842 case hashCalc(`ch_AuxSLA`): 3843 return soundBank[bankNum][presetNum].channel.auxSendA; 3844 case hashCalc(`ch_AuxSLB`): 3845 return soundBank[bankNum][presetNum].channel.auxSendB; 3846 case hashCalc(`ch_EEGDetune`): 3847 return soundBank[bankNum][presetNum].channel.eegDetuneAm; 3848 case hashCalc(`ch_PitchBendSens`): 3849 return soundBank[bankNum][presetNum].channel.pitchBendSens; 3850 case hashCalc(`ch_Tune`): 3851 return soundBank[bankNum][presetNum].channel.chnlTun; 3852 case hashCalc(`ch_PLFO`): 3853 return soundBank[bankNum][presetNum].channel.pLFOlevel; 3854 case hashCalc(`ch_SusLevel`): 3855 return soundBank[bankNum][presetNum].channel.susLevel; 3856 case hashCalc(`ch_ShpA`): 3857 return soundBank[bankNum][presetNum].channel.shpAX; 3858 case hashCalc(`ch_ShpR`): 3859 return soundBank[bankNum][presetNum].channel.shpRX; 3860 case hashCalc(`ch_GlobalFB`): 3861 return soundBank[bankNum][presetNum].channel.globalFb; 3862 case hashCalc(`ch_EEGToLeft`): 3863 return soundBank[bankNum][presetNum].channel.eegLevels[0]; 3864 case hashCalc(`ch_EEGToRight`): 3865 return soundBank[bankNum][presetNum].channel.eegLevels[1]; 3866 case hashCalc(`ch_EEGToAuxA`): 3867 return soundBank[bankNum][presetNum].channel.eegLevels[2]; 3868 case hashCalc(`ch_EEGToAuxB`): 3869 return soundBank[bankNum][presetNum].channel.eegLevels[3]; 3870 case hashCalc(`ch_LFOToLeft`): 3871 return soundBank[bankNum][presetNum].channel.aLFOlevels[0]; 3872 case hashCalc(`ch_LFOToRight`): 3873 return soundBank[bankNum][presetNum].channel.aLFOlevels[1]; 3874 case hashCalc(`ch_LFOToAuxA`): 3875 return soundBank[bankNum][presetNum].channel.aLFOlevels[2]; 3876 case hashCalc(`ch_LFOToAuxB`): 3877 return soundBank[bankNum][presetNum].channel.aLFOlevels[3]; 3878 case hashCalc(`ch_MWToGFB`): 3879 return soundBank[bankNum][presetNum].channel.mwToGFB; 3880 case hashCalc(`ch_VelToGFB`): 3881 return soundBank[bankNum][presetNum].channel.velToGFB; 3882 //ch end 3883 3884 //commons begin 3885 case hashCalc(`_PLFORate`): return pLFOFreq; 3886 case hashCalc(`_ALFORate`): return aLFOFreq; 3887 case hashCalc(`_FilterLCFreq`): 3888 return filterCtrl[0]; 3889 case hashCalc(`_FilterLCQ`): 3890 return filterCtrl[1]; 3891 case hashCalc(`_FilterRCFreq`): 3892 return filterCtrl[2]; 3893 case hashCalc(`_FilterRCQ`): 3894 return filterCtrl[3]; 3895 case hashCalc(`_FilterACFreq`): 3896 return filterCtrl[4]; 3897 case hashCalc(`_FilterACQ`): 3898 return filterCtrl[5]; 3899 case hashCalc(`_FilterBCFreq`): 3900 return filterCtrl[6]; 3901 case hashCalc(`_FilterBCQ`): 3902 return filterCtrl[7]; 3903 case hashCalc(`_HPFLCFreq`): 3904 return hpfCtrl[0]; 3905 case hashCalc(`_HPFLCQ`): 3906 return hpfCtrl[1]; 3907 case hashCalc(`_HPFRCFreq`): 3908 return hpfCtrl[2]; 3909 case hashCalc(`_HPFRCQ`): 3910 return hpfCtrl[3]; 3911 case hashCalc(`_HPFACFreq`): 3912 return hpfCtrl[4]; 3913 case hashCalc(`_HPFACQ`): 3914 return hpfCtrl[5]; 3915 case hashCalc(`_HPFBCFreq`): 3916 return hpfCtrl[6]; 3917 case hashCalc(`_HPFBCQ`): 3918 return hpfCtrl[6]; 3919 //commons end 3920 default: 3921 return double.nan; 3922 } 3923 3924 } 3925 /** 3926 * Reads the given value (int). 3927 * Params: 3928 * presetID = The preset ID, or uint.max for global module values. 3929 * paramID = The parameter ID. 3930 * Returns: The value of the given preset and parameter 3931 */ 3932 public override string readParam_string(uint presetID, uint paramID) nothrow { 3933 return null; 3934 } 3935 }