1 module pixelperfectengine.audio.base.func;
2 
3 /*
4  * Copyright (C) 2015-2021, by Laszlo Szeremi under the Boost license.
5  *
6  * Pixel Perfect Engine, audio.base.func module.
7  *
8  * Contains common audio functions for mixing, codecs, etc.
9  */
10 
11 import inteli.emmintrin;
12 import bitleveld.reinterpret;
13 import bitleveld.datatypes;
14 
15 import std.math;
16 
17 
18 public import pixelperfectengine.audio.base.types;
19 import pixelperfectengine.system.etc;
20 
21 ///Constant for fast integer to floating point conversion
22 package immutable __m128 CONV_RATIO_RECIPROCAL = __m128(-1.0 / ushort.min);
23 ///For IMA ADPCM
24 ///Needs less storage at the cost of worse quality
25 package static immutable byte[4] ADPCM_INDEX_TABLE_2BIT = 
26 			[-1, 2,
27 			 -1, 2];
28 ///For IMA ADPCM
29 ///Needs less storage at the cost of worse quality
30 package static immutable byte[8] ADPCM_INDEX_TABLE_3BIT = 
31 			[-1, -1, 2, 4,
32 			 -1, -1, 2, 4,];
33 ///For IMA and Dialogic ADPCM
34 ///Standard quality and size
35 package static immutable byte[16] ADPCM_INDEX_TABLE_4BIT = 
36 			[-1, -1, -1, -1, 2, 4, 6, 8, 
37 			 -1, -1, -1, -1, 2, 4, 6, 8];	
38 ///For IMA ADPCM
39 ///Better quality, but needs more storage
40 package static immutable byte[32] ADPCM_INDEX_TABLE_5BIT = 
41 			[-1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16
42 			 -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16];
43 ///For the Yamaha ADPCM A found in YM2610 and probably other chips
44 package static immutable byte[16] Y_ADPCM_INDEX_TABLE =
45 			[-1, -1, -1, -1, 2, 5, 7, 9, 
46 			 -1, -1, -1, -1, 2, 5, 7, 9];
47 ///Most OKI and Yamaha chips seems to use this step-table
48 package static immutable ushort[49] DIALOGIC_ADPCM_STEP_TABLE = 
49 			[16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55,
50 			60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190,	
51 			209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598,
52 			658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552];		
53 /** 
54  * Used by IMA ADPCM and its derivatives.
55  */
56 package static immutable ushort[89] IMA_ADPCM_STEP_TABLE = 
57 			[7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 
58 			19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 
59 			50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 
60 			130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
61 			337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
62 			876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 
63 			2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
64 			5894, 6484, 7132, 7845, 8630, 9493, 10_442, 11_487, 12_635, 13_899, 
65 			15_289, 16_818, 18_500, 20_350, 22_385, 24_623, 27_086, 29_794, 32_767];
66 /**
67  * Used for decoding Mu-Law encoded PCM samples
68  */
69 package static immutable short[256] MU_LAW_DECODER_TABLE =
70 			[-32_124,-31_100,-30_076,-29_052,-28_028,-27_004,-25_980,-24_956,
71 			-23_932,-22_908,-21_884,-20_860,-19_836,-18_812,-17_788,-16_764,
72 			-15_996,-15_484,-14_972,-14_460,-13_948,-13_436,-12_924,-12_412,
73 			-11_900,-11_388,-10_876,-10_364, -9852, -9340, -8828, -8316,
74 			-7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
75 			-5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
76 			-3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
77 			-2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
78 			-1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
79 			-1372, -1308, -1244, -1180, -1116, -1052,  -988,  -924,
80 			-876,  -844,  -812,  -780,  -748,  -716,  -684,  -652,
81 			-620,  -588,  -556,  -524,  -492,  -460,  -428,  -396,
82 			-372,  -356,  -340,  -324,  -308,  -292,  -276,  -260,
83 			-244,  -228,  -212,  -196,  -180,  -164,  -148,  -132,
84 			-120,  -112,  -104,   -96,   -88,   -80,   -72,   -64,
85 			-56,   -48,   -40,   -32,   -24,   -16,    -8,     -1,
86 			32_124, 31_100, 30_076, 29_052, 28_028, 27_004, 25_980, 24_956,
87 			23_932, 22_908, 21_884, 20_860, 19_836, 18_812, 17_788, 16_764,
88 			15_996, 15_484, 14_972, 14_460, 13_948, 13_436, 12_924, 12_412,
89 			11_900, 11_388, 10_876, 10_364,  9852,  9340,  8828,  8316,
90 			7932,  7676,  7420,  7164,  6908,  6652,  6396,  6140,
91 			5884,  5628,  5372,  5116,  4860,  4604,  4348,  4092,
92 			3900,  3772,  3644,  3516,  3388,  3260,  3132,  3004,
93 			2876,  2748,  2620,  2492,  2364,  2236,  2108,  1980,
94 			1884,  1820,  1756,  1692,  1628,  1564,  1500,  1436,
95 			1372,  1308,  1244,  1180,  1116,  1052,   988,   924,
96 			876,   844,   812,   780,   748,   716,   684,   652,
97 			620,   588,   556,   524,   492,   460,   428,   396,
98 			372,   356,   340,   324,   308,   292,   276,   260,
99 			244,   228,   212,   196,   180,   164,   148,   132,
100 			120,   112,   104,    96,    88,    80,    72,    64,
101 			56,    48,    40,    32,    24,    16,     8,     0];
102 /**
103  * Used for decoding A-Law encoded PCM streams.
104  */
105 package static immutable short[256] A_LAW_DECODER_TABLE = 
106 			[-5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
107 			-7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
108 			-2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
109 			-3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
110 			-22_016,-20_992,-24_064,-23_040,-17_920,-16_896,-19_968,-18_944,
111 			-30_208,-29_184,-32_256,-31_232,-26_112,-25_088,-28_160,-27_136,
112 			-11_008,-10_496,-12_032,-11_520,-8960, -8448, -9984, -9472,
113 			-15_104,-14_592,-16_128,-15_616,-13_056,-12_544,-14_080,-13_568,
114 			-344,  -328,  -376,  -360,  -280,  -264,  -312,  -296,
115 			-472,  -456,  -504,  -488,  -408,  -392,  -440,  -424,
116 			-88,   -72,   -120,  -104,  -24,   -8,    -56,   -40,
117 			-216,  -200,  -248,  -232,  -152,  -136,  -184,  -168,
118 			-1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
119 			-1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
120 			-688,  -656,  -752,  -720,  -560,  -528,  -624,  -592,
121 			-944,  -912,  -1008, -976,  -816,  -784,  -880,  -848,
122 			5504,  5248,  6016,  5760,  4480,  4224,  4992,  4736,
123 			7552,  7296,  8064,  7808,  6528,  6272,  7040,  6784,
124 			2752,  2624,  3008,  2880,  2240,  2112,  2496,  2368,
125 			3776,  3648,  4032,  3904,  3264,  3136,  3520,  3392,
126 			22_016, 20_992, 24_064, 23_040, 17_920, 16_896, 19_968, 18_944,
127 			30_208, 29_184, 32_256, 31_232, 26_112, 25_088, 28_160, 27_136,
128 			11_008, 10_496, 12_032, 11_520, 8960,  8448,  9984,  9472,
129 			15_104, 14_592, 16_128, 15_616, 13_056, 12_544, 14_080, 13_568,
130 			344,   328,   376,   360,   280,   264,   312,   296,
131 			472,   456,   504,   488,   408,   392,   440,   424,
132 			88,    72,   120,   104,    24,     8,    56,    40,
133 			216,   200,   248,   232,   152,   136,   184,   168,
134 			1376,  1312,  1504,  1440,  1120,  1056,  1248,  1184,
135 			1888,  1824,  2016,  1952,  1632,  1568,  1760,  1696,
136 			688,   656,   752,   720,   560,   528,   624,   592,
137 			944,   912,  1008,   976,   816,   784,   880,   848];
138 
139 alias ADPCMStream = NibbleArray;
140 
141 
142 @nogc nothrow pure:
143 	
144 	/**
145 	 * Mixes an audio stream to the destination.
146 	 */
147 	public void mixIntoStream(size_t length, float* src, float* dest, float amount = 1.0, float corr = 0.5) {
148 		const __m128 amountV = __m128(amount);
149 		const __m128 corrV = __m128(corr);
150 		while (length) {
151 			const __m128 srcV = _mm_load_ps(src);
152 			__m128 destV = _mm_load_ps(dest);
153 			destV += srcV * amountV;
154 			destV *= corrV;
155 			_mm_store_ps(dest, destV);
156 			length -= 4;
157 			src += 4;
158 			dest += 4;
159 		}
160 	}
161 	/**
162 	 * Interleaves two channels.
163 	 * `dest` must be as big as the length of `srcL` and `srcR`.
164 	 */
165 	public void interleave(size_t length, float* srcL, float* srcR, float* dest) {
166 		while (length) {
167 			dest[0] = *srcL;
168 			dest[1] = *srcR;
169 			dest += 2;
170 			srcL++;
171 			srcR++;
172 			length--;
173 		}
174 	}
175 	/**
176 	 * Converts a 32 bit extended integer stream to 32 bit floating point.
177 	 */
178 	public void convExIntToFlt(size_t length, int* src, float* dest) {
179 		while (length) {
180 			_mm_store_ps(dest, _mm_cvtepi32_ps(_mm_load_si128(cast(__m128i*)src)) * CONV_RATIO_RECIPROCAL);
181 			length -= 4;
182 			src += 4;
183 			dest += 4;
184 		}
185 	}
186 	/**
187 	 * Decodes an amount of 8 bit unsigned PCM to extended 32 bit.
188 	 * Amount is decided by dest.length. `src` is a full waveform. Position is stored in wp.pos.
189 	 */
190 	public void decode8bitPCM(const(ubyte)[] src, int[] dest, ref DecoderWorkpad wp) @safe {
191 		for (size_t i ; i < dest.length ; i++) {
192 			const ubyte val = src[wp.pos + i];
193 			dest[i] = ((val) | (val<<8)) + short.min;
194 		}
195 		wp.pos += dest.length;
196 	}
197 	/**
198 	 * Decodes an amount of 16 bit signed PCM to extended 32 bit.
199 	 * Amount is decided by dest.length. `src` is a full waveform. Position is stored in wp.pos.
200 	 */
201 	public void decode16bitPCM(const(short)[] src, int[] dest, ref DecoderWorkpad wp) @safe {
202 		for (size_t i ; i < dest.length ; i++) {
203 			dest[i] = src[wp.pos + i];
204 		}
205 		wp.pos += dest.length;
206 	}
207 	/**
208 	 * Decodes an amount of 4 bit IMA ADPCM stream to extended 32 bit.
209 	 * Amount is decided by dest.length. `src` is a full waveform. Position is stored in wp.pos.
210 	 */
211 	public void decode4bitIMAADPCM(ADPCMStream src, int[] dest, ref DecoderWorkpad wp) @safe {
212 		for (size_t i ; i < dest.length ; i++) {
213 			const ubyte index = src[i];
214 			uint stepSize;
215 			int d_n;
216 			wp.pred += ADPCM_INDEX_TABLE_4BIT[index];
217 			clamp(wp.pred, 0, 88);
218 			stepSize = IMA_ADPCM_STEP_TABLE[wp.pred];
219 			d_n = ((stepSize) * (index & 0b0100)>>2) + ((stepSize>>1) * (index & 0b0010)>>1) + ((stepSize>>2) * index & 0b0001) 
220 					+ (stepSize>>3);
221 			if(index & 0b1000)
222 				d_n *= -1;
223 			d_n += wp.outn1;
224 			dest[i] = d_n;
225 			wp.outn1 = d_n;
226 		}
227 		wp.pos += dest.length;
228 	}
229 	/**
230 	 * Decodes an amount of 4 bit Oki/Dialogic ADPCM stream to extended 32 bit.
231 	 * Amount is decided by dest.length. `src` is a full waveform. Position is stored in wp.pos.
232 	 */
233 	public void decode4bitDialogicADPCM(ADPCMStream src, int[] dest, ref DecoderWorkpad wp) @safe {
234 		for (size_t i ; i < dest.length ; i++) {
235 			const ubyte index = src[i];
236 			uint stepSize;
237 			int d_n;
238 			wp.pred += ADPCM_INDEX_TABLE_4BIT[index];
239 			clamp(wp.pred, 0, 48);
240 			stepSize = DIALOGIC_ADPCM_STEP_TABLE[wp.pred];
241 			d_n = ((stepSize) * (index & 0b0100)>>2) + ((stepSize>>1) * (index & 0b0010)>>1) + ((stepSize>>2) * index & 0b0001) 
242 					+ (stepSize>>3);
243 			if(index & 0b1000)
244 				d_n *= -1;
245 			d_n += wp.outn1;
246 			dest[i] = ((d_n<<4) | (d_n>>8)) + short.min;
247 			wp.outn1 = d_n;
248 		}
249 		wp.pos += dest.length;
250 	}
251 	/**
252 	 * Decodes a Mu-Law encoded stream.
253 	 */
254 	public void decodeMuLawStream(const(ubyte)[]src, int[] dest, ref DecoderWorkpad wp) @safe {
255 		for (size_t i ; i < dest.length ; i++) {
256 			dest[i] = MU_LAW_DECODER_TABLE[src[wp.pos + i]];
257 		}
258 		wp.pos += dest.length;
259 	}
260 	/**
261 	 * Decodes an A-Law encoded stream.
262 	 */
263 	public void decodeALawStream(const(ubyte)[]src, int[] dest, ref DecoderWorkpad wp) @safe {
264 		for (size_t i ; i < dest.length ; i++) {
265 			dest[i] = A_LAW_DECODER_TABLE[src[wp.pos + i]];
266 		}
267 		wp.pos += dest.length;
268 	}
269 	/**
270 	 * Streches a buffer to the given amount using no interpolation.
271 	 * Amount decided by `dest.length`.
272 	 * Can be used to pitch the sample.
273 	 * Params:
274 	 *   src = source of the stream.
275 	 *   dest = destination stream, it's length is also equals to how much samples are needed.
276 	 *   wp = wave modulation workpad, storing information such as source position.
277 	 *   modifier = jump amount, might be moved to a template parameter later on.
278 	 *   clamping = Used for situations where not the whole waveform is decoded. Limits buffer size in a way, that it
279 	 * allows for double buffered decoding by allowing it to turn around at the end of one buffer.
280 	 */
281 	public void stretchAudioNoIterpol(const(int)[] src, int[] dest, ref WavemodWorkpad wp, uint modifier = 0x1_00_00_00, 
282 			uint clamping = 0xFF) @safe {
283 		//wp.lookupVal &= 0x_FF_FF_FF;
284 		for (size_t i ; i < dest.length /* && wp.lookupVal>>24 < src.length */ ; i++) {
285 			dest[i] = src[cast(size_t)(wp.lookupVal>>24) & clamping];
286 			wp.lookupVal += modifier;
287 		}
288 	}
289 	/**
290 	 * Converts MIDI note to frequency.
291 	 * Params:
292 	 *   note = MIDI note number.
293 	 *   baseFreq = A-4 note frequency
294 	 */
295 	public double midiToFreq(int note, const double baseFreq = 440.0) @safe {
296 		double r = note - 69;
297 		r /= 12;
298 		r = pow(2, r);
299 		return r * baseFreq;
300 	}
301 	/**
302 	 * Converts note number to frequency.
303 	 * Params:
304 	 *   note = MIDI note number.
305 	 *   baseFreq = A-4 note frequency
306 	 */
307 	public double noteToFreq(double note, const double baseFreq = 440.0) @safe {
308 		double r = note - 69;
309 		r /= 12;
310 		r = pow(2, r);
311 		return r * baseFreq;
312 	}
313 	/** 
314 	 * Bends the frequency by the given amount of seminotes.
315 	 * Params:
316 	 *   freq = The frequency to be modified.
317 	 *   am = The amount of seminotes. Positive means upwards, negative means downwards.
318 	 * Returns: The modified frequency.
319 	 */
320 	public double bendFreq(double freq, double am) @safe {
321 		return freq * pow(2, am / 12);
322 	}
323 	/**
324 	 * Calculates biquad low-pass filter coefficients from the supplied values.
325 	 *
326 	 * fs: Sampling frequency.
327 	 * f0: Corner frequency.
328 	 * q: The Q factor of the filter.
329 	 */
330 	public BiquadFilterValues createLPF(float fs, float f0, float q) @safe {
331 		BiquadFilterValues result;
332 		const float w0 = 2 * PI * f0 / fs;
333 		const float alpha = sin(w0) / (2 * q);
334 		result.b1 = 1 - cos(w0);
335 		result.b0 = result.b1 / 2;
336 		result.b2 = result.b0;
337 		result.a0 = 1 + alpha;
338 		result.a1 = -2 * cos(w0);
339 		result.a2 = 1 - alpha;
340 		return result;
341 	}
342 	/** 
343 	 * Calculates biquad high-pass filter coefficients from the supplied values.
344 	 * Params:
345 	 *   fs = Sampling frequency.
346 	 *   f0 = Corner frequency.
347 	 *   q = The Q factor of the filter.
348 	 * Returns: A struct with the coefficient values for the filter.
349 	 */
350 	public BiquadFilterValues createHPF(float fs, float f0, float q) @safe {
351 		BiquadFilterValues result;
352 		const float w0 = 2 * PI * f0 / fs;
353 		const float alpha = sin(w0) / (2 * q);
354 		result.b1 = (1 + cos(w0)) * -1;
355 		result.b0 = (1 + cos(w0)) / 2;
356 		result.b2 = result.b0;
357 		result.a0 = 1 + alpha;
358 		result.a1 = -2 * cos(w0);
359 		result.a2 = 1 - alpha;
360 		return result;
361 	}
362 	/** 
363 	 * Calculates biquad band pass filter (constant skirt gain, peak gain = Q) filter coefficients from the supplied values.
364 	 * Params:
365 	 *   fs = Sampling frequency.
366 	 *   f0 = Corner frequency.
367 	 *   q = Peak gain.
368 	 * Returns: A struct with the coefficient values for the filter.
369 	 */
370 	public BiquadFilterValues createBPF0(float fs, float f0, float q) @safe {
371 		BiquadFilterValues result;
372 		const float w0 = 2 * PI * f0 / fs;
373 		const float alpha = sin(w0) / (2 * q);
374 		result.b1 = 0;
375 		result.b0 = q * alpha;
376 		result.b2 = result.b0 * -1;
377 		result.a0 = 1 + alpha;
378 		result.a1 = -2 * cos(w0);
379 		result.a2 = 1 - alpha;
380 		return result;
381 	}
382 	/** 
383 	 * Calculates biquad band pass filter (constant 0 db peak gain) filter coefficients from the supplied values.
384 	 * Params:
385 	 *   fs = Sampling frequency.
386 	 *   f0 = Corner frequency.
387 	 *   q = Peak gain.
388 	 * Returns: A struct with the coefficient values for the filter.
389 	 */
390 	public BiquadFilterValues createBPF1(float fs, float f0, float q) @safe {
391 		BiquadFilterValues result;
392 		const float w0 = 2 * PI * f0 / fs;
393 		const float alpha = sin(w0) / (2 * q);
394 		result.b1 = 0;
395 		result.b0 = alpha;
396 		result.b2 = alpha * -1;
397 		result.a0 = 1 + alpha;
398 		result.a1 = -2 * cos(w0);
399 		result.a2 = 1 - alpha;
400 		return result;
401 	}
402 	public BiquadFilterValues createNotchFilt(float fs, float f0, float q) @safe {
403 		BiquadFilterValues result;
404 		const float w0 = 2 * PI * f0 / fs;
405 		const float alpha = sin(w0) / (2 * q);
406 		result.b1 = 0;
407 		result.b0 = alpha;
408 		result.b2 = alpha * -1;
409 		result.a0 = 1 + alpha;
410 		result.a1 = -2 * cos(w0);
411 		result.a2 = 1 - alpha;
412 		return result;
413 	}
414 	/** 
415 	 * Calculates the time factor for an LP6 filter.
416 	 * Filter formula:
417 	 * `y[n] = y[n-1] + (x[n] - y[n-1]) * factor`
418 	 * Where factor is:
419 	 * `1.0 - exp(-1.0 / (timeConstantInSeconds * samplerate))`
420 	 * Params:
421 	 *   fs = Sampling frequency.
422 	 *   f0 = Cutoff frequency.
423 	 * Returns: The `factor` value.
424 	 */
425 	public double calculateLP6factor(float fs, float f0) @safe {
426 		return 1.0 - exp(-1.0 / ((1 / f0) * fs));
427 	}
428 	/** 
429 	 * Creates the alpha value for a HP20 filter.
430 	 * Filter formula:
431 	 * `y[n] = (y[n-1] + x[n] - x[n-1]) * alpha`
432 	 * Where alpha is:
433 	 * `1 / (1 + 2 * pi * timeConstantInSeconds * samplerate)`
434 	 * Params:
435 	 *   fs = Sampling frequency.
436 	 *   f0 = Cutoff frequency.
437 	 * Returns: The `alpha` value.
438 	 */
439 	public double calculateHP20alpha(float fs, float f0) @safe {
440 		return 1 / (1 + 2 * PI * (1 / f0) * fs);
441 	}
442 	/** 
443 	 * Converts MIDI 1.0 14 bit control values to MIDI 2.0 32 bit. Might not work the best with certain values.
444 	 * Params:
445 	 *   msb = most significant 7 bits
446 	 *   lsb = least significant 7 bits
447 	 * Returns: The 32 bit control value.
448 	 */
449 	public uint convertM1CtrlValToM2(ubyte msb, ubyte lsb) @safe {
450 		const uint addedTotal = msb<<7 | lsb;
451 		return cast(uint)(uint.max * (cast(real)(addedTotal) / (ushort.max>>2)));
452 	}
453 	/** 
454 	 * Sets an array (buffer) to all zeros.
455 	 * Params:
456 	 *   targetBuffer = The buffer to be reset.
457 	 */
458 	public void resetBuffer(T)(T[] targetBuffer) @safe {
459 		static if (is(T == __m128) || is(T == __vector(float[4]))) {
460 			for (size_t i ; i < targetBuffer.length ; i++) {
461 				targetBuffer[i] = __m128(0);
462 			}
463 		} else static if (is(T == float[4]) || is(T == int[4])) {
464 			for (size_t i ; i < targetBuffer.length ; i++) {
465 				targetBuffer[i] = [0, 0, 0, 0];
466 			}
467 		} else {
468 			for (size_t i ; i < targetBuffer.length ; i++) {
469 				targetBuffer[i] = 0;
470 			}
471 		}
472 	}
473 	/** 
474 	 * Original algorithm for C++ by Martin Leitner-Ankerl (https://martin.ankerl.com/2007/10/04/optimized-pow-approximation-for-java-and-c-c/).
475 	 * Computes the power of `a` on the `b`th much faster than std.math.pow, at the cost of some accuracy.
476 	 * Good enough for envelop curve shaping.
477 	 */
478 	double fastPow(double a, double b) @safe {
479 	    union U {
480 	        double d;
481 	        int[2] x;
482 	    }
483 		U u;
484 		u.d = a;
485 	    u.x[1] = cast(int)(b * (u.x[1] - 1_072_632_447) + 1_072_632_447);
486 	    u.x[0] = 0;
487 	    return u.d;
488 	}
489 	/**
490 	 * Returns the Cubic Lagrange coefficients for the supplied positions
491 	 * Params:
492 	 *   x = position ideally between x_n[1] and x_n[2].
493 	 *   x_n = the supplied positions. All values must be different, otherwise the returned value will be NaN.
494 	 * Returns: an array with the coefficients.
495 	 */
496 	float[4] getCubicLagrCoeffs(float x, float[4] x_n) @safe {
497 		float[4] result;
498 		result[0]= ((x - x_n[1]) * (x - x_n[2]) * (x - x_n[3])) / ((x_n[0] - x_n[1]) * (x_n[0] - x_n[2]) * (x_n[0] - x_n[3]));
499 		result[1]= ((x - x_n[0]) * (x - x_n[2]) * (x - x_n[3])) / ((x_n[1] - x_n[0]) * (x_n[1] - x_n[2]) * (x_n[1] - x_n[3]));
500 		result[2]= ((x - x_n[0]) * (x - x_n[1]) * (x - x_n[3])) / ((x_n[2] - x_n[0]) * (x_n[2] - x_n[1]) * (x_n[2] - x_n[3]));
501 		result[3]= ((x - x_n[0]) * (x - x_n[1]) * (x - x_n[2])) / ((x_n[3] - x_n[0]) * (x_n[3] - x_n[1]) * (x_n[3] - x_n[2]));
502 		return result;
503 	}
504 	/**
505 	 * Returns the Cubic Lagrange coefficients for positions -1, 0, 1, 2.
506 	 * Params:
507 	 *   x = position ideally between 0 and 1
508 	 * Returns: an array with the coefficients.
509 	 */
510 	float[4] getCubicLagrCoeffs(float x) @safe {
511 		float[4] result;
512 		result[0] = (x * (x - 1) * (x - 2))       / -6;
513 		result[1] = ((x + 1) * (x - 1) * (x - 2)) / -2;
514 		result[2] = ((x + 1) * x * (x - 2))       / -2;
515 		result[3] = ((x + 1) * x * (x - 1))       /  6;
516 		return result;
517 	}
518 	double smoothstep(double a, double b, double x) @safe {
519 		x = (x - a) / (b - a);
520 		return x * x * (3 - 2 * x);
521 	}