Name: compose
Owner: Underscore
Description: Compositional music composition using Scala, SuperCollider, and Web Audio.
Created: 2015-01-26 15:54:41.0
Updated: 2018-04-05 21:55:30.0
Pushed: 2017-08-08 18:12:48.0
Size: 1547
Language: Scala
GitHub Committers
User | Most Recent Commit | # Commits |
---|
Other Committers
User | Most Recent Commit | # Commits |
---|
A compositional music composition library.
Copyright 2015-2016 Dave Gurnell. Licensed Apache 2.
Compose is a library for writing songs using functional programming. It is split into a number of subprojects:
compose-core
- data structures and DSLs for building songs;compose-examples
- example songs written using compose-core
;compose-player
- players for the JVM and ScalaJS;compose-demo
- local project for quick experimentation (not published to Bintray).You can read more about Compose on the Underscore blog.
Compose is cross-built for the JVM and ScalaJS. The JVM player uses ScalaCollider and Supercollider to play songs using a synthesizer (a sine wave by default). The ScalaJS player uses the web audio API to play songs using samples.
On the JVM:
Install SuperCollider 3.7+
Set the environment variable SC_HOME
to point to
Content/Resources
inside your SuperCollider directory:
rt SC_HOME=/path/to/SuperCollider.app/Content/Resources
Run sbt demoJVM/run
In Javascript:
sbt demoJS/fastOptJS
If you're working on the JVM, you can add Compose to your SBT build as follows:
aryDependencies ++= Seq(
o.underscore" %% "compose-core" % "<<VERSION>>",
o.underscore" %% "compose-player" % "<<VERSION>>",
o.underscore" %% "compose-examples" % "<<VERSION>>"
If you're working in ScalaJS, use the following settings instead:
aryDependencies ++= Seq(
o.underscore" %%% "compose-core" % "<<VERSION>>",
o.underscore" %%% "compose-player" % "<<VERSION>>",
o.underscore" %%% "compose-examples" % "<<VERSION>>"
Once you've added Compose to your build, you can write songs as follows:
rt compose.core._
song =
te(Pitch.C3, Duration.Quarter) ~
te(Pitch.E3, Duration.Quarter) ~
te(Pitch.G3, Duration.Quarter) ~
te(Pitch.G3, Duration.Whole)
There are numerous shortcuts and conversions to make this code easier to write. Check out the examples for inspiration.
You can play your song on the JVM as follows:
rt compose.player._
rt scala.concurrent.Await
rt scala.concurrent.ExecutionContext.Implicits.global
rt scala.concurrent.duration.{ Duration => Dur }
reate a player:
aColliderPlayer.withPlayer(4) { player: ScalaColliderPlayer =>
Start the song playing:
l playing: Future[ScalaColliderPlayer.State] =
player.play(song, Tempo(180))
Wait for the song to finish:
ait.result(playing, Dur.Inf)
On ScalaJS, the code looks like the following:
rt compose.player._
rt scala.concurrent.Await
rt scala.concurrent.duration.{ Duration => Dur }
rt scalajs.concurrent.JSExecutionContext.Implicits.queue
reate a player:
player: WebAudioPlayer = new WebAudioPlayer()
tart the song playing:
playing: Future[WebAudioPlayer.State] =
ayer.play(song, Tempo(180))
ait for the song to finish:
t.result(playing, Dur.Inf)
That's all. If you have any questions, please ask on Gitter. Happy composing!
The samples in the samples
directory are sourced from the following places:
bell.wav
, beep1.wav
, and beep2.wav
created with Ableton Live;kick.wav
, snare.wav
, and hat.wav
from 808 Trapstep Volume 1 by [TRISAMPLES][trisamples];meow.wav
by Mr Smith, sourced from soundbible.com.