Audio
Dependencies
This library does not require any dependencies.
Usage
Play audio on button click.
import { AudioManagerGlobal } from "@arclockproject/common/library/Audio";
function Example() {
return (
<div>
<button
onClick={() => {
AudioManagerGlobal.play("/assets/sound.mp4");
}}
/>
</div>
);
}
Play audio on element load and keep looping until element unmounts.
import { AudioManagerGlobal } from "@arclockproject/common/library/Audio";
import { useEffect } from "react";
function Example() {
useEffect(() => {
AudioManagerGlobal.play("/assets/sound.mp4", {
loop: true,
singleInstance: true,
});
return () => {
AudioManagerGlobal.stopInstance("/assets/sound.mp4", {
gradual: true,
});
};
}, []);
return (
<div>
<button onClick={() => {}} />
</div>
);
}
There are two kinds of sounds:
- One-shot (default): every
playstarts the file from the beginning, and plays can overlap. Each overlapping play uses its own<audio>element. Good for clicks and effects. - Single instance (
singleInstance: true): one shared player per file. It resumes where it stopped and is the only kindstopInstancecan stop. Good for music.
The examples below are live. Edit the code to try your own values. beepUrl(frequency) is only
available on this site. It makes a short beep so the examples don't need sound files.
Sound effects
Click quickly: one-shot sounds overlap instead of cutting each other off.
▶ Show code (click to view and edit)
function SoundEffects() { return ( <div> {[262, 330, 392, 523].map((frequency) => ( <button key={frequency} onClick={() => AudioManagerGlobal.play(beepUrl(frequency))} style={{ marginRight: 4 }}> {frequency} Hz </button> ))} </div> ); }
Limiting overlapping sounds
To cap how many copies of a one-shot sound can play at once, create your own AudioManager
with the cache option:
const sfx = new AudioManager({ cache: { maxInstances: 5, onMax: "drop" } });
onMax decides what happens at the limit:
"drop"skips the sound."throw"throws anError.- A function decides. Return
trueto skip the sound.
AudioManagerGlobal has no limit. It only warns in the console past 10.
Pick a limit, then play the same beep 5 times at once.
▶ Show code (click to view and edit)
function LimitPlayground() { const [maxInstances, setMaxInstances] = useState(3); const [mode, setMode] = useState("drop"); const [log, setLog] = useState([]); const playFive = () => { let result; const onMax = { drop: (path, count) => { result = `skipped, ${count} busy`; return true; }, warn: (path, count) => { result = `created element ${count + 1}`; }, throw: "throw", }[mode]; const manager = new AudioManager({ cache: { maxInstances, onMax } }); const lines = []; for (let i = 1; i <= 5; i++) { result = "played"; try { manager.play(beepUrl(440)); } catch (error) { result = `threw "${error.message}"`; } lines.push(`Play ${i}: ${result}`); } setLog(lines); }; return ( <div> <label> maxInstances{" "} <input type="number" min={1} max={5} value={maxInstances} onChange={(e) => setMaxInstances(Number(e.target.value))} style={{ width: 50 }} /> </label>{" "} <label> onMax{" "} <select value={mode} onChange={(e) => setMode(e.target.value)}> <option value="drop">drop (function returning true)</option> <option value="warn">warn (function returning nothing)</option> <option value="throw">"throw"</option> </select> </label>{" "} <button onClick={playFive}>Play 5 at once</button> <pre>{log.join("\n") || "Press the button."}</pre> </div> ); }
Music
A looping single-instance track with fade in and out, volume and speed.
▶ Show code (click to view and edit)
function MusicPlayer() { const song = `${REMOTE.base}/PXQZNGjZIFo.m4a`; const [volume, setVolume] = useState(AudioManagerGlobal.maxVolume); const [speed, setSpeed] = useState(1); const [preservesPitch, setPreservesPitch] = useState(true); // Stop the music when this example is removed from the page. useEffect(() => () => AudioManagerGlobal.stopInstance(song), []); const play = () => AudioManagerGlobal.play(song, { singleInstance: true, loop: true, gradual: true, speed, preservesPitch }); return ( <div> <button onClick={play}>Play / resume</button>{" "} <button onClick={() => AudioManagerGlobal.stopInstance(song, { gradual: true })}>Fade out</button>{" "} <button onClick={() => AudioManagerGlobal.stopInstance(song)}>Stop now</button> <p> Volume{" "} <input type="range" min={0} max={1} step={0.05} value={volume} onChange={(e) => { setVolume(Number(e.target.value)); AudioManagerGlobal.setMaxVolume(Number(e.target.value)); }} />{" "} {Math.round(volume * 100)}% </p> <p> Speed{" "} <input type="range" min={0.5} max={2} step={0.25} value={speed} onChange={(e) => setSpeed(Number(e.target.value))} />{" "} {speed}x{" "} <label> <input type="checkbox" checked={preservesPitch} onChange={() => setPreservesPitch(!preservesPitch)} /> keep pitch </label> </p> <small>Speed and pitch apply the next time you press Play.</small> </div> ); }
API
See the Audio API reference for every prop, method and type.