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 Workpad 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 Workpad 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 Workpad 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 Workpad 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 Workpad 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 Workpad 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 	 * Can be used to pitch the sample.
272 	 */
273 	public void stretchAudioNoIterpol(const(int)[] src, int[] dest, ref WavemodWorkpad wp, uint modifier = 0x10_00_00) 
274 			@safe {
275 		for (size_t i ; i < dest.length ; i++) {
276 			dest[i] = src[cast(size_t)(wp.lookupVal>>20)];
277 			wp.lookupVal += modifier;
278 		}
279 	}
280 	/**
281 	 * Converts MIDI note to frequency.
282 	 */
283 	public double midiToFreq(int note, const double baseFreq = 440.0) @safe {
284 		double r = note - 69;
285 		r /= 12;
286 		r = pow(2, r);
287 		return r * baseFreq;
288 	}
289 	/**
290 	 * Converts note number to frequency.
291 	 */
292 	public double noteToFreq(double note, const double baseFreq = 440.0) @safe {
293 		double r = note - 69;
294 		r /= 12;
295 		r = pow(2, r);
296 		return r * baseFreq;
297 	}
298 	/**
299 	 * Calculates biquad low-pass filter values from the supplied values.
300 	 *
301 	 * fs: sampling frequency.
302 	 * f0: cutting frequency.
303 	 * q: the Q factor of the filter.
304 	 */
305 	public BiquadFilterValues createLPF(float fs, float f0, float q) @safe {
306 		BiquadFilterValues result;
307 		const float w0 = 2 * PI * f0 / fs;
308 		const float alpha = sin(w0) / (2 * q);
309 		result.b1 = 1 - cos(w0);
310 		result.b0 = result.b1 / 2;
311 		result.b2 = result.b0;
312 		result.a0 = 1 + alpha;
313 		result.a1 = -2 * cos(w0);
314 		result.a2 = 1 - alpha;
315 		return result;
316 	}