Skip to content

Instantly share code, notes, and snippets.

@danigb
Created April 3, 2016 20:23
Show Gist options
  • Save danigb/eee7e92371d1aa3fa65d7dbc380581ac to your computer and use it in GitHub Desktop.
Save danigb/eee7e92371d1aa3fa65d7dbc380581ac to your computer and use it in GitHub Desktop.

ScoreJS (next)

This is an explanation of how it works the 4th iteration of the scorejs prototype. All the examples shown are valid code (at least for today ;-)

Basics

The library makes two big assumptions:

  • an score is made by combining indivisible entities called elements: an object with a duration property. Currently the only type of elements supported are notes (an element with pitch property)
  • The notes (or any element) can be combined in two ways: sequentially or simultaneously. The resulting structures can be re-combined also in that two ways.

This is an example:

var melody = score.seq(score.note(1, 'C'), score.note(1, 'D'), score.note(1, 'E'))
var chord = score.sim(score.note(1, 'C'), score.note(1, 'E'), score.note(1, 'G'))
var song = score.sim(melody, chord)

The other important requirement (for me) is that the score (or score fragments) should be expressed in a declarative way. A serializable json format is the preferred way to express the above:

var melody = score(
  ['seq', ['note', 1, 'C'], ['note', 1, 'D'], ['note', 1, 'E']]
)
var chord = score(
  ['sim', ['note', 1, 'C'], ['note', 1, 'E'], ['note', 1, 'G']]
)
var song = score(['sim', melody, chord])

Since write this is not very practical, some helper functions are implemented:

var melody = score.phrase('C D E', 1)
var chord = score.chord('C E G', 1)

And since simultaneously is the default combination of the score function, the above example can be written as:

var song = score(['phrase', 'C D E', 1], ['chord', 'C E G', 1])

With this system (and the help of a couple of -currently implemented- helper functions) you can write something like this:

var song2 = score(
  ['melody', '4/4', 'c2 d2 e2 (f2 g2) | a2 b2 | c3'],
  ['harmony', '4/4', 'Cmaj7 | Dm7 G7 | Cmaj7'])

Transforming elements

The map function allows to create element transformations. For example:

var medioForte = score.map(function (element) {
  element.velocity = 50
  return element
})

The above code has the problem that it mutates the original element, so it's not mapping it. It should be written like this:

var medioForte = score.map(function (element) {
  return score.el(element, { velocity: 50 })
})

At can be used like this:

var song = score(
  [medioForte, ['phrase', 'C D E']],
  ['chord', 'C E Bb']
)

Functions currently implented: trans (to transpose notes), inst to assign instrument to notes, vel to set note velocity, and tempo to convert duration to seconds. Also some helpers: phrase to make a sequence of notes, chord to build a fragment of simultaneous notes and melody and harmony to parse measutres.

Create events

Any score can be converted to an array of time ordered events with the events function:

score.events(score(['phrase', 'C D E'])) // => [
  // { pitch: 'C', time: 0, duration: 1 }
  // { pitch: 'D', time: 1, duration: 1 }
  // { pitch: 'E', time: 2, duration: 1 } ]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment