1 /**
2  * Some simple wave generator functions.
3  *
4  * License:
5  *   This Source Code Form is subject to the terms of
6  *   the Mozilla Public License, v. 2.0. If a copy of
7  *   the MPL was not distributed with this file, You
8  *   can obtain one at http://mozilla.org/MPL/2.0/.
9  *
10  * Authors:
11  *   Vladimir Panteleev <vladimir@thecybershadow.net>
12  */
13 
14 module ae.utils.sound.wave;
15 
16 import std.algorithm;
17 import std.conv;
18 import std.math;
19 import std.range;
20 
21 import ae.utils.math;
22 import ae.utils.range;
23 
24 auto squareWave(T)(real interval)
25 {
26 	return infiniteIota!size_t
27 		.map!(n => cast(T)(T.max + cast(int)(n * 2 / interval) % 2));
28 }
29 
30 auto sawToothWave(T)(real interval)
31 {
32 	return infiniteIota!size_t
33 		.map!(n => cast(T)((n % interval * 2 - interval) * T.max / interval));
34 }
35 
36 auto triangleWave(T)(real interval)
37 {
38 	return infiniteIota!size_t
39 		.map!(n => cast(T)((abs(n % interval * 2 - interval) * 2 - interval) * T.max / interval));
40 }
41 
42 auto sineWave(T)(real interval)
43 {
44 	return infiniteIota!size_t
45 		.map!(n => (sin(n * 2 * PI / interval) * T.max).to!T);
46 }
47 
48 auto whiteNoise(T)()
49 {
50 	import std.random;
51 	return infiniteIota!size_t
52 		.map!(n => cast(T)Xorshift(cast(uint)n).front);
53 }
54 
55 auto whiteNoiseSqr(T)()
56 {
57 	import std.random;
58 	return infiniteIota!size_t
59 		.map!(n => Xorshift(cast(uint)n).front % 2 ? T.max : T.min);
60 }
61 
62 // Fade out this wave (multiply samples by a linearly descending factor).
63 auto fade(W)(W w)
64 {
65 	alias T = typeof(w.front);
66 	sizediff_t dur = w.length;
67 	return dur.iota.map!(p => cast(T)(w[p] * (dur-p) / dur));
68 }
69 
70 // Stretch a wave with linear interpolation
71 auto stretch(W)(W wave, real factor)
72 {
73 	static if (is(typeof(wave.length)))
74 	{
75 		auto length = cast(size_t)(wave.length * factor);
76 		auto baseRange = length.iota;
77 	}
78 	else
79 		auto baseRange = infiniteIota!size_t;
80 	return baseRange
81 		.map!((n) {
82 				auto p = n / factor;
83 				auto ip = cast(size_t)p;
84 				return cast(typeof(wave.front))itpl(wave[ip], wave[ip+1], p, ip, ip+1);
85 		});
86 }