NanoTunes
NanoTunes is a small schema for structuring music. This repository includes a JavaScript implementation, built upon OscillatorNode
.
Developers must shape their own sounds; NanoTunes is simply a means of representing the notes that should be played, and for how long per bar.
Try out the demo.
The Schema
The general structure is:
<Instrument Name /><Note 1><Letter /><Octave /><Length /></Note 1>...<Note n><Letter /><Octave /><Length /></Note>
Where:
<Instrument Name>
is a three-character string that refers to a previously defined instrument<Note n>
is a string composed of three ordered parts:
- The note's musical letter (A-G), and an optional # to sharpen the note by a semitone.
X0
can be used as a rest note - The octave (1-8)
- The length of the note (1-16)
A "Note" On Note Lengths
As of this version, NanoTunes only supports semiquaver (1/16th) resolution (this will hopefully be increased in the next major release.) Essentially, this means:
- A note length of
16
will last for a whole bar (semibreve) - A note length of
8
will last for half a bar (minim) - A note length of
4
will last for half a bar (crotchet) - A note length of
2
will last for half a bar (quaver) - A note length of
1
will last for half a bar (semiquaver)
Example
VOXC44A#412
translates to:
- Play this track with a user-defined instrument called "VOX";
- Play C4 for a quaver length;
- Play A#4 for the remainder of the bar;
JavaScript Implementation
Example
'use strict';
var instruments = {
VOX: {
wave: 'square',
pan: -0.5,
gain: 0.3
},
BSS: {
wave: 'triangle',
pan: 0.5,
gain: 0.7
},
GTR: {
wave: 'sawtooth',
pan: 0.8,
gain: 0.4
},
};
var tracks = {
title: {
bpm: 180,
isLooping: true,
parts: [
'VOXC44C44G44A44A#44A44G44E44',
'GTRC32C42C32C42E32E42E32E42G32G42G32G42C32C42C32C4',
'BSSC24C24G14G14A#14A#14B14B14',
]
}
};
var nanoTunes = new NT(instruments, tracks);
nanoTunes.play('title');
File Sizes:
- Unminified - 4.3 KB
- Minified - 1.6 KB
- Minified and gzipped - 830 bytes
Browser Compatibility
- Chrome
- Firefox
- Edge
- Safari - works, but somewhat buggy
Setup
npm
Nanotunes is available as a CommonJS module, which is compatible with Browserify and Webpack.
npm i --save nanotunes
This module exposes the NT
constructor directly:
'use strict';
const NT = require('nanotunes');
const nanoTunes = new NT(instruments, tracks);
Standalone
There are two scripts in the dist
directory
- An unminified version for those who minify everything
- A minified version for those who bundle third-party dependencies separately
Loading this script will attach the NT
constructor to the window
object.
API
NT(instruments, tracks [, audioContext])
A constructor function to create a new instance of NanoTunes. The third parameter, which is optional, allows you to use a previously instantiated AudioContext
. This is desirable if, for example, you're also generating sound effects with the Web Audio API.
Defining Instruments
The instruments
parameter is an Object
whose keys are three-letter instrument names. The below properties can be configured for each definition. most of which conform with the Web Audio API:
-
wave
- the instrument's waveform. This can be any value assignable value to OscillatorNode.type
. Unfortunately, custom waves aren't supported at this time, but will be available in the next major release
-
pan
- controls the instrument's stereo panning. Like StereoPannerNode
's pan
property, it can range from -1 for the left speaker, to 1 for the right speaker
-
gain
- controls the instrument's pre-output gain. Like GainNode
's gain
property, it can be a positive number
Defining Tracks
The tracks
parameter is an Object
whose keys are identifiable track names. For each, these properties can be specified:
-
bpm
: - the song's beats per minute
-
isLooping
- the song will loop infinitely if this is truthy, otherwise it will automatically stop after a single play
-
parts
- an array of strings for each track. These will be played in parallel
NT.prototype.play(trackName)
Plays a track by name.
NT.prototype.stop()
Stops playing the current track.
The onStop
callback
It's possible to attach a method to your NanoTunes instance called onStop
. This will invoke whenever a non-looping track ends. This is useful for scheduling.
var nanoTunes = new NT(instruments, tracks);
nanoTunes.onStop = function onStop() {
console.log('Current track has ended.');
};
Building Locally
run npm i
in the project's directory, which will install Babel. This is used to transpile ES2015 block variables and arrow functions to their ES5 counterparts, because Closure Compiler doesn't support this latest standard as a compilation target. I therefore thought that it would beneficial to align the languages of both the unminified and minified versions. Once Closure supports ES2015 traspilation, Babel will be removed.
Additionally, the minified build is generated by Closure Compiler. You'll need to download the compiler JAR and expose it to your environment as closure-compiler
. You can achieve this by writing a shell wrapper and placing this in one of your $PATH
's directories.
Scripts
npm run build
- builds both versions of the distributable, and copies the minified version to the demo
directory
Tests
There are some unit tests which can be run with npm test
. Increasing coverage is ongoing. Functional tests will also be available soon.