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