sample-player
Flexible audio sample player for browser:
var player = require('sample-player')
var ac = new AudioContext()
var sample = player(ac, <AudioBuffer>)
sample.start()
sample.start()
sample.stop()
## Features
Create multi-sample player
Pass a map of names to audio buffers to create a multi-sample player:
var player = require('sample-player')
var ac = new AudioContext()
var drums = player(ac, {
kick: <AudioBuffer>,
snare: <AudioBuffer>,
hihat: <AudioBuffer>
})
drums.start('kick')
drums.start('snare', ac.currentTime, { gain: 0.5 })
Map note names to midi (and oposite)
If the buffers are mapped to note names, you can pass note names (including enharmonics) or midi numbers:
var samples = { 'C2': <AudioBuffer>, 'Db2': <AudioBuffer>, ... }
var piano = player(ac, samples)
piano.start(69)
piano.start('C#2')
Decimal midi note numbers can be used to detune the notes:
piano.start(69.5)
Events
You can register event handlers with the on
function:
var drums = player(ac, { kick: ..., snare: ..., hihat ... })
drums.on('start', function (when, name) {
console.log('start', name)
})
drums.on('ended', function (when, name) {
console.log('ended', name)
})
drums.start('kick')
To add a listener to all events use: player.on(function (eventName, when, obj, opts))
.
Currently it fires: start
, started
, stop
, ended
, scheduled
Amplitude envelope control
You can apply an amplitude envelope control player-wide or shot-wide. You can pass a signle adsr
option with an array of [attack, decay, sustain, release]
or add each parameter to the options object:
var longSound = player(ac, <AudioBuffer>, { adsr: [1.2, 0.5, 0.8, 1.3] })
longSound.start()
longSound.start(ac.currentTime + 10, { attack: 3 })
#### Listen to midi inputs
Easily attach the player to a Web MIDI API MidiInput
:
var piano = player(...)
window.navigator.requestMIDIAccess().then(function (midiAccess) {
midiAccess.inputs.forEach(function (midiInput) {
piano.listenToMidi(midiInput)
})
})
#### Schedule to play buffers at given times
var buffers = { 'C2': <AudioBuffer>, 'Db2': <AudioBuffer>, ... }
var marimba = player(ac, buffers)
marimba.schedule(ac.currentTime, [
{ note: 'c2', time: 0, gain: 0.9 },
{ note: 'e2', time: 0.25, gain: 0.7 },
{ note: 'g2', time: 0.5, gain: 0.5 },
{ note: 'c3', time: 0.75, gain: 0.3 }
])
## Install
Via npm: npm i --save sample-player
or grab the browser ready file which exports SamplePlayer
as window global.
Options
The options can be passed to the SamplePlayer
function to apply to all buffers, or to start
function to apply to one shot.
gain
: float between 0 to 1attack
: the attack time of the amplitude envelopedecay
: the decay time of the amplitude envelopesustain
: the sustain gain value of the amplitude enveloperelease
: the release time of the amplitude envelopeadsr
: an array of [attack, decay, sustain, release]
. Overrides other parameters.duration
: set the playing duration in seconds of the buffer(s)loop
: set to true to loop the audio buffer
API
SamplePlayer(ac, source, options) ⇒ player
Create a sample player.
Returns: player
- the player
Param | Type | Description |
---|
ac | AudioContext | the audio context |
source | ArrayBuffer | Object.<String, ArrayBuffer> | |
options | Onject | (Optional) an options object |
Example
var SamplePlayer = require('sample-player')
var ac = new AudioContext()
var snare = SamplePlayer(ac, <AudioBuffer>)
snare.start()
player.play
An alias for player.start
See: player.start
player.start(name, when, options) ⇒ AudioNode
Start a sample buffer. The returned object has a function stop(when)
to stop the sound.
Returns: AudioNode
- an audio node with a stop
function
Param | Type | Description |
---|
name | String | the name of the buffer. If the source of the SamplePlayer is one sample buffer, this parameter is not required |
when | Float | (Optional) when to start (current time if by default) |
options | Object | additional sample playing options |
Example
var sample = player(ac, <AudioBuffer>).connect(ac.destination)
var first = sample.start(ac.currentTime, { loop: true })
var second = sample.start(ac.currentTime + 0.5, { loop: true, gain: 0.7 })
first.stop(ac.currentTime + 1)
sample.stop()
Example
var drums = player(ac, { snare: <AudioBuffer>, kick: <AudioBuffer>, ... }).connect(ac.destination)
drums.start('snare')
drums.start('snare', 0, { gain: 0.3 })
player.stop(when, nodes) ⇒ Array
Stop some or all samples
Returns: Array
- an array of ids of the stoped samples
Param | Type | Description |
---|
when | Float | (Optional) an absolute time in seconds (or currentTime if not specified) |
nodes | Array | (Optional) an array of nodes or nodes ids to stop |
Example
var longSound = player(ac, <AudioBuffer>).connect(ac.destination)
longSound.start(ac.currentTime)
longSound.start(ac.currentTime + 1)
longSound.start(ac.currentTime + 2)
longSound.stop(ac.currentTime + 3)
player.connect(destination) ⇒ AudioPlayer
Connect the player to a destination node
Chainable
Returns: AudioPlayer
- the player
Param | Type | Description |
---|
destination | AudioNode | the destination node |
Example
var sample = player(ac, <AudioBuffer>).connect(ac.destination)
player.on(event, callback) ⇒ SamplePlayer
Adds a listener of an event
Chainable
Returns: SamplePlayer
- the player
Param | Type | Description |
---|
event | String | the event name |
callback | function | the event handler |
Example
player.on('start', function(time, note) {
console.log(time, note)
})
player.schedule(when, events) ⇒ Array
Schedule a list of events to be played at specific time.
It supports two formats of events:
- An array with
[time, note]
- An array with objects
{ time: ?, [name|note|midi|key]: ? }
Returns: Array
- an array of ids
Param | Type | Description |
---|
when | Float | an absolute time to start (or AudioContext's currentTime if it's less than currentTime) |
source | Array | the events array |
Example
var piano = player(ac, ...).connect(ac.destination)
piano.schedule(0, [ [0, 'C2'], [0.5, 'C3'], [1, 'C4'] ])
Example
var drums = player(ac, ...).connect(ac.destination)
drums.schedule(ac.currentTime, [
{ name: 'kick', time: 0 },
{ name: 'snare', time: 0.5 },
{ name: 'kick', time: 1 },
{ name: 'snare', time: 1.5 }
])
player.listenToMidi(input, options) ⇒ SamplePlayer
Connect a player to a midi input
The options accepts:
- channel: the channel to listen to. Listen to all channels by default.
Returns: SamplePlayer
- the player
Param | Type | Description |
---|
input | MIDIInput | |
options | Object | (Optional) |
Example
var piano = player(...)
window.navigator.requestMIDIAccess().then(function (midiAccess) {
midiAccess.inputs.forEach(function (midiInput) {
piano.listenToMidi(midiInput)
})
})
Run tests and examples
To run the test, clone this repo and:
npm install
npm test
To run the examples:
npm i -g budo
budo examples/microtone.js
(Take a look into examples
folder)
License
MIT License