andy-audio
v0.3.4
Published
![andy](static/andy.png)
Downloads
2
Maintainers
Readme
Andy
Andy is a simple library to play sounds (.wav, .m4a) and midi files (.mid) on the web.
(Andy Logo by Peter Chen)
Examples:
- Andy example in React
- Midi File Player
- Patch Editor (use keys
z-,
andq-i
on your keyboard as piano keys)
Andy is the audio system from within my online game engine. It is the main part of the system, but the 3d audio, and some other bits have been stripped out.
Adding Andy to Your Project
You can use standard NPM.
npm i andy-audio
yarn add andy-audio
When you do your build into your own project, you will also have to copy a few workers from the node_modules folder and store them wherever you load your javascript files from:
cp node_modules/andy-audio/dist/types/metronome.worker.js dist/metronome.worker.js
cp node_modules/andy-audio/dist/types/noise.processor.js dist/noise.processor.js
Have a look through the example project code.
Roadmap
See the Project Board for the latest.
Usage
Loading and Playing a WAV, M4A, etc
Andy is a "low level" library in that it just provides an easier way to load and play audio files. You'll have to write your own manager / context / come up with your own way of managing the files (see example below). Here is a "raw" Typescript example of Andy's basic usage:
import { SoundSystem, Sound, loadSound } from "andy-audio";
const system = new SoundSystem();
const sounds = {
s0: loadSound("http://envelope.robrohan.com/andy/coin4.wav", system),
s1: loadSound("http://envelope.robrohan.com/andy/coin3.m4a", system),
};
Promise.all([sounds.s0, sounds.s1]).then((s) => {
sounds.s0 = s[0];
sounds.s1 = s[1];
window.sound = system;
window.sounds = sounds;
});
Then later you could play the sound (say from the HTML page itself):
function uiSound() {
window.sound.play(window.sounds.s0);
}
Of course, it's better to use Andy within your chosen framework. For example in a React Context, or what have you. Additionally, you can provide your own loadSound
method if you wish (have a look at that function).
Loading and Playing a MIDI file
Andy also can play MIDI files. It uses it currently uses it's own hand rolled synth (see Andy's Synth below), and tries to support all the General Midi Standard set of instruments (but it currently does not).
The following is an example of loading a midi file, and playing it using the built in synth.
import {
SoundSystem,
loadMidi,
createRun,
insertRun,
playHeadToggle,
playHeadRewind,
rewindRun,
silenceRun,
} from "andy-audio";
const system = new SoundSystem();
loadMidi("static/TestMidiTuneMarkers.mid").then((song) => {
// Create a run from the midi song data we loaded
songRun = createRun(system, song);
// Insert the run into the player
insertRun(system, songRun);
playHeadToggle();
// Example of how to stop it
setTimeout(() => {
playHeadToggle();
silenceRun(songRun);
// Rewind example
playHeadRewind();
rewindRun(songRun);
}, 2000);
});
Exported midi files exported from Reaper and MuseScore 3 are what we currently test with. However, any midi file from any program should theoretically work...theoretically.
React Context Example
Here is a simple example of using andy within a React Context (in Typescript).
Create a file called SoundContext.tsx with the following content:
import React from "react";
import { Sound, SoundSystem, loadSound } from "andy-audio";
export interface ISounds {
load: Function;
play: Function;
}
export interface SoundRepository {
[key: string]: Sound;
}
const sounds = {} as SoundRepository;
const system = new SoundSystem();
const createKey = (url: string): string => {
const parts = url.split("/");
return parts[parts.length - 1];
};
export const SoundContext = React.createContext<ISounds>({
load: async (soundUrl: string, key?: string) => {
const sound = await loadSound(soundUrl, system);
sounds[key || createKey(soundUrl)] = sound;
},
play: (name: string, loop: boolean = false) => {
system.play(sounds[name], loop);
},
});
You can then use this context within your app. Here is an example usage with the create react app:
...
import { SoundContext } from './SoundContext';
...
const App = () => {
const ctx = useContext(SoundContext);
// Note: browsers require a user interaction to play a sound
ctx.load("http://localhost:3000/coin4.wav", "coin");
return (
<div className="App">
<div
className="App-link"
onClick={() => ctx.play("coin4")}
>Learn React</div>
</div>
);
}
Andy's Synth
Andy's Synth is currently very basic. While we are planning on future version supporting more robust synths, Andy currently has a very, very simple Additive Synthesis.
We also do not have many instruments created. See this file for currently supported instruments - patches welcome!
Andy will use the Organ sound if it doesn't have a supported instrument.
The current implementation consists of a chain of:
Max 8 oscillators. Each independently can be a:
- sine
- triangle
- square
- white noise (use "custom")
One filter
- highpass
- lowpass
- bandpass
- highshelf
- lowshelf
- peaking
- notch
One ADSR
One Compressor
They are applied in this order.
Each oscillators can have it's own volume, and it's frequency can be set using one of the following:
frequency - a specific frequency. "1300" for example
freqOffset - a frequency off set from the base frequency. "200" for example. This means that if they pressed the key that did "440" it would generate a wave at "640". If they did "620" it would generate "820".
freqMult - multiply to the base frequency. "2" for example. If the base frequency was "440" this wave would generate "880".
Checkout the Patch Editor, use keys z-,
and q-i
on your keyboard as piano keys, and mess with the JSON in the textbox to get a feel for what you can do with it.
Tip: open the browser console to check if you've typed something that made the json invalid - like not starting a value with a leading zero, or leaving out a comma.