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 }