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 }