npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

sample-player

v0.5.5

Published

A flexible web audio buffer player

Downloads

4,329

Readme

sample-player npm

Build Status js-standard-style license

Flexible audio sample player for browser:

var player = require('sample-player')
var ac = new AudioContext()

var sample = player(ac, <AudioBuffer>)
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:

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) // => Plays 'A4'
piano.start('C#2') // => Plays 'Db2'

Decimal midi note numbers can be used to detune the notes:

piano.start(69.5) // => Plays a note in the middle of 'A4' and 'Bb4'

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')
// 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:

// using a single option to set all envelop
var longSound = player(ac, <AudioBuffer>, { 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:

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 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

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

// A single sample player
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 }) // name not required since is only one AudioBuffer
first.stop(ac.currentTime + 1) // only stops first sound
sample.stop() // stop all sounds

Example

// A multi-sample player
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) // 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

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

// Event format: [time, note]
var piano = player(ac, ...).connect(ac.destination)
piano.schedule(0, [ [0, 'C2'], [0.5, 'C3'], [1, 'C4'] ])

Example

// 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

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