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 }