1 /* 2 * Copyright (C) 2015-2018, by Laszlo Szeremi under the Boost license. 3 * 4 * Pixel Perfect Engine, audio.pcm32 module 5 */ 6 7 module PixelPerfectEngine.audio.pcm32; 8 9 import PixelPerfectEngine.audio.common; 10 import PixelPerfectEngine.audio.firFilter; 11 import PixelPerfectEngine.audio.envGen; 12 import PixelPerfectEngine.audio.lfo; 13 14 import PixelPerfectEngine.system.platform; 15 import PixelPerfectEngine.system.binarySearchTree; 16 17 static if(USE_INTEL_INTRINSICS) 18 import inteli.emmintrin; 19 20 import libPCM.codecs; 21 import libPCM.common; 22 import libPCM.file; 23 import libPCM.types; 24 25 import std.bitmanip; 26 import std.math; 27 import std.container.array; 28 29 import core.stdc.stdlib; 30 import core.stdc..string; 31 32 /** 33 * Sampling synthesizer implementation. Has per channel FIR (1024 stage) and IIR (low-pass) filters, and four stereo outputs. 34 */ 35 public class PCM32 : AbstractPPEFX{ 36 enum LFO_TABLE_LENGTH = 256; 37 enum FIR_TABLE_LENGTH = 1024; 38 enum WHOLE_STEP_FORWARD = 1_048_576; 39 /** 40 * Defines the source of certain modifier values 41 */ 42 public enum ControlSource : ubyte{ 43 NULL = 0, 44 Pitch = 1, 45 Velocity = 2, 46 ExpressiveVal = 3, 47 } 48 /** 49 * Control data. 50 * Bitfield: 51 * <ul> 52 * <li>cSource: Enables input for controlling parameters with key command parameters</li> 53 * <li>damping: Sets per-octave dampening of the value</li> 54 * <li>invertCS: Inverts Velocity and ExpressiveVal control sources</li> 55 * <li>modifyEG: Modifies the output levels of the envelope generators by the control source</li> 56 * <li>envGenA: Enables envelope generator A to modify this parameter</li> 57 * <li>invertEGA: Inverts the output of the envelope generator A</li> 58 * <li>envGenB: Enables envelope generator A to modify this parameter</li> 59 * <li>invertEGB: Inverts the output of the envelope generator A</li> 60 * <li>fixValue: Toggles the role of the fix value: sets a fix value if true, sets the ratio of the modifiers if false</li> 61 * <li>lfo: Toggles the LFO</li> 62 * <li>reserved: Unused, might have some role in the future</li> 63 * </ul> 64 */ 65 public struct ControlData{ 66 mixin(bitfields!( 67 ubyte, "cSource", 2, 68 ubyte, "damping", 2, 69 bool, "invertCS", 1, 70 bool, "modifyEG", 1, 71 bool, "envGenA", 1, 72 bool, "invertEGA", 1, 73 bool, "envGenB", 1, 74 bool, "invertEGB", 1, 75 bool, "fixValue", 1, 76 bool, "lfo", 1, 77 ubyte, "reserved", 4, 78 )); 79 } 80 /** 81 * Defines the type of IIR filter 82 */ 83 public enum IIRFilterType : ubyte{ 84 Bypass = 0, 85 LPF = 1, 86 HPF = 2, 87 BPF = 3, 88 } 89 /** 90 * Per-octave dampening 91 */ 92 public enum Dampening : ubyte{ 93 DB00 = 0, ///No dampening 94 DB15 = 1, ///1.5db dampening 95 DB30 = 2, ///3.0db dampening 96 DB60 = 3, ///6.0db dampening 97 } 98 /** 99 * Preset data. 100 * Does not store the data regarding instrument samples. 101 */ 102 public struct ChannelPresetMain{ 103 ubyte firTypeL; ///Selects the FIR filter type for the left channel 104 ubyte firTypeR; ///Selects the FIR filter type for the right channel 105 ubyte iirType; ///Selects the IIR filter type 106 ubyte lfoWave; ///Selects the LFO Waveform 107 108 short firLevel; ///Sets the output level of the FIR filter, negative values invert the signal 109 short firFeedback; ///Sets the feedback level of the FIR filter, negative values invert the signal 110 111 float _Q; ///Mostly Q 112 float f0; ///Frequency center of the filtering 113 float iirDryLevel; ///Sets the level of the dry signal 114 float iirWetLevel; ///Sets the level of the wet signal 115 float lfoFreq; ///Sets the LFO frequency 116 117 float[4] sendLevels; ///1: Main left; 2: Main right; 3: Aux left; 4: Aux right 118 119 ControlData firLevelCtrl; ///Sets the modifiers for the firLevel (fixValue controls don't work) 120 ControlData firFeedbackCtrl; ///Sets the modifiers for the firFeedback (fixValue controls don't work) 121 122 ControlData sendLevelLCtrl; ///Modifies all left channel outputs 123 ControlData sendLevelRCtrl; ///Modifies all right channel outputs 124 125 ControlData _QCtrl; 126 ControlData f0Ctrl; 127 ControlData iirDryLevelCtrl; 128 ControlData iirWetLevelCtrl; 129 ControlData lfoFreqCtrl; 130 /* 131 * Routing policies: 132 * enableIIR: Enables IIR filter 133 * enableFIR: Enables FIR filter 134 * serialFIR: If true, it runs the two FIR filters in serial [L -> R] 135 * monoFIR: If true, only the left channel will be used, and serialFIR is ignored 136 * routeFIRintoIIR: Reverses the routing of the two filters 137 * 138 * Legato: 139 * resetSample: Disables sample resetting if keyOn command received without keyoff 140 * resetEGA: Disables resetting of envelope generator A 141 * resetEGB: Disables resetting of envelope generator B 142 * resetLFO: Disables resetting of LFO 143 * 144 * Other: 145 * loopOnKeyOff: Enables the use of release stages of the LFO to control the runtime after key off commands. 146 * Recommended for wavetables. 147 */ 148 mixin(bitfields!( 149 bool,"enableIIR",1, 150 bool,"enableFIR",1, 151 bool,"serialFIR",1, 152 bool,"monoFIR",1, 153 bool,"routeFIRintoIIR",1, 154 155 bool,"resetSample",1, 156 bool,"resetEGA",1, 157 bool,"resetEGB",1, 158 bool,"resetLFO",1, 159 bool,"loopOnKeyOff",1, 160 161 ushort,"reserved",6, 162 )); 163 } 164 /** 165 * Preset data. 166 * Stores data on how to handle instrument samples. 167 * Important: fromX are always the lower values. Overlapping values are not supported. 168 */ 169 public struct ChannelPresetSamples{ 170 ///Sets certain properties of the sample 171 enum Flags : ushort{ 172 ///Enables sample looping 173 enableLoop = 0b0000_0000_0000_0001, 174 ///Changes looping from one-way to ping-pong (doesn't work with most differental codecs) 175 pingPongLoop = 0b0000_0000_0000_0010, 176 ///Disables pitch changes on different notes. 177 isPercussive = 0b0000_0000_0000_0100, 178 ///Plays only a slice from the sample (doesn't work with most differental codecs) 179 slice = 0b0000_0000_0000_1000, 180 } 181 uint sampleSelect; ///Selects the sample that will be used 182 uint loopFrom; 183 uint loopTo; 184 float midFreq; 185 ushort loopFlags; ///See enum Flags for options 186 ushort midNote; 187 ushort fromNote = 0x0FFF; 188 ushort toNote = 0x0FFF + 0x7F; 189 /+ushort fromVelocity; 190 ushort toVelocity = ushort.max; 191 ushort fromExpressiveVal; 192 ushort toExpressiveVal = ushort.max;+/ 193 @nogc @property bool isPercussive(){ 194 return (loopFlags & Flags.isPercussive) != 0; 195 } 196 @nogc @property bool isLooping(){ 197 return (loopFlags & Flags.isPercussive) != 0; 198 } 199 @nogc @property bool pingPongLoop(){ 200 return (loopFlags & Flags.isPercussive) != 0; 201 } 202 /** 203 * Used mainly for ordering them in a BSTree. 204 */ 205 @nogc int opCmp(ChannelPresetSamples rhs){ 206 if(this.toNote < rhs.fromNote) 207 return -1; 208 else if(this.fromNote > rhs.toNote) 209 return 1; 210 else 211 return 0; 212 } 213 /** 214 * Range lookup. 215 */ 216 @nogc int opCmp(ushort rhs){ 217 if(this.fromNote > rhs){//hit from lower range 218 if(this.toNote < rhs){//hit from upper range 219 return 0; 220 }else{//overshoot 221 return 1; 222 } 223 }else{//undershoot 224 return -1; 225 } 226 } 227 /** 228 * Equals function for other ChannelPresetSamples. 229 */ 230 @nogc bool opEquals(ChannelPresetSamples b) { 231 return opCmp(b) == 0; 232 } 233 /** 234 * Equals function for ushort by note. 235 */ 236 @nogc bool opEquals(ushort b) { 237 return opCmp(b) == 0; 238 } 239 } 240 /** 241 * Stores information regarding to samples. 242 * IMPORTANT: Always call unloadSample for unloading samples from the memory. 243 */ 244 public struct Sample{ 245 size_t length; ///Length of sample 246 ubyte* dataPtr; ///Points to the first sample of the stream 247 CodecType codec; ///Selects the codec type 248 ushort flags; ///Mainly for 32bit alignment, placeholder for future flags (stereo sample support?) 249 float sampleFreq; ///Overrides the *.pcm file's sampling frequency 250 this(size_t length, ubyte* dataPtr, CodecType codec){ 251 this.length = length; 252 this.dataPtr = dataPtr; 253 this.codec = codec; 254 } 255 /** 256 * Unloads the sample from memory. 257 */ 258 @nogc void unloadSample(){ 259 length = 0; 260 free(dataPtr); 261 } 262 } 263 /** 264 * Stores sample preset data for editing and storing purposes. 265 */ 266 public struct SamplePreset{ 267 char[32] name; ///Must match file source name without the .pcm extension in the sample pool(s) being used 268 float freq; 269 uint id; 270 } 271 /** 272 * Stores data on LFO or FIR for editing and storing purposes. 273 */ 274 public struct FXSamplePreset{ 275 char[32] name; ///Must match file source name without the .pcm extension in the sample pool(s) being used 276 ubyte id; 277 ubyte[3] unused; 278 } 279 /** 280 * Stores instrument preset data for editing and storing purposes. 281 */ 282 public struct InstrumentPreset{ 283 char[32] name; 284 ushort id; 285 ushort egaStages; 286 ushort egbStages; 287 ushort sampleLayers; 288 } 289 /** 290 * Stores global settings of the instrument. 291 */ 292 public struct GlobalSettings{ 293 float tuning = 440.0; ///base tuning 294 ///Used for channel masking. The channel indicated by this value is used as the first channel that won't be ignored. 295 ///Last channel not to be ignored is baseChannel + 31 296 ushort baseChannel; 297 /* 298 * Bitfields: 299 * enablePassthruCH29 - 32: Enables the channels to be used for external effecting purposes. 300 * Note commands can be used to control the filters if needed. 301 * Input for CH29 is PPEFXinput 0 302 * Input for CH30 is PPEFXinput 1 303 * Input for CH31 is PPEFXinput 2 304 * Input for CH32 is PPEFXinput 3 305 */ 306 mixin(bitfields!( 307 bool,"enablePassthruCH29",1, 308 bool,"enablePassthruCH30",1, 309 bool,"enablePassthruCH31",1, 310 bool,"enablePassthruCH32",1, 311 ushort,"unused",12, 312 )); 313 } 314 /** 315 * RIFF header to identify preset data in banks. 316 */ 317 enum RIFFID : char[4]{ 318 riffInitial = "RIFF", ///to initialize the RIFF format 319 bankInitial = "BANK", ///currently unused 320 globalSettings = "GLOB", ///global settings (eg. tunings, routing, channel masking) 321 instrumentPreset = "INSP", ///indicates that the next chunk is an instrument preset. length = InstrumentPreset.sizeof + ChannelPresetMain.sizeof 322 envGenA = "ENVA", ///indicates that there's envelope generator data for the current preset. length = EnvelopeStage.sizeof * egaStages 323 envGenB = "ENVB", ///indicates that there's envelope generator data for the current preset. length = EnvelopeStage.sizeof * egbStages 324 instrumentData = "INSD", ///indicates that the next chunk contains sample layer data for the current preset. length = ChannelPresetSamples.sizeof * sampleLayers 325 samplePreset = "SLMP", ///indicates that the next chunk is a sample preset. length = SamplePreset * sizeof 326 lfoPreset = "LFOP", ///indicates that the next chunk is an LFO preset. length = FXSamplePreset * sizeof 327 fiResponse = "FIRS", ///indicates that the next chunk is an FIR preset. length = FXSamplePreset * sizeof 328 } 329 /** 330 * Stores data for a single channel. 331 */ 332 protected struct Channel{ 333 ChannelPresetMain preset; 334 @nogc short function(ubyte*, DecoderWorkpad*) codec; 335 uint loopfrom, loopto; ///describe a loop cycle between the two values for the current sample 336 uint stepping; ///describes how much the sample should go forward, 1_048_576 equals a whole step 337 ulong forward; ///current position 338 Sample* sample; 339 short*[3] intBuff; ///buffer for FIR-filters [0,1], output [2], IIR-filter output converted to int [3] 340 CodecType codecType; 341 DecoderWorkpad workpad, secWorkpad; 342 ushort presetID; 343 ushort note; 344 ushort vel; 345 ushort exprVal; 346 float freq; 347 float baseFreq; 348 float pitchbend = 0f; 349 float iirF0; 350 float iir_q; 351 float[4] sendLevels; 352 EnvelopeGenerator envGenA; 353 EnvelopeGenerator envGenB; 354 FiniteImpulseResponseFilter!(FIR_TABLE_LENGTH)[2] firFilter; 355 LowFreqOsc!(LFO_TABLE_LENGTH) lfo; 356 //bool keyON; 357 //bool isRunning; 358 ushort arpeggiatorSpeed; ///ms between notes 359 360 enum ArpMode : ubyte{ 361 off, 362 ascending, 363 descending, 364 ascThenDesc, 365 } 366 mixin(bitfields!( 367 bool,"keyON",1, 368 bool,"isRunning",1, 369 bool,"enableLooping",1, 370 bool,"pingPongLoop",1, 371 bool,"slice",1, 372 ubyte,"arpMode",3, 373 ubyte,"octaves",4, 374 bool,"arpWay",1, 375 ubyte,"nOfNotes",3, 376 )); 377 ushort[4] arpeggiatorNotes; ///notes to arpeggiate 378 ushort arpPos; 379 ubyte curOctave, curNote; 380 short output, firBuf0, firBuf1; ///Previous outputs 381 short firLevel0, firLevel1, firFbk0, firFbk1; 382 } 383 384 static if(ARCH_INTEL_X86){ 385 static if(USE_INTEL_INTRINSICS){ 386 /** 387 * Contains IIR related registers in order for use in SSE2 applications 388 */ 389 protected struct IIRFilterBuff{ 390 __m128 b0a0; 391 //__m128 x_n; 392 __m128 b1a0; 393 __m128 x_n_minus1; 394 __m128 b2a0; 395 __m128 x_n_minus2; 396 __m128 a1a0; 397 __m128 y_n_minus1; 398 __m128 a2a0; 399 __m128 y_n_minus2; 400 //__m128 y_n; 401 } 402 }else{ 403 /** 404 * Contains IIR related registers in order for use in SSE2 applications 405 */ 406 protected struct IIRFilterBuff{ 407 float[4] b0a0; 408 //float[4] x_n; 409 float[4] b1a0; 410 float[4] x_n_minus1; 411 float[4] b2a0; 412 float[4] x_n_minus2; 413 float[4] a1a0; 414 float[4] y_n_minus1; 415 float[4] a2a0; 416 float[4] y_n_minus2; 417 //float[4] y_n; 418 } 419 } 420 IIRFilterBuff[8] iirFilters; 421 void* iirFiltersPtr; 422 }else{ 423 protected float[32] x_n_minus1, x_n_minus2, y_n_minus1, y_n_minus2, b0a0, b1a0, b2a0, a1a0, a2a0; 424 } 425 protected BinarySearchTree!(ushort,EnvelopeStageList) envGenA; 426 protected BinarySearchTree!(ushort,EnvelopeStageList) envGenB; 427 protected BinarySearchTree!(ushort,ChannelPresetMain) presets; 428 protected BinarySearchTree!(ushort,BinarySearchTree2!(ChannelPresetSamples)) sampleLayers; 429 430 protected float*[32] y_n; ///Output 431 protected float*[32] x_n; ///Input 432 protected float[32] iirDryLevel, iirWetLevel; 433 protected Channel[32] channels; 434 protected float sampleRate; 435 protected size_t frameLength, nOfFrames; 436 protected BinarySearchTree!(ubyte, FiniteImpulseResponse!(1024)) finiteImpulseResponses; 437 protected BinarySearchTree!(uint, Sample) samples; 438 protected BinarySearchTree!(ubyte, ubyte[256]) lfoTables; 439 440 //global parameters 441 protected GlobalSettings globals; 442 443 protected string samplePoolPath; ///Specifies the path for the sample pool 444 /** 445 * Make sure that the string describes a valid path. 446 */ 447 public this(string samplePoolPath = "./audio/samples/"){ 448 this.samplePoolPath = samplePoolPath; 449 this.globals.tuning = 440.0f; 450 } 451 public @nogc @property BinarySearchTree!(ushort,ChannelPresetMain)* presetPtr(){ 452 return &presets; 453 } 454 public @nogc @property BinarySearchTree!(ushort,EnvelopeStageList)* envGenAPtr(){ 455 return &envGenA; 456 } 457 public @nogc @property BinarySearchTree!(ushort,EnvelopeStageList)* envGenBPtr(){ 458 return &envGenB; 459 } 460 public @nogc @property BinarySearchTree!(ushort,BinarySearchTree2!(ChannelPresetSamples))* sampleLayersPtr(){ 461 return &sampleLayers; 462 } 463 protected @nogc void calculateIIR(){ 464 static if(USE_INTEL_INTRINSICS){ 465 //float* y_nptr = cast(float*)y_n.ptr; 466 //float* x_nptr = cast(float*)x_n.ptr; 467 float* vals = cast(float*)iirFiltersPtr; 468 float* iirDryLevelPtr = iirDryLevel.ptr; 469 float* iirWetLevelPtr = iirWetLevel.ptr; 470 for(size_t i = frameLength ; i >= 0 ; i--){ 471 for(int j ; j < 8 ; j++){ 472 const int k = j << 2; 473 __m128 workVal = _mm_load_ps(vals);//b0a0 474 __m128 x_n0;// = [x_n[k][i],x_n[k+1][i],x_n[k+2][i],x_n[k+3][i]]; 475 x_n0[0] = x_n[k][i]; 476 x_n0[1] = x_n[k+1][i]; 477 x_n0[2] = x_n[k+2][i]; 478 x_n0[3] = x_n[k+3][i]; 479 __m128 y_n0;//output 480 y_n0 = workVal * x_n0;//(b0/a0)*x_n0 481 vals += 4; 482 workVal = _mm_load_ps(vals);//b1a0 483 vals += 4; 484 __m128 x_n1 = _mm_load_ps(vals);//x_n1 485 _mm_store_ps(vals,x_n0);//store current x_n0 as x_n1 486 y_n0 += x_n1 * workVal;//(b0/a0)*x_n0 + (b1/a0)*x_n1 487 vals += 4; 488 workVal = _mm_load_ps(vals);//b2a0 489 vals += 4; 490 const __m128 x_n2 = _mm_load_ps(vals);//x_n2 491 _mm_store_ps(vals,x_n1);//store current x_n1 as x_n2 492 y_n0 += x_n2 * workVal;//(b0/a0)*x_n0 + (b1/a0)*x_n1 + (b2/a0)*x_n2 493 vals += 4; 494 workVal = _mm_load_ps(vals);//a1a0 495 vals += 4; 496 __m128 y_n1 = _mm_load_ps(vals);//y_n1 497 float* vals_y_n0 = vals;//store current position for storing the new output 498 y_n0 -= y_n1 * workVal;//(b0/a0)*x_n0 + (b1/a0)*x_n1 + (b2/a0)*x_n2 - (a1/a0)*x_n2 499 vals += 4; 500 workVal = _mm_load_ps(vals);//a2a0 501 vals += 4; 502 const __m128 y_n2 = _mm_load_ps(vals);//y_n2 (I know, the variable has a different name) 503 _mm_store_ps(vals,y_n1);//store current y_n1 as y_n2 504 y_n0 -= y_n2 * workVal;//(b0/a0)*x_n0 + (b1/a0)*x_n1 + (b2/a0)*x_n2 - (a1/a0)*x_n2 505 _mm_store_ps(vals_y_n0,y_n0);//store current y_n0 as y_n1 506 //calculate mixing 507 y_n0 = y_n0 * _mm_load_ps(iirWetLevelPtr) + x_n0 * _mm_load_ps(iirDryLevelPtr); 508 //_mm_store_ps(y_nptr,y_n0);//store output in buffer 509 y_n[k][i] = y_n0[0]; 510 y_n[k+1][i] = y_n0[1]; 511 y_n[k+2][i] = y_n0[2]; 512 y_n[k+3][i] = y_n0[3]; 513 vals += 4; 514 //x_nptr += 4; 515 //y_nptr += 4; 516 } 517 vals = cast(float*)iirFiltersPtr; 518 } 519 }else{ 520 float* y_nptr = cast(float*)y_n.ptr; 521 float* x_nptr = cast(float*)x_n.ptr; 522 for(int i = frameLength ; i >= 0 ; i--){ 523 asm @nogc{ 524 mov ECX, 8; 525 //mov ESI, iirFiltersPtr[EBP]; 526 mov EDI, y_nptr; 527 mov EBX, x_nptr; 528 iirLoop: 529 movaps XMM0, [ESI];//load b0/a0 530 movaps XMM1, [EBX];//load x_n 531 mulps XMM0, XMM1; //(b0/a0) * x_n 532 add ESI, 16; //offset ESI to b1a0 533 movaps XMM2, [ESI];//load b1a0 534 add ESI, 16; //offset ESI to x_n_minus1 535 movaps XMM3, [ESI];//load x_n_minus1 536 movaps [ESI], XMM1;//store current x_n as x_n_minus1 537 mulps XMM2, XMM3; //(b1/a0) * x_n_minus1 538 addps XMM0, XMM2; //(b0/a0) * x_n + (b1/a0) * x_n_minus1 539 add ESI, 16; //offset ESI to b2a0 540 movaps XMM2, [ESI];//load b2a0 541 add ESI, 16; //offset ESI to x_n_minus2 542 movaps XMM4, [ESI];//load x_n_minus2 543 movaps [ESI], XMM3;//store current x_n_minus1 as x_n_minus2 544 mulps XMM2, XMM4; //(b2/a0) * x_n_minus2 545 addps XMM0, XMM2; //(b0/a0) * x_n + (b1/a0) * x_n_minus1 + (b2/a0) * x_n_minus2 546 add ESI, 16; //offset ESI to a1a0 547 movaps XMM1, [ESI];//load a1a0 548 add ESI, 16; //offset ESI to y_n_minus1 549 movaps XMM2, [ESI];//load y_n_minus1 550 mulps XMM1, XMM2; //(a1/a0) * y_n_minus1 551 subps XMM0, XMM1; //(b0/a0) * x_n + (b1/a0) * x_n_minus1 + (b2/a0) * x_n_minus2 - (a1/a0) * y_n_minus1 552 add ESI, 16; //offset ESI to a2a0 553 movaps XMM1, [ESI];//load a2a0 554 add ESI, 16; //offset ESI to y_n_minus2 555 movaps XMM3, [ESI];//load y_n_minus2 556 movaps [ESI], XMM2;//store y_n_minus1 as new y_n_minus2 557 mulps XMM1, XMM3; //(a2/a0) * y_n_minus2 558 subps XMM0, XMM1; //(b0/a0) * x_n + (b1/a0) * x_n_minus1 + (b2/a0) * x_n_minus2 - (a1/a0) * y_n_minus1 - (a2/a0) * y_n_minus2 559 sub ESI, 48; //set back pointer to y_n_minus1 560 movaps [ESI], XMM0;//store y_n as y_n_minus1 561 movaps [EDI], XMM0;//store y_n as output 562 add EDI, 16; 563 add ESI, 48; 564 dec ECX; 565 cmp ECX, 0; 566 jne iirLoop; 567 } 568 x_nptr += 32; 569 y_nptr += 32; 570 } 571 } 572 } 573 public @nogc void refreshFilter(int ch, IIRFilterType type, float freq, float Q){ 574 575 } 576 override public @nogc void render(float** inputBuffers, float** outputBuffers){ 577 float* mainL = outputBuffers[0], mainR = outputBuffers[1], auxL = outputBuffers[2], auxR = outputBuffers[3]; 578 float* ch29 = inputBuffers[0], ch30 = inputBuffers[1], ch31 = inputBuffers[2], ch32 = inputBuffers[3]; 579 for(int fr; fr < nOfFrames; fr++){ 580 int ch; 581 for(; ch < 28; ch++){ 582 if(channels[ch].isRunning){ 583 for(int s; s < frameLength; s++){ 584 ulong prevForvard = channels[ch].forward; 585 channels[ch].forward += channels[ch].stepping; 586 while(prevForvard>>10 < channels[ch].forward>>10){ 587 channels[ch].output = channels[ch].codec(channels[ch].sample.dataPtr, &channels[ch].workpad); 588 prevForvard += WHOLE_STEP_FORWARD; 589 if(channels[ch].enableLooping){ 590 if(channels[ch].workpad.position == channels[ch].loopfrom){ 591 channels[ch].secWorkpad = channels[ch].workpad; 592 }else if(channels[ch].workpad.position == channels[ch].loopto){ 593 channels[ch].workpad = channels[ch].secWorkpad; 594 } 595 } 596 } 597 if(channels[ch].sample.length <= channels[ch].workpad.position){ 598 channels[ch].isRunning = false; 599 break; 600 } 601 channels[ch].intBuff[2][s] = channels[ch].output; 602 } 603 604 if(channels[ch].preset.enableFIR){ 605 if(channels[ch].preset.routeFIRintoIIR){ 606 for(int s; s < frameLength; s++){ 607 channels[ch].firBuf0 = cast(short)channels[ch].firFilter[0].calculate(cast(short)(channels[ch].intBuff[2][s] + 608 (channels[ch].firBuf0 * channels[ch].firFbk0)>>16)); 609 channels[ch].intBuff[0][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel0); 610 } 611 if(!channels[ch].preset.monoFIR){ 612 if(channels[ch].preset.serialFIR){ 613 for(int s; s < frameLength; s++){ 614 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[0][s] + 615 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 616 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel1); 617 } 618 int16ToFloat(channels[ch].intBuff[1],x_n[ch],frameLength); 619 }else{//parralel mixing due to channel limit 620 for(int s; s < frameLength; s++){ 621 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[2][s] + 622 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 623 channels[ch].intBuff[0][s] += cast(short)(channels[ch].firBuf0 * channels[ch].firLevel1); 624 } 625 int16ToFloat(channels[ch].intBuff[0],x_n[ch],frameLength); 626 } 627 }else{ 628 int16ToFloat(channels[ch].intBuff[0],x_n[ch],frameLength); 629 } 630 mixStreamIntoTarget(y_n[ch], mainL, frameLength, channels[ch].sendLevels[0]); 631 mixStreamIntoTarget(y_n[ch], mainR, frameLength, channels[ch].sendLevels[1]); 632 mixStreamIntoTarget(y_n[ch], auxL, frameLength, channels[ch].sendLevels[2]); 633 mixStreamIntoTarget(y_n[ch], auxR, frameLength, channels[ch].sendLevels[3]); 634 }else{ 635 int16ToFloat(channels[ch].intBuff[2],x_n[ch],frameLength); 636 floatToInt16(y_n[ch],channels[ch].intBuff[2],frameLength); 637 for(int s; s < frameLength; s++){ 638 channels[ch].firBuf0 = cast(short)channels[ch].firFilter[0].calculate(cast(short)(channels[ch].intBuff[2][s] + 639 (channels[ch].firBuf0 * channels[ch].firFbk0)>>16)); 640 channels[ch].intBuff[0][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel0); 641 } 642 if(!channels[ch].preset.monoFIR){ 643 if(channels[ch].preset.serialFIR){ 644 for(int s; s < frameLength; s++){ 645 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[0][s] + 646 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 647 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel1); 648 } 649 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainL, frameLength, channels[ch].sendLevels[0]); 650 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainR, frameLength, channels[ch].sendLevels[1]); 651 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxL, frameLength, channels[ch].sendLevels[2]); 652 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxR, frameLength, channels[ch].sendLevels[3]); 653 }else{ 654 for(int s; s < frameLength; s++){ 655 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[2][s] + 656 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 657 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf1 * channels[ch].firLevel1); 658 } 659 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainL, frameLength, channels[ch].sendLevels[0]); 660 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainR, frameLength, channels[ch].sendLevels[1]); 661 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxL, frameLength, channels[ch].sendLevels[2]); 662 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxR, frameLength, channels[ch].sendLevels[3]); 663 } 664 }else{ 665 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainL, frameLength, channels[ch].sendLevels[0]); 666 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainR, frameLength, channels[ch].sendLevels[1]); 667 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxL, frameLength, channels[ch].sendLevels[2]); 668 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxR, frameLength, channels[ch].sendLevels[3]); 669 } 670 } 671 672 673 }else{ 674 int16ToFloat(channels[ch].intBuff[2],x_n[ch],frameLength); 675 mixStreamIntoTarget(y_n[ch], mainL, frameLength, channels[ch].sendLevels[0]); 676 mixStreamIntoTarget(y_n[ch], mainR, frameLength, channels[ch].sendLevels[1]); 677 mixStreamIntoTarget(y_n[ch], auxL, frameLength, channels[ch].sendLevels[2]); 678 mixStreamIntoTarget(y_n[ch], auxR, frameLength, channels[ch].sendLevels[3]); 679 } 680 channels[ch].envGenA.step; 681 channels[ch].envGenB.step; 682 channels[ch].lfo.step; 683 } 684 } 685 if(globals.enablePassthruCH29){ 686 if(channels[ch].preset.enableFIR){ 687 if(channels[ch].preset.routeFIRintoIIR){ 688 floatToInt16(ch29, channels[ch].intBuff[2], frameLength); 689 for(int s; s < frameLength; s++){ 690 channels[ch].firBuf0 = cast(short)channels[ch].firFilter[0].calculate(cast(short)(channels[ch].intBuff[2][s] + 691 (channels[ch].firBuf0 * channels[ch].firFbk0)>>16)); 692 channels[ch].intBuff[0][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel0); 693 } 694 if(!channels[ch].preset.monoFIR){ 695 if(channels[ch].preset.serialFIR){ 696 for(int s; s < frameLength; s++){ 697 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[0][s] + 698 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 699 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel1); 700 } 701 int16ToFloat(channels[ch].intBuff[1],x_n[ch],frameLength); 702 }else{//parralel mixing due to channel limit 703 for(int s; s < frameLength; s++){ 704 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[2][s] + 705 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 706 channels[ch].intBuff[0][s] += cast(short)(channels[ch].firBuf1 * channels[ch].firLevel1); 707 } 708 int16ToFloat(channels[ch].intBuff[0],x_n[ch],frameLength); 709 } 710 }else{ 711 int16ToFloat(channels[ch].intBuff[0],x_n[ch],frameLength); 712 } 713 mixStreamIntoTarget(y_n[ch], mainL, frameLength, channels[ch].sendLevels[0]); 714 mixStreamIntoTarget(y_n[ch], mainR, frameLength, channels[ch].sendLevels[1]); 715 mixStreamIntoTarget(y_n[ch], auxL, frameLength, channels[ch].sendLevels[2]); 716 mixStreamIntoTarget(y_n[ch], auxR, frameLength, channels[ch].sendLevels[3]); 717 }else{ 718 //int16ToFloat(channels[ch].intBuff[2],x_n[ch],frameLength); 719 memcpy(x_n[ch], ch29, frameLength * float.sizeof); 720 floatToInt16(y_n[ch],channels[ch].intBuff[2],frameLength); 721 for(int s; s < frameLength; s++){ 722 channels[ch].firBuf0 = cast(short)channels[ch].firFilter[0].calculate(cast(short)(channels[ch].intBuff[2][s] + 723 (channels[ch].firBuf0 * channels[ch].firFbk0)>>16)); 724 channels[ch].intBuff[0][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel0); 725 } 726 if(!channels[ch].preset.monoFIR){ 727 if(channels[ch].preset.serialFIR){ 728 for(int s; s < frameLength; s++){ 729 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[0][s] + 730 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 731 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf1 * channels[ch].firLevel1); 732 } 733 734 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainL, frameLength, channels[ch].sendLevels[0]); 735 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainR, frameLength, channels[ch].sendLevels[1]); 736 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxL, frameLength, channels[ch].sendLevels[2]); 737 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxR, frameLength, channels[ch].sendLevels[3]); 738 }else{ 739 for(int s; s < frameLength; s++){ 740 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[2][s] + 741 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 742 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf1 * channels[ch].firLevel1); 743 } 744 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainL, frameLength, channels[ch].sendLevels[0]); 745 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainR, frameLength, channels[ch].sendLevels[1]); 746 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxL, frameLength, channels[ch].sendLevels[2]); 747 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxR, frameLength, channels[ch].sendLevels[3]); 748 } 749 }else{ 750 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainL, frameLength, channels[ch].sendLevels[0]); 751 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainR, frameLength, channels[ch].sendLevels[1]); 752 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxL, frameLength, channels[ch].sendLevels[2]); 753 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxR, frameLength, channels[ch].sendLevels[3]); 754 } 755 } 756 }else{ 757 memcpy(x_n[ch], ch29, frameLength * float.sizeof); 758 mixStreamIntoTarget(y_n[ch], mainL, frameLength, channels[ch].sendLevels[0]); 759 mixStreamIntoTarget(y_n[ch], mainR, frameLength, channels[ch].sendLevels[1]); 760 mixStreamIntoTarget(y_n[ch], auxL, frameLength, channels[ch].sendLevels[2]); 761 mixStreamIntoTarget(y_n[ch], auxR, frameLength, channels[ch].sendLevels[3]); 762 } 763 channels[ch].envGenA.step; 764 channels[ch].envGenB.step; 765 channels[ch].lfo.step; 766 }else{ 767 if(channels[ch].isRunning){ 768 for(int s; s < frameLength; s++){ 769 ulong prevForvard = channels[ch].forward; 770 channels[ch].forward += channels[ch].stepping; 771 while(prevForvard>>10 < channels[ch].forward>>10){ 772 channels[ch].output = channels[ch].codec(channels[ch].sample.dataPtr, &channels[ch].workpad); 773 prevForvard += WHOLE_STEP_FORWARD; 774 if(channels[ch].enableLooping){ 775 if(channels[ch].workpad.position == channels[ch].loopfrom){ 776 channels[ch].secWorkpad = channels[ch].workpad; 777 }else if(channels[ch].workpad.position == channels[ch].loopto){ 778 channels[ch].workpad = channels[ch].secWorkpad; 779 } 780 } 781 } 782 if(channels[ch].sample.length <= channels[ch].workpad.position){ 783 channels[ch].isRunning = false; 784 break; 785 } 786 channels[ch].intBuff[2][s] = channels[ch].output; 787 } 788 789 if(channels[ch].preset.enableFIR){ 790 if(channels[ch].preset.routeFIRintoIIR){ 791 for(int s; s < frameLength; s++){ 792 channels[ch].firBuf0 = cast(short)channels[ch].firFilter[0].calculate(cast(short)(channels[ch].intBuff[2][s] + 793 (channels[ch].firBuf0 * channels[ch].firFbk0)>>16)); 794 channels[ch].intBuff[0][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel0); 795 } 796 if(!channels[ch].preset.monoFIR){ 797 if(channels[ch].preset.serialFIR){ 798 for(int s; s < frameLength; s++){ 799 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[0][s] + 800 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 801 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel1); 802 } 803 int16ToFloat(channels[ch].intBuff[1],x_n[ch],frameLength); 804 }else{//parralel mixing due to channel limit 805 for(int s; s < frameLength; s++){ 806 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[2][s] + 807 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 808 channels[ch].intBuff[0][s] += cast(short)(channels[ch].firBuf0 * channels[ch].firLevel1); 809 } 810 int16ToFloat(channels[ch].intBuff[0],x_n[ch],frameLength); 811 } 812 }else{ 813 int16ToFloat(channels[ch].intBuff[0],x_n[ch],frameLength); 814 } 815 mixStreamIntoTarget(y_n[ch], mainL, frameLength, channels[ch].sendLevels[0]); 816 mixStreamIntoTarget(y_n[ch], mainR, frameLength, channels[ch].sendLevels[1]); 817 mixStreamIntoTarget(y_n[ch], auxL, frameLength, channels[ch].sendLevels[2]); 818 mixStreamIntoTarget(y_n[ch], auxR, frameLength, channels[ch].sendLevels[3]); 819 }else{ 820 int16ToFloat(channels[ch].intBuff[2],x_n[ch],frameLength); 821 floatToInt16(y_n[ch],channels[ch].intBuff[2],frameLength); 822 for(int s; s < frameLength; s++){ 823 channels[ch].firBuf0 = cast(short)channels[ch].firFilter[0].calculate(cast(short)(channels[ch].intBuff[2][s] + 824 (channels[ch].firBuf0 * channels[ch].firFbk0)>>16)); 825 channels[ch].intBuff[0][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel0); 826 } 827 if(!channels[ch].preset.monoFIR){ 828 if(channels[ch].preset.serialFIR){ 829 for(int s; s < frameLength; s++){ 830 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[0][s] + 831 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 832 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel1); 833 } 834 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainL, frameLength, channels[ch].sendLevels[0]); 835 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainR, frameLength, channels[ch].sendLevels[1]); 836 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxL, frameLength, channels[ch].sendLevels[2]); 837 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxR, frameLength, channels[ch].sendLevels[3]); 838 }else{ 839 for(int s; s < frameLength; s++){ 840 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[2][s] + 841 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 842 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf1 * channels[ch].firLevel1); 843 } 844 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainL, frameLength, channels[ch].sendLevels[0]); 845 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainR, frameLength, channels[ch].sendLevels[1]); 846 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxL, frameLength, channels[ch].sendLevels[2]); 847 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxR, frameLength, channels[ch].sendLevels[3]); 848 } 849 }else{ 850 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainL, frameLength, channels[ch].sendLevels[0]); 851 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainR, frameLength, channels[ch].sendLevels[1]); 852 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxL, frameLength, channels[ch].sendLevels[2]); 853 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxR, frameLength, channels[ch].sendLevels[3]); 854 } 855 } 856 857 858 }else{ 859 int16ToFloat(channels[ch].intBuff[2],x_n[ch],frameLength); 860 mixStreamIntoTarget(y_n[ch], mainL, frameLength, channels[ch].sendLevels[0]); 861 mixStreamIntoTarget(y_n[ch], mainR, frameLength, channels[ch].sendLevels[1]); 862 mixStreamIntoTarget(y_n[ch], auxL, frameLength, channels[ch].sendLevels[2]); 863 mixStreamIntoTarget(y_n[ch], auxR, frameLength, channels[ch].sendLevels[3]); 864 } 865 channels[ch].envGenA.step; 866 channels[ch].envGenB.step; 867 channels[ch].lfo.step; 868 } 869 } 870 ch++; 871 if(globals.enablePassthruCH30){ 872 if(channels[ch].preset.enableFIR){ 873 if(channels[ch].preset.routeFIRintoIIR){ 874 floatToInt16(ch29, channels[ch].intBuff[2], frameLength); 875 for(int s; s < frameLength; s++){ 876 channels[ch].firBuf0 = cast(short)channels[ch].firFilter[0].calculate(cast(short)(channels[ch].intBuff[2][s] + 877 (channels[ch].firBuf0 * channels[ch].firFbk0)>>16)); 878 channels[ch].intBuff[0][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel0); 879 } 880 if(!channels[ch].preset.monoFIR){ 881 if(channels[ch].preset.serialFIR){ 882 for(int s; s < frameLength; s++){ 883 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[0][s] + 884 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 885 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel1); 886 } 887 int16ToFloat(channels[ch].intBuff[1],x_n[ch],frameLength); 888 }else{//parralel mixing due to channel limit 889 for(int s; s < frameLength; s++){ 890 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[2][s] + 891 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 892 channels[ch].intBuff[0][s] += cast(short)(channels[ch].firBuf1 * channels[ch].firLevel1); 893 } 894 int16ToFloat(channels[ch].intBuff[0],x_n[ch],frameLength); 895 } 896 }else{ 897 int16ToFloat(channels[ch].intBuff[0],x_n[ch],frameLength); 898 } 899 mixStreamIntoTarget(y_n[ch], mainL, frameLength, channels[ch].sendLevels[0]); 900 mixStreamIntoTarget(y_n[ch], mainR, frameLength, channels[ch].sendLevels[1]); 901 mixStreamIntoTarget(y_n[ch], auxL, frameLength, channels[ch].sendLevels[2]); 902 mixStreamIntoTarget(y_n[ch], auxR, frameLength, channels[ch].sendLevels[3]); 903 }else{ 904 //int16ToFloat(channels[ch].intBuff[2],x_n[ch],frameLength); 905 memcpy(x_n[ch], ch29, frameLength * float.sizeof); 906 floatToInt16(y_n[ch],channels[ch].intBuff[2],frameLength); 907 for(int s; s < frameLength; s++){ 908 channels[ch].firBuf0 = cast(short)channels[ch].firFilter[0].calculate(cast(short)(channels[ch].intBuff[2][s] + 909 (channels[ch].firBuf0 * channels[ch].firFbk0)>>16)); 910 channels[ch].intBuff[0][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel0); 911 } 912 if(!channels[ch].preset.monoFIR){ 913 if(channels[ch].preset.serialFIR){ 914 for(int s; s < frameLength; s++){ 915 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[0][s] + 916 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 917 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf1 * channels[ch].firLevel1); 918 } 919 920 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainL, frameLength, channels[ch].sendLevels[0]); 921 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainR, frameLength, channels[ch].sendLevels[1]); 922 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxL, frameLength, channels[ch].sendLevels[2]); 923 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxR, frameLength, channels[ch].sendLevels[3]); 924 }else{ 925 for(int s; s < frameLength; s++){ 926 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[2][s] + 927 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 928 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf1 * channels[ch].firLevel1); 929 } 930 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainL, frameLength, channels[ch].sendLevels[0]); 931 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainR, frameLength, channels[ch].sendLevels[1]); 932 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxL, frameLength, channels[ch].sendLevels[2]); 933 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxR, frameLength, channels[ch].sendLevels[3]); 934 } 935 }else{ 936 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainL, frameLength, channels[ch].sendLevels[0]); 937 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainR, frameLength, channels[ch].sendLevels[1]); 938 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxL, frameLength, channels[ch].sendLevels[2]); 939 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxR, frameLength, channels[ch].sendLevels[3]); 940 } 941 } 942 }else{ 943 memcpy(x_n[ch], ch29, frameLength * float.sizeof); 944 mixStreamIntoTarget(y_n[ch], mainL, frameLength, channels[ch].sendLevels[0]); 945 mixStreamIntoTarget(y_n[ch], mainR, frameLength, channels[ch].sendLevels[1]); 946 mixStreamIntoTarget(y_n[ch], auxL, frameLength, channels[ch].sendLevels[2]); 947 mixStreamIntoTarget(y_n[ch], auxR, frameLength, channels[ch].sendLevels[3]); 948 } 949 channels[ch].envGenA.step; 950 channels[ch].envGenB.step; 951 channels[ch].lfo.step; 952 }else{ 953 if(channels[ch].isRunning){ 954 for(int s; s < frameLength; s++){ 955 ulong prevForvard = channels[ch].forward; 956 channels[ch].forward += channels[ch].stepping; 957 while(prevForvard>>10 < channels[ch].forward>>10){ 958 channels[ch].output = channels[ch].codec(channels[ch].sample.dataPtr, &channels[ch].workpad); 959 prevForvard += WHOLE_STEP_FORWARD; 960 if(channels[ch].enableLooping){ 961 if(channels[ch].workpad.position == channels[ch].loopfrom){ 962 channels[ch].secWorkpad = channels[ch].workpad; 963 }else if(channels[ch].workpad.position == channels[ch].loopto){ 964 channels[ch].workpad = channels[ch].secWorkpad; 965 } 966 } 967 } 968 if(channels[ch].sample.length <= channels[ch].workpad.position){ 969 channels[ch].isRunning = false; 970 break; 971 } 972 channels[ch].intBuff[2][s] = channels[ch].output; 973 } 974 975 if(channels[ch].preset.enableFIR){ 976 if(channels[ch].preset.routeFIRintoIIR){ 977 for(int s; s < frameLength; s++){ 978 channels[ch].firBuf0 = cast(short)channels[ch].firFilter[0].calculate(cast(short)(channels[ch].intBuff[2][s] + 979 (channels[ch].firBuf0 * channels[ch].firFbk0)>>16)); 980 channels[ch].intBuff[0][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel0); 981 } 982 if(!channels[ch].preset.monoFIR){ 983 if(channels[ch].preset.serialFIR){ 984 for(int s; s < frameLength; s++){ 985 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[0][s] + 986 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 987 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel1); 988 } 989 int16ToFloat(channels[ch].intBuff[1],x_n[ch],frameLength); 990 }else{//parralel mixing due to channel limit 991 for(int s; s < frameLength; s++){ 992 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[2][s] + 993 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 994 channels[ch].intBuff[0][s] += cast(short)(channels[ch].firBuf0 * channels[ch].firLevel1); 995 } 996 int16ToFloat(channels[ch].intBuff[0],x_n[ch],frameLength); 997 } 998 }else{ 999 int16ToFloat(channels[ch].intBuff[0],x_n[ch],frameLength); 1000 } 1001 mixStreamIntoTarget(y_n[ch], mainL, frameLength, channels[ch].sendLevels[0]); 1002 mixStreamIntoTarget(y_n[ch], mainR, frameLength, channels[ch].sendLevels[1]); 1003 mixStreamIntoTarget(y_n[ch], auxL, frameLength, channels[ch].sendLevels[2]); 1004 mixStreamIntoTarget(y_n[ch], auxR, frameLength, channels[ch].sendLevels[3]); 1005 }else{ 1006 int16ToFloat(channels[ch].intBuff[2],x_n[ch],frameLength); 1007 floatToInt16(y_n[ch],channels[ch].intBuff[2],frameLength); 1008 for(int s; s < frameLength; s++){ 1009 channels[ch].firBuf0 = cast(short)channels[ch].firFilter[0].calculate(cast(short)(channels[ch].intBuff[2][s] + 1010 (channels[ch].firBuf0 * channels[ch].firFbk0)>>16)); 1011 channels[ch].intBuff[0][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel0); 1012 } 1013 if(!channels[ch].preset.monoFIR){ 1014 if(channels[ch].preset.serialFIR){ 1015 for(int s; s < frameLength; s++){ 1016 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[0][s] + 1017 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 1018 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel1); 1019 } 1020 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainL, frameLength, channels[ch].sendLevels[0]); 1021 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainR, frameLength, channels[ch].sendLevels[1]); 1022 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxL, frameLength, channels[ch].sendLevels[2]); 1023 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxR, frameLength, channels[ch].sendLevels[3]); 1024 }else{ 1025 for(int s; s < frameLength; s++){ 1026 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[2][s] + 1027 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 1028 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf1 * channels[ch].firLevel1); 1029 } 1030 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainL, frameLength, channels[ch].sendLevels[0]); 1031 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainR, frameLength, channels[ch].sendLevels[1]); 1032 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxL, frameLength, channels[ch].sendLevels[2]); 1033 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxR, frameLength, channels[ch].sendLevels[3]); 1034 } 1035 }else{ 1036 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainL, frameLength, channels[ch].sendLevels[0]); 1037 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainR, frameLength, channels[ch].sendLevels[1]); 1038 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxL, frameLength, channels[ch].sendLevels[2]); 1039 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxR, frameLength, channels[ch].sendLevels[3]); 1040 } 1041 } 1042 1043 1044 }else{ 1045 int16ToFloat(channels[ch].intBuff[2],x_n[ch],frameLength); 1046 mixStreamIntoTarget(y_n[ch], mainL, frameLength, channels[ch].sendLevels[0]); 1047 mixStreamIntoTarget(y_n[ch], mainR, frameLength, channels[ch].sendLevels[1]); 1048 mixStreamIntoTarget(y_n[ch], auxL, frameLength, channels[ch].sendLevels[2]); 1049 mixStreamIntoTarget(y_n[ch], auxR, frameLength, channels[ch].sendLevels[3]); 1050 } 1051 channels[ch].envGenA.step; 1052 channels[ch].envGenB.step; 1053 channels[ch].lfo.step; 1054 } 1055 } 1056 ch++; 1057 if(globals.enablePassthruCH31){ 1058 if(channels[ch].preset.enableFIR){ 1059 if(channels[ch].preset.routeFIRintoIIR){ 1060 floatToInt16(ch29, channels[ch].intBuff[2], frameLength); 1061 for(int s; s < frameLength; s++){ 1062 channels[ch].firBuf0 = cast(short)channels[ch].firFilter[0].calculate(cast(short)(channels[ch].intBuff[2][s] + 1063 (channels[ch].firBuf0 * channels[ch].firFbk0)>>16)); 1064 channels[ch].intBuff[0][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel0); 1065 } 1066 if(!channels[ch].preset.monoFIR){ 1067 if(channels[ch].preset.serialFIR){ 1068 for(int s; s < frameLength; s++){ 1069 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[0][s] + 1070 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 1071 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel1); 1072 } 1073 int16ToFloat(channels[ch].intBuff[1],x_n[ch],frameLength); 1074 }else{//parralel mixing due to channel limit 1075 for(int s; s < frameLength; s++){ 1076 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[2][s] + 1077 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 1078 channels[ch].intBuff[0][s] += cast(short)(channels[ch].firBuf1 * channels[ch].firLevel1); 1079 } 1080 int16ToFloat(channels[ch].intBuff[0],x_n[ch],frameLength); 1081 } 1082 }else{ 1083 int16ToFloat(channels[ch].intBuff[0],x_n[ch],frameLength); 1084 } 1085 mixStreamIntoTarget(y_n[ch], mainL, frameLength, channels[ch].sendLevels[0]); 1086 mixStreamIntoTarget(y_n[ch], mainR, frameLength, channels[ch].sendLevels[1]); 1087 mixStreamIntoTarget(y_n[ch], auxL, frameLength, channels[ch].sendLevels[2]); 1088 mixStreamIntoTarget(y_n[ch], auxR, frameLength, channels[ch].sendLevels[3]); 1089 }else{ 1090 //int16ToFloat(channels[ch].intBuff[2],x_n[ch],frameLength); 1091 memcpy(x_n[ch], ch29, frameLength * float.sizeof); 1092 floatToInt16(y_n[ch],channels[ch].intBuff[2],frameLength); 1093 for(int s; s < frameLength; s++){ 1094 channels[ch].firBuf0 = cast(short)channels[ch].firFilter[0].calculate(cast(short)(channels[ch].intBuff[2][s] + 1095 (channels[ch].firBuf0 * channels[ch].firFbk0)>>16)); 1096 channels[ch].intBuff[0][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel0); 1097 } 1098 if(!channels[ch].preset.monoFIR){ 1099 if(channels[ch].preset.serialFIR){ 1100 for(int s; s < frameLength; s++){ 1101 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[0][s] + 1102 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 1103 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf1 * channels[ch].firLevel1); 1104 } 1105 1106 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainL, frameLength, channels[ch].sendLevels[0]); 1107 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainR, frameLength, channels[ch].sendLevels[1]); 1108 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxL, frameLength, channels[ch].sendLevels[2]); 1109 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxR, frameLength, channels[ch].sendLevels[3]); 1110 }else{ 1111 for(int s; s < frameLength; s++){ 1112 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[2][s] + 1113 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 1114 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf1 * channels[ch].firLevel1); 1115 } 1116 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainL, frameLength, channels[ch].sendLevels[0]); 1117 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainR, frameLength, channels[ch].sendLevels[1]); 1118 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxL, frameLength, channels[ch].sendLevels[2]); 1119 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxR, frameLength, channels[ch].sendLevels[3]); 1120 } 1121 }else{ 1122 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainL, frameLength, channels[ch].sendLevels[0]); 1123 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainR, frameLength, channels[ch].sendLevels[1]); 1124 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxL, frameLength, channels[ch].sendLevels[2]); 1125 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxR, frameLength, channels[ch].sendLevels[3]); 1126 } 1127 } 1128 }else{ 1129 memcpy(x_n[ch], ch29, frameLength * float.sizeof); 1130 mixStreamIntoTarget(y_n[ch], mainL, frameLength, channels[ch].sendLevels[0]); 1131 mixStreamIntoTarget(y_n[ch], mainR, frameLength, channels[ch].sendLevels[1]); 1132 mixStreamIntoTarget(y_n[ch], auxL, frameLength, channels[ch].sendLevels[2]); 1133 mixStreamIntoTarget(y_n[ch], auxR, frameLength, channels[ch].sendLevels[3]); 1134 } 1135 channels[ch].envGenA.step; 1136 channels[ch].envGenB.step; 1137 channels[ch].lfo.step; 1138 }else{ 1139 if(channels[ch].isRunning){ 1140 for(int s; s < frameLength; s++){ 1141 ulong prevForvard = channels[ch].forward; 1142 channels[ch].forward += channels[ch].stepping; 1143 while(prevForvard>>10 < channels[ch].forward>>10){ 1144 channels[ch].output = channels[ch].codec(channels[ch].sample.dataPtr, &channels[ch].workpad); 1145 prevForvard += WHOLE_STEP_FORWARD; 1146 if(channels[ch].enableLooping){ 1147 if(channels[ch].workpad.position == channels[ch].loopfrom){ 1148 channels[ch].secWorkpad = channels[ch].workpad; 1149 }else if(channels[ch].workpad.position == channels[ch].loopto){ 1150 channels[ch].workpad = channels[ch].secWorkpad; 1151 } 1152 } 1153 } 1154 if(channels[ch].sample.length <= channels[ch].workpad.position){ 1155 channels[ch].isRunning = false; 1156 break; 1157 } 1158 channels[ch].intBuff[2][s] = channels[ch].output; 1159 } 1160 1161 if(channels[ch].preset.enableFIR){ 1162 if(channels[ch].preset.routeFIRintoIIR){ 1163 for(int s; s < frameLength; s++){ 1164 channels[ch].firBuf0 = cast(short)channels[ch].firFilter[0].calculate(cast(short)(channels[ch].intBuff[2][s] + 1165 (channels[ch].firBuf0 * channels[ch].firFbk0)>>16)); 1166 channels[ch].intBuff[0][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel0); 1167 } 1168 if(!channels[ch].preset.monoFIR){ 1169 if(channels[ch].preset.serialFIR){ 1170 for(int s; s < frameLength; s++){ 1171 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[0][s] + 1172 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 1173 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel1); 1174 } 1175 int16ToFloat(channels[ch].intBuff[1],x_n[ch],frameLength); 1176 }else{//parralel mixing due to channel limit 1177 for(int s; s < frameLength; s++){ 1178 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[2][s] + 1179 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 1180 channels[ch].intBuff[0][s] += cast(short)(channels[ch].firBuf0 * channels[ch].firLevel1); 1181 } 1182 int16ToFloat(channels[ch].intBuff[0],x_n[ch],frameLength); 1183 } 1184 }else{ 1185 int16ToFloat(channels[ch].intBuff[0],x_n[ch],frameLength); 1186 } 1187 mixStreamIntoTarget(y_n[ch], mainL, frameLength, channels[ch].sendLevels[0]); 1188 mixStreamIntoTarget(y_n[ch], mainR, frameLength, channels[ch].sendLevels[1]); 1189 mixStreamIntoTarget(y_n[ch], auxL, frameLength, channels[ch].sendLevels[2]); 1190 mixStreamIntoTarget(y_n[ch], auxR, frameLength, channels[ch].sendLevels[3]); 1191 }else{ 1192 int16ToFloat(channels[ch].intBuff[2],x_n[ch],frameLength); 1193 floatToInt16(y_n[ch],channels[ch].intBuff[2],frameLength); 1194 for(int s; s < frameLength; s++){ 1195 channels[ch].firBuf0 = cast(short)channels[ch].firFilter[0].calculate(cast(short)(channels[ch].intBuff[2][s] + 1196 (channels[ch].firBuf0 * channels[ch].firFbk0)>>16)); 1197 channels[ch].intBuff[0][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel0); 1198 } 1199 if(!channels[ch].preset.monoFIR){ 1200 if(channels[ch].preset.serialFIR){ 1201 for(int s; s < frameLength; s++){ 1202 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[0][s] + 1203 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 1204 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel1); 1205 } 1206 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainL, frameLength, channels[ch].sendLevels[0]); 1207 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainR, frameLength, channels[ch].sendLevels[1]); 1208 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxL, frameLength, channels[ch].sendLevels[2]); 1209 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxR, frameLength, channels[ch].sendLevels[3]); 1210 }else{ 1211 for(int s; s < frameLength; s++){ 1212 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[2][s] + 1213 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 1214 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf1 * channels[ch].firLevel1); 1215 } 1216 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainL, frameLength, channels[ch].sendLevels[0]); 1217 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainR, frameLength, channels[ch].sendLevels[1]); 1218 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxL, frameLength, channels[ch].sendLevels[2]); 1219 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxR, frameLength, channels[ch].sendLevels[3]); 1220 } 1221 }else{ 1222 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainL, frameLength, channels[ch].sendLevels[0]); 1223 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainR, frameLength, channels[ch].sendLevels[1]); 1224 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxL, frameLength, channels[ch].sendLevels[2]); 1225 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxR, frameLength, channels[ch].sendLevels[3]); 1226 } 1227 } 1228 1229 1230 }else{ 1231 int16ToFloat(channels[ch].intBuff[2],x_n[ch],frameLength); 1232 mixStreamIntoTarget(y_n[ch], mainL, frameLength, channels[ch].sendLevels[0]); 1233 mixStreamIntoTarget(y_n[ch], mainR, frameLength, channels[ch].sendLevels[1]); 1234 mixStreamIntoTarget(y_n[ch], auxL, frameLength, channels[ch].sendLevels[2]); 1235 mixStreamIntoTarget(y_n[ch], auxR, frameLength, channels[ch].sendLevels[3]); 1236 } 1237 channels[ch].envGenA.step; 1238 channels[ch].envGenB.step; 1239 channels[ch].lfo.step; 1240 } 1241 } 1242 ch++; 1243 if(globals.enablePassthruCH32){ 1244 if(channels[ch].preset.enableFIR){ 1245 if(channels[ch].preset.routeFIRintoIIR){ 1246 floatToInt16(ch29, channels[ch].intBuff[2], frameLength); 1247 for(int s; s < frameLength; s++){ 1248 channels[ch].firBuf0 = cast(short)channels[ch].firFilter[0].calculate(cast(short)(channels[ch].intBuff[2][s] + 1249 (channels[ch].firBuf0 * channels[ch].firFbk0)>>16)); 1250 channels[ch].intBuff[0][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel0); 1251 } 1252 if(!channels[ch].preset.monoFIR){ 1253 if(channels[ch].preset.serialFIR){ 1254 for(int s; s < frameLength; s++){ 1255 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[0][s] + 1256 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 1257 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel1); 1258 } 1259 int16ToFloat(channels[ch].intBuff[1],x_n[ch],frameLength); 1260 }else{//parralel mixing due to channel limit 1261 for(int s; s < frameLength; s++){ 1262 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[2][s] + 1263 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 1264 channels[ch].intBuff[0][s] += cast(short)(channels[ch].firBuf1 * channels[ch].firLevel1); 1265 } 1266 int16ToFloat(channels[ch].intBuff[0],x_n[ch],frameLength); 1267 } 1268 }else{ 1269 int16ToFloat(channels[ch].intBuff[0],x_n[ch],frameLength); 1270 } 1271 mixStreamIntoTarget(y_n[ch], mainL, frameLength, channels[ch].sendLevels[0]); 1272 mixStreamIntoTarget(y_n[ch], mainR, frameLength, channels[ch].sendLevels[1]); 1273 mixStreamIntoTarget(y_n[ch], auxL, frameLength, channels[ch].sendLevels[2]); 1274 mixStreamIntoTarget(y_n[ch], auxR, frameLength, channels[ch].sendLevels[3]); 1275 }else{ 1276 //int16ToFloat(channels[ch].intBuff[2],x_n[ch],frameLength); 1277 memcpy(x_n[ch], ch29, frameLength * float.sizeof); 1278 floatToInt16(y_n[ch],channels[ch].intBuff[2],frameLength); 1279 for(int s; s < frameLength; s++){ 1280 channels[ch].firBuf0 = cast(short)channels[ch].firFilter[0].calculate(cast(short)(channels[ch].intBuff[2][s] + 1281 (channels[ch].firBuf0 * channels[ch].firFbk0)>>16)); 1282 channels[ch].intBuff[0][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel0); 1283 } 1284 if(!channels[ch].preset.monoFIR){ 1285 if(channels[ch].preset.serialFIR){ 1286 for(int s; s < frameLength; s++){ 1287 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[0][s] + 1288 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 1289 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf1 * channels[ch].firLevel1); 1290 } 1291 1292 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainL, frameLength, channels[ch].sendLevels[0]); 1293 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainR, frameLength, channels[ch].sendLevels[1]); 1294 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxL, frameLength, channels[ch].sendLevels[2]); 1295 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxR, frameLength, channels[ch].sendLevels[3]); 1296 }else{ 1297 for(int s; s < frameLength; s++){ 1298 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[2][s] + 1299 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 1300 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf1 * channels[ch].firLevel1); 1301 } 1302 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainL, frameLength, channels[ch].sendLevels[0]); 1303 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainR, frameLength, channels[ch].sendLevels[1]); 1304 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxL, frameLength, channels[ch].sendLevels[2]); 1305 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxR, frameLength, channels[ch].sendLevels[3]); 1306 } 1307 }else{ 1308 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainL, frameLength, channels[ch].sendLevels[0]); 1309 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainR, frameLength, channels[ch].sendLevels[1]); 1310 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxL, frameLength, channels[ch].sendLevels[2]); 1311 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxR, frameLength, channels[ch].sendLevels[3]); 1312 } 1313 } 1314 }else{ 1315 memcpy(x_n[ch], ch29, frameLength * float.sizeof); 1316 mixStreamIntoTarget(y_n[ch], mainL, frameLength, channels[ch].sendLevels[0]); 1317 mixStreamIntoTarget(y_n[ch], mainR, frameLength, channels[ch].sendLevels[1]); 1318 mixStreamIntoTarget(y_n[ch], auxL, frameLength, channels[ch].sendLevels[2]); 1319 mixStreamIntoTarget(y_n[ch], auxR, frameLength, channels[ch].sendLevels[3]); 1320 } 1321 channels[ch].envGenA.step; 1322 channels[ch].envGenB.step; 1323 channels[ch].lfo.step; 1324 }else{ 1325 if(channels[ch].isRunning){ 1326 for(int s; s < frameLength; s++){ 1327 ulong prevForvard = channels[ch].forward; 1328 channels[ch].forward += channels[ch].stepping; 1329 while(prevForvard>>10 < channels[ch].forward>>10){ 1330 channels[ch].output = channels[ch].codec(channels[ch].sample.dataPtr, &channels[ch].workpad); 1331 prevForvard += WHOLE_STEP_FORWARD; 1332 if(channels[ch].enableLooping){ 1333 if(channels[ch].workpad.position == channels[ch].loopfrom){ 1334 channels[ch].secWorkpad = channels[ch].workpad; 1335 }else if(channels[ch].workpad.position == channels[ch].loopto){ 1336 channels[ch].workpad = channels[ch].secWorkpad; 1337 } 1338 } 1339 } 1340 if(channels[ch].sample.length <= channels[ch].workpad.position){ 1341 channels[ch].isRunning = false; 1342 break; 1343 } 1344 channels[ch].intBuff[2][s] = channels[ch].output; 1345 } 1346 1347 if(channels[ch].preset.enableFIR){ 1348 if(channels[ch].preset.routeFIRintoIIR){ 1349 for(int s; s < frameLength; s++){ 1350 channels[ch].firBuf0 = cast(short)channels[ch].firFilter[0].calculate(cast(short)(channels[ch].intBuff[2][s] + 1351 (channels[ch].firBuf0 * channels[ch].firFbk0)>>16)); 1352 channels[ch].intBuff[0][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel0); 1353 } 1354 if(!channels[ch].preset.monoFIR){ 1355 if(channels[ch].preset.serialFIR){ 1356 for(int s; s < frameLength; s++){ 1357 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[0][s] + 1358 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 1359 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel1); 1360 } 1361 int16ToFloat(channels[ch].intBuff[1],x_n[ch],frameLength); 1362 }else{//parralel mixing due to channel limit 1363 for(int s; s < frameLength; s++){ 1364 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[2][s] + 1365 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 1366 channels[ch].intBuff[0][s] += cast(short)(channels[ch].firBuf0 * channels[ch].firLevel1); 1367 } 1368 int16ToFloat(channels[ch].intBuff[0],x_n[ch],frameLength); 1369 } 1370 }else{ 1371 int16ToFloat(channels[ch].intBuff[0],x_n[ch],frameLength); 1372 } 1373 mixStreamIntoTarget(y_n[ch], mainL, frameLength, channels[ch].sendLevels[0]); 1374 mixStreamIntoTarget(y_n[ch], mainR, frameLength, channels[ch].sendLevels[1]); 1375 mixStreamIntoTarget(y_n[ch], auxL, frameLength, channels[ch].sendLevels[2]); 1376 mixStreamIntoTarget(y_n[ch], auxR, frameLength, channels[ch].sendLevels[3]); 1377 }else{ 1378 int16ToFloat(channels[ch].intBuff[2],x_n[ch],frameLength); 1379 floatToInt16(y_n[ch],channels[ch].intBuff[2],frameLength); 1380 for(int s; s < frameLength; s++){ 1381 channels[ch].firBuf0 = cast(short)channels[ch].firFilter[0].calculate(cast(short)(channels[ch].intBuff[2][s] + 1382 (channels[ch].firBuf0 * channels[ch].firFbk0)>>16)); 1383 channels[ch].intBuff[0][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel0); 1384 } 1385 if(!channels[ch].preset.monoFIR){ 1386 if(channels[ch].preset.serialFIR){ 1387 for(int s; s < frameLength; s++){ 1388 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[0][s] + 1389 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 1390 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf0 * channels[ch].firLevel1); 1391 } 1392 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainL, frameLength, channels[ch].sendLevels[0]); 1393 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainR, frameLength, channels[ch].sendLevels[1]); 1394 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxL, frameLength, channels[ch].sendLevels[2]); 1395 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxR, frameLength, channels[ch].sendLevels[3]); 1396 }else{ 1397 for(int s; s < frameLength; s++){ 1398 channels[ch].firBuf1 = cast(short)channels[ch].firFilter[1].calculate(cast(short)(channels[ch].intBuff[2][s] + 1399 (channels[ch].firBuf1 * channels[ch].firFbk1)>>16)); 1400 channels[ch].intBuff[1][s] = cast(short)(channels[ch].firBuf1 * channels[ch].firLevel1); 1401 } 1402 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainL, frameLength, channels[ch].sendLevels[0]); 1403 convAndMixStreamIntoTarget(channels[ch].intBuff[1], mainR, frameLength, channels[ch].sendLevels[1]); 1404 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxL, frameLength, channels[ch].sendLevels[2]); 1405 convAndMixStreamIntoTarget(channels[ch].intBuff[1], auxR, frameLength, channels[ch].sendLevels[3]); 1406 } 1407 }else{ 1408 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainL, frameLength, channels[ch].sendLevels[0]); 1409 convAndMixStreamIntoTarget(channels[ch].intBuff[0], mainR, frameLength, channels[ch].sendLevels[1]); 1410 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxL, frameLength, channels[ch].sendLevels[2]); 1411 convAndMixStreamIntoTarget(channels[ch].intBuff[0], auxR, frameLength, channels[ch].sendLevels[3]); 1412 } 1413 } 1414 1415 1416 }else{ 1417 int16ToFloat(channels[ch].intBuff[2],x_n[ch],frameLength); 1418 mixStreamIntoTarget(y_n[ch], mainL, frameLength, channels[ch].sendLevels[0]); 1419 mixStreamIntoTarget(y_n[ch], mainR, frameLength, channels[ch].sendLevels[1]); 1420 mixStreamIntoTarget(y_n[ch], auxL, frameLength, channels[ch].sendLevels[2]); 1421 mixStreamIntoTarget(y_n[ch], auxR, frameLength, channels[ch].sendLevels[3]); 1422 } 1423 channels[ch].envGenA.step; 1424 channels[ch].envGenB.step; 1425 channels[ch].lfo.step; 1426 } 1427 } 1428 //update arpeggiators on all channels 1429 updateArppegiators(); 1430 calculateIIR(); 1431 } 1432 1433 } 1434 protected @nogc void updateArppegiators(){ 1435 for(int ch; ch < 32; ch++){ 1436 if(channels[ch].arpMode != Channel.ArpMode.off){ 1437 if(channels[ch].arpPos++ >= channels[ch].arpeggiatorSpeed){ 1438 channels[ch].arpPos = 0; 1439 final switch(channels[ch].arpMode){ 1440 case Channel.ArpMode.ascending: 1441 if(channels[ch].arpPos++ == channels[ch].nOfNotes){ 1442 channels[ch].arpPos = 0; 1443 if(channels[ch].curOctave++ == channels[ch].octaves){ 1444 channels[ch].curOctave = 0; 1445 } 1446 } 1447 break; 1448 case Channel.ArpMode.descending: 1449 if(channels[ch].arpPos-- == 0){ 1450 channels[ch].arpPos = channels[ch].nOfNotes; 1451 if(channels[ch].curOctave-- == 0){ 1452 channels[ch].curOctave = channels[ch].octaves; 1453 } 1454 } 1455 break; 1456 case Channel.ArpMode.ascThenDesc: 1457 if(channels[ch].arpWay){ 1458 if(channels[ch].arpPos++ == channels[ch].nOfNotes){ 1459 channels[ch].arpPos = 0; 1460 if(channels[ch].curOctave++ == channels[ch].octaves){ 1461 channels[ch].curOctave = 0; 1462 channels[ch].arpWay = false; 1463 } 1464 } 1465 }else{ 1466 if(channels[ch].arpPos-- == 0){ 1467 channels[ch].arpPos = channels[ch].nOfNotes; 1468 if(channels[ch].curOctave-- == 0){ 1469 channels[ch].curOctave = channels[ch].octaves; 1470 channels[ch].arpWay = true; 1471 } 1472 } 1473 } 1474 break; 1475 } 1476 keyOn(cast(ubyte)ch, cast(ushort)(channels[ch].arpeggiatorNotes[channels[ch].arpPos] + channels[ch].curOctave * 12), 1477 channels[ch].vel, channels[ch].exprVal); 1478 } 1479 } 1480 } 1481 } 1482 override public @nogc void receiveMICPCommand(MICPCommand cmd){ 1483 cmd.channel = cast(ushort)(cmd.channel - globals.baseChannel); 1484 switch(cmd.command){ 1485 case MICPCommandList.KeyOn: 1486 keyOn(cast(ubyte)cmd.channel, cmd.val0, cmd.vals[0], cmd.vals[1]); 1487 break; 1488 case MICPCommandList.KeyOff: 1489 keyOff(cast(ubyte)cmd.channel, cmd.val0, cmd.vals[0], cmd.vals[1]); 1490 break; 1491 case MICPCommandList.ParamEdit: 1492 break; 1493 case MICPCommandList.ParamEditFP: 1494 break; 1495 default: 1496 break; 1497 } 1498 } 1499 /** 1500 * Changes the preset of a given channel. 1501 * ch must be between 0 and 31. 1502 */ 1503 public @nogc void changePreset(ubyte ch, ushort preset){ 1504 channels[ch].presetID = preset; 1505 channels[ch].envGenA.reset; 1506 channels[ch].envGenA.stages = envGenA.getPtr(preset); 1507 channels[ch].envGenB.reset; 1508 channels[ch].envGenB.stages = envGenB.getPtr(preset); 1509 channels[ch].preset = presets[preset]; 1510 channels[ch].lfo.reset; 1511 channels[ch].lfo.table = lfoTables.getPtr(channels[ch].preset.lfoWave); 1512 channels[ch].presetID = preset; 1513 channels[ch].firFilter[0].impulseResponse = finiteImpulseResponses.getPtr(channels[ch].preset.firTypeL); 1514 channels[ch].firFilter[1].impulseResponse = finiteImpulseResponses.getPtr(channels[ch].preset.firTypeR); 1515 1516 } 1517 /** 1518 * Sets a key-on command on the selected channel with the given note, velocity, and expressive value. 1519 */ 1520 public @nogc void keyOn(ubyte ch, ushort note, ushort vel, ushort exprVal){ 1521 channels[ch].keyON = true; 1522 channels[ch].isRunning = true; 1523 channels[ch].note = note; 1524 channels[ch].vel = vel; 1525 channels[ch].exprVal = exprVal; 1526 channels[ch].forward = 0; 1527 //get sample to play 1528 ChannelPresetSamples cps = sampleLayers[channels[ch].presetID].lookup(note); 1529 channels[ch].sample = samples.getPtr(cps.sampleSelect); 1530 //calculate stepping 1531 if(cps.isPercussive){//if percussive, ignore pitch change except for the pitch bend commands 1532 channels[ch].baseFreq = cps.midFreq; 1533 channels[ch].freq = bendFreqByPitch(channels[ch].pitchbend, channels[ch].baseFreq); 1534 channels[ch].stepping = calculateStepping(channels[ch].freq); 1535 }else{//calculate note frequency with pitchbend 1536 const float delta_note = cast(float)note - cast(float)cps.midNote; 1537 channels[ch].baseFreq = bendFreqByPitch(delta_note, cps.midFreq); 1538 channels[ch].freq = bendFreqByPitch(channels[ch].pitchbend, channels[ch].baseFreq); 1539 channels[ch].stepping = calculateStepping(channels[ch].freq); 1540 } 1541 channels[ch].enableLooping = cps.isLooping; 1542 channels[ch].pingPongLoop = cps.pingPongLoop; 1543 if(channels[ch].preset.resetEGA){ 1544 channels[ch].envGenA.setKeyOn; 1545 } 1546 if(channels[ch].preset.resetEGB){ 1547 channels[ch].envGenB.setKeyOn; 1548 } 1549 if(channels[ch].preset.resetLFO){ 1550 channels[ch].lfo.reset; 1551 } 1552 1553 } 1554 /** 1555 * Sets a key-off command on the selected channel with the given note, velocity, and expressive value. 1556 */ 1557 public @nogc void keyOff(ubyte ch, ushort note, ushort vel, ushort exprVal){ 1558 channels[ch].keyON = false; 1559 channels[ch].note = note; 1560 channels[ch].vel = vel; 1561 channels[ch].exprVal = exprVal; 1562 channels[ch].envGenA.setKeyOff; 1563 channels[ch].envGenB.setKeyOff; 1564 } 1565 /** 1566 * Programs a note into the channel's sequencer. 1567 * If exprVal not 0, it sets which note has to be rewritten, otherwise it adds a new note to the sequencer. 1568 */ 1569 public @nogc void prgKeyOn(ubyte ch, ushort note, ushort vel, ushort exprVal){ 1570 if(exprVal){ 1571 exprVal--; 1572 exprVal &= 3; 1573 channels[ch].arpeggiatorNotes[exprVal] = note; 1574 }else{ 1575 if(channels[ch].nOfNotes < 3){ 1576 channels[ch].arpeggiatorNotes[channels[ch].nOfNotes] = note; 1577 channels[ch].nOfNotes = cast(ubyte)(channels[ch].nOfNotes + 1); 1578 } 1579 } 1580 } 1581 /** 1582 * Removes a note from the channel's sequencer. 1583 * If note not 0, it removes the note from the list if there's an equal of it. 1584 * If exprVal not 0, it removes the given note. 1585 */ 1586 public @nogc void prgKeyOff(ubyte ch, ushort note, ushort vel, ushort exprVal){ 1587 if(note){ 1588 for(int i; i < 4; i++) 1589 if(channels[ch].arpeggiatorNotes[exprVal] == note) 1590 exprVal = cast(ushort)(i+1); 1591 } 1592 if(exprVal){ 1593 exprVal--; 1594 exprVal &= 3; 1595 channels[ch].arpeggiatorNotes[exprVal] = 0; 1596 for(; exprVal < 3; exprVal++) 1597 channels[ch].arpeggiatorNotes[exprVal] = channels[ch].arpeggiatorNotes[exprVal + 1]; 1598 1599 if(channels[ch].nOfNotes) 1600 channels[ch].nOfNotes = cast(ubyte)(channels[ch].nOfNotes - 1); 1601 }else{ 1602 if(channels[ch].nOfNotes > 0){ 1603 channels[ch].arpeggiatorNotes[channels[ch].nOfNotes] = 0; 1604 channels[ch].nOfNotes = cast(ubyte)(channels[ch].nOfNotes - 1); 1605 } 1606 } 1607 1608 } 1609 /** 1610 * Calculates the length of the stepping for each sample. 1611 * Uses double precision to ensure precision. 1612 */ 1613 protected @nogc uint calculateStepping(float freq){ 1614 return cast(uint)((cast(double)freq / cast(double)sampleRate) * cast(double)WHOLE_STEP_FORWARD); 1615 } 1616 override public @nogc int setRenderParams(float samplerate, size_t framelength, size_t nOfFrames){ 1617 this.sampleRate = samplerate; 1618 this.frameLength = framelength; 1619 this.nOfFrames = nOfFrames; 1620 return 0; 1621 } 1622 /** 1623 * Loads a bank into the synthesizer, also loads samples on the way from the selected sample pool. 1624 * For the latter, it'll be able to use compression through lzbacon's datapak file format (default path for 1625 * that is ./audio/samplepool.dpk), otherwise a folder with uncompressed data is used (default path for that 1626 * is ./audio/samplepool/). 1627 */ 1628 override public void loadConfig(ref void[] data){ 1629 import PixelPerfectEngine.system.file : RIFFHeader; 1630 import std..string : toStringz; 1631 size_t pos; 1632 bool riffHeaderFound, envGenAFound, envGenBFound, cpsFound; 1633 InstrumentPreset currentInstr; 1634 while(data.length < pos){ 1635 RIFFHeader header = *cast(RIFFHeader*)(data.ptr + pos); 1636 pos += RIFFHeader.sizeof; 1637 switch(header.data){ 1638 case RIFFID.riffInitial: 1639 riffHeaderFound = true; 1640 break; 1641 case RIFFID.instrumentPreset: 1642 envGenAFound = false; 1643 envGenBFound = false; 1644 cpsFound = false; 1645 currentInstr = *cast(InstrumentPreset*)(data.ptr + pos); 1646 pos += InstrumentPreset.sizeof; 1647 presets[currentInstr.id] = *cast(ChannelPresetMain*)(data.ptr + pos); 1648 pos += ChannelPresetMain.sizeof; 1649 break; 1650 case RIFFID.envGenA: 1651 if(!envGenAFound){ 1652 envGenAFound = true; 1653 EnvelopeStageList ega; 1654 ega.reserve(currentInstr.egaStages); 1655 for(int i ; i < currentInstr.egaStages ; i++){ 1656 ega.insertBack(*cast(EnvelopeStage*)(data.ptr + pos)); 1657 pos += EnvelopeStage.sizeof; 1658 } 1659 envGenA[currentInstr.id] = ega; 1660 } 1661 break; 1662 case RIFFID.envGenB: 1663 if(!envGenBFound){ 1664 envGenBFound = true; 1665 EnvelopeStageList egb; 1666 egb.reserve(currentInstr.egbStages); 1667 for(int i ; i < currentInstr.egbStages ; i++){ 1668 egb.insertBack(*cast(EnvelopeStage*)(data.ptr + pos)); 1669 pos += EnvelopeStage.sizeof; 1670 } 1671 envGenB[currentInstr.id] = egb; 1672 } 1673 break; 1674 case RIFFID.instrumentData: 1675 if(!envGenBFound){ 1676 cpsFound = true; 1677 for(int i ; i < currentInstr.sampleLayers ; i++){ 1678 sampleLayers[currentInstr.id].add(*cast(ChannelPresetSamples*)(data.ptr + pos)); 1679 pos += ChannelPresetSamples.sizeof; 1680 } 1681 } 1682 break; 1683 /*case RIFFID.instrumentPreset: 1684 presets[currentInstr.id] = *cast(ChannelPresetMain*)(data.ptr + pos); 1685 pos += ChannelPresetMain.sizeof; 1686 break;*/ 1687 case RIFFID.samplePreset: 1688 SamplePreset slmp = *cast(SamplePreset*)(data.ptr + pos); 1689 pos += SamplePreset.sizeof; 1690 string filename = samplePoolPath; 1691 foreach(c ; slmp.name){ 1692 if(c){ 1693 filename ~= c; 1694 }else{ 1695 break; 1696 } 1697 } 1698 filename ~= ".pcm"; 1699 PCMFile file = loadPCMFile(toStringz(filename)); 1700 //sampleSrc ~= file.data; 1701 Sample s; 1702 s.codec = file.data.codecType; 1703 s.sampleFreq = slmp.freq; 1704 s.length = file.header.length; 1705 s.dataPtr = cast(ubyte*)malloc(file.data.data.length); 1706 memcpy(s.dataPtr, file.data.data.ptr, file.data.data.length); 1707 file.destroy; 1708 samples[slmp.id] = s; 1709 break; 1710 case RIFFID.fiResponse: 1711 FXSamplePreset slmp = *cast(FXSamplePreset*)(data.ptr + pos); 1712 pos += FXSamplePreset.sizeof; 1713 string filename = samplePoolPath; 1714 foreach(c ; slmp.name){ 1715 if(c){ 1716 filename ~= c; 1717 }else{ 1718 break; 1719 } 1720 } 1721 filename ~= ".pcm"; 1722 PCMFile file = loadPCMFile(toStringz(filename)); 1723 FiniteImpulseResponse!(FIR_TABLE_LENGTH) fir; 1724 memcpy(fir.vals.ptr, file.data.data.ptr, FIR_TABLE_LENGTH); 1725 file.destroy; 1726 finiteImpulseResponses[slmp.id] = fir; 1727 break; 1728 case RIFFID.lfoPreset: 1729 FXSamplePreset slmp = *cast(FXSamplePreset*)(data.ptr + pos); 1730 pos += FXSamplePreset.sizeof; 1731 string filename = samplePoolPath; 1732 foreach(c ; slmp.name){ 1733 if(c){ 1734 filename ~= c; 1735 }else{ 1736 break; 1737 } 1738 } 1739 filename ~= ".pcm"; 1740 PCMFile file = loadPCMFile(toStringz(filename)); 1741 ubyte[LFO_TABLE_LENGTH] table; 1742 memcpy(table.ptr, file.data.data.ptr, FIR_TABLE_LENGTH); 1743 file.destroy; 1744 lfoTables[slmp.id] = table; 1745 break; 1746 case RIFFID.globalSettings: 1747 globals = *cast(GlobalSettings*)(data.ptr + pos); 1748 pos += GlobalSettings.sizeof; 1749 break; 1750 default: 1751 throw new Exception("Invalid data error!"); 1752 } 1753 } 1754 } 1755 /** 1756 *Not supported currently 1757 */ 1758 override public ref void[] saveConfig(){ 1759 throw new Exception("Unimplemented feature!"); 1760 } 1761 } 1762