1 module soundtab.audio.generators; 2 3 import std.math : log2, exp2, sin, cos, pow, PI; 4 5 immutable WAVETABLE_SIZE_BITS = 14; 6 immutable WAVETABLE_SIZE = 1 << WAVETABLE_SIZE_BITS; 7 immutable WAVETABLE_SIZE_MASK = WAVETABLE_SIZE - 1; 8 immutable WAVETABLE_SIZE_MASK_MUL_256 = (1 << (WAVETABLE_SIZE_BITS + 8)) - 1; 9 immutable WAVETABLE_SCALE_BITS = 14; 10 immutable WAVETABLE_SCALE = (1 << WAVETABLE_SCALE_BITS); 11 12 13 int[] genWaveTableSin() { 14 int[] res; 15 res.length = WAVETABLE_SIZE; 16 for (int i = 0; i < WAVETABLE_SIZE; i++) { 17 double f = i * 2 * PI / WAVETABLE_SIZE; 18 double v = sin(f); 19 res[i] = cast(int)(v * WAVETABLE_SCALE); 20 } 21 return res; 22 } 23 24 float[] genWaveTableSinF() { 25 float[] res; 26 res.length = WAVETABLE_SIZE; 27 for (int i = 0; i < WAVETABLE_SIZE; i++) { 28 double f = i * 2 * PI / WAVETABLE_SIZE; 29 double v = sin(f); 30 res[i] = cast(float)v; 31 } 32 return res; 33 } 34 35 // (cos^2 + 1)/2 half period 36 float[] genWaveTableCosSquaredF() { 37 float[] res; 38 res.length = WAVETABLE_SIZE + 1; 39 for (int i = 0; i <= WAVETABLE_SIZE; i++) { 40 double f = i * PI / WAVETABLE_SIZE; 41 double v = (cos(f) + 1) / 2; 42 v = v * v; 43 res[i] = cast(float)v; 44 } 45 return res; 46 } 47 48 int[] genWaveTableSquare() { 49 int[] res; 50 res.length = WAVETABLE_SIZE; 51 for (int i = 0; i < WAVETABLE_SIZE; i++) { 52 if (i < WAVETABLE_SIZE / 2) 53 res[i] = WAVETABLE_SCALE; 54 else 55 res[i] = -WAVETABLE_SCALE; 56 } 57 return res; 58 } 59 60 float[] genWaveTableSquareF() { 61 float[] res; 62 res.length = WAVETABLE_SIZE; 63 for (int i = 0; i < WAVETABLE_SIZE; i++) { 64 if (i < WAVETABLE_SIZE / 2) 65 res[i] = 1.0f; 66 else 67 res[i] = -1.0f; 68 } 69 return res; 70 } 71 72 // Based on code from STK library - https://github.com/thestk/stk 73 // impuls_20 waveform 74 immutable short[] VOICE_IMPULSE = [ 75 -385, -30598, -2710, -28077, -16329, 24091, 7938, -2834, -28189, 17376, -1053, -24596, -32265, -4351, -19447, 30477, 76 -7412, -24824, 3586, -3846, -2572, 25585, -10512, 11507, -25609, -4100, -11263, 11269, 18694, 3333, -5375, -16131, 77 -25863, 30454, 1781, -30219, -14345, 7931, -19458, -22783, 19203, 18947, -18687, 1279, -6917, 7417, 22263, -2570, 78 1016, 13050, -3844, -29185, 26625, 5122, 29185, -19457, 19709, -9990, -3592, 2296, 20984, -20231, -13829, 5374, 79 0, 6145, 7169, 4608, 17150, 8444, 13562, -2568, -20488, 27897, -1286, -3076, -9474, 13824, -18944, 15872, 80 -3586, 8701, 17659, -12039, 7673, 22009, 26362, 3324, -9219, 25343, 16384, 17152, 28159, -3331, 13564, -24326, 81 -25863, 24825, -7, 20219, -1796, -27394, -17153, 10240, -16129, -24834, 3325, 28155, 10234, -29703, -16647, -19718, 82 11004, -13827, 10239, -3841, -3585, 11263, -12035, 14076, -15366, -11527, -24839, 13562, 28667, 253, -31490, -25601, 83 0, -25601, -31490, 253, 28667, 13562, -24839, -11527, -15366, 14076, -12035, 11263, -3585, -3841, 10239, -13827, 84 11004, -19718, -16647, -29703, 10234, 28155, 3325, -24834, -16129, 10240, -17153, -27394, -1796, 20219, -7, 24825, 85 -25863, -24326, 13564, -3331, 28159, 17152, 16384, 25343, -9219, 3324, 26362, 22009, 7673, -12039, 17659, 8701, 86 -3586, 15872, -18944, 13824, -9474, -3076, -1286, 27897, -20488, -2568, 13562, 8444, 17150, 4608, 7169, 6145, 87 0, 5374, -13829, -20231, 20984, 2296, -3592, -9990, 19709, -19457, 29185, 5122, 26625, -29185, -3844, 13050, 88 1016, -2570, 22263, 7417, -6917, 1279, -18687, 18947, 19203, -22783, -19458, 7931, -14345, -30219, 1781, 30454, 89 -25863, -16131, -5375, 3333, 18694, 11269, -11263, -4100, -25609, 11507, -10512, 25585, -2572, -3846, 3586, -24824, 90 -7412, 30477, -19447, -4351, -32265, -24596, -1053, 17376, -28189, -2834, 7938, 24091, -16329, -28077, -2710, -30598, 91 ]; 92 93 float[] genWaveTableRescaledF(immutable short[] data) { 94 float[] res; 95 res.length = WAVETABLE_SIZE; 96 for (int i = 0; i < WAVETABLE_SIZE; i++) { 97 int index = cast(int)(i * data.length / WAVETABLE_SIZE); 98 int indexMod = cast(int)(i * data.length % WAVETABLE_SIZE); 99 float v1 = data[index % data.length]; 100 float v2 = data[(index + 1) % data.length]; 101 float v = (cast(long)v1 * (WAVETABLE_SIZE - indexMod) + v2 * indexMod) / WAVETABLE_SIZE; 102 v /= 32768; 103 res[i] = v; 104 } 105 return res; 106 } 107 108 class Osciller { 109 int[] _origWavetable; 110 int[] _wavetable; 111 int _scale; 112 int _offset; 113 int _phase; // *256 114 int _step; 115 this(int[] wavetable, int scale = WAVETABLE_SCALE, int offset = 0) { 116 _origWavetable = wavetable; 117 rescale(scale, offset); 118 } 119 void rescale(int scale = WAVETABLE_SCALE, int offset = 0) { 120 _scale = scale; 121 _offset = offset; 122 if (scale == WAVETABLE_SCALE && offset == 0) { 123 _wavetable = _origWavetable; 124 } else { 125 _wavetable = _origWavetable.dup; 126 for (int i = 0; i < _origWavetable.length; i++) { 127 _wavetable[i] = _origWavetable[i] * scale / WAVETABLE_SCALE + offset; 128 } 129 } 130 } 131 void setStep(int step_mul_256) { 132 _step = step_mul_256; 133 } 134 /// set step based on pitch frequency (Hz) and samples per second 135 void setPitch(double freq, int samplesPerSecond) { 136 _step = cast(int)(WAVETABLE_SIZE * 256 * freq / samplesPerSecond); 137 } 138 int step(int step_mul_256) { 139 _phase = (_phase + step_mul_256) & WAVETABLE_SIZE_MASK_MUL_256; 140 return _wavetable[_phase >> 8]; 141 } 142 // step by value with gain (*0x10000) 143 int stepWithGain(int step_mul_256, int gain) { 144 _phase = (_phase + step_mul_256) & WAVETABLE_SIZE_MASK_MUL_256; 145 return (_wavetable[_phase >> 8] * gain) >> 16; 146 } 147 // use current step value 148 int step() { 149 _phase = (_phase + _step) & WAVETABLE_SIZE_MASK_MUL_256; 150 return _wavetable[_phase >> 8]; 151 } 152 // multiplies passed value to next step and divide by 0x10000 153 int stepMultiply(int n) { 154 _phase = (_phase + _step) & WAVETABLE_SIZE_MASK_MUL_256; 155 int value = _wavetable[_phase >> 8]; 156 return cast(int)((cast(long)n * value) >> 16); 157 } 158 // multiplies passed value to next step using modulation gain relative to 0x10000 159 int stepMultiply(int n, int gain) { 160 _phase = (_phase + _step) & WAVETABLE_SIZE_MASK_MUL_256; 161 int value = _origWavetable[_phase >> 8]; 162 if (gain > 30) 163 value = ((value * gain) >> WAVETABLE_SCALE_BITS) + 0x10000; 164 return cast(int)((cast(long)n * value) >> 16); 165 } 166 void resetPhase() { 167 _phase = 0; 168 } 169 } 170 171 class OscillerF { 172 float[] _origWavetable; 173 float[] _wavetable; 174 float _scale; 175 float _offset; 176 int _phase; // *256 177 int _step; 178 this(float[] wavetable, float scale = 1.0f, float offset = 0, immutable(float[]) formants = null) { 179 _origWavetable = wavetable; 180 rescale(scale, offset, formants); 181 } 182 void rescale(float scale = 1.0f, float offset = 0, immutable(float[]) formants = null) { 183 _scale = scale; 184 _offset = offset; 185 if (scale == 1.0f && offset == 0 && !formants.length) { 186 _wavetable = _origWavetable; 187 } else { 188 _wavetable = _origWavetable.dup; 189 float maxAmp = 0; 190 for (int i = 0; i < _origWavetable.length; i++) { 191 float v = _origWavetable[i]; 192 if (formants.length) { 193 v *= formants[0]; 194 for (int j = 2; j < formants.length; j++) { 195 v += _origWavetable[i * j % _origWavetable.length] * formants[j]; 196 } 197 } 198 _wavetable[i] = v; 199 if (v > maxAmp) 200 maxAmp = v; 201 else if (-v > maxAmp) 202 maxAmp = -v; 203 } 204 float mult = 1 / maxAmp; 205 for (int i = 0; i < _origWavetable.length; i++) { 206 _wavetable[i] = _wavetable[i] * mult * scale + offset; 207 } 208 } 209 } 210 void setStep(int step_mul_256) { 211 _step = step_mul_256; 212 } 213 /// set step based on pitch frequency (Hz) and samples per second 214 void setPitch(double freq, int samplesPerSecond) { 215 _step = cast(int)(WAVETABLE_SIZE * 256 * freq / samplesPerSecond); 216 } 217 float step(int step_mul_256) { 218 _phase = (_phase + step_mul_256) & WAVETABLE_SIZE_MASK_MUL_256; 219 return _wavetable[_phase >> 8]; 220 } 221 float stepPitchMultiply(int step_mul_256, int mult_by_100000) { 222 step_mul_256 = cast(int)((cast(long)step_mul_256 * mult_by_100000) / 100000); 223 _phase = (_phase + step_mul_256) & WAVETABLE_SIZE_MASK_MUL_256; 224 return _wavetable[_phase >> 8]; 225 } 226 // step by value with gain (*0x10000) 227 float stepWithGain(int step_mul_256, float gain) { 228 _phase = (_phase + step_mul_256) & WAVETABLE_SIZE_MASK_MUL_256; 229 return _wavetable[_phase >> 8] * gain; 230 } 231 // use current step value 232 float step() { 233 _phase = (_phase + _step) & WAVETABLE_SIZE_MASK_MUL_256; 234 return _wavetable[_phase >> 8]; 235 } 236 void resetPhase() { 237 _phase = 0; 238 } 239 } 240 241 struct Interpolator { 242 private int _target; 243 private int _value; 244 private int _step; 245 private int _dstep; 246 private bool _const = true; 247 private bool _zero = true; 248 /// reset to const 249 void reset(int v) { 250 _value = v; 251 _step = _dstep = 0; 252 _const = true; 253 _zero = (_value == 0); 254 } 255 /// reset to target value 256 void reset() { 257 _value = _target; 258 _step = _dstep = 0; 259 _const = true; 260 _zero = (_value == 0); 261 } 262 /// set target value for interpolation 263 @property void target(int newValue) { 264 _target = newValue; 265 } 266 /// get target value 267 @property int target() { return _target; } 268 /// get current value 269 @property int value() { return _value; } 270 /// returns true if interpolator will return const value 271 @property bool isConst() { return _const; } 272 /// returns true if interpolator will return const value 0 273 @property bool isZero() { return _zero; } 274 /// set interpolation parameters to interpolate values in range _value .. _newValue in len frames 275 void init(int len) { 276 if (_target == _value) { 277 _const = true; 278 _zero = (_value == 0); 279 } else { 280 _const = false; 281 _zero = false; 282 int delta = _target - _value; 283 _step = delta / len; 284 _dstep = delta % len; 285 } 286 } 287 /// get next interpolated value 288 @property int next() { 289 if (_const) 290 return _value; 291 int res = _value; 292 _value += _step; 293 if (_dstep > 0) { 294 _value++; 295 _dstep--; 296 } else if (_dstep < 0) { 297 _value--; 298 _dstep++; 299 } 300 return res; 301 } 302 } 303 304 /// float value interpolator 305 struct InterpolatorF { 306 private float _target = 0; 307 private float _value = 0; 308 private float _step = 0; 309 private bool _const = true; 310 private bool _zero = true; 311 /// reset to const 312 void reset(float v) { 313 _value = v; 314 _step = 0; 315 _const = true; 316 _zero = (v == 0); 317 } 318 /// reset to target 319 void reset() { 320 _value = _target; 321 _step = 0; 322 _const = true; 323 _zero = (_value == 0); 324 } 325 /// returns true if interpolator will return const value 326 @property bool isConst() { return _const; } 327 /// returns true if interpolator will return const value 0 328 @property bool isZero() { return _zero; } 329 /// set target value for interpolation 330 @property void target(float newValue) { 331 _target = newValue; 332 } 333 /// get target value 334 @property float target() { return _target; } 335 /// get current value 336 @property float value() { return _value; } 337 /// set interpolation parameters to interpolate values in range _value .. _target in len frames 338 void init(int len) { 339 _step = (_target - _value) / len; 340 if (_step >= -0.0000000001f && _step <= 0.0000000001f) { 341 _const = true; 342 _zero = (_value >= -0.000001f && _value <= 0.000001f); 343 } else { 344 _const = false; 345 _zero = false; 346 } 347 } 348 /// get next interpolated value 349 @property float next() { 350 if (_const) 351 return _value; 352 float res = _value; 353 _value += _step; 354 return res; 355 } 356 /// limit speed of target change 357 void limitTargetChange(int frameMillis, int attackMillis, int releaseMillis) { 358 if (_value < _target) { 359 // attack 360 if (frameMillis < attackMillis) 361 _target = _value + (_target - _value) * frameMillis / attackMillis; 362 } else { 363 // release 364 if (frameMillis < releaseMillis) 365 _target = _value + (_target - _value) * frameMillis / releaseMillis; 366 } 367 } 368 } 369 370 __gshared int[] SIN_TABLE; 371 __gshared int[] SQUARE_TABLE; 372 __gshared float[] SIN_TABLE_F; 373 __gshared float[] SQUARE_TABLE_F; 374 __gshared float[] COS_2_TABLE_F; 375 __gshared float[] VOICE_IMPULSE_F; 376 __gshared float[] SAW_TABLE_F; 377 __gshared float[] SAW_TABLE_2_F; 378 __gshared float[] VOICE_EXPERIMENTAL_F; 379 __gshared float[] VOICE_EX_1_F; 380 381 float[] normalize(float[] data, float amp = 1) { 382 float[] res = data.dup; 383 float s = 0; 384 foreach(sample; res) 385 s+=sample; 386 s /= res.length; 387 foreach(ref sample; res) 388 sample -= s; 389 float minv = res[0]; 390 float maxv = res[0]; 391 foreach(sample; res) { 392 if (minv > sample) 393 minv = sample; 394 if (maxv < sample) 395 maxv = sample; 396 } 397 if (-minv > maxv) 398 maxv = -minv; 399 float mult = amp / maxv; 400 foreach(ref sample; res) 401 sample *= mult; 402 return res; 403 } 404 405 immutable ulong RANDOM_MULTIPLIER = 0x5DEECE66D; 406 immutable ulong RANDOM_MASK = ((cast(ulong)1 << 48) - 1); 407 immutable ulong RANDOM_ADDEND = cast(ulong)0xB; 408 409 struct Random { 410 ulong seed; 411 //Random(); 412 void setSeed(ulong value) { 413 seed = (value ^ RANDOM_MULTIPLIER) & RANDOM_MASK; 414 } 415 416 int next(int bits) { 417 seed = (seed * RANDOM_MULTIPLIER + RANDOM_ADDEND) & RANDOM_MASK; 418 return cast(int)(seed >> (48 - bits)); 419 } 420 421 int nextInt() { 422 return next(31); 423 } 424 int nextInt(int n) { 425 if ((n & -n) == n) // i.e., n is a power of 2 426 return cast(int)((n * cast(long)next(31)) >> 31); 427 int bits, val; 428 do { 429 bits = next(31); 430 val = bits % n; 431 } while (bits - val + (n - 1) < 0); 432 return val; 433 } 434 } 435 436 struct Noise { 437 Random _rnd; 438 float tick() { 439 int value = _rnd.next(16) - 32768; 440 return value / 32768.0f; 441 } 442 } 443 444 __gshared static this() { 445 SIN_TABLE = genWaveTableSin(); 446 SIN_TABLE_F = genWaveTableSinF(); 447 SQUARE_TABLE = genWaveTableSquare(); 448 SQUARE_TABLE_F = genWaveTableSquareF(); 449 COS_2_TABLE_F = genWaveTableCosSquaredF(); 450 VOICE_IMPULSE_F = genWaveTableRescaledF(VOICE_IMPULSE); 451 SAW_TABLE_F = genWaveTableRescaledF([0, 32767, 0, -32767]); 452 SAW_TABLE_2_F = genWaveTableRescaledF([0, 32767]); 453 //VOICE_EXPERIMENTAL_F = genWaveTableRescaledF([0, 32767, 30000, -24000, -20000, 16384, 15000, -12000, -10000, 8000, -4000, 2000, -1000, 0, 0, 0, 0,]); 454 //VOICE_EXPERIMENTAL_F = genWaveTableRescaledF([0, 32767, 30000, 4000, -32767, -30000, -4000, -2000, 0, 0, 0, 0, 0, 0, 0, 0,]); 455 //VOICE_EXPERIMENTAL_F = genWaveTableRescaledF([0, 32767, 32767, -24000, -24000, 8000, 8000, -4000, -4000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,]); 456 VOICE_EX_1_F = genWaveTableRescaledF([ 457 0, 458 30000, 459 30000, 460 0, 461 0, 462 0, 463 0, 464 0, 465 0, 466 -100, 467 -300, 468 -500, 469 -1000, 470 -2000, 471 -3000, 472 -2000, 473 -1000, 474 ]); 475 VOICE_EXPERIMENTAL_F = genWaveTableRescaledF([ 476 0, 477 25000, 478 30000, 479 32000, 480 30000, 481 26000, 482 15000, 483 12000, 484 10000, 485 7000, 486 4000, 487 3000, 488 2000, 489 1000, 490 500, 491 0, 492 -500, 493 -1000, 494 -2000, 495 -3000, 496 -4000, 497 -5000, 498 -6000, 499 -7000, 500 -10000, 501 -12000, 502 -15000, 503 -26000, 504 -30000, 505 -32000, 506 -30000, 507 -25000, 508 ]); 509 }