https://github.com/danigb/sample-player
A web audio audio sample player
https://github.com/danigb/sample-player
Last synced: 5 months ago
JSON representation
A web audio audio sample player
- Host: GitHub
- URL: https://github.com/danigb/sample-player
- Owner: danigb
- License: mit
- Archived: true
- Created: 2015-12-22T00:36:47.000Z (over 10 years ago)
- Default Branch: master
- Last Pushed: 2023-05-16T17:02:28.000Z (about 3 years ago)
- Last Synced: 2025-10-22T00:28:38.295Z (8 months ago)
- Language: JavaScript
- Homepage:
- Size: 1.2 MB
- Stars: 31
- Watchers: 2
- Forks: 9
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG
- License: LICENSE
Awesome Lists containing this project
README
# sample-player [](https://www.npmjs.com/package/sample-player)
[](https://travis-ci.org/danigb/sample-player)
[](https://github.com/feross/standard) [](https://www.npmjs.com/package/sample-player)
⚠️ This is old codebase I don't want to maintain anymore. There are lot of alternatives out there, this is one: https://github.com/danigb/smplr Thanks! ⚠️
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': , 'Db2': , ... }
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, , { adsr: [1.2, 0.5, 0.8, 1.3] })
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': , 'Db2': , ... }
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](https://raw.githubusercontent.com/danigb/sample-player/master/dist/sample-player.min.js) 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 1
- `attack`: the attack time of the amplitude envelope
- `decay`: the decay time of the amplitude envelope
- `sustain`: the sustain gain value of the amplitude envelope
- `release`: the release time of the amplitude envelope
- `adsr`: 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**
```js
var SamplePlayer = require('sample-player')
var ac = new AudioContext()
var snare = SamplePlayer(ac, )
snare.start()
```
* [SamplePlayer(ac, source, options)](#SamplePlayer) ⇒ player
* [.play](#player.play)
* [.start(name, when, options)](#player.start) ⇒ AudioNode
* [.stop(when, nodes)](#player.stop) ⇒ Array
* [.on(event, callback)](#player.on) ⇒ [SamplePlayer](#SamplePlayer)
* [.connect(destination)](#player.connect) ⇒ [SamplePlayer](#SamplePlayer)
* [.schedule(source, map, when)](#player.schedule) ⇒ Array
* [.listenToMidi(input, options)](#player.listenToMidi) ⇒ [SamplePlayer](#SamplePlayer)
### 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**
```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 })
```
### 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**
```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
```
### 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**
```js
var sample = player(ac, ).connect(ac.destination)
```
### player.on(event, callback) ⇒ [SamplePlayer](#SamplePlayer)
Adds a listener of an event
**Chainable**
**Returns**: [SamplePlayer](#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)
})
```
### 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**
```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 }
])
```
### player.listenToMidi(input, options) ⇒ [SamplePlayer](#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](#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)
## License
MIT License