1 module pixelperfectengine.audio.modules.pcm8;
2 
3 import pixelperfectengine.audio.base.modulebase;
4 import pixelperfectengine.audio.base.types;
5 import pixelperfectengine.audio.base.envgen;
6 import pixelperfectengine.audio.base.func;
7 import pixelperfectengine.audio.base.envgen;
8 import pixelperfectengine.audio.base.osc;
9 import pixelperfectengine.system.etc : min;
10 
11 import std.math;
12 import core.stdc.string;
13 
14 import collections.treemap;
15 
16 import inteli.emmintrin;
17 
18 import midi2.types.structs;
19 import midi2.types.enums;
20 
21 import bitleveld.datatypes;
22 
23 /**
24 PCM8 - implements a sample-based synthesizer.
25 
26 It has support for 
27  * 8 bit and 16 bit linear PCM
28  * Mu-Law and A-Law PCM
29  * IMA ADPCM
30  * Dialogic ADPCM
31 
32 The module has 8 sample-based channels with looping capabilities and each has an ADSR envelop, and 4 outputs with a filter.
33 */
34 public class PCM8 : AudioModule {
35 	shared static this () {
36 		import std.range : iota;
37 		import std.conv : to;
38 		for (uint i ; i < 128 ; i++) {		//TODO: Make a version to leave this out, otherwise it'll just consume memory for the end user.
39 			SAMPLE_SET_VALS ~= MValue(MValueType.Int32, i | 0x10_00, "Sample-"~to!string(i)~"_Select");
40 			SAMPLE_SET_VALS ~= MValue(MValueType.Float, i | 0x11_00, "Sample-"~to!string(i)~"_SlmpFreq");
41 			SAMPLE_SET_VALS ~= MValue(MValueType.Int32, i | 0x12_00, "Sample-"~to!string(i)~"_LoopBegin");
42 			SAMPLE_SET_VALS ~= MValue(MValueType.Int32, i | 0x13_00, "Sample-"~to!string(i)~"_LoopEnd");
43 		}
44 		for (int i ; i < 128 ; i++) {
45 			ADSR_TIME_TABLE[i] = pow(i / 64.0, 1.8);
46 		}
47 	}
48 	protected static MValue[] SAMPLE_SET_VALS;
49 	public static immutable float[128] ADSR_TIME_TABLE;
50 	/**
51 	Contains a table to calculate Sustain control values.
52 
53 	All values are seconds with fractions. Actual values are live-calculated depending on sustain level and sampling
54 	frequency. Please note that with certain levels of sustain, the actual max time might be altered.
55 	*/
56 	public static immutable float[63] SUSTAIN_CONTROL_TIME_TABLE = [
57 	//	0     |1     |2     |3     |4     |5     |6     |7     |8     |9     |A     |B     |C     |D     |E     |F
58 		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
59 		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
60 		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
61 		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
62 	];
63 	alias DecodeFunc = void function(ubyte[] src, int[] dest, ref DecoderWorkpad wp) @nogc nothrow pure;
64 	/**
65 	Defines a single sample.
66 	*/
67 	protected struct Sample {
68 		///Stores sample data, which later can be decompressed
69 		ubyte[]		sampleData;
70 		///Stores what kind of format the sample has
71 		WaveFormat	format;
72 		///Points to the decoder function
73 		DecodeFunc	decode;
74 		size_t samplesLength() @nogc @safe pure nothrow const {
75 			return (sampleData.length * 8) / format.bitsPerSample;
76 		}
77 	}
78 	/**
79 	Defines a single sample-to-note assignment.
80 	*/
81 	protected struct SampleAssignment {
82 		///Number of sample that is assigned.
83 		uint		sampleNum;
84 		///The base frequency of the sample.
85 		///Overrides the format definition.
86 		float		baseFreq;
87 		///Start of a looppoint.
88 		///-1, if looppoint is not available.
89 		int			loopBegin	=	-1;
90 		///End of a looppoint.
91 		///-1, if looppoint is not available.
92 		int			loopEnd		=	-1;
93 	}
94 	/** 
95 	Stores preset information.
96 	*/
97 	protected struct Preset {
98 		/// Stores sample mappings for each note.
99 		SampleAssignment[128]	sampleMapping;
100 		ubyte			eAtk;		///Attack time selector
101 		ubyte			eDec;		///Decay time selector
102 		ubyte			eSusC;		///Sustain control (0: percussive; 1-63: descending; 64: constant; 65-127: ascending)
103 		ubyte			eRel;		///Release time selector
104 		float			eAtkShp = 0.5;///Attack shaping
105 		float			eRelShp = 0.5;///Release shaping
106 		float			eSusLev = 1;///Sustain level
107 		float			masterVol = 1;///Master output volume
108 		float			balance = 0.5;///Master output balance
109 		float			auxSendA = 0;///Aux send level A
110 		float			auxSendB = 0;///Aux send level B
111 		float			velToLevelAm = 0;///Assigns velocity to output levels
112 		float			velToAuxSendAm = 0;///Assigns velocity to aux send levels
113 		float			velToAtkShp = 0;///Assigns velocity to attack shape of envelop generator
114 		float			velToRelShp = 0;///Assigns velocity to release shape of envelop generator
115 		float			lfoToVol = 0;	///Tremolo level (LFO to volume)
116 		float			adsrToVol = 0;	///ADSR to output level amount 
117 		float			adsrToDetune = 0;///ADSR to pitch bend amount
118 		float			vibrAm = 0;	///FLO to pitch bend amount
119 
120 		float			pitchBendAm = 2;///Pitch bend range
121 
122 		uint			flags;		///Contains various binary settings
123 	}
124 	///Defines preset setting flags.
125 	protected enum PresetFlags {
126 		cutoffOnKeyOff		=	1<<0,		///If set, the sample playback will cut off on every key off event
127 		modwheelToLFO		=	1<<1,		///Assigns modulation wheel to amplitude and/or pitch LFO levels
128 		panningLFO			=	1<<2,		///Sets amplitude LFO to panning on this channel
129 		/* ADSRtoVol			=	1<<3,		///If set, then envGen will control the volume */
130 	}
131 	///Defines LFO setting flags.
132 	protected enum LFOFlags {
133 		saw					=	1<<0,
134 		triangle			=	1<<1,
135 		pulse				=	1<<2,
136 		sawpulse			=	1<<3,
137 		invert				=	1<<4,
138 		ringmod				=	1<<5
139 	}
140 	///Defines channel statuses.
141 	protected enum ChannelStatusFlags {
142 		noteOn				=	1<<0,	///Set if key is on
143 		sampleRunout		=	1<<1,	///Set if sample have ran out (decoder proceeds to stop)
144 		inLoop				=	1<<2,	///Set if sample is looping
145 		bufferHalf			=	1<<3,
146 	}
147 	/**
148 	Defines a single channel's statuses.
149 	*/
150 	protected struct Channel {
151 		//int[256]		decoderBuffer;
152 		int[256]		decoderBuffer;		///Stores decoded samples.
153 		Preset			presetCopy;			///The copy of the preset.
154 		DecoderWorkpad	decoderWorkpad;		///Stores the current state of the decoder.
155 		DecoderWorkpad	savedDWState;		///The state of the decoder when the beginning of the looppoint has been reached.
156 		WavemodWorkpad	waveModWorkpad;		///Stores the current state of the wave modulator.
157 		double			freqRatio;			///Sampling-to-playback frequency ratio, with pitch bend, LFO, and envGen applied.
158 		ulong			outPos;				///Position in decoded amount, including fractions
159 		ulong			samplesHave;		///Amount of decoded samples with fractions offsetted
160 		//uint			decodeAm;			///Decoded amount, mainly used to determine output buffer half
161 		uint 			jumpAm;				///Jump amount for current sample, calculated from freqRatio.
162 		//WavemodWorkpad	savedWMWState;		///The state of the wave modulator when the beginning of the looppoint has been reached.
163 		ADSREnvelopGenerator	envGen;		///Channel envelop generator.
164 
165 		ubyte			currNote = 255;		///The currently played note + Bit 8 indicates suspension.
166 		ubyte			presetNum;			///Selected preset.
167 		ushort			bankNum;			///Bank select number.
168 		uint			status;				///Channel status flags. Bit 1: Note on, Bit 2: Sample run out approaching, Bit 3: In loop, Bit 4: Bufferhalf
169 
170 		float			pitchBend = 0;		///Current amount of pitch bend.
171 
172 		float			velocity = 0;		///Velocity normalized between 0 and 1
173 		float			modWheel = 0;		///Modulation wheel normalized between 0 and 1
174 
175 		float			currShpA;			///The current attack shape
176 		float			currShpR;			///The current release shape
177 		/**
178 		Decodes one more block worth of samples, depending on internal state.
179 		Params:
180 		* sa = The sample's assigned data.
181 		* slmp = The sample to be decoded.
182 		Bugs: 
183 		* Upon pitchbend and when looping, it can cause buffer alignment issues, which in turn will cause audio glitches. FIXED!
184 		*/
185 		void decodeMore(ref SampleAssignment sa, ref Sample slmp) @nogc nothrow pure {
186 			//Check if sample runout have happened already, stop decoding if yes.
187 			if (status & ChannelStatusFlags.sampleRunout) {
188 				currNote = 255;
189 			}
190 			if (currNote == 255) {
191 				return;
192 			}
193 			//Determine how much samples we will need.
194 			sizediff_t samplesNeeded = 128;
195 			//Determine offset based on which cycle we will need
196 			const size_t offset = status & ChannelStatusFlags.bufferHalf ? 128 : 0;
197 			//Determine if note is on.
198 			const bool keyOn = (status & 1) == 1;
199 			//Determine if sample is looping
200 			const bool isLooping = (sa.loopBegin != -1 && sa.loopEnd != -1) && ((sa.loopEnd - sa.loopBegin) > 0) && keyOn;
201 			
202 			//Special Case 1: sample is running out, and there are no looppoints or note isn't on.
203 			if (!isLooping && (decoderWorkpad.pos + samplesNeeded >= slmp.samplesLength())) {
204 				samplesNeeded -= decoderWorkpad.pos + samplesNeeded - slmp.samplesLength();
205 				status |= ChannelStatusFlags.sampleRunout;
206 				for (size_t i = samplesNeeded ; i < 128 ; i++) 
207 					decoderBuffer[offset + i] = 0;
208 			}
209 			size_t dPos = offset;	//Decoder position
210 			while (samplesNeeded > 0) {
211 				//Special Case 2: sample might enter the beginning or the end of the loop.
212 				//If loop is short enough, it can happen multiple times
213 				const bool loopBegin = isLooping && (decoderWorkpad.pos + samplesNeeded >= sa.loopBegin) && 
214 						!(status & ChannelStatusFlags.inLoop);
215 				const bool loopEnd = isLooping && (decoderWorkpad.pos + samplesNeeded >= sa.loopEnd);
216 				const size_t samplesToDecode = loopBegin ? samplesNeeded - (sa.loopBegin - decoderWorkpad.pos) : (loopEnd ? 
217 						samplesNeeded - (sa.loopEnd - decoderWorkpad.pos) : samplesNeeded);//Determine how much saples will we need
218 				slmp.decode(slmp.sampleData, decoderBuffer[dPos..dPos + samplesToDecode], decoderWorkpad);//Decode some amount of samples
219 				if (loopBegin) {//Save decoder workpad state on the beginning of the loop (important for ADPCM!)
220 					status |= ChannelStatusFlags.inLoop;
221 					savedDWState = decoderWorkpad;
222 				} else if (loopEnd) {//Restore decoder and other necessary statuses.
223 					decoderWorkpad = savedDWState;
224 				}
225 				samplesNeeded -= samplesToDecode;
226 				dPos += samplesToDecode;
227 				samplesHave += (samplesToDecode<<24);
228 			}
229 			status ^= ChannelStatusFlags.bufferHalf;
230 			//decodeAm++;	//Flip decode buffer
231 		}
232 		///Calculates jump amount for the sample.
233 		void calculateJumpAm(int sampleRate, float lfoOut) @nogc @safe pure nothrow {
234 			freqRatio = sampleRate / bendFreq(presetCopy.sampleMapping[currNote & 127].baseFreq, pitchBend + 
235 					(presetCopy.vibrAm * lfoOut * (presetCopy.flags & PresetFlags.modwheelToLFO ? modWheel : 1.0)) + 
236 					(presetCopy.adsrToDetune * 
237 					envGen.shp(envGen.position == ADSREnvelopGenerator.Stage.Attack ? currShpA : currShpR)));
238 			jumpAm = cast(uint)((1<<24) / freqRatio);
239 		}
240 		///Resets all internal states.
241 		void reset() @nogc @safe pure nothrow {
242 			outPos = 0;
243 			status = 0;
244 			status &= ~ChannelStatusFlags.bufferHalf;
245 			//decodeAm = 0;
246 			samplesHave = 0;
247 			decoderWorkpad = DecoderWorkpad.init;
248 			savedDWState = DecoderWorkpad.init;
249 			waveModWorkpad = WavemodWorkpad.init;
250 		}
251 		///Recalculates shape params.
252 		void setShpVals(float vel = 1.0) @nogc @safe pure nothrow {
253 			currShpA = presetCopy.eAtkShp - (presetCopy.velToAtkShp * presetCopy.eAtkShp) + 
254 					(presetCopy.velToAtkShp * presetCopy.eAtkShp * vel);
255 			currShpR = presetCopy.eRelShp - (presetCopy.velToRelShp * presetCopy.eRelShp) + 
256 					(presetCopy.velToRelShp * presetCopy.eRelShp * vel);
257 		}
258 		void setADSR(int sampleRate) @nogc @safe pure nothrow {
259 			envGen.sustainLevel = presetCopy.eSusLev;
260 			if (presetCopy.eAtk) {
261 				envGen.attackRate = calculateRate(ADSR_TIME_TABLE[presetCopy.eAtk], sampleRate);
262 			} else {
263 				envGen.attackRate = 1.0;
264 			}
265 			if (presetCopy.eDec) {
266 				envGen.decayRate = calculateRate(ADSR_TIME_TABLE[presetCopy.eDec] * 2, sampleRate, 
267 						ADSREnvelopGenerator.maxOutput, envGen.sustainLevel);
268 			} else {
269 				envGen.decayRate = 1.0;
270 			}
271 			if (presetCopy.eSusC) {
272 				envGen.isPercussive = false;
273 				if (presetCopy.eSusC == 64) {
274 					envGen.sustainControl = 0.0;
275 				} else if (presetCopy.eSusC < 64) {
276 					envGen.sustainControl =  
277 							calculateRate(SUSTAIN_CONTROL_TIME_TABLE[62 - (presetCopy.eSusC - 1)], sampleRate);
278 				} else {
279 					envGen.sustainControl = -1.0 *
280 							calculateRate(SUSTAIN_CONTROL_TIME_TABLE[presetCopy.eSusC - 64], sampleRate);
281 				}
282 			} else {
283 				envGen.isPercussive = true;
284 				envGen.sustainControl = 0.0;
285 			}
286 			//Set release phase
287 			if (presetCopy.eRel) {
288 				envGen.releaseRate = calculateRate(ADSR_TIME_TABLE[presetCopy.eRel] * 2, sampleRate, envGen.sustainLevel);
289 			} else {
290 				envGen.releaseRate = 1.0;
291 			}
292 		}
293 	}
294 	alias SampleMap = TreeMap!(uint, Sample);
295 	alias PresetMap = TreeMap!(uint, Preset);
296 	protected SampleMap		sampleBank;			///Stores all current samples.
297 	protected PresetMap		presetBank;			///Stores all current presets. (bits: 0-6: preset number, 7-13: bank lsb, 14-20: bank msb)
298 	protected Channel[8]	channels;			///Channel status data.
299 	protected MultiTapOsc	lfo;				///Low frequency oscillator to modify values in real-time
300 	protected float[]		lfoOut;				///LFO output buffer
301 	protected uint			lfoFlags = LFOFlags.triangle;///LFO state flags containing info about current waveform data
302 	protected float			lfoFreq = 6.0;		///LFO frequency
303 	protected float			lfoPWM = 0.5;		///LFO pulse width modulation
304 	protected float[]		dummyBuf;			///Dummy buffer if one or more output aren't used
305 	protected int[]			iBuf;				///Integer output buffers
306 	protected __m128[]		lBuf;				///Local output buffer
307 	///Stores output filter values.
308 	///0: a0; 1: a1; 2: a2; 3: b0; 4: b1; 5: b2; 6: x[n-1]; 7: x[n-2]; 8: y[n-1] 9: y[n-2]
309 	protected __m128[10]		filterVals;
310 	///Stores control values of the output values.
311 	///Layout: [LF, LQ, RF, RQ, AF, AQ, BF, BQ]
312 	protected float[8]			filterCtrl	=	[16_000, 0.707, 16_000, 0.707, 16_000, 0.707, 16_000, 0.707];
313 	protected float				mixdownVal = short.max + 1;
314 	protected ubyte[32]			sysExBuf;		///SysEx command buffer [0-30] + length [31]
315 	protected ubyte[68][9]		chCtrlLower;	///Lower parts of the channel controllers (0-31 / 32-63) + (Un)registered parameter select (64-65)
316 	public this() @safe nothrow {
317 		info.nOfAudioInput = 0;
318 		info.nOfAudioOutput = 4;
319 		info.outputChNames = ["mainL", "mainR", "auxSendA", "auxSendB"];
320 		info.isInstrument = true;
321 		info.hasMidiIn = true;
322 		info.hasMidiOut = true;
323 		info.midiSendback = true;
324 		lfo = MultiTapOsc.init;
325 	}
326 	/**
327 	 * Sets the module up.
328 	 *
329 	 * Can be overridden in child classes to allow resets.
330 	 */
331 	public override void moduleSetup(ubyte[] inputs, ubyte[] outputs, int sampleRate, size_t bufferSize, 
332 			ModuleManager handler) @safe nothrow {
333 		enabledInputs = StreamIDSet(inputs);
334 		enabledOutputs = StreamIDSet(outputs);
335 		this.sampleRate = sampleRate;
336 		this.bufferSize = bufferSize;
337 		/+for (int i ; i < 8 ; i++) {
338 			channels[i].decoderBuffer.length = bufferSize * 2;
339 		}+/
340 		dummyBuf.length = bufferSize;
341 		iBuf.length = bufferSize;
342 		lBuf.length = bufferSize;
343 		lfoOut.length = bufferSize;
344 		this.handler = handler;
345 		//Reset filters
346 		for (int i ; i < 4 ; i++) {
347 			resetLPF(i);
348 			filterVals[6][i] = 0;
349 			filterVals[7][i] = 0;
350 			filterVals[8][i] = 0;
351 			filterVals[9][i] = 0;
352 		}
353 		resetLFO();
354 	}
355 	///Recalculates the low pass filter vlues for the given output channel.
356 	protected void resetLPF(int i) @nogc @safe pure nothrow {
357 		BiquadFilterValues vals = createLPF(sampleRate, filterCtrl[i * 2], filterCtrl[(i * 2) + 1]);
358 		filterVals[0][i] = vals.a0;
359 		filterVals[1][i] = vals.a1;
360 		filterVals[2][i] = vals.a2;
361 		filterVals[3][i] = vals.b0;
362 		filterVals[4][i] = vals.b1;
363 		filterVals[5][i] = vals.b2;
364 	}
365 	/**
366 	 * MIDI 2.0 data received here.
367 	 *
368 	 * data0: Header of the up to 128 bit MIDI 2.0 data.
369 	 * data1-3: Other packets if needed.
370 	 */
371 	public override void midiReceive(UMP data0, uint data1 = 0, uint data2 = 0, uint data3 = 0) @nogc nothrow {
372 		switch (data0.msgType) {
373 			case MessageType.MIDI1:
374 				if (data0.channel < 8) {
375 					switch (data0.status) {
376 						case MIDI1_0Cmd.PitchBend:
377 							channels[data0.channel].pitchBend = channels[data0.channel].presetCopy.pitchBendAm * 
378 									((cast(double)data0.bend - 0x20_00) / 0x3F_FF);
379 							//channels[data0.channel].calculateJumpAm(sampleRate);
380 							break;
381 						case MIDI1_0Cmd.NoteOn:
382 							keyOn(data0.note, data0.channel, data0.value/127.0);
383 							break;
384 						case MIDI1_0Cmd.NoteOff:
385 							keyOff(data0.note, data0.channel, data0.value/127.0);
386 							break;
387 						case MIDI1_0Cmd.CtrlCh:
388 							uint val;
389 							if (data0.note < 64) {
390 								chCtrlLower[data0.channel][data0.note] = data0.value;
391 								val = convertM1CtrlValToM2(chCtrlLower[data0.channel][data0.note & 0x1F], 
392 										chCtrlLower[data0.channel][data0.note | 0x20]);
393 							} else if (data0.note >= 70 && data0.note <= 73) {
394 								val = data0.value<<25;
395 							} else {
396 								val = convertM1CtrlValToM2(data0.value, data0.value);
397 							}
398 							if (data0.note == 0 || data0.note == 32)
399 								channels[data0.channel].bankNum = (chCtrlLower[data0.channel][0]<<7) | chCtrlLower[data0.channel][32];
400 							else
401 								ctrlCh (data0.channel, data0.note, val);
402 							break;
403 						case MIDI1_0Cmd.PrgCh:
404 							channels[data0.channel].presetCopy = presetBank[(channels[data0.channel].bankNum<<7) | data0.note];
405 							channels[data0.channel].presetNum = data0.note;
406 							break;
407 						default:
408 							break;
409 					}
410 				}
411 				break;
412 			case MessageType.MIDI2:
413 				if (data0.channel < 8) {
414 					switch (data0.status) {
415 						case MIDI2_0Cmd.PitchBend:
416 							channels[data0.channel].pitchBend = channels[data0.channel].presetCopy.pitchBendAm * 
417 									((cast(double)data1 - int.max) / (int.max));
418 							//channels[data0.channel].calculateJumpAm(sampleRate);
419 							break;
420 						case MIDI2_0Cmd.NoteOn:
421 							NoteVals nv = *cast(NoteVals*)&data1;
422 							keyOn(data0.note, data0.channel, nv.velocity / ushort.max);
423 							break;
424 						case MIDI2_0Cmd.NoteOff:
425 							NoteVals nv = *cast(NoteVals*)&data1;
426 							keyOff(data0.note, data0.channel, nv.velocity / ushort.max);
427 							break;
428 						case MIDI2_0Cmd.CtrlChOld, MIDI2_0Cmd.CtrlCh:
429 							ctrlCh(data0.channel, data0.note, data1);
430 							break;
431 						case MIDI2_0Cmd.PrgCh:
432 							channels[data0.channel].bankNum = data1 & ushort.max;
433 							channels[data0.channel].presetNum = data1>>24;
434 							presetRecall(data0.channel);
435 							break;
436 						default:
437 							break;
438 					}
439 				}
440 				break;
441 			case MessageType.Data64:
442 				if (data0.status == SysExSt.Start || data0.status == SysExSt.Complete)
443 					sysExBuf[31] = 0;
444 				ubyte[4] packet1 = [cast(ubyte)(data1>>24), cast(ubyte)(data1>>16), cast(ubyte)(data1>>8), cast(ubyte)data1];
445 				int length = data0.channel;
446 				for (int i ; i < 2 && length - 4 > 0 ; i++, length--) {
447 					sysExBuf[sysExBuf[31]] = data0.bytes[i];
448 					sysExBuf[31]++;
449 					if (sysExBuf[31] > 30) {
450 						length = 0;
451 						sysExBuf[31] = 0;
452 					}
453 				}
454 				for (int i ; i < 4 && length > 0 ; i++, length--) {
455 					sysExBuf[sysExBuf[31]] = packet1[i];
456 					sysExBuf[31]++;
457 					if (sysExBuf[31] > 30) {
458 						length = 0;
459 						sysExBuf[31] = 0;
460 					}
461 				}
462 				if (data0.status == SysExSt.Complete || data0.status == SysExSt.End)
463 					sysExCmd(sysExBuf[0..sysExBuf[31]]);
464 				break;
465 			case MessageType.Data128:
466 				if (data0.status == SysExSt.Start || data0.status == SysExSt.Complete)
467 					sysExBuf[31] = 0;
468 				ubyte[13] data = [data0.value, 
469 						cast(ubyte)(data1>>24), cast(ubyte)(data1>>16), cast(ubyte)(data1>>8), cast(ubyte)data1,
470 						cast(ubyte)(data2>>24), cast(ubyte)(data2>>16), cast(ubyte)(data2>>8), cast(ubyte)data2,
471 						cast(ubyte)(data3>>24), cast(ubyte)(data3>>16), cast(ubyte)(data3>>8), cast(ubyte)data3];
472 				for (int i ; i < data0.channel ; i++, sysExBuf[31]++) {
473 					sysExBuf[sysExBuf[31]] = data[i];
474 					if (sysExBuf[31] > 30)
475 						sysExBuf[31] = 0;
476 				}
477 				if (data0.status == SysExSt.Complete || data0.status == SysExSt.End)
478 					sysExCmd(sysExBuf[0..sysExBuf[31]]);
479 				break;
480 			default:
481 				break;
482 		}
483 	}
484 	protected void keyOn(ubyte note, ubyte ch, float vel) @nogc pure nothrow {
485 		channels[ch].currNote = note;
486 		channels[ch].velocity = vel;
487 		channels[ch].calculateJumpAm(sampleRate, lfoOut[0]);
488 		channels[ch].setShpVals(vel);
489 		channels[ch].setADSR(sampleRate);
490 		channels[ch].envGen.keyOn();
491 		//reset all on channel
492 		channels[ch].reset();
493 		//set noteOn status flag
494 		channels[ch].status |= ChannelStatusFlags.noteOn;
495 	}
496 	protected void keyOff(ubyte note, ubyte ch, float vel) @nogc pure nothrow {
497 		if (!(channels[ch].currNote & 128))
498 			channels[ch].currNote = note;
499 		channels[ch].velocity = vel;
500 		channels[ch].calculateJumpAm(sampleRate, lfoOut[0]);
501 		channels[ch].setShpVals(vel);
502 		channels[ch].envGen.keyOff();
503 		channels[ch].status &= ~ChannelStatusFlags.noteOn;
504 	}
505 	protected void ctrlCh(ubyte ch, ubyte param, uint val) @nogc pure nothrow {
506 		if (param >= 32 && param < 64) param &= 0x1F;
507 		if (ch <= 7) {	//Channel locals
508 			switch (param) {
509 				case 7:
510 					channels[ch].presetCopy.masterVol = (1.0 / uint.max) * val;
511 					break;
512 				case 8:
513 					channels[ch].presetCopy.balance = (1.0 / uint.max) * val;
514 					break;
515 				case 91:
516 					channels[ch].presetCopy.auxSendA = (1.0 / uint.max) * val;
517 					break;
518 				case 92:
519 					channels[ch].presetCopy.auxSendB = (1.0 / uint.max) * val;
520 					break;
521 				case 73:
522 					channels[ch].presetCopy.eAtk = cast(ubyte)(val>>25);
523 					break;
524 				case 14:
525 					channels[ch].presetCopy.eAtkShp = (1.0 / uint.max) * val;
526 					break;
527 				case 70:
528 					channels[ch].presetCopy.eDec = cast(ubyte)(val>>25);
529 					break;
530 				case 71:
531 					channels[ch].presetCopy.eSusC = cast(ubyte)(val>>25);
532 					break;
533 				case 9:
534 					channels[ch].presetCopy.eSusLev = (1.0 / uint.max) * val;
535 					break;
536 				case 72:
537 					channels[ch].presetCopy.eRel = cast(ubyte)(val>>25);
538 					break;
539 				case 15:
540 					channels[ch].presetCopy.eRelShp = (1.0 / uint.max) * val;
541 					break;
542 				case 20:
543 					channels[ch].presetCopy.velToLevelAm = (1.0 / uint.max) * val;
544 					break;
545 				case 21:
546 					channels[ch].presetCopy.velToAuxSendAm = (1.0 / uint.max) * val;
547 					break;
548 				case 22:
549 					channels[ch].presetCopy.velToAtkShp = (1.0 / uint.max) * val;
550 					break;
551 				case 23:
552 					channels[ch].presetCopy.velToRelShp = (1.0 / uint.max) * val;
553 					break;
554 				case 24:
555 					channels[ch].presetCopy.lfoToVol = (1.0 / uint.max) * val;
556 					break;
557 				case 25:
558 					channels[ch].presetCopy.adsrToVol = (1.0 / uint.max) * val;
559 					break;
560 				case 26:
561 					channels[ch].presetCopy.adsrToDetune = (1.0 / uint.max) * val * 24;
562 					break;
563 				case 27:
564 					channels[ch].presetCopy.vibrAm = (1.0 / uint.max) * val * 12;
565 					break;
566 				case 102:
567 					if (val)
568 						channels[ch].presetCopy.flags |= PresetFlags.cutoffOnKeyOff;
569 					else
570 						channels[ch].presetCopy.flags &= ~PresetFlags.cutoffOnKeyOff;
571 					break;
572 				case 103:
573 					if (val)
574 						channels[ch].presetCopy.flags |= PresetFlags.modwheelToLFO;
575 					else
576 						channels[ch].presetCopy.flags &= ~PresetFlags.modwheelToLFO;
577 					break;
578 				case 104:
579 					if (val)
580 						channels[ch].presetCopy.flags |= PresetFlags.panningLFO;
581 					else
582 						channels[ch].presetCopy.flags &= ~PresetFlags.panningLFO;
583 					break;
584 				default:
585 					break;
586 			}
587 		} else if (ch == 8) {	//Module globals
588 			switch (param) {
589 				case 2:
590 					filterCtrl[0] = (1.0 / uint.max) * val * 16_000;
591 					resetLPF(0);
592 					break;
593 				case 3:
594 					filterCtrl[1] = (1.0 / uint.max) * val * 40;
595 					resetLPF(0);
596 					break;
597 				case 4:
598 					filterCtrl[2] = (1.0 / uint.max) * val * 16_000;
599 					resetLPF(1);
600 					break;
601 				case 5:
602 					filterCtrl[3] = (1.0 / uint.max) * val * 40;
603 					resetLPF(1);
604 					break;
605 				case 6:
606 					filterCtrl[4] = (1.0 / uint.max) * val * 16_000;
607 					resetLPF(2);
608 					break;
609 				case 7:
610 					filterCtrl[5] = (1.0 / uint.max) * val * 40;
611 					resetLPF(2);
612 					break;
613 				case 8:
614 					filterCtrl[6] = (1.0 / uint.max) * val * 16_000;
615 					resetLPF(3);
616 					break;
617 				case 9:
618 					filterCtrl[7] = (1.0 / uint.max) * val * 40;
619 					resetLPF(3);
620 					break;
621 				case 10:
622 					if (lfoFlags & LFOFlags.ringmod)
623 						lfoFreq = noteToFreq((1.0 / uint.max) * val * 127);
624 					else
625 						lfoFreq = (1.0 / uint.max) * val * 20;
626 					resetLFO();
627 					break;
628 				case 11:
629 					lfoPWM = (1.0 / uint.max) * val;
630 					resetLFO();
631 					break;
632 				case 102:
633 					if (val)
634 						lfoFlags |= LFOFlags.saw;
635 					else
636 						lfoFlags &= ~LFOFlags.saw;
637 					resetLFO();
638 					break;
639 				case 103:
640 					if (val)
641 						lfoFlags |= LFOFlags.triangle;
642 					else
643 						lfoFlags &= ~LFOFlags.triangle;
644 					resetLFO();
645 					break;
646 				case 104:
647 					if (val)
648 						lfoFlags |= LFOFlags.pulse;
649 					else
650 						lfoFlags &= ~LFOFlags.pulse;
651 					resetLFO();
652 					break;
653 				case 105:
654 					if (val)
655 						lfoFlags |= LFOFlags.sawpulse;
656 					else
657 						lfoFlags &= ~LFOFlags.sawpulse;
658 					resetLFO();
659 					break;
660 				case 106:
661 					if (val)
662 						lfoFlags |= LFOFlags.invert;
663 					else
664 						lfoFlags &= ~LFOFlags.invert;
665 					resetLFO();
666 					break;
667 				case 107:
668 					if (val)
669 						lfoFlags |= LFOFlags.ringmod;
670 					else
671 						lfoFlags &= ~LFOFlags.ringmod;
672 					resetLFO();
673 					break;
674 				default:
675 					break;
676 			}
677 		}
678 	}
679 	protected void sysExCmd(ubyte[] msg) @nogc nothrow {
680 		//Check manufacturer ID (7D: internal use)
681 		if (msg[0] == 0x7D || msg[1] == 0x7D) {
682 			const int msgPos = msg[0] ? 1 : 2;
683 			switch (msg[msgPos]) {
684 				case 0x01:	//Suspend channel
685 					if (msg[msgPos + 1] >= 8) return;
686 					if (!(channels[msg[msgPos + 1]].status & ChannelStatusFlags.sampleRunout)) {
687 						channels[msg[msgPos + 1]].currNote |= 0x80;
688 					}
689 					break;
690 				case 0x02:	//Resume channel
691 					if (msg[msgPos + 1] >= 8) return;
692 					if (!(channels[msg[msgPos + 1]].status & ChannelStatusFlags.sampleRunout)) {
693 						channels[msg[msgPos + 1]].currNote &= 0x7F;
694 					}
695 					break;
696 				case 0x03:	//Overwrite preset
697 					if (msg[msgPos + 1] >= 8) return;
698 					if (msg.length == msgPos + 5) {
699 						channels[msg[msgPos + 1]].presetNum = msg[msgPos + 2];
700 						channels[msg[msgPos + 1]].bankNum = (msg[msgPos + 3]>>1) | msg[msgPos + 4];
701 					}
702 					*(presetBank.ptrOf((channels[msg[msgPos + 1]].bankNum<<7) | channels[msg[msgPos + 1]].presetNum)) = 
703 							channels[msg[msgPos + 1]].presetCopy;
704 					break;
705 				case 0x20:	//Jump to sample position by restoring codec data
706 					if (msg[msgPos + 1] >= 8) return;
707 					channels[msg[msgPos + 1]].decoderWorkpad.pos = (msg[msgPos + 2] << 21) | (msg[msgPos + 3] << 14) | 
708 						(msg[msgPos + 4] << 7) | msg[msgPos + 5];
709 					channels[msg[msgPos + 1]].waveModWorkpad.lookupVal = 0;
710 					if (msg.length == msgPos + 10) {
711 						channels[msg[msgPos + 1]].decoderWorkpad.pred = msg[msgPos + 6];
712 						channels[msg[msgPos + 1]].decoderWorkpad.outn1 = (msg[msgPos + 7]<<30) | (msg[msgPos + 8]<<23) | 
713 								(msg[msgPos + 9]<<16);
714 						channels[msg[msgPos + 1]].decoderWorkpad.outn1>>=16;
715 					}
716 					//decode the sample
717 					if (channels[msg[msgPos + 1]].currNote & 128) return;
718 					//get the data for the sample
719 					SampleAssignment sa = channels[msg[msgPos + 1]].presetCopy.sampleMapping[channels[msg[msgPos + 1]].currNote];
720 					Sample slmp = sampleBank[sa.sampleNum];
721 					channels[msg[msgPos + 1]].decodeMore(sa, slmp);
722 					break;
723 				case 0x21:	//Dump codec data
724 					if (msg[msgPos + 1] >= 8) return;
725 					uint[2] dump;
726 					const int delta = channels[msg[msgPos + 1]].decoderWorkpad.outn1;
727 					dump[0] = cast(uint)channels[msg[msgPos + 1]].decoderWorkpad.pos;
728 					dump[0] = ((dump[0] & 0xF_E0_00_00)<<3) | ((dump[0] & 0x1F_C0_00)<<2) | ((dump[0] & 0x3F_80)<<1) | 
729 							(dump[0] & 0x7F);
730 					dump[1] = channels[msg[msgPos + 1]].decoderWorkpad.pred<<24;
731 					dump[1] |= ((delta & 0xC0_00)<<2) | ((delta & 0x3F_80)<<1) | (delta & 0x7F);
732 					if (midiOut !is null) midiOut(UMP(MessageType.Data128, 0x0, SysExSt.Complete, 9, 0x0, 0x7D), dump[0], 
733 							dump[1]);
734 					break;
735 				case 0xA0:	//Jump to sample position by restoring codec data (8bit)
736 					if (msg[msgPos + 1] >= 8) return;
737 					channels[msg[msgPos + 1]].decoderWorkpad.pos = (msg[msgPos + 2] << 24) | (msg[msgPos + 3] << 16) | 
738 						(msg[msgPos + 4] << 8) | msg[msgPos + 5];
739 					channels[msg[msgPos + 1]].waveModWorkpad.lookupVal = 0;
740 					if (msg.length == msgPos + 9) {
741 						channels[msg[msgPos + 1]].decoderWorkpad.pred = msg[msgPos + 6];
742 						channels[msg[msgPos + 1]].decoderWorkpad.outn1 = (msg[msgPos + 7]<<24) | (msg[msgPos + 8]<<16);
743 						channels[msg[msgPos + 1]].decoderWorkpad.outn1>>=16;
744 					}
745 					//decode the sample
746 					if (channels[msg[msgPos + 1]].currNote & 128) return;
747 					//get the data for the sample
748 					SampleAssignment sa = channels[msg[msgPos + 1]].presetCopy.sampleMapping[channels[msg[msgPos + 1]].currNote];
749 					Sample slmp = sampleBank[sa.sampleNum];
750 					channels[msg[msgPos + 1]].decodeMore(sa, slmp);
751 					break;
752 				case 0xA1:	//Dump codec data (8bit)
753 					if (msg[msgPos + 1] >= 8) return;
754 					uint[2] dump;
755 					dump[0] = cast(uint)channels[msg[msgPos + 1]].decoderWorkpad.pos;
756 					dump[1] = channels[msg[msgPos + 1]].decoderWorkpad.pred<<24;
757 					dump[1] |= (channels[msg[msgPos + 1]].decoderWorkpad.outn1 & ushort.max)<<8;
758 					if (midiOut !is null) midiOut(UMP(MessageType.Data128, 0x0, SysExSt.Complete, 8, 0x0, 0x7D), dump[0], 
759 							dump[1]);
760 					break;
761 				default:
762 					break;
763 			}
764 		}
765 	}
766 	protected void resetLFO() @nogc @safe pure nothrow {
767 		const int divident = ((lfoFlags>>3) & 1) + ((lfoFlags>>2) & 1) + ((lfoFlags>>1) & 1) + (lfoFlags & 1);
768 		const short value = cast(short)(short.max / divident * (lfoFlags & LFOFlags.invert ? -1 : 1));
769 		if (lfoFlags & LFOFlags.pulse)
770 			lfo.pulseAm = value;
771 		if (lfoFlags & LFOFlags.saw)
772 			lfo.sawAm = value;
773 		if (lfoFlags & LFOFlags.sawpulse)
774 			lfo.sawPulseAm = value;
775 		if (lfoFlags & LFOFlags.triangle)
776 			lfo.triAm = value;
777 		lfo.pulseWidth = cast(uint)(lfoPWM * uint.max);
778 		lfo.setRate(sampleRate, lfoFreq);
779 	}
780 	protected void presetRecall(ubyte ch) @nogc pure nothrow {
781 		channels[ch].presetCopy = presetBank[channels[ch].presetNum | (channels[ch].bankNum<<7)];
782 	}
783 	/** 
784 	 * Creates a decoder function.
785 	 * Params:
786 	 *   fmt = the format of the sample.
787 	 * Returns: The decoder function, or null if format not supported.
788 	 */
789 	protected DecodeFunc getDecoderFunction(WaveFormat fmt) @nogc pure nothrow {
790 		switch (fmt.format) {		//Hope this branching won't impact performance too much
791 			case AudioFormat.PCM:
792 				if (fmt.bitsPerSample == 8)
793 					return (ubyte[] src, int[] dest, ref DecoderWorkpad wp) {decode8bitPCM(cast(const(ubyte)[])src, dest, wp);};
794 				else if (fmt.bitsPerSample == 16)
795 					return (ubyte[] src, int[] dest, ref DecoderWorkpad wp) {decode16bitPCM(cast(const(short)[])src, dest, wp);};
796 				return null;
797 			case AudioFormat.ADPCM, AudioFormat.IMA_ADPCM:
798 				return (ubyte[] src, int[] dest, ref DecoderWorkpad wp) 
799 						{decode4bitIMAADPCM(ADPCMStream(src, src.length*2), dest, wp);};
800 				
801 			case AudioFormat.DIALOGIC_OKI_ADPCM, AudioFormat.OKI_ADPCM:
802 				return (ubyte[] src, int[] dest, ref DecoderWorkpad wp) 
803 						{decode4bitDialogicADPCM(ADPCMStream(src, src.length*2), dest, wp);};
804 				
805 			case AudioFormat.MULAW:
806 				return (ubyte[] src, int[] dest, ref DecoderWorkpad wp) {decodeMuLawStream(cast(const(ubyte)[])src, dest, wp);};
807 				
808 			case AudioFormat.ALAW:
809 				return (ubyte[] src, int[] dest, ref DecoderWorkpad wp) {decodeALawStream(cast(const(ubyte)[])src, dest, wp);};
810 				
811 			default:
812 				return null;
813 		}
814 	}
815 	/**
816 	 * Renders the current audio frame.
817 	 * 
818 	 * input: the input buffers if any, null if none.
819 	 * output: the output buffers if any, null if none.
820 	 *
821 	 * NOTE: Buffers must have matching sizes.
822 	 */
823 	public override void renderFrame(float*[] input, float*[] output) @nogc nothrow {
824 		for (int i ; i < bufferSize ; i++) {
825 			lfoOut[i] = lfo.outputF(0.5, 1.0 / ushort.max);
826 		}
827 		for (int i ; i < 8 ; i++) {
828 			if (!(channels[i].currNote & 128) && channels[i].jumpAm) {
829 				channels[i].calculateJumpAm(sampleRate, lfoOut[0]);
830 				//get the data for the sample
831 				SampleAssignment sa = channels[i].presetCopy.sampleMapping[channels[i].currNote];	//get sample assignment data
832 				Sample slmp = sampleBank[sa.sampleNum];		//get sample
833 				if (!slmp.sampleData.length) continue;		//break if no sample found
834 				size_t samplesNeeded = bufferSize;			//determine the amount of needed samples for this frame, initially it's equals with the frame buffer size
835 				size_t outpos;								//position in output buffer
836 				while (samplesNeeded && !(channels[i].currNote & 128)) {
837 					//Calculate the amount of samples that are needed for this block
838 					ulong samplesToAdvance = channels[i].jumpAm * samplesNeeded;
839 					//Determine if there's enough decoded samples in the output buffer.
840 					//If not, decode more.
841 					if ((channels[i].outPos + samplesToAdvance) > (channels[i].samplesHave))
842 						channels[i].decodeMore(sa, slmp);
843 					//Get the amount of unused samples in the decoder buffer with fractions
844 					const ulong decoderBufPos = channels[i].samplesHave - channels[i].outPos;
845 					//Determine if there's enough decoded samples, if not then reduce the amount of samplesToAdvance
846 					if ((128<<24L) - decoderBufPos < samplesToAdvance){
847 						samplesToAdvance = (128<<24L) - decoderBufPos;
848 					}
849 					debug assert(samplesToAdvance, "Lockup event in PCM8!");	//Test for lockups, crash thread if anything goes wrong
850 					//Calculate how many samples will be outputted
851 					const size_t samplesOutputted = cast(size_t)(samplesToAdvance / channels[i].jumpAm);
852 					stretchAudioNoIterpol(channels[i].decoderBuffer, iBuf[outpos..outpos + samplesOutputted], 
853 							channels[i].waveModWorkpad, channels[i].jumpAm);		//Output the audio to the intermediary buffer
854 					samplesNeeded -= samplesOutputted;		//substract the number of outputted samples from the needed samples
855 					channels[i].outPos += samplesToAdvance;	//add the samples needed to advance to the output position
856 					outpos += samplesOutputted;				//shift the output position by the amount of the outputted samples
857 				}
858 				//apply envelop (if needed) and volume, then mix it to the local buffer
859 				__m128 levels;
860 				levels[0] = channels[i].presetCopy.masterVol * channels[i].presetCopy.balance;
861 				levels[1] = channels[i].presetCopy.masterVol * (1 - channels[i].presetCopy.balance);
862 				levels[2] = channels[i].presetCopy.auxSendA;
863 				levels[3] = channels[i].presetCopy.auxSendB;
864 				for (int j ; j < bufferSize ; j++) {
865 					__m128 sample = _mm_cvtepi32_ps(__m128i(iBuf[j]));
866 					const float adsrEnv = channels[i].envGen.shp(channels[i].envGen.position == ADSREnvelopGenerator.Stage.Attack ? 
867 							channels[i].currShpA : channels[i].currShpR) * channels[i].presetCopy.adsrToVol;
868 					channels[i].envGen.advance();
869 					sample *= __m128((1 - channels[i].presetCopy.adsrToVol) + adsrEnv) * __m128((1 - channels[i].presetCopy.lfoToVol) + 
870 							(lfoOut[j] * channels[i].presetCopy.lfoToVol)) * levels;
871 					lBuf[j] += sample;
872 				}
873 				resetBuffer(iBuf);
874 			}
875 		}
876 		float*[4] outBuf;
877 		for (ubyte i, j ; i < 4 ; i++) {
878 			if (enabledOutputs.has(i)) {
879 				outBuf[i] = output[j];
880 				j++;
881 			} else {
882 				outBuf[i] = dummyBuf.ptr;
883 			}
884 		}
885 		//apply filtering and mix to destination
886 		const __m128 b0_a0 = filterVals[3] / filterVals[0], b1_a0 = filterVals[4] / filterVals[0], 
887 				b2_a0 = filterVals[5] / filterVals[0], a1_a0 = filterVals[1] / filterVals[0], a2_a0 = filterVals[2] / filterVals[0];
888 		for (int i ; i < bufferSize ; i++) {
889 			__m128 input0 = lBuf[i];
890 			input0 /= __m128(mixdownVal);
891 			input0 = _mm_max_ps(input0, __m128(-1.0));
892 			input0 = _mm_min_ps(input0, __m128(1.0));
893 			__m128 output0 = b0_a0 * input0 + b1_a0 * filterVals[6] + b2_a0 * filterVals[7] - a1_a0 * filterVals[8] - 
894 					a2_a0 * filterVals[9];
895 			for (int j ; j < 4 ; j++)
896 				outBuf[j][i] += output0[j];
897 			filterVals[7] = filterVals[6];
898 			filterVals[6] = input0;
899 			filterVals[9] = filterVals[8];
900 			filterVals[8] = output0;
901 		}
902 		resetBuffer(lBuf);
903 	}
904 	/**
905 	 * Receives waveform data that has been loaded from disk for reading. Returns zero if successful, or a specific 
906 	 * errorcode.
907 	 *
908 	 * id: The ID of the waveform.
909 	 * rawData: The data itself, in unprocessed form.
910 	 * format: The format of the wave data, including the data type, bit depth, base sampling rate
911 	 */
912 	public override int waveformDataReceive(uint id, ubyte[] rawData, WaveFormat format) nothrow {
913 		int result;
914 		if (!(format.format == AudioFormat.PCM || format.format == AudioFormat.MULAW || format.format == AudioFormat.ALAW || 
915 				format.format == AudioFormat.ADPCM || format.format == AudioFormat.IMA_ADPCM || 
916 				format.format == AudioFormat.DIALOGIC_OKI_ADPCM || format.format == AudioFormat.OKI_ADPCM)) 
917 			result |= SampleLoadErrorCode.FormatNotSupported; 
918 		result |= format.channels == 1 ? 0 : SampleLoadErrorCode.ChNumNotSupported;
919 		if (result) {
920 			return result; 
921 		} else {
922 			sampleBank[id] = Sample(rawData, format, getDecoderFunction(format));
923 			return 0;
924 		}
925 	}
926 	/** 
927 	 * Creates a new waveform from an existing one using slicing.
928 	 * Params:
929 	 *   id = The ID of the new sample.
930 	 *   src = The ID of the original sample.
931 	 *   pos = The position where the slice begins.
932 	 *   length = The length of the slice.
933 	 * Returns: 0 on success, -1 if module don't support this feature, -2 if slice is out of bounds (longer than the
934 	 * sample, etc.), -3 if sample is not slicable (ADPCM, etc.).
935 	 */
936 	public override int waveformSlice(uint id, uint src, uint pos, uint length) nothrow {
937 		Sample srcSlmp = sampleBank[src];
938 		switch (srcSlmp.format.format) {
939 			case AudioFormat.UNKNOWN:
940 				return -4;
941 			case AudioFormat.ADPCM, AudioFormat.IMA_ADPCM, AudioFormat.OKI_ADPCM, AudioFormat.DIALOGIC_OKI_ADPCM:
942 				return -3;
943 			default:
944 				break;
945 		}
946 		const size_t samplelen = srcSlmp.samplesLength();
947 		if (pos > samplelen || pos + length > samplelen) {
948 			return -2;
949 		}
950 		const size_t begin = (pos * 8) / srcSlmp.format.bitsPerSample, 
951 				end = ((pos + length) * 8) / srcSlmp.format.bitsPerSample;
952 		sampleBank[id] = Sample(srcSlmp.sampleData[begin..end], srcSlmp.format, srcSlmp.decode);
953 		return 0;
954 	}
955 	/** 
956 	 * Returns the waveform data from the
957 	 * Params:
958 	 *   id = The ID of the waveform.
959 	 * Returns: The raw waveform data, or null on error (unsupported feature, waveform not found, etc.)
960 	 */
961 	public override const(ubyte)[] getWaveformData(uint id) nothrow {
962 		return cast(const(ubyte)[])sampleBank[id].sampleData;
963 	}
964 	/** 
965 	 * Returns the format of the selected waveform
966 	 * Params:
967 	 *   id = The ID of the waveform.
968 	 * Returns: The format of the waveform data, or WaveFormat.init if not available.
969 	 */
970 	public override WaveFormat getWaveformDataFormat(uint id) nothrow {
971 		return sampleBank[id].format;
972 	}
973 	///Returns the available waveform ID list
974 	public override uint[] getWaveformIDList() nothrow {
975 		uint[] result;
976 		foreach (uint key, Sample elem; sampleBank) {
977 			result ~= key;
978 		}
979 		return result;
980 	}
981 	/**
982 	 * Restores a parameter to the given preset.
983 	 * Returns an errorcode on failure.
984 	 */
985 	public override int writeParam_int(uint presetID, uint paramID, int value) nothrow {
986 		Preset* presetPtr = presetBank.ptrOf(presetID);
987 		if (presetPtr is null) {
988 			presetBank[presetID] = Preset.init;
989 			presetPtr = presetBank.ptrOf(presetID);
990 		}
991 		if (paramID & 0x10_00) {
992 			switch (paramID & 0x0F_00) {
993 				case 0x00_00:
994 					presetPtr.sampleMapping[paramID & 0x7F].sampleNum = value;
995 					return 0;
996 				case 0x02_00:
997 					presetPtr.sampleMapping[paramID & 0x7F].loopBegin = value;
998 					return 0;
999 				case 0x03_00:
1000 					presetPtr.sampleMapping[paramID & 0x7F].loopEnd = value;
1001 					return 0;
1002 				default:
1003 					break;
1004 			}
1005 		} else if (paramID & 0x80_00) {
1006 			switch (paramID) {
1007 				case 0x80_09:
1008 					if (value)
1009 						lfoFlags |= LFOFlags.saw;
1010 					else
1011 						lfoFlags &= ~LFOFlags.saw;
1012 					resetLFO();
1013 					return 0;
1014 				case 0x80_0a:
1015 					if (value)
1016 						lfoFlags |= LFOFlags.triangle;
1017 					else
1018 						lfoFlags &= ~LFOFlags.triangle;
1019 					resetLFO();
1020 					return 0;
1021 				case 0x80_0b:
1022 					if (value)
1023 						lfoFlags |= LFOFlags.pulse;
1024 					else
1025 						lfoFlags &= ~LFOFlags.pulse;
1026 					resetLFO();
1027 					return 0;
1028 				case 0x80_0c:
1029 					if (value)
1030 						lfoFlags |= LFOFlags.sawpulse;
1031 					else
1032 						lfoFlags &= ~LFOFlags.sawpulse;
1033 					resetLFO();
1034 					return 0;
1035 				case 0x80_0d:
1036 					if (value)
1037 						lfoFlags |= LFOFlags.invert;
1038 					else
1039 						lfoFlags &= ~LFOFlags.invert;
1040 					resetLFO();
1041 					return 0;
1042 				case 0x80_0f:
1043 					if (value)
1044 						lfoFlags |= LFOFlags.ringmod;
1045 					else
1046 						lfoFlags &= ~LFOFlags.ringmod;
1047 					resetLFO();
1048 					return 0;
1049 				default:
1050 					break;
1051 			}
1052 		} else {
1053 			switch (paramID) {
1054 				case 0x00:
1055 					presetPtr.eAtk = cast(ubyte)(value & 0x7F);
1056 					return 0;
1057 				case 0x01:
1058 					presetPtr.eDec = cast(ubyte)(value & 0x7F);
1059 					return 0;
1060 				case 0x02:
1061 					presetPtr.eSusC = cast(ubyte)(value & 0x7F);
1062 					return 0;
1063 				case 0x03:
1064 					presetPtr.eRel = cast(ubyte)(value & 0x7F);
1065 					return 0;
1066 				case 0x10:
1067 					presetPtr.flags = value;
1068 					return 0;
1069 				case 0x00_11:
1070 					if (value)
1071 						presetPtr.flags |= PresetFlags.cutoffOnKeyOff;
1072 					else
1073 						presetPtr.flags &= ~PresetFlags.cutoffOnKeyOff;
1074 					return 0;
1075 				case 0x00_12:
1076 					if (value)
1077 						presetPtr.flags |= PresetFlags.modwheelToLFO;
1078 					else
1079 						presetPtr.flags &= ~PresetFlags.modwheelToLFO;
1080 					return 0;
1081 				case 0x00_13:
1082 					if (value)
1083 						presetPtr.flags |= PresetFlags.panningLFO;
1084 					else
1085 						presetPtr.flags &= ~PresetFlags.panningLFO;
1086 					return 0;
1087 				/* case 0x00_14:
1088 					if (value)
1089 						presetPtr.flags |= PresetFlags.ADSRtoVol;
1090 					else
1091 						presetPtr.flags &= ~PresetFlags.ADSRtoVol;
1092 					return 0; */
1093 				default:
1094 					break;
1095 			}
1096 		}
1097 		return 1;
1098 	}
1099 	/**
1100 	 * Restores a parameter to the given preset.
1101 	 * Returns an errorcode on failure.
1102 	 */
1103 	public override int writeParam_long(uint presetID, uint paramID, long value) nothrow {
1104 		return 0;
1105 	}
1106 	/**
1107 	 * Restores a parameter to the given preset.
1108 	 * Returns an errorcode on failure.
1109 	 */
1110 	public override int writeParam_double(uint presetID, uint paramID, double value) nothrow {
1111 		Preset* presetPtr = presetBank.ptrOf(presetID);
1112 		if (presetPtr is null) {
1113 			presetBank[presetID] = Preset.init;
1114 			presetPtr = presetBank.ptrOf(presetID);
1115 		}
1116 		if (paramID & 0x10_00) {
1117 			switch (paramID & 0x0F_00) {
1118 				case 0x01_00:
1119 					presetPtr.sampleMapping[paramID & 0x7F].baseFreq = value;
1120 					return 0;
1121 				default:
1122 					break;
1123 			}
1124 		} else if (paramID & 0x80_00) {
1125 			switch (paramID) {
1126 				case 0x80_00: 
1127 					filterCtrl[0] = value; 
1128 					resetLPF(0); 
1129 					return 0;
1130 				case 0x80_01: 
1131 					filterCtrl[1] = value; 
1132 					resetLPF(0); 
1133 					return 0;
1134 				case 0x80_02: 
1135 					filterCtrl[2] = value; 
1136 					resetLPF(1); 
1137 					return 0;
1138 				case 0x80_03: 
1139 					filterCtrl[3] = value; 
1140 					resetLPF(1); 
1141 					return 0;
1142 				case 0x80_04: 
1143 					filterCtrl[4] = value; 
1144 					resetLPF(2); 
1145 					return 0;
1146 				case 0x80_05: 
1147 					filterCtrl[5] = value; 
1148 					resetLPF(2); 
1149 					return 0;
1150 				case 0x80_06: 
1151 					filterCtrl[6] = value; 
1152 					resetLPF(3); 
1153 					return 0;
1154 				case 0x80_07: 
1155 					filterCtrl[7] = value; 
1156 					resetLPF(3); 
1157 					return 0;
1158 				case 0x80_08: 
1159 					lfoFreq = value;
1160 					resetLFO();
1161 					return 0;
1162 				case 0x80_0e: 
1163 					lfoPWM = value;
1164 					resetLFO();
1165 					return 0;
1166 				default:
1167 					break;
1168 			}
1169 		} else {
1170 			switch (paramID) {
1171 				case 0x00_14:
1172 					presetPtr.adsrToDetune = value;
1173 					return 0;
1174 				case 0x00_15:
1175 					presetPtr.vibrAm = value;
1176 					return 0;
1177 				case 0x00_20:
1178 					presetPtr.pitchBendAm = value;
1179 					return 0;
1180 				default: break;
1181 			}
1182 			if (value < 0 || value > 1) return 2;
1183 			switch (paramID) {
1184 				case 0x00_04:
1185 					presetPtr.eAtkShp = value;
1186 					return 0;
1187 				case 0x00_05:
1188 					presetPtr.eRelShp = value;
1189 					return 0;
1190 				case 0x00_06:
1191 					presetPtr.eSusLev = value;
1192 					return 0;
1193 				case 0x00_07:
1194 					presetPtr.masterVol = value;
1195 					return 0;
1196 				case 0x00_08:
1197 					presetPtr.balance = value;
1198 					return 0;
1199 				case 0x00_09:
1200 					presetPtr.auxSendA = value;
1201 					return 0;
1202 				case 0x00_0A:
1203 					presetPtr.auxSendB = value;
1204 					return 0;
1205 				case 0x00_0B:
1206 					presetPtr.velToLevelAm = value;
1207 					return 0;
1208 				case 0x00_0C:
1209 					presetPtr.velToAuxSendAm = value;
1210 					return 0;
1211 				case 0x00_0D:
1212 					presetPtr.velToAtkShp = value;
1213 					return 0;
1214 				case 0x00_0E:
1215 					presetPtr.velToRelShp = value;
1216 					return 0;
1217 				case 0x00_0F:
1218 					presetPtr.adsrToVol = value;
1219 					return 0;
1220 				
1221 				default:
1222 					break;
1223 			}
1224 		}
1225 		return 1;
1226 	}
1227 	/**
1228 	 * Restores a parameter to the given preset.
1229 	 * Returns an errorcode on failure.
1230 	 */
1231 	public override int writeParam_string(uint presetID, uint paramID, string value) nothrow {
1232 		return 0;
1233 	}
1234 	/** 
1235 	 * Returns all the possible parameters this module has.
1236 	 */
1237 	public override MValue[] getParameters() nothrow {
1238 		return [
1239 			MValue(MValueType.Int32, 0x00_00, "envGenAtk"), MValue(MValueType.Int32, 0x00_01, "envGenDec"),
1240 			MValue(MValueType.Int32, 0x00_02, "envGenSusC"), MValue(MValueType.Int32, 0x00_03, "envGenRel"),
1241 			MValue(MValueType.Float, 0x00_04, "envGenAtkShp"), MValue(MValueType.Float, 0x00_05, "envGenDecShp"),
1242 			MValue(MValueType.Float, 0x00_06, "envGenSusLevel"), MValue(MValueType.Float, 0x00_07, "masterVol"),
1243 			MValue(MValueType.Float, 0x00_08, "balance"), MValue(MValueType.Float, 0x00_09, "auxSendA"),
1244 			MValue(MValueType.Float, 0x00_0A, "auxSendB"), MValue(MValueType.Float, 0x00_0B, "velToLevelAm"),
1245 			MValue(MValueType.Float, 0x00_0C, "velToAuxSendAm"), MValue(MValueType.Float, 0x00_0D, "velToAtkShp"),
1246 			MValue(MValueType.Float, 0x00_0E, "velToRelShp"), MValue(MValueType.Float, 0x00_0F, "adsrToVol"),
1247 			MValue(MValueType.Float, 0x00_14, "adsrToDetune"), MValue(MValueType.Float, 0x00_15, "vibrAm"),
1248 			MValue(MValueType.Int32, 0x00_10, "flags"),
1249 			MValue(MValueType.Boolean, 0x00_11, "f_cutoffOnKeyOff"),
1250 			MValue(MValueType.Boolean, 0x00_12, "f_modwheelToLFO"),
1251 			MValue(MValueType.Boolean, 0x00_13, "f_panningLFO"),
1252 			MValue(MValueType.Float, 0x00_20, "pitchBendRange"),
1253 			/* MValue(MValueType.Boolean, 0x00_13, "f_ADSRtoVol"), */
1254 		] ~ SAMPLE_SET_VALS.dup ~ [
1255 			MValue(MValueType.Float, 0x80_00, `_FilterLCFreq`), MValue(MValueType.Float, 0x80_01, `_FilterLCQ`),
1256 			MValue(MValueType.Float, 0x80_02, `_FilterRCFreq`), MValue(MValueType.Float, 0x80_03, `_FilterRCQ`),
1257 			MValue(MValueType.Float, 0x80_04, `_FilterACFreq`), MValue(MValueType.Float, 0x80_05, `_FilterACQ`),
1258 			MValue(MValueType.Float, 0x80_06, `_FilterBCFreq`), MValue(MValueType.Float, 0x80_07, `_FilterBCQ`),
1259 			MValue(MValueType.Float, 0x80_08, "_LFOFreq"), MValue(MValueType.Boolean, 0x80_09, "_LFOSaw"),
1260 			MValue(MValueType.Boolean, 0x80_0a, "_LFOTri"), MValue(MValueType.Boolean, 0x80_0b, "_LFOPul"), 
1261 			MValue(MValueType.Boolean, 0x80_0c, "_LFOSawPul"), MValue(MValueType.Boolean, 0x80_0d, "_LFOInv"),
1262 			MValue(MValueType.Float, 0x80_0e, "_LFOPWM"), MValue(MValueType.Boolean, 0x80_0f, "_LFORingmod")
1263 		];
1264 	}
1265 	/** 
1266 	 * Reads the given value (int).
1267 	 * Params:
1268 	 *   presetID = The preset ID, or uint.max for global module values.
1269 	 *   paramID = The parameter ID.
1270 	 * Returns: The value of the given preset and parameter
1271 	 */
1272 	public override int readParam_int(uint presetID, uint paramID) nothrow {
1273 		Preset* presetPtr = presetBank.ptrOf(presetID);
1274 		if (presetPtr is null) return 0;
1275 		if (paramID & 0x10_00) {
1276 			switch (paramID & 0x0F_00) {
1277 				case 0x00_00:
1278 					return presetPtr.sampleMapping[paramID & 0x7F].sampleNum;
1279 				case 0x02_00:
1280 					return presetPtr.sampleMapping[paramID & 0x7F].loopBegin;
1281 				case 0x03_00:
1282 					return presetPtr.sampleMapping[paramID & 0x7F].loopEnd;
1283 				default:
1284 					break;
1285 			}
1286 		} else if (paramID & 0x80_00) {
1287 			switch (paramID) {
1288 				case 0x80_09:
1289 					return lfoFlags & LFOFlags.saw ? 1 : 0;
1290 				case 0x80_0a:
1291 					return lfoFlags & LFOFlags.triangle ? 1 : 0;
1292 				case 0x80_0b:
1293 					return lfoFlags & LFOFlags.pulse ? 1 : 0;
1294 				case 0x80_0c:
1295 					return lfoFlags & LFOFlags.sawpulse ? 1 : 0;
1296 				case 0x80_0d:
1297 					return lfoFlags & LFOFlags.invert ? 1 : 0;
1298 				case 0x80_0f:
1299 					return lfoFlags & LFOFlags.ringmod ? 1 : 0;
1300 				default:
1301 					break;
1302 			}
1303 		} else {
1304 			switch (paramID) {
1305 				case 0x00:
1306 					return presetPtr.eAtk;
1307 				case 0x01:
1308 					return presetPtr.eDec;
1309 				case 0x02:
1310 					return presetPtr.eSusC;
1311 				case 0x03:
1312 					return presetPtr.eRel;
1313 				case 0x10:
1314 					return presetPtr.flags;
1315 				case 0x00_11:
1316 					return presetPtr.flags & PresetFlags.cutoffOnKeyOff ? 1 : 0;
1317 				case 0x00_12:
1318 					return presetPtr.flags & PresetFlags.modwheelToLFO ? 1 : 0;
1319 				case 0x00_13:
1320 					return presetPtr.flags & PresetFlags.panningLFO ? 1 : 0;
1321 				/* case 0x00_14:
1322 					return presetPtr.flags |= PresetFlags.ADSRtoVol ? 1 : 0; */
1323 				default:
1324 					break;
1325 			}
1326 		}
1327 		return 0;
1328 	}
1329 	/** 
1330 	 * Reads the given value (int).
1331 	 * Params:
1332 	 *   presetID = The preset ID, or uint.max for global module values.
1333 	 *   paramID = The parameter ID.
1334 	 * Returns: The value of the given preset and parameter
1335 	 */
1336 	public override long readParam_long(uint presetID, uint paramID) nothrow {
1337 		return 0;
1338 	}
1339 	/** 
1340 	 * Reads the given value (int).
1341 	 * Params:
1342 	 *   presetID = The preset ID, or uint.max for global module values.
1343 	 *   paramID = The parameter ID.
1344 	 * Returns: The value of the given preset and parameter
1345 	 */
1346 	public override double readParam_double(uint presetID, uint paramID) nothrow {
1347 		Preset* presetPtr = presetBank.ptrOf(presetID);
1348 		if (presetPtr is null) return double.nan;
1349 		if (paramID & 0x10_00) {
1350 			switch (paramID & 0x0F_00) {
1351 				case 0x01_00:
1352 					return presetPtr.sampleMapping[paramID & 0x7F].baseFreq;
1353 				default:
1354 					break;
1355 			}
1356 		} else if (paramID & 0x80_00) {
1357 			switch (paramID) {
1358 				case 0x80_00: 
1359 					return filterCtrl[0];
1360 				case 0x80_01: 
1361 					return filterCtrl[1];
1362 				case 0x80_02: 
1363 					return filterCtrl[2];
1364 				case 0x80_03: 
1365 					return filterCtrl[3];
1366 				case 0x80_04: 
1367 					return filterCtrl[4];
1368 				case 0x80_05: 
1369 					return filterCtrl[5];
1370 				case 0x80_06: 
1371 					return filterCtrl[6];
1372 				case 0x80_07: 
1373 					return filterCtrl[7];
1374 				case 0x80_08: 
1375 					return lfoFreq;
1376 				case 0x80_0e: 
1377 					return lfoPWM;
1378 				default:
1379 					break;
1380 			}
1381 		} else {
1382 			switch (paramID) {
1383 				case 0x00_04:
1384 					return presetPtr.eAtkShp;
1385 				case 0x00_05:
1386 					return presetPtr.eRelShp;
1387 				case 0x00_06:
1388 					return presetPtr.eSusLev;
1389 				case 0x00_07:
1390 					return presetPtr.masterVol;
1391 				case 0x00_08:
1392 					return presetPtr.balance;
1393 				case 0x00_09:
1394 					return presetPtr.auxSendA;
1395 				case 0x00_0A:
1396 					return presetPtr.auxSendB;
1397 				case 0x00_0B:
1398 					return presetPtr.velToLevelAm;
1399 				case 0x00_0C:
1400 					return presetPtr.velToAuxSendAm;
1401 				case 0x00_0D:
1402 					return presetPtr.velToAtkShp;
1403 				case 0x00_0E:
1404 					return presetPtr.velToRelShp;
1405 				case 0x00_0F:
1406 					return presetPtr.adsrToVol;
1407 				case 0x00_14:
1408 					return presetPtr.adsrToDetune;
1409 				case 0x00_15:
1410 					return presetPtr.vibrAm;
1411 				case 0x0020:
1412 					return presetPtr.pitchBendAm;
1413 				default:
1414 					break;
1415 			}
1416 		}
1417 		return double.nan;
1418 	}
1419 	/** 
1420 	 * Reads the given value (int).
1421 	 * Params:
1422 	 *   presetID = The preset ID, or uint.max for global module values.
1423 	 *   paramID = The parameter ID.
1424 	 * Returns: The value of the given preset and parameter
1425 	 */
1426 	public override string readParam_string(uint presetID, uint paramID) nothrow {
1427 		return null;
1428 	}
1429 }