Created
May 4, 2012 22:34
-
-
Save rndmcnlly/2598145 to your computer and use it in GitHub Desktop.
snapshot of cfml in scala
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package as.adamsmith.riddle.instructions | |
import java.util.concurrent._ | |
object InstructionBuilders { | |
def after[A](children: Instruction[A]*) = children.reduce(After(_, _)) | |
def during[A](children: Instruction[A]*) = children.reduce(During(_, _)) | |
def choose[A](children: Instruction[A]*) = | |
Resolve(() => children((math.random * children.length).asInstanceOf[Int]) ) | |
def call[A](f: => Instruction[A]) = Resolve(() => f) | |
def halt[A] = Halt[A]() | |
def nop[A] = Nop[A]() | |
def pulse[A](count: Int, duration: Long, job: A => Unit): Instruction[A] = | |
repeat(count, after(delay(duration), exec(job))) | |
def rotate[A](children: Instruction[A]*) = { | |
var i: Int = 0 | |
Resolve(() => { | |
val kid = children(i % children.length) | |
i += 1 | |
kid | |
}) | |
} | |
def loopWhile[A](pred: => Boolean, child: Instruction[A]): Instruction[A] = | |
Resolve(() => | |
if (pred) After(child, loopWhile(pred, child)) else Nop() | |
) | |
def repeat[A](count: Int, child: Instruction[A]) = | |
List.fill(count)(child).reduce(After(_,_)) | |
def forever[A](child: Instruction[A]): Instruction[A] = | |
after(child, Resolve(() => forever(child))) | |
def exec[A](f: A => Unit) = Exec[A]((s,t) => f(s)) | |
def tweak[A](f: A => A, child: Instruction[A]) = Tweak[A]((s,t) => f(s), child) | |
def delay[A](dur: Long) = Delay[A](dur) | |
} | |
object Instruction { | |
def now: Long = System.currentTimeMillis | |
val anticipationMillis = 0L | |
private var service: Option[ScheduledExecutorService] = None | |
private def ensureServiceable { | |
synchronized { | |
if (service.isEmpty) { | |
service = Some(Executors.newSingleThreadScheduledExecutor()) | |
} | |
} | |
} | |
def schedule(cmd: () => Unit, whenMillis: Long) { | |
synchronized { | |
assume(service.isDefined) | |
service.get.schedule(new Runnable { | |
def run() = cmd() | |
}, whenMillis - now, TimeUnit.MILLISECONDS) | |
} | |
} | |
def shutdown() { | |
synchronized { | |
assume(service.isDefined) | |
service.get.shutdownNow() | |
service = None | |
} | |
} | |
def launch[A](instruction: Instruction[A], initialState: A, onComplete: () => Unit) { | |
ensureServiceable | |
schedule(() => execute(instruction, initialState, now, { t => onComplete() }), now) | |
} | |
def execute[S](instruction: Instruction[S], s: S, t: Long, k: Long => Unit): Unit = { | |
instruction match { | |
case Halt() => Instruction.schedule(() => shutdown(), t) | |
case Nop() => k(t) | |
case Spawn(child) => { | |
execute(child, s, t, _=>()) | |
k(t) | |
} | |
case Exec(f) => { | |
schedule(() => f(s, t), t) | |
k(t) | |
} | |
case Delay(dur) => | |
schedule(() => k(t + dur), t + dur - anticipationMillis) | |
case During(left, right) => { | |
var other: Option[Long] = None | |
def complete(dur: Long) = | |
other match { | |
case None => other = Some(dur) | |
case Some(otherDur) => k(math.max(dur, otherDur)) | |
} | |
execute(left, s, t, complete) | |
execute(right, s, t, complete) | |
} | |
case After(l, r) => execute(l, s, t, { later => execute(r, s, later, k) }) | |
case Resolve(thunk) => execute(thunk(), s, t, k) | |
case Tweak(f, child) => execute(child, f(s, t), t, k) | |
} | |
} | |
} | |
sealed trait Instruction[A] | |
case class Halt[A]() extends Instruction[A] | |
case class Nop[A]() extends Instruction[A] | |
case class Spawn[A](child: Instruction[A]) extends Instruction[A] | |
case class Exec[A](f: (A, Long) => Unit) extends Instruction[A] | |
case class Delay[A](dur: Long) extends Instruction[A] | |
case class After[A](left: Instruction[A], right: Instruction[A]) extends Instruction[A] | |
case class During[A](left: Instruction[A], right: Instruction[A]) extends Instruction[A] | |
case class Resolve[A](thunk: () => Instruction[A]) extends Instruction[A] | |
case class Tweak[A](f: (A, Long) => A, child: Instruction[A]) extends Instruction[A] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package as.adamsmith.riddle | |
import as.adamsmith.riddle.instructions._ | |
import as.adamsmith.riddle.instructions.InstructionBuilders._ | |
import net.beadsproject.beads.core._ | |
import net.beadsproject.beads.ugens._ | |
import net.beadsproject.beads.data._ | |
object Main extends App { | |
val filename = | |
"39914__digifishmusic__katy-sings-laaoooaaa.wav" | |
val samp = SampleManager.sample(getClass.getClassLoader.getResourceAsStream(filename)) | |
val ac = new AudioContext() | |
val players = List( | |
new SamplePlayer(ac, samp), | |
new SamplePlayer(ac, samp) { setPitch(new Static(ac, 1.5f)) }, | |
new SamplePlayer(ac, samp) { setPitch(new Static(ac, 0.5f)) }) | |
val rev = new Reverb(ac, 2) { | |
setDamping(0f) | |
} | |
val g = new Gain(ac, 1, 1.5f) | |
players foreach (rev addInput _) | |
g addInput rev | |
ac.out addInput g | |
ac.start() | |
def doSkip(s: Map[SamplePlayer,Float]) = | |
for ((player, pos) <- s) | |
player.setPosition(pos) | |
def shiftSkip(s: Map[SamplePlayer,Float]) = | |
(for(p <- players) yield p -> (samp.getLength*math.random).toFloat).toMap | |
val root: Instruction[Map[SamplePlayer,Float]] = | |
forever(tweak(shiftSkip, pulse(32, 125L, doSkip))) | |
Instruction.launch( | |
root, | |
(for(p <- players) yield p -> 0f).toMap, | |
{ () => ac.stop(); System.exit(0) }) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment