Skip to content

Instantly share code, notes, and snippets.

@Sciss
Last active May 6, 2018 11:55
Show Gist options
  • Save Sciss/496609c7507746870f06ec10a93fd35d to your computer and use it in GitHub Desktop.
Save Sciss/496609c7507746870f06ec10a93fd35d to your computer and use it in GitHub Desktop.
import de.sciss.kollflitz.Vec
import de.sciss.kollflitz.Ops._
case class Segment(numFrames: Int, targetLevel: Double, curve: Curve = Curve.linear) {
require (numFrames > 0)
}
object Envelope {
implicit def constant(f: Double): Envelope = Envelope(f, Vector.empty)
}
case class Envelope(startLevel: Double, segments: Vec[Segment]) {
private[this] val pairs = (Segment(numFrames = 1, targetLevel = startLevel) +: segments).mapPairs { (s1, s2) =>
s1.targetLevel -> s2
}
/* private[this] */ val frameAccum = {
(0 +: segments.map(_.numFrames)).integrate.toArray
}
/* private[this] */ val numFrames = if (frameAccum.isEmpty) 0 else frameAccum.last
/* private[this] */ val lastLevel = if (segments .isEmpty) startLevel else segments.last.targetLevel
def levelAt(frame: Int): Double = {
if (frame <= 0) startLevel else if (frame >= numFrames) lastLevel
else {
val i = java.util.Arrays.binarySearch(frameAccum, frame)
val j = if (i < 0) -(i + 2) else i
println(s"i = $i, j = $j, pairs.size = ${pairs.size}, frameAccum.size = ${frameAccum.size}")
val (startLevel, seg) = pairs(j)
val pos = (frame - frameAccum(j)).toDouble / seg.numFrames
seg.curve.levelAt(pos = pos.toFloat, y1 = startLevel.toFloat, y2 = seg.targetLevel.toFloat)
}
}
}
val e1 = 3.4: Envelope
e1.levelAt(-1)
e1.levelAt(0)
e1.levelAt(1)
val e2 = Envelope(3.4, Vector(Segment(1000, 4.0)))
e2.levelAt(-1)
e2.levelAt(0)
e2.levelAt(1)
e2.levelAt(999)
e2.levelAt(1000)
e2.levelAt(1001)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment