Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/zya/beet.js

Polyrhythmic Sequencer library for Web Audio API.
https://github.com/zya/beet.js

audio js library music sequencing webaudio webaudio-api

Last synced: 13 days ago
JSON representation

Polyrhythmic Sequencer library for Web Audio API.

Awesome Lists containing this project

README

        

# beet.js
Polyrhythmic Sequencer library for Web Audio API.

The sequencer can have multiple layers where each layer has a different step count. This feature allows the user to create complex [polyrhythms](https://en.wikipedia.org/?title=Polyrhythm) and [euclidean rhythms](http://cgm.cs.mcgill.ca/~godfried/publications/banff.pdf) using a simple api.
### Installation
You can install `beet` from npm.
````
npm install beet.js
````
Or grab the latest version from [build folder](https://github.com/zya/beet.js/tree/master/build) and include it in your html.
````html

````
### Example Usage
````js
var context = new AudioContext();

// initialize beet
var beet = new Beet({
context: context,
tempo: 100
});

// create a euclidean pattern - 5 pulses distrubted in 7 steps
var pattern = beet.pattern(5,7);

// create a beet layer - pass it the pattern and a callback
var layer = beet.layer(pattern, callback);

function callback(time){
var osc = context.createOscillator();
osc.connect(context.destination);
osc.start(time);
osc.stop(time + 0.1);
}

// add the layer
beet.add(layer);

// start the sequencer
beet.start();
````
## API

### Beet

#### `new Beet(opts)`
Beet constructor. Returns a new instance of beet.

#### Parameters
* `opts` (required) - an object containing the initialisation options
* context (required) - an instance of AudioContext
* tempo (optional) - speed in BPM - defaults to 120

#### `beet.start(time)`

Starts the sequencer after a given time in seconds.

#### Parameters
* `time` - a number in seconds - defaults to 0

#### `beet.stop(time)`

Stops the sequencer after a given time in seconds and resets the current step number.

#### Parameters
* `time` (optional) - a number in seconds - defaults to 0

#### `beet.pause(time)`

Pauses the sequencer after a given time in seconds but keeps the current step number.

#### Parameters
* `time` (optional) - a number in seconds - defaults to 0

#### `beet.add(layer(s))`

Adds a given `beet.layer` to the list of layers to play. Can also be used with multiple layers. `beet.add(layer1, layer2)`

#### Parameters
* `layer` (Required) - a `beet.layer` object.

#### `beet.remove(layer)`

Removes a given `beet.layer` from the list of layers to play.

#### Parameters
* `layer` (Required) - a `beet.layer` object.

### Pattern
The pattern method will return a `pattern` object based on the provided values. If `pulses` and `steps` are passed in as numbers, an equally distributed pattern will be generated and returned. Alternatively, you can use a custom pattern string. For example '1000101010'.
#### `beet.pattern(pulses, steps)`
Returns a `pattern` object containing a [bjorklund](https://github.com/zya/bjorklund) sequence with equally distributed number of `pulses` over `steps`.

#### Parameters
* `pulses` (required) - number of pulses (active steps) in the sequence
* `steps` (optional) - number of steps in the sequence - value of `pulses` will be used steps is not specified.

#### example
````js
var pattern = beet.pattern(3, 7);
// a pattern object containing a sequence as below
// '1010100'

var pattern2 = beet.pattern(4);
// a pattern object with a sequence as below
// '1111'
````

#### `beet.pattern(patternString)`
Returns a `pattern` object containing a the custom pattern. This can be used to generated custom sequences when neccessary.

#### Parameters
* `patternString` (required) - a binary sequence string with an arbitrary length using `1`'s for pulses and `0`'s for empty slots.

#### example
````js
var pattern = beet.pattern('100010010');
var pattern2 = beet.pattern('10001111');
````

#### `.update(pulses, steps)`
Updates the pattern object with the new values. You can also update the values directly. See example below.

#### Parameters
* `pulses` (required) - number of pulses (active steps) in the sequence.
* `steps` (optional) - number of steps in the sequence. value of `pulses` will be used steps is not specified.

#### example
````js
var pattern = beet.pattern(2, 5);
pattern.update(5,8); // updates the pattern to '10100'

// you can also set the values separately
pattern.pulses = 4;
pattern.steps = 8;
````

#### `.shift(offset)`
Shifts the sequence by the offset and returns the pattern object.

#### Parameters
* `offset` (required) - number of steps to shift the sequence by

#### example
````js
var pattern = beet.pattern(1, 4); // returns '1000'
pattern.shift(1) // updates the sequence to '0100'
````

### Layer
#### `layer(pattern, onCallback, offCallback)`
Creates a `beet.layer` object and returns it.

#### Parameters
* `pattern` (required) - a `beet.pattern` object.
* `onCallback` (required) - a function to call on pattern's pulses e.g. 1's
* `offCallback` (optional) - a function to call on pattern's empty slots e.g. 0's.

#### example
````js
var pattern = beet.pattern(1, 4); // returns '1000'
var layer = beet.layer(pattern, on, off);
// on will be called on 1
// off will be called on 0's
````
#### Callback format
The callbacks are functions that will be called from the scheduler.
The functions will be called with `time`, `step` and `timeFromScheduled` parameters.
You can use the `time` parameter for web audio methods. `step` can be used to change audio behaviour according to the current step.
`timeFromScheduled` is a value in seconds which corresponds to the time it will take for an audio event to occur from the time it was scheduled (`time - context.currentTime`). It can be used to schedule JS events using `setTimeout`.

#### example
````js
function callback (time, step, timeFromScheduled) {
var osc = context.createOscillator();
osc.connect(context.destination);
if(step === 1){
osc.frequency.value = 880;
}
osc.start(time);
osc.stop(time + 0.2);
setTimeout(function(){
// trigger some js event such as animation - will be synced to the audio
}, timeFromScheduled * 1000);
}
````

#### Play/Pause/Stop layers
You can play and pause individual layers using:
````js
var pattern = beet.pattern(1, 4); // returns '1000'
var layer = beet.layer(pattern, on, off);
layer.play()
layer.pause()
layer.stop()
````

### Utils
Beet comes with a series of useful utilities for web audio api. These might me moved to a separate module in the future as these are not specific to beet's functionality. But for now, features will be added gradually.

#### `.envelope(audioparam, now, opts)`
Applies an envelope to the audio param given a series of options.

#### Parameters
* `audioparam` (required) - an [AudioParam](https://developer.mozilla.org/en-US/docs/Web/API/AudioParam) object to be automated.
* `now` (required) - the time for the automation to start, e.g. the time parameter in `beet` callback.
* `opts` (optional) - an JavaScript object that contains the envelope parameters.
* `start` (optional) - the start value for the automation curve. the audio param will be set to this value at the beginning of the automation.
* `peak` (optional) - the maximum value for the automation curve that the attack stage will end up in.
* `attack` (optional) - the time in seconds for the attack stage.
* `decay` (optional) - the time in seconds for the decay stage.
* `sustain` (optional) - the value for that the decay stage will end up in.
* `release` (optional) - the time in seconds for the release stage.

#### example
````js
var osc = context.createOscillator();
var gain = context.createGain();
osc.connect(gain);
gain.connect(context.destination);

beet.utils.envelope(gain.gain, time, {
start: 0,
peake: 1.0,
attack: 0.1,
decay: 0.2,
sustain: 0.8,
release: 0.5
});

osc.start(time);
osc.stop(time + 2);
````

#### `.load(path, success, failure, context)`
Loads an audio file for a given path and returns a decoded [AudioBuffer](https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer) object.

#### Parameters
* `path` (required) - the path to your audio file.
* `success` (required) - function to be called on load success. The passed function will be called with a `buffer` parameters which is an AudioBuffer object.
* `failure` (required) - function to be called on load or decode error.
* `context` (optional) - an instance of AudioContext, if not provided, global variable `context` will be used

#### example
````js
beet.utils.load('path/to/file.wav', function(buffer){
// do something with the buffer
}, failureHandler, context);
````

#### `.mtof(midi_note)`
Converts a give midi note to a frequency value in hz.

#### Parameters
* `midi_note` (required) - the midi note number (0 to 127).
#### example
````js
beet.utils.mtof(69); // will return 440 for A4
````

#### `.ntof(note_name)`
Converts a given note name to a frequency value in hz.

#### Parameters
* `note_name` (required) - the note name followed by octave e.g. 'a4'
#### example
````js
beet.utils.ntof('a4'); // will return 440 for A4
````

#### `.mtop(midi_note)`
Converts a given midi note to a value representing the [`playbackRate`](https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode/playbackRate).

#### Parameters
* `midi_note` (required) - the midi note number (0 to 127).
#### example
````js
beet.utils.mtop(60); // will return 1 for C4 - meaning the sample will be played in the original speed
beet.utils.mtop(72); // will return 2 for C3
beet.utils.mtop(48); // will return 0.5 for C2
````