• Stars
    star
    148
  • Rank 249,983 (Top 5 %)
  • Language
    TypeScript
  • Created almost 9 years ago
  • Updated 7 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A web audio sampler instrument

smplr

npm version

smplr is a collection of sampled instruments for Web Audio API ready to be used with no setup required.

Examples:

import { Soundfont } from "smplr";

const context = new AudioContext();
const marimba = new Soundfont(context, { instrument: "marimba" });
marimba.start({ note: 60, velocity: 80 });
import { DrumMachine } from "smplr";

const context = new AudioContext();
const dm = new DrumMachine(context);
dm.start({ note: "kick" });
import { SplendidGrandPiano, Reverb } from "smplr";

const context = new AudioContext();
const piano = new SplendidGrandPiano(context);
piano.output.addEffect("reverb", new Reverb(context), 0.2);

piano.start({ note: "C4" });

See demo: https://danigb.github.io/smplr/

smplr is still under development and features are considered unstable until v 1.0

Read CHANGELOG for changes.

Library goals

  • No setup: specifically, all samples are online, so no need for a server.
  • Easy to use: everything should be intuitive for non-experienced developers
  • Decent sounding: uses high quality open source samples. For better or worse, it is sample based 🀷

Setup

You can install the library with a package manager or use it directly by importing from the browser.

Samples are stored at https://github.com/smpldsnds and there is no need to download them. Kudos to all samplerist πŸ™Œ

Using a package manger

Use npm or your favourite package manager to install the library to use it in your project:

npm i smplr

Usage from the browser

You can import directly from the browser. For example:

<html>
  <body>
    <button id="btn">play</button>
  </body>
  <script type="module">
    import { SplendidGrandPiano } from "https://unpkg.com/smplr/dist/index.mjs"; // needs to be a url
    const context = new AudioContext(); // create the audio context
    const marimba = new SplendidGrandPiano(context); // create and load the instrument

    document.getElementById("btn").onclick = () => {
      context.resume(); // enable audio context after a user interaction
      marimba.start({ note: 60, velocity: 80 }); // play the note
    };
  </script>
</html>

The package needs to be serve as a url from a service like unpkg or similar.

Documentation

Create and load an instrument

All instruments follows the same pattern: new Instrument(context, options). For example:

import { SplendidGrandPiano, Soundfont } from "smplr";

const context = new AudioContext();
const piano = new SplendidGrandPiano(context, { decayTime: 0.5 });
const marimba = new Soundfont(context, { instrument: "marimba" });

Wait for audio loading

You can start playing notes as soon as one audio is loaded. But if you want to wait for all of them, you can use the load property that returns a promise:

piano.load.then(() => {
  // now the piano is fully loaded
});

Since the promise returns the instrument instance, you can create and wait in a single line:

const piano = await new SplendidGrandPiano(context).load;

⚠️ In versions lower than 0.8.0 a loaded() function was exposed instead.

Shared configuration options

All instruments share some configuration options that are passed as second argument of the constructor. As it name implies, all fields are optional:

  • volume: A number from 0 to 127 representing the instrument global volume. 100 by default
  • destination: An AudioNode that is the output of the instrument. AudioContext.destination is used by default
  • volumeToGain: a function to convert the volume to gain. It uses MIDI standard as default.
  • scheduleLookaheadMs: the lookahead of the scheduler. If the start time of the note is less than current time plus this lookahead time, the note will be started. 200ms by default.
  • scheduleIntervalMs: the interval of the scheduler. 50ms by default.
  • onStart: a function that is called when starting a note. It receives the note started as parameter. Bear in mind that the time this function is called is not precise, and it's determined by lookahead.
  • onEnded: a function that is called when the note ends. It receives the started note as parameter.

Usage with standardized-audio-context

This package should be compatible with standardized-audio-context:

import { AudioContext } from "standardized-audio-context";

const context = new AudioContext();
const piano = new SplendidGrandPiano(context);

However, if you are using Typescript, you might need to "force cast" the types:

import { Soundfont } from "smplr";
import { AudioContext as StandardizedAudioContext } from "standardized-audio-context";

const context = new StandardizedAudioContext() as unknown as AudioContext;
const marimba = new Soundfont(context, { instrument: "marimba" });

Play

Start and stop notes

The start function accepts a bunch of options:

piano.start({ note: "C4", velocity: 80, time: 5, duration: 1 });

The velocity is a number between 0 and 127 the represents at which velocity the key is pressed. The bigger the number, louder the sound. But velocity not only controls the loudness. In some instruments, it also affects the timbre.

The start function returns a stop function for the given note:

const stopNote = piano.start({ note: 60 });
stopNote({ time: 10 });

Bear in mind that you may need to call context.resume() before playing a note

Instruments have a global stop function that can be used to stop all notes:

// This will stop all notes
piano.stop();

Or stop the specified one:

// This will stop C4 note
piano.stop(60);

Schedule notes

You can schedule notes using time and duration properties. Both are measured in seconds. Time is the number of seconds since the AudioContext was created, like in audioContext.currentTime

For example, next example plays a C major arpeggio, one note per second:

const now = context.currentTime;
["C4", "E4", "G4", "C5"].forEach((note, i) => {
  piano.start({ note, time: now + i, duration: 0.5 });
});

Looping

You can loop a note by using loop, loopStart and loopEnd:

const sampler = new Sampler(audioContext, { duh: "duh-duh-ah.mp3" });
sampler.start({
  note: "duh"
  loop: true
  loopStart: 1.0,
  loopEnd: 9.0,
});

If loop is true but loopStart or loopEnd are not specified, 0 and total duration will be used by default, respectively.

Change volume

Instrument output attribute represents the main output of the instrument. output.setVolume method accepts a number where 0 means no volume, and 127 is max volume without amplification:

piano.output.setVolume(80);

⚠️ volume is global to the instrument, but velocity is specific for each note.

Events

Two events are supported onStart and onEnded. Both callbacks will receive as parameter started note.

Events can be configured globally:

const context = new AudioContext();
const sampler = new Sample(context, {
  onStart: (note) => {
    console.log(note.time, context.currentTime);
  },
});

or per note basis:

piano.start({
  note: "C4",
  duration: 1,
  onEnded: () => {
    // will be called after 1 second
  },
});

Global callbacks will be invoked regardless of whether local events are defined.

⚠️ The invocation time of onStart is not exact. It triggers slightly before the actual start time and is influenced by the scheduleLookaheadMs parameter.

Effects

Reverb

An packed version of DattorroReverbNode algorithmic reverb is included.

Use output.addEffect(name, effect, mix) to connect an effect using a send bus:

import { Reverb, SplendidGrandPiano } from "smplr";
const reverb = new Reverb(context);
const piano = new SplendidGrandPiano(context, { volume });
piano.output.addEffect("reverb", reverb, 0.2);

To change the mix level, use output.sendEffect(name, mix):

piano.output.sendEffect("reverb", 0.5);

Experimental features

Cache requests

If you use default samples, they are stored at github pages. Github rate limits the number of requests per second. That could be a problem, specially if you're using a development environment with hot reload (like most React frameworks).

If you want to cache samples on the browser you can use a CacheStorage object:

import { SplendidGrandPiano, CacheStorage } from "smplr";

const context = new AudioContext();
const storage = new CacheStorage();
// First time the instrument loads, will fetch the samples from http. Subsequent times from cache.
const piano = new SplendidGrandPiano(context, { storage });

⚠️ CacheStorage is based on Cache API and only works in secure environments that runs with https. Read your framework documentation for setup instructions. For example, in nextjs you can use https://www.npmjs.com/package/next-dev-https. For vite there's https://github.com/liuweiGL/vite-plugin-mkcert. Find the appropriate solution for your environment.

Instruments

Sampler

An audio buffer sampler. Pass a buffers object with the files to be load:

import { Sampler } from "smplr";

const buffers = {
  kick: "https://danigb.github.io/samples/drum-machines/808-mini/kick.m4a",
  snare: "https://danigb.github.io/samples/drum-machines/808-mini/snare-1.m4a",
};
const sampler = new Sampler(new AudioContext(), { buffers });

And then use the name of the buffer as note name:

sampler.start({ note: "kick" });

Soundfont

A Soundfont player. By default it loads audio from Benjamin Gleitzman's package of pre-rendered sound fonts.

import { Soundfont, getSoundfontNames, getSoundfontKits } from "smplr";

const marimba = new Soundfont(new AudioContext(), { instrument: "marimba" });
marimba.start({ note: "C4" });

It's intended to be a modern replacement of soundfont-player

Soundfont instruments and kits

Use getSoundfontNames to get all available instrument names and getSoundfontKits to get kit names.

There are two kits available: MusyngKite or FluidR3_GM. The first one is used by default: it sounds better but samples weights more.

const marimba = new Soundfont(context, {
  instrument: "clavinet",
  kit: "FluidR3_GM", // "MusyngKite" is used by default if not specified
});

Alternatively, you can pass your custom url as the instrument. In that case, the kit is ignored:

const marimba = new Soundfont(context, {
  instrumentUrl:
    "https://gleitz.github.io/midi-js-soundfonts/MusyngKite/marimba-mp3.js",
});

Soundfont sustained notes

You can enable note looping to make note names indefinitely long by loading loop data:

const marimba = new Soundfont(context, {
  instrument: "cello",
  loadLoopData: true,
});

⚠️ This feature is still experimental and can produces clicks on lot of instruments.

SplendidGrandPiano

A sampled acoustic piano. It uses Steinway samples with 4 velocity groups from SplendidGrandPiano

import { SplendidGrandPiano } from "smplr";

const piano = new SplendidGrandPiano(new AudioContext());

piano.start({ note: "C4" });

SplendidGrandPiano constructor

The second argument of the constructor accepts the following options:

  • baseUrl:
  • detune: global detune in cents (0 if not specified)
  • velocity: default velocity (100 if not specified)
  • volume: default volume (100 if not specified)
  • decayTime: default decay time (0.5 seconds)
  • notesToLoad: an object with the following shape: { notes: number[], velocityRange: [number, number]} to specify a subset of notes to load

Example:

const piano = new SplendidGrandPiano(context, {
  detune: -20,
  volume: 80,
  notesToLoad: {
    notes: [60],
    velocityRange: [1, 127],
  },
});

Electric Piano

A sampled electric pianos. Samples from https://github.com/sfzinstruments/GregSullivan.E-Pianos

import { ElectricPiano, getElectricPianoNames } from "smplr";

const instruments = getElectricPianoNames(); // => ["CP80", "PianetT", "WurlitzerEP200"]

const epiano = new ElectricPiano(new AudioContext(), {
  instrument: "PianetT",
});

epiano.start({ note: "C4" });

// Includes a (basic) tremolo effect:
epiano.tremolo.level(30);

Available instruments:

  • CP80: Yamaha CP80 Electric Grand Piano v1.3 (29-Sep-2004)
  • PianetT: Hohner Pianet T (type 2) v1.3 (24-Sep-2004)
  • WurlitzerEP200: Wurlitzer EP200 Electric Piano v1.1 (16-May-1999)

Mallets

Samples from The Versilian Community Sample Library

import { Mallet, getMalletNames } from "smplr";

const instruments = getMalletNames();

const mallet = new Mallet(new AudioContext(), {
  instrument: instruments[0],
});

Mellotron

Samples from archive.org

import { Mellotron, getMellotronNames } from "smplr";

const instruments = getMellotronNames();

const mallet = new Mellotron(new AudioContext(), {
  instrument: instruments[0],
});

Drum Machines

Sampled drum machines. Samples from different sources:

import { DrumMachine, getDrumMachineNames } from "smplr";

const instruments = getDrumMachineNames();

const context = new AudioContext();
const drums = new DrumMachine(context, { instrument: "TR-808" });
drums.start({ note: "kick" });

// Drum samples could have variations:
const now = context.currentTime;
drums.getVariations("kick").forEach((variation, index) => {
  drums.start({ note: variation, time: now + index });
});

Smolken double bass

import { Smolken, getSmolkenNames } from "smplr";

const instruments = getSmolkenNames(); // => Arco, Pizzicato & Switched

// Create an instrument
const context = new AudioContext();
const doubleBass = await new Smolken(context, { instrument: "Arco" }).load;

Versilian

Versilian is a sample capable of using the Versilian Community Sample Library.

⚠️ Not all features are implemented. Some instruments may sound incorrect ⚠️

import { Versilian, getVersilianInstruments } from "smplr";

// getVersilianInstruments returns a Promise
const instrumentNames = await getVersilianInstruments();

const context = new AudioContext();
const sampler = new Versilian(context, { instrument: instrumentNAmes[0] });

License

MIT License

More Repositories

1

soundfont-player

Quick soundfont loader and player for browser
JavaScript
436
star
2

music-scale

Music scales made easy
JavaScript
63
star
3

note-parser

Parse notes with javascript
JavaScript
55
star
4

timestretch

Simple audio timestretch OLA algorithm implemented in javascript
JavaScript
39
star
5

scorejs

Create musical scores with javascript
JavaScript
35
star
6

sample-player

A web audio audio sample player
JavaScript
30
star
7

audio-contour

A 5 stage audio envelope generator
JavaScript
20
star
8

music-pitch

Note names, midi, frequencies
JavaScript
19
star
9

music-chord

Music chords made easy
JavaScript
14
star
10

in-seconds

time calculator for music applications
JavaScript
14
star
11

synth-kit

A (web audio) synth construction kit
JavaScript
13
star
12

web-audio-assembler

JavaScript
10
star
13

polytone

Create polyphonic instruments from audio sources (Web Audio API)
JavaScript
8
star
14

rock-corpus

A Corpus Study of Rock Music
Perl
8
star
15

samples

Repository to audio samples served from github pages
HTML
8
star
16

all-that-chords

A javascript music chords library
JavaScript
7
star
17

interval-parser

Music interval parser for javascript
JavaScript
6
star
18

music.kit

Your javascript music kit
JavaScript
6
star
19

chord.dictionary

A music chord dictionary
JavaScript
5
star
20

midi-freq

Get frequency of a midi note
JavaScript
5
star
21

rust-synth

Rust
4
star
22

music.note

Tiny library to convert from midi and frequency to note names
JavaScript
4
star
23

elm-twelve-tone

Simple tutorial to setup a test driven project in elm-lang
Elm
4
star
24

yuml_rails

generate yuml class diagram from rails plugin
Ruby
3
star
25

music-interval

Musical intervals in javascript
JavaScript
3
star
26

neural-networks-and-deep-learning-es-lang

3
star
27

tonal-extensions

A multi-package repo with tonal module extensions
JavaScript
3
star
28

pitch-parser

Music pitch parser for javascript
JavaScript
3
star
29

tonal-hyperapp-app

Tonal live docs and theory app
JavaScript
3
star
30

musical-note

Musical notes in javascript
JavaScript
3
star
31

music.chords

A dictionary of music chords
JavaScript
3
star
32

audiovm

Audio Virtual Machine
JavaScript
3
star
33

wecex

wecex web app
Ruby
3
star
34

node-gibberish

JavaScript
3
star
35

music.harmonizer

Simple and fast music harmonizer
JavaScript
2
star
36

step-seq

A tiny step sequencer for web audio
JavaScript
2
star
37

pages

calc pages second try
JavaScript
2
star
38

matematicas-abn

MatemΓ‘ticas ABM
TypeScript
2
star
39

calcalendar

calc calendar rails plugin
2
star
40

tonal.scale

Music scales made easy
HTML
2
star
41

nand-to-tetris

Assembly
2
star
42

elm-school-of-music

A port of HSoM to elm
Elm
2
star
43

pitch-fifths

Pitches and intervals expressed in fifths
JavaScript
2
star
44

audio-pack

audio-pack
JavaScript
2
star
45

emite-library

emite gwt xmpp library
Java
2
star
46

lox

TypeScript
2
star
47

jazzapp

my jazz app
JavaScript
2
star
48

comic

experimental-minimalistic rails cms
JavaScript
2
star
49

music.chord

Music chords made easy
JavaScript
2
star
50

achord

Simple chord detection with js
JavaScript
2
star
51

interval-notation

Parse and build musical intervals in shorthand notation
JavaScript
2
star
52

music-gamut

Manipulate notes made easy
JavaScript
2
star
53

pitch-transpose

Simple and fast pitch transposition
JavaScript
2
star
54

ts-ocarina

An onging port of `purescript-ocarina` audio library to typescript
TypeScript
2
star
55

music-parser

Parse music notation with javascript
JavaScript
2
star
56

music.interval

Music intervals
JavaScript
2
star
57

lasbuenasnoches

los datos de la web
JavaScript
2
star
58

mailservice

a simple REST webservice mail service with background task and management
2
star
59

chromatic

Chromatic scales
JavaScript
2
star
60

grow3

A rails web ide for personal use
Ruby
2
star
61

hablar

hablar emite widget
Java
2
star
62

impro-visor-js

Convert awesome impro-visor musical knowledge data to json format
LiveScript
2
star
63

n3

novaron web page
Ruby
2
star
64

lasbuenasnoches.com

Las Buenas Noches middleman site
HTML
1
star
65

Asambleas

JavaScript
1
star
66

tzatziki

eat your own cucumber
Ruby
1
star
67

pitch-array

A simple format to represent musical pitches and intervals
1
star
68

rhythmically

Create musical sequences with javascript
JavaScript
1
star
69

crestas

JavaScript
1
star
70

scale-names

Musical scale names
JavaScript
1
star
71

micro-blog

HTML
1
star
72

clox

C
1
star
73

bucolicas.cc

HTML
1
star
74

calcaxy.com

calcaxy.com middleman website
HTML
1
star
75

note-duration

Parse note durations
JavaScript
1
star
76

despachodepan.com

despachodepan.com
HTML
1
star
77

pitch-op

Music pitch operator
JavaScript
1
star
78

gwtbooka-old

booka gwt version
Java
1
star
79

gwtbooka

gwt booka
Java
1
star
80

biocordoba

biocordoba
Ruby
1
star
81

binary-scale

All the 2048 western well tempered scales in all its glory
JavaScript
1
star
82

zaszas

zaszas homepage
Ruby
1
star
83

BandInATab

Play along with me
JavaScript
1
star
84

music.note.height

Tiny library to convert from midi <-> note name <-> frequency
JavaScript
1
star
85

recortable

recortable
Ruby
1
star
86

rap

thor task to control apache and passenger locally
Ruby
1
star
87

music.note.transpose

Note transposition fast and easy
JavaScript
1
star
88

audio-player

A flexible audio-player
1
star
89

music.scale.build

Build musical scales
JavaScript
1
star
90

note-pitch

Note pitch manipulation in javascript
JavaScript
1
star
91

zap

zap projects!
JavaScript
1
star
92

scorejs-player

A simple player for score-js
JavaScript
1
star
93

clismon.com

Industrias Clismon
HTML
1
star
94

minimax

Another minimax implementation in JS
JavaScript
1
star
95

music.transpose

Transpose notes fast and easy
JavaScript
1
star
96

q2010

cuestionario.r08.es
Ruby
1
star
97

sampler.js

A simple web audio piano player using soundfont samples
JavaScript
1
star
98

a.pitch

Abstract pitch transformations
JavaScript
1
star
99

tonal.note

Musical notes for javascript
JavaScript
1
star
100

music.operator

Your music operator
JavaScript
1
star