Add Soundfont and AudioContext to a React Adapter Hook
Get the project source code below, and follow along with the lesson material.
Download Project Source CodeTo set up the project on your local machine, please follow the directions provided in the README.md
file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.
This lesson preview is part of the Fullstack React with TypeScript Masterclass course and can be unlocked immediately with a single-time purchase. Already have access to this course? Log in here.
Get unlimited access to Fullstack React with TypeScript Masterclass with a single-time purchase.

[00:00 - 00:21] adapter hook. In this section we'll add the sounds to our app. First, add a custom sound font type to react up and dts. Type sound font type equals type of sound font. This type is going to be useful when we create an adapter for a sound font. Sound font adapter.
[00:22 - 00:36] The adapter should take what sound font provides through the public API, the instrument, nodes array, play stop methods and other API. Take whatever the wind object gives us. Here we want audio context. And return an object with all the props for the component.
[00:37 - 01:34] Play stop load the status is loading and the current instrument. Load. We'll load the current instrument is loading. We'll represent the loading state and the current is the instrument that we're using right now. Play and stop will allow us to play the notes. Create a new folder adapters. And here create another folder sound font where we'll define a hook, use, sound font, ds. First let's define the imports. We'll need use state and use ref from react, sound font instrument name and player from sound font player, MIDI value from the node domain optional from the types, audio nodes registry and default instrument from the sound domain. The audio nodes registry should be defined in the sound domain. So let 's add it there. We'll need to import MIDI value from the node and optional from the types.
[01:35 - 02:41] Now we can expert type audio nodes registry. That should be a record with keys of type MIDI value and values of an optional type player. Impress the player from the sound font player. Audio nodes registry will represent an object where for each note we will have a player that is going to be playing this note. Go back to the use sound font adapter. Define the input and the output types of this adapter. So as an input is going to get the type settings. That is an object with field audio context of type audio context . And as an output it's going to have an interface adapted that should have flooding, boolean, current. It's an optional instrument name and then methods. Lord, it's going to receive an instrument of type instrument name and return a promise that will just resolve to void. Play will receive note of type MIDI value and also return a promise of type void.
[02:42 - 03:08] Same with the stop. Now define the adapter hook expert function use sound font. It will receive audio context as it is defined in the settings and return adapted. Here we'll need the active nodes registry. Let active nodes of type audio nodes registry is going to be an object. We are making it mutable because we don't want it to be observable.
[03:09 - 03:37] We don't want to use state here. Then we'll have current set current. That's going to be a state that will store the current instrument use state of an optional type instrument name. And the default value is going to be null. Next we'll need to store the loading state loading set loading equals use state of type boolean. And the default value here is false.
[03:38 - 05:29] Then we'll need the player state const player set player equals use state optional player default null. And then we'll need the audio. That's going to be our context const audio equals use ref new audio context loading the sound set. Let's implement the load method that will load the instrument sound set at the following code. It's going to be an async function called load. That's going to receive an instrument of type instrument name. And it's going to have a default value default instrument. We provide the default value because in our type is defined as an optional argument with this question mark here. Next let's define the function body. Here we first set loading to true. Then we get the player const player equals await sound font instrument. We pass the current audio context audio current and the instrument name. Then after we got the player we set loading to false. We set current instrument to the instrument. That's the instrument name we got from the arguments. And then we set player to player that we got from the sound font. Then we'll need the resume method async function resume. It's going to return audio current state compared to suspended . So if the audio state is suspended, then we resume we call the resume method on the current value of the audio ref. Otherwise we just resolve the promise. So let's do this. So if it is suspended, then we await audio current resume. Otherwise we just return promise resolve.
[05:30 - 06:24] Form of the document. And now let's define the play and stop methods. And a sync function play will play the notes note of type media value. Inside of it, it's going to call await resume. We need to make sure that there is a player. If not player return, then we get the node by playing the note from arguments, node player play note to string. And then we add this node to the active nodes object, active nodes equals active nodes, note node node. Alright, and let's implement the stop method. I sync function stop. Here we get the note, media value, we also await to resume check if there is an active node by this note.
[06:25 - 07:16] Otherwise, there would be nothing to stop. We return. Then if there is a note that is playing, we stop it active nodes, note stop. We use an exclamation mark here because we are sure that active nodes note exists, because we already checked for its existence in line 53. After we stop the note, we remove it from the active nodes object, active nodes equals an object, we get the old ones active nodes. And then we set note to now. So there is your method that we've used both and stop and the play methods. That's a very important thing. It checks what the audio state is right now. If it's suspended, this means that audio context is holding audio hardware access and reducing the CPU and battery usage in the process.
[07:17 - 08:11] To continue, we call there is your method on it. This is why we have to call it both in the play and the stop methods before we play or stop the notes. Also, let's look at the play method here. We convert the note to string because the type player only accepts strings. The first value with the first argument is string and its name. Now, let's go back, scroll down to our adapter and let's return all those values. Return as you remember, we need to return loading current, load, play and stop. All right, the red underlines are gone because we now match the interface that we've declared here. Create a new file index dot TS inside of the adapter sound font. And here we will re expert, expert everything from use sound font. Congratulations, we've just created our first sound provider.