A flexible web audio buffer player
npm install sample-player
 
Flexible audio sample player for browser:
``js
var player = require('sample-player')
var ac = new AudioContext()
var sample = player(ac,
sample.start()
sample.start() // can start several samples at the same time
sample.stop() // stop all playing sounds
`
## Features
#### Create multi-sample player
Pass a map of names to audio buffers to create a multi-sample player:
`js`
var player = require('sample-player')
var ac = new AudioContext()
var drums = player(ac, {
kick:
snare:
hihat:
})
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:
`js`
var samples = { 'C2':
var piano = player(ac, samples)
piano.start(69) // => Plays 'A4'
piano.start('C#2') // => Plays 'Db2'
Decimal midi note numbers can be used to detune the notes:
`js`
piano.start(69.5) // => Plays a note in the middle of 'A4' and 'Bb4'
#### Events
You can register event handlers with the on function:
`js`
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')
// console logs 'start kick'
// console.logs 'ended kick' when sound ends
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:
`js`
// using a single option to set all envelop
var longSound = player(ac,
longSound.start()
// override only the attack
longSound.start(ac.currentTime + 10, { attack: 3 })
#### Listen to midi inputs
Easily attach the player to a Web MIDI API MidiInput:
`js`
var piano = player(...)
window.navigator.requestMIDIAccess().then(function (midiAccess) {
midiAccess.inputs.forEach(function (midiInput) {
piano.listenToMidi(midiInput)
})
})
#### Schedule to play buffers at given times
`js`
var buffers = { 'C2':
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.
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
playerReturns: player - the player
| Param | Type | Description |
| --- | --- | --- |
| ac | AudioContext | the audio context |
| source | ArrayBuffer | Object.<String, ArrayBuffer> | |
| options | Onject | (Optional) an options object |
Example
`js`
var SamplePlayer = require('sample-player')
var ac = new AudioContext()
var snare = SamplePlayer(ac,
snare.start()
* SamplePlayer(ac, source, options) ⇒ player
* .play
* .start(name, when, options) ⇒ AudioNode
* .stop(when, nodes) ⇒ Array
* .on(event, callback) ⇒ SamplePlayer
* .connect(destination) ⇒ SamplePlayer
* .schedule(source, map, when) ⇒ Array
* .listenToMidi(input, options) ⇒ SamplePlayer
See: player.start $3
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
`js
// A single sample player
var sample = player(ac, ).connect(ac.destination)
var first = sample.start(ac.currentTime, { loop: true })
var second = sample.start(ac.currentTime + 0.5, { loop: true, gain: 0.7 }) // name not required since is only one AudioBuffer
first.stop(ac.currentTime + 1) // only stops first sound
sample.stop() // stop all sounds
`Example
`js
// A multi-sample player
var drums = player(ac, { snare: , kick: , ... }).connect(ac.destination)
drums.start('snare')
drums.start('snare', 0, { gain: 0.3 })
`$3
Stop some or all samplesReturns: 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
`js
var longSound = player(ac, ).connect(ac.destination)
longSound.start(ac.currentTime)
longSound.start(ac.currentTime + 1)
longSound.start(ac.currentTime + 2)
longSound.stop(ac.currentTime + 3) // stop the three sounds
`$3
Connect the player to a destination nodeChainable
Returns: AudioPlayer - the player
| Param | Type | Description |
| --- | --- | --- |
| destination | AudioNode | the destination node |
Example
`js
var sample = player(ac, ).connect(ac.destination)
`$3
Adds a listener of an eventChainable
Returns: SamplePlayer - the player
| Param | Type | Description |
| --- | --- | --- |
| event | String | the event name |
| callback | function | the event handler |
Example
`js
player.on('start', function(time, note) {
console.log(time, note)
})
`$3
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
`js
// Event format: [time, note]
var piano = player(ac, ...).connect(ac.destination)
piano.schedule(0, [ [0, 'C2'], [0.5, 'C3'], [1, 'C4'] ])
`Example
`js
// Event format: object { time: , name: }
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 }
])
`$3
Connect a player to a midi inputThe 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
`js
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:
`bash
npm install
npm test
`To run the examples:
`bash
npm i -g budo
budo examples/microtone.js
`(Take a look into
examples` folder)MIT License