Mercurial > hg > may
changeset 562:3b07478932a1
Add sweeps and time-varying sinusoids
author | Chris Cannam |
---|---|
date | Thu, 01 May 2014 11:36:14 +0100 |
parents | c5afeb185539 |
children | 8c1b62eb33c7 |
files | src/may/mathmisc.yeti src/may/stream/syntheticstream.yeti src/may/stream/waves.yeti |
diffstat | 3 files changed, 43 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/src/may/mathmisc.yeti Wed Apr 30 13:32:14 2014 +0100 +++ b/src/may/mathmisc.yeti Thu May 01 11:36:14 2014 +0100 @@ -80,5 +80,6 @@ isPowerOfTwo, nextPowerOfTwo, random, + eps = 1e-15, }
--- a/src/may/stream/syntheticstream.yeti Wed Apr 30 13:32:14 2014 +0100 +++ b/src/may/stream/syntheticstream.yeti Thu May 01 11:36:14 2014 +0100 @@ -7,9 +7,14 @@ load may.stream.type; +/** + * Generate a stream using a generator function. The generator takes + * a sample index and returns a number in the range -1,+1. The + * generator is guaranteed to be called with sample indices in order + * 0,1,2,... so it may maintain state between calls if desired. + */ generated sampleRate generator = - (// generator takes sample number as arg, returns number in -1,+1 range - var position = 0; + (var position = 0; { get position () = position, get channels () = 1, @@ -29,6 +34,15 @@ sinusoid sampleRate freq = generated sampleRate (sin . (* (2 * pi * freq / sampleRate))); +varyingSinusoid sampleRate freqGenerator = + (var phase = 0; + generator i = + (ifreq = freqGenerator i; + result = sin phase; + phase := phase + 2 * pi * ifreq / sampleRate; + result); + generated sampleRate generator); + whiteNoise sampleRate = generated sampleRate \((Math#random() * 2.0) - 1.0); @@ -113,6 +127,7 @@ precalculatedMono is number -> vec.vector_t -> stream_t, precalculatedRepeated is number -> mat.matrix_t -> stream_t, sinusoid is number -> number -> stream_t, + varyingSinusoid is number -> (number -> number) -> stream_t, whiteNoise is number -> stream_t, silent is number -> stream_t, empty is number -> number -> stream_t,
--- a/src/may/stream/waves.yeti Wed Apr 30 13:32:14 2014 +0100 +++ b/src/may/stream/waves.yeti Thu May 01 11:36:14 2014 +0100 @@ -5,10 +5,10 @@ module may.stream.waves; { sinusoid, generated } = load may.stream.syntheticstream; -{ sum, scaledBy } = load may.stream.manipulate; -{ precalculatedRepeated } = load may.stream.syntheticstream; +{ sum, scaledBy, withDuration } = load may.stream.manipulate; +{ precalculatedRepeated, varyingSinusoid } = load may.stream.syntheticstream; { resampledTo } = load may.stream.resample; -{ gcd, floor, ceil } = load may.mathmisc; +{ gcd, floor, ceil, log10, pow, eps } = load may.mathmisc; load may.stream.type; @@ -75,6 +75,27 @@ fi; fi; +//!!! todo: test. How? +sineSweep sampleRate { startFrequency, endFrequency, duration, logarithmic } = + (forward = + if logarithmic then + do x: log10 if x < eps then eps else x fi done + else id + fi; + inverse = + if logarithmic then pow 10 + else id + fi; + a = forward startFrequency; + b = forward endFrequency; + withDuration duration + (varyingSinusoid sampleRate + do i: + dist = i / duration; + inverse (a + (b - a) * dist); + done) + ); + cached f sampleRate freq = (n = cycleLengthFor sampleRate freq; if n == 0 then @@ -96,6 +117,7 @@ saw is number -> number -> stream_t, triangle is number -> number -> stream_t, impulseTrain is number -> number -> stream_t, + sineSweep is number -> { startFrequency is number, endFrequency is number, duration is number, logarithmic is boolean } -> stream_t, cycleLengthFor is number -> number -> number, }