Skip to content

Instantly share code, notes, and snippets.

@Sciss
Created April 13, 2020 20:18
Show Gist options
  • Save Sciss/4faa433a3c990f024e2ac7569a7e281f to your computer and use it in GitHub Desktop.
Save Sciss/4faa433a3c990f024e2ac7569a7e281f to your computer and use it in GitHub Desktop.
def snd = AudioFileIn("in")
val dur = 60.0
val sr = snd.sampleRate
val framesIn = snd.numFrames
val framesOut = (dur * sr).toInt
def mkPosBs(el: Double = 0.0, posSq: Seq[Double] = Nil, bsSq: Seq[Double] = Nil): (GE, GE) =
if (el >= dur) (ValueDoubleSeq(posSq: _*), ValueDoubleSeq(bsSq: _*))
else {
val pos = el / dur
val bs = (pos * 2 * math.Pi).sin.linLin(-1, 1, 0.5, 3.0)
mkPosBs(el + bs/2, posSq :+ pos, bsSq :+ bs)
}
val (pos, bs) = mkPosBs()
var mix = Seq(0.5, 1, 1.5, 2, 4).foldLeft(0.0: GE) { (in, speed) =>
val f = speed.reciprocal
val r = Resample(snd, f)
val frInR = framesIn * f
val posInFr = (pos * frInR).toInt
val posOutFr= (pos * framesOut).toInt
val winSz = (bs * sr).toInt.nextPowerOfTwo // toInt
val step = posOutFr.differentiate
val spans = posInFr zip (posInFr + winSz)
val slic = Slices(r, spans)
val fft = Real1FFT(slic, winSz)
val mag = fft.complex.mag
val phase = fft.complex.phase
val freq0 = pos * 5000 + 1000
val magSz = winSz/2
val freqN = RepeatWindow(freq0 / sr, 1, magSz)
val lpf = LPF(mag, freqN)
val rec = (lpf zip phase).complex.polToCar
val ifft = Real1IFFT(rec, winSz)
val layer = ifft * GenWindow.Hann(winSz)
val lap = OverlapAdd(layer, winSz, step).take(framesOut)
in + LeakDC(lap)
}
val amp = mix.abs.maximum
val norm = BufferDisk(mix) / amp
AudioFileOut("out", norm, sampleRate = sr)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment