Home

Awesome

RetroJS - a Web Audio API experimental player

The RetroJS is a music parser and player that uses the Web Audio API. Created as an experiment (and for lots of fun), it parses a custom musical notation input, and outputs the sound through the browser.

Demo: http://eshiota.github.io/retro-audio-js/

Usage

Create a Player instance:

var player = new Player();

Load songs either through the load method, passing the JSON song as parameter; or load it through the loadUrl method, passing an URL that serves the JSON song.

// load a locally defined JSON song
var mysong = {
  "title" : "Test song",
  "tempo" : 60,
  "time_signature" : "4/4",
  "score" : [
    {
      "instrument" : "oscillator-sine",
      "volume" : 0.5,
      "sheet" : [ "C.4", "D.4", "E.4", "F.4", "G.4", "A.4", "B.4", "C5.4" ]
    }
  ]
};

player.load(mysong);

// or load an URL serving the JSON song
player.loadUrl("http://www.foo.com/mysong.json");

Musical notation

WARNING: This musical notation will change as needed, and I'll try to keep backwards compatibility whenever possible. But whenever that's not possible, please be patient, and sorry. =)

Every song is a JSON object with a title, tempo, time signature, and the score itself. The tempo always refer to how many quarter notes (crochets) are played per second.

Please check the provided examples on /src/songs/.

{
  "title" : "Test song",
  "tempo" : 60,
  "time_signature" : "4/4",
  "score" : []
};

The score and tracks

The score is an array of tracks. A track is an object with an instrument (identified by a string), volume (a float from 0 to 1), and a sheet. A sheet is an array of notes or chords. All instruments must share a common way of writing a note's value and key, and some may have their own properties (a drumkit has no keys, for example).

{
  "instrument" : "oscillator-sine",
  "volume" : 0.5,
  "sheet" : [ "C.4", "D.4", "E.4", "F.4", "G.4", "A.4", "B.4", "C5.4" ]
}

The notes

A note is a string with the following format:

[key/rest/sample information].[duration information]

The information to the left of the dot tells either the note's key (C, D, E...), or if the note is a rest, or if any other information for a specific instrument.

The information to the right tells the note's value—given the song's tempo, it tells what's the duration of the note.

Keys and rests

A key is a letter from A to G, plus an option accidental, plus an optional octave information. Some examples:

A rest is always represented as a dash -. If a track has a period of silence, always use a rest. Every empty space must be filled so that the parser calculates the correct cycle position for each note.

Values

The note's value represents the length of a note. The final duration will be a product of the length of the note, times the tempo of the song.

More information: http://en.wikipedia.org/wiki/Note_value

The notation is always related to the fraction of a whole note (semibreve), which has a value of 1. So:

The notation also supports a few modifiers:

Whenever a parser finds a tuplet note, the following "n-1" notes are considered part of it, being "n" the tuplet value. So ["C.8T3", "C.8T3", "C.8T3"] is the same as ["C.8T3", "C.8", "C.8"].

Chords

Chords are array of notes inside a sheet.

"sheet" : [ ["C.4", "E.4", "G.4"], "D.4", "E.4" ]

In the example above, the C.4, E.4, G.4 notes are played together, followed by D.4 and E.4.

The parser always assume that the chord has the duration of the longest note inside the array. If any of the notes is indicated as part of a tuplet, the whole chord is considered as part of it.

Instruments

Currently, these are the supported instruments:

Controls

The RetroJS player may be controlled through DOM nodes using the Controls class. It uses the following data attributes to bind them to the player:

Here's a sample markup:

<div data-player-controls>
    <div data-song-controls>
      <select data-song-select>
        <option value="src/songs/test.json">Test</option>
      </select>

      <button type="button" data-song-load>Load</button>
    </div>

    <div data-playback-controls>
      <button type="button" data-play>Play</button>
      <button type="button" data-pause>Pause</button>
      <button type="button" data-stop>Stop</button>
    </div>

    <div data-song-info>
      <p data-current-song>Please load a song</p>
    </div>
  </div>
</div>

Current limitations

These are the player's limitations that have no priority to be fixed:

Contributing

Always check the project's issues to see whether what's left to be fixed, and what's already been done or dismissed.

  1. Fork the project
  2. Create a topic branch - git checkout -b my_branch
  3. Push to your branch - git push origin my_branch
  4. Create an Issue with a link to your branch
  5. That's it!

Respect the project's code standards, and the JSHint options.

License

(The MIT License)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.