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 🙏

© 2025 – Pkg Stats / Ryan Hefner

orchestre-js

v3.0.0

Published

Audio tool to create dynamic music

Downloads

17

Readme

Orchestre-JS

Logo

Orchestre-JS is a web audio tool to create adaptive and interactive music.

  • 🎶 Vertical Layering: Manage songs with several instruments and toggle them on and off
  • 🎼 Seamless Loops: Play tracks in loop while keeping them in rhythm and preserving their decay
  • 🥁 Sync to the Beat: Subscribe to events and trigger actions on the rhythm
  • 🌊 Syncopation: Layer loops of different duration to create rich patterns
  • ⏳️ Scheduling: Prepare the start and stop of instruments to make change just when you need to
  • 💻️ Developer Friendly: Everything is done through code, no extra tool to learn
  • ☁️ Zero Dependency: Works with all modern browsers
  • 🌐 Web Audio API Compatible: Plug your music to any effects

Orchestre-JS is the perfect solution for managing music in your web game or application. Its modularity gives you the basic tools to play your music and design all kind of dynamic system around it. Its goal is to be easy to use, while powerful enough to support complex compositions.

See the demo to learn all of its features.

You can also see it in action here:

If you use Orchestre-JS in your creations, I would be really glad to see them! Feel free to show them to me.

Install

npm

npm install orchestre-js

From file

Download the latest release.

Load

import { Orchestre } from 'orchestre-js';

Basic Usage

Create an orchestra

The first thing you need is to create an “Orchestre” (French for orchestra, as you've probably already figured). The only thing it needs is the song's BPM (beats per minute).

const orchestra = new Orchestre(120);

Add players

Then, you will need to register your song's separate tracks. In Orchestre-JS, those are called Players. Each player needs:

  • A unique name that will identify it
  • The URL of the sound file it will play
  • The length in beats of the track

Be aware that you need a local server to request files.

The length is the number of fourth notes in the track. For example, in a 4/4 signature, a track of one bar would have a length of 4, one of two bars would have 8, etc… You can also use a track of one bar and three beats (which gives a total of 7) and make it phases as it loops!

To add a single player, use:

await orchestra.addPlayer('bass', './assets/music/bass.ogg', 16);

addPlayer returns a promise that resolves once the sound file has been fetched. A player can't be used until it is fully loaded.

However, you might want to use more than a single player! Therefore, you should use the addPlayers function, which takes an array of player configurations, and load them all:

const players = [
  {
    name: 'chords',
    url: './assets/music/chords.ogg',
    length: 16,
  },
  {
    name: 'bass',
    url: './assets/music/bass.ogg',
    length: 16,
  },
  {
    name: 'guitar',
    url: './assets/music/guitar.ogg',
    length: 8,
  },
];

await orchestra.addPlayers(players);

You can add players at anytime, even once the orchestra has been started.

Start the orchestra

Speaking of which, here is how it's done:

orchestra.start();

This won't play any sound yet. But it will initiate a metronome, that will set the beginning of the music, and count each beat based on the BPM.

If you want to start with some tracks immediately, you can call start with an array of player names as parameter.

orchestra.start(['bass', 'chords']);

Activate players

Once the orchestra has been loaded, you can activate your players:

orchestra.play('guitar');

To stop them, use:

orchestra.stop('guitar');

Players will start and stop on the next beat. They will then stay in rhythm according to their type (relative or absolute). It's as simple as that!

You don't have to worry if your player is already playing or not. If you call play when a player is already active, or stop when it isn't, nothing will happen. Thus you can use play and stop to make sure the player is in the right state.

You can also call the function toggle, that just changes the player's state between play and stop.

orchestra.toggle('guitar');

See below for more playing options

You now know the basics of Orchestre-JS. But it provides more tools to design a dynamic music system! Let's explore them.

Features

Absolute & relative player position

When adding a player, you can configure its position as either "absolute" or "relative". By default, it's absolute.

await orchestra.addPlayer('melody', './assets/music/melody.ogg', 8, 'relative');
// or
await orchestra.addPlayers([
  {
    name: 'melody',
    url: './assets/music/melody.ogg',
    length: 8,
    position: 'relative',
  },
]);

What does this position mean? When you call the play method, an absolute players will start with an offset so that it is always aligned in the song. It's as if they were already playing silently and they volume has just been turned up. It's probably what you expect for an adaptive song.

A relative player however will always start from its beginning, no matter when you're calling play. It will still be on beat and in rhythm. But they won't be aligned on global a global sheet: they can play at any beat of any bar (with any length even).

Here is a diagram to better understand how it works. Each player here has a length of 4 beats, and are activated at the same time. See how the absolute player starts already in sync with the bar, while the relative one starts on its first beat.

Absolute vs relative diagram

Most of the time, you will want absolute players. They are guaranteed to stay aligned with each other, as they are playing on the bars of your song.

Relative players are useful for stingers: small melodic phrases played only once on an event (with the once option). They can also be used for complex generative compositions.

Playing options

play, stop and toggle can take a second parameter options, which is an object that allows you to define some of those properties:

  • fade (float): time constant in seconds for a fade in or fade out. The length of fading is approximately equal to 1.6 times your constant. See setTargetAtTime for more details.
  • now (bool): if true, sound will start / stop immediately instead of waiting for next beat. This is better used with a fading.
  • once (bool): for play only. Play the track only once (instead of a loop).
  • keep (bool): for stop only. Keep playing the track until its completion, then stop looping.

Scheduling

You can schedule a play/stop action on a player several beats in advance with the following method:

orchestra.schedule('bass', 4, 'toggle'); // bass will be toggled after the next 4 beats
orchestra.schedule('guitar', 8, 'play', { absolute: true }); // guitar will play on the next bar of 8 beats

Warning: Once an action has been scheduled, it can't be cancelled.

Events

Orchestre-JS provide several methods for subscribing to the beat of the music.

To subscribe to a beat interval, use addListener. It takes a callback and the length of the interval in beats.

// Called every beat
const listenerId = orchestra.addListener(() => {
  /* Do something */
}, 1);
// Called every 4 beats (starting from now)
const listenerId2 = orchestra.addListener(() => {
  /* Do something */
}, 4);

addListener takes also a second options parameter:

  • absolute (bool): listen to absolute bars of n beats
  • offset (number): use with absolute to set a position in the bar

For example, addListener(cb, 4, { absolute: true }), will trigger on every bar of 4 beat, while addListener(cb, 4, { absolute: true, offset: 1 }) will trigger on the second beat of the bars (index "1").

To remove a listener, use removeListener with its id:

orchestra.removeListener(listenerId);

If you want to trigger an event just once, you can use the wait method. It takes the number of beats to wait, and the same options as addListener. It then returns a Promise that resolves once the beat is reached.

await orchestra.wait(2); // Waits 2 beats
await orchestra.wait(4, { absolute: true }); // Waits for next bar of 4
await orchestra.wait(4, { absolute: true, offset: 2 }); // Waits for next 3rd beat in a bar

Stop

Once you are done with your song, you can call fullStop on the orchestra to immediately stop all the instruments as well as its metronome.

orchestra.fullStop();

The orchestra will need to be started to be used again.

Accessibility

In order for your application to be accessible to anyone (including users with screen-readers), there are two important rules:

  • User must have a way to stop or pause the sound
  • User must have a control on the sound's volume

Orchestre-JS provides some functions that you can use in that order.

You can pause the orchestra by calling orchestre.suspend(), and start it again with orchestre.resume(). This will immediately interrupt all players and the metronome. Calling resume will make it start just where it was.

You can change the volume of the whole orchestre with orchestre.setVolume(value), where value is a float between 0 and 1 (or higher, but this is at your own risk). Do not use this method for a fade out or any other effect. It has been intended for giving users a way to change volume, and therefore is applied immediately.

Advanced

Using the Web Audio API

Orchestre-JS uses the Web Audio API. You don't need to have experience with it to use Orchestre-JS. But knowing some if its basics can allow you to extend the possibilities that the lib offers. Here are some connecting options at your disposition.

By default, every new Orchestre creates its own audio context. But you can pass your own as a second argument.

const context = new (window.AudioContext || window.webkitAudioContext)();
const orchestra = new Orchestre(120, context);

You can also access the audio context from the context property of the orchestra.

Players are by default connected to the orchestra's master gain (orchestre.master), which is connected to the context's destination. But if you want to connect players to your own nodes, you can change that with the destination parameter.

await orchestra.addPlayer(
  'bass',
  './assets/music/bass.ogg',
  16,
  'absolute',
  myAudioNode
);
// Or
await orchestra.addPlayers([
  {
    name: 'guitar',
    url: './assets/music/guitar.ogg',
    length: 8,
    destination: myAudioNode,
  },
]);

This allows you to add effects on individual players (like panning or reverb) or analyse their output.

Alternatively, you can also connect or disconnect players after they have been added:

orchestra.connect('bass', myAudioNode);
orchestra.disconnect('bass', myAudioNode);
orchestra.disconnect('bass'); // Will disconnect from every nodes

Warning: If a player is not connected to orchestre.master, it is no longer affected by the setVolume method. The best practice is to connect your final node to orchestre.master so that it can be affected by the orchestra's volume.

orchestra.connect('bass', myAudioNode);
myAudioNode.connect(orchestra.master);

Metronome

Orchestre-JS orchestra uses a metronome to sync all tracks. In most use cases, you don't need to interact with it. But you can still access it from the metronome property of a created Orchestre.

The metronome gives you access to the property beatsLength, which is the length of a beat in seconds. Beats are the tiniest unit of time calculated. By default, they correspond to fourth notes. If you want to be more precise, the better is to multiply your BPM (doubling the BPM for example will align beats to eighth notes).

Here are some metronome's methods you can use :

  • getNextBeatTime(): float gives you the time, in second, of the next beat
  • getNextNthBeatTime(beats: number): float gives you the time, in second, of the next nth beat
  • getOffset(time: float): float gives in seconds the offset of the given time relatively to the closest beat before it
  • getTimeBeforeBeat(beat: number = 1): float gives in seconds the time remaining before the next nth beat
  • getBeatPosition(time: float, barSize: number): number for absolute bars of barSize beats, gives the position of the given time. For example, for a bar of 4 beat, results may go from 0 (first beat) to 3 (last beat).
  • getBeatsToBar(barSize: number, bars: number = 1): number gives the beats remaining before the next nth bar of the given size

For the simple tasks though (such as counting the position in a bar), I would advise not to use these functions and instead use the addListener method on the orchestra to manage your own counters.

API

API Documentation

Troubleshooting

  • My players loop too early / too late: Make sure that the BPM you provided to your Orchestre matches your song's one, and that you wrote the correct number of beats in your loop in the player's length. For example, 4 bars in 4/4 will have a length of 16. Orchestre will use these values to loop your tracks, regardless of the audio file's actual length. This allows not only to keep them synchronized to the rhythm, but also to make them overlap if they have reverb or delay at the end.
  • My audio files don't play: Make sure that you wrote the correct folder and name in the url property of the player, and that this file is accessible. You can check its download in your browser's devtools. If you see another error in the console, refer to the Web Audio API documentation. Some browser might not accept all formats! You should be safe with .ogg, .wav or .mp3 though.