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 libPCM.codecs; 15 import libPCM.common; 16 17 import std.bitmanip; 18 19 /** 20 * Sampling synthesizer implementation. Has per channel FIR (1024 stage) and IIR (low-pass) filters, and four stereo outputs. 21 */ 22 public class PCM32 : AbstractPPEFX{ 23 /** 24 * Defines the source of certain modifier values 25 */ 26 public enum ControlSource : ubyte{ 27 NULL = 0, 28 Pitch = 1, 29 Velocity = 2, 30 ExpressiveVal = 3, 31 } 32 /** 33 * Per-octave dampening 34 */ 35 public enum Dampening : ubyte{ 36 DB00 = 0, 37 DB15 = 1, 38 DB30 = 2, 39 DB60 = 3, 40 } 41 protected struct Channel{ 42 short delegate(ubyte* inputStream, DecoderWorkpad* workpad) codec; 43 uint loopfrom, loopto; ///describe a loop cycle between the two values 44 uint stepping; ///describes how much the sample should go forward, 65536 equals a whole step 45 ulong forward; ///current position 46 short[] intBuff; ///buffer for FIR-filters 47 CodecType codecType; 48 DecoderWorkpad workpad, secWorkpad; 49 EnvelopeGenerator envGenA; 50 EnvelopeGenerator envGenB; 51 FiniteImpulseResponseFilter!(1024)[2] firFilter; 52 LowFreqOsc!(256) lfo; 53 } 54 float sampleRate; 55 int frameLength, bufferLength; 56 version(X86){ 57 /** 58 * Contains IIR related registers in order for use in SSE2 applications 59 */ 60 protected struct IIRFilterBuff{ 61 float[4] b0a0; 62 //float[4] x_n; 63 float[4] b1a0; 64 float[4] x_n_minus1; 65 float[4] b2a0; 66 float[4] x_n_minus2; 67 float[4] a1a0; 68 float[4] y_n_minus1; 69 float[4] a2a0; 70 float[4] y_n_minus2; 71 //float[4] y_n; 72 } 73 IIRFilterBuff[8] iirFilters; 74 void* iirFiltersPtr; 75 }else{ 76 float[32] x_n_minus1, x_n_minus2, y_n_minus1, y_n_minus2, b0a0, b1a0, b2a0, a1a0, a2a0; 77 } 78 float[32][] y_n, x_n; 79 80 81 protected @nogc void calculateIIR(){ 82 version(X86){ 83 float* y_nptr = cast(float*)y_n.ptr; 84 float* x_nptr = cast(float*)x_n.ptr; 85 for(int i = frameLength * bufferLength ; i >= 0 ; i--){ 86 asm @nogc{ 87 mov ECX, 8; 88 //mov ESI, iirFiltersPtr[EBP]; 89 mov EDI, y_nptr; 90 mov EBX, x_nptr; 91 iirLoop: 92 movaps XMM0, [ESI];//load b0/a0 93 movaps XMM1, [EBX];//load x_n 94 mulps XMM0, XMM1; //(b0/a0) * x_n 95 add ESI, 16; //offset ESI to b1a0 96 movaps XMM2, [ESI];//load b1a0 97 add ESI, 16; //offset ESI to x_n_minus1 98 movaps XMM3, [ESI];//load x_n_minus1 99 movaps [ESI], XMM1;//store current x_n as x_n_minus1 100 mulps XMM2, XMM3; //(b1/a0) * x_n_minus1 101 addps XMM0, XMM2; //(b0/a0) * x_n + (b1/a0) * x_n_minus1 102 add ESI, 16; //offset ESI to b2a0 103 movaps XMM2, [ESI];//load b2a0 104 add ESI, 16; //offset ESI to x_n_minus2 105 movaps XMM4, [ESI];//load x_n_minus2 106 movaps [ESI], XMM3;//store current x_n_minus1 as x_n_minus2 107 mulps XMM2, XMM4; //(b2/a0) * x_n_minus2 108 addps XMM0, XMM2; //(b0/a0) * x_n + (b1/a0) * x_n_minus1 + (b2/a0) * x_n_minus2 109 add ESI, 16; //offset ESI to a1a0 110 movaps XMM1, [ESI];//load a1a0 111 add ESI, 16; //offset ESI to y_n_minus1 112 movaps XMM2, [ESI];//load y_n_minus1 113 mulps XMM1, XMM2; //(a1/a0) * y_n_minus1 114 subps XMM0, XMM1; //(b0/a0) * x_n + (b1/a0) * x_n_minus1 + (b2/a0) * x_n_minus2 - (a1/a0) * y_n_minus1 115 add ESI, 16; //offset ESI to a2a0 116 movaps XMM1, [ESI];//load a2a0 117 add ESI, 16; //offset ESI to y_n_minus2 118 movaps XMM3, [ESI];//load y_n_minus2 119 movaps [ESI], XMM2;//store y_n_minus1 as new y_n_minus2 120 mulps XMM1, XMM3; //(a2/a0) * y_n_minus2 121 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 122 sub ESI, 48; //set back pointer to y_n_minus1 123 movaps [ESI], XMM0;//store y_n as y_n_minus1 124 movaps [EDI], XMM0;//store y_n as output 125 add EDI, 16; 126 add ESI, 48; 127 dec ECX; 128 cmp ECX, 0; 129 jne iirLoop; 130 } 131 x_nptr += 32; 132 y_nptr += 32; 133 } 134 } 135 } 136 } 137