2
\$\begingroup\$

My goal was to make playing sounds in my React game easy and efficient. Using<audio> tags wasn't an option, because on mobile it creates huge delays between the action and the sound. I'm just starting with the Web Audio API, so please forgive me if I did something silly. It works though.

I decided to make it a React hook calleduseAudio():

import { useMemo, useCallback } from "react";const useAudio = (paths: Map<unknown, string>) => {    const audioContext = useMemo(        () => new AudioContext(),        []    );    const arrayBuffers = useMemo(        () => new Map([ ...paths ].map(            ([ key, path ]) => [                key,                fetch(path).then(response => response.arrayBuffer())            ]        )),        [paths]    );    const decodedTracks = useMemo(        () => new Map([ ...arrayBuffers ].map(            ([ key, arrayBufferPromise ]) => [                key,                arrayBufferPromise.then(                    arrayBuffer => audioContext.decodeAudioData(arrayBuffer)                )            ]        )),        [arrayBuffers, audioContext]    );    const play = useCallback(        async (key: unknown) => {            if (!decodedTracks.has(key)) {                throw new Error("Invalid track key");            }            const decodedTrack = await decodedTracks.get(key)!;            const bufferSource = audioContext.createBufferSource();            bufferSource.buffer = decodedTrack;            bufferSource.connect(audioContext.destination);            bufferSource.start();        },        [audioContext, decodedTracks]    );    return [ play ] as const;};export default useAudio;

And here's how you'd use it in your app:

const audioFiles = new Map([    ["cat", "./audio/Meow.mp3"],    [true, "https://pikachu.test/pikapika.wav"], // You can use any key you wish!    [777, "./lucky.aac"],]);const Harmony = () => {    const [ playAudio ] = useAudio(audioFiles);    return (        <nav>            <button                type="button"                onClick={() => playAudio("cat")}            >                Meow!            </button>            <button                type="button"                onClick={() => playAudio(true)}            >                Pika pika            </button>            <button                type="button"                onClick={() => playAudio(123)}            >                Gonna throw an error at ya!            </button>        </nav>    );};

I wanted to allow using any format of a key, hence usingMap ofunknown keys.

The main reason I'm asking for your reviews is to understand if I'm using Web Audio API correctly and if I could further optimize it, or perhaps I over-optimized something at the cost of clarity? I tried to memoize and reuse as much as I knew was possible.

Sᴀᴍ Onᴇᴌᴀ's user avatar
Sᴀᴍ Onᴇᴌᴀ
29.6k16 gold badges46 silver badges203 bronze badges
askedMar 9, 2023 at 0:15
Robo Robok's user avatar
\$\endgroup\$

0

You mustlog in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.