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 <ae@cy.md> 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 enum sampleMax(T) = is(T : long) ? T.max : T(1); 25 26 /// Simple wave generator. 27 auto squareWave(T)(real interval) 28 { 29 return infiniteIota!size_t 30 .map!(n => cast(T)(sampleMax!T + cast(int)(n * 2 / interval) % 2)); 31 } 32 33 /// ditto 34 auto sawToothWave(T)(real interval) 35 { 36 return infiniteIota!size_t 37 .map!(n => cast(T)((n % interval * 2 - interval) * sampleMax!T / interval)); 38 } 39 40 /// ditto 41 auto triangleWave(T)(real interval) 42 { 43 return infiniteIota!size_t 44 .map!(n => cast(T)((abs(n % interval * 2 - interval) * 2 - interval) * sampleMax!T / interval)); 45 } 46 47 /// ditto 48 auto sineWave(T)(real interval) 49 { 50 return infiniteIota!size_t 51 .map!(n => (sin(n * 2 * PI / interval) * sampleMax!T).to!T); 52 } 53 54 /// ditto 55 auto whiteNoise(T)() 56 { 57 import std.random; 58 return infiniteIota!size_t 59 .map!(n => cast(T)Xorshift(cast(uint)n).front); 60 } 61 62 /// ditto 63 auto whiteNoiseSqr(T)() 64 { 65 import std.random; 66 return infiniteIota!size_t 67 .map!(n => Xorshift(cast(uint)n).front % 2 ? sampleMax!T : T.min); 68 } 69 70 /// Fade out this wave (multiply samples by a linearly descending factor). 71 auto fade(W)(W w) 72 { 73 alias T = typeof(w.front); 74 sizediff_t dur = w.length; 75 return dur.iota.map!(p => cast(T)(w[p] * (dur-p) / dur)); 76 } 77 78 /// Stretch a wave with linear interpolation. 79 auto stretch(W)(W wave, real factor) 80 { 81 static if (is(typeof(wave.length))) 82 { 83 auto length = cast(size_t)(wave.length * factor); 84 auto baseRange = length.iota; 85 } 86 else 87 auto baseRange = infiniteIota!size_t; 88 return baseRange 89 .map!((n) { 90 auto p = n / factor; 91 auto ip = cast(size_t)p; 92 return cast(typeof(wave.front))itpl(wave[ip], wave[ip+1], p, ip, ip+1); 93 }); 94 }