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