Check out a free preview of the full Web Audio Synthesis & Visualization course

The "Buffering Audio" Lesson is part of the full, Web Audio Synthesis & Visualization course featured in this preview video. Here's what you'd learn in this lesson:

Matt discusses buffering an audio file to fully download and decode the file to allow the audio to immediately be played. To help avoid errors from edge cases a best practice is to make sure the audioContext is resumed before playing audio.


Transcript from the "Buffering Audio" Lesson

>> And the next is a similar concept. So I'll try and go through that one a little bit more quickly now that some of the basics have been covered. But if we go to the next demo, which in our little list here would be this one here, mp3 buffer, [SOUND] and it plays a very loud chime noise.

And it plays it on mousePressed as this first demo. Something that's different with this demo, though, is that instead of streaming the audio in, which is great for long, sort of tracks background music, this one is using what's called buffering. So we download the entire audio file into memory first.

We decode it, so that when we actually press the Play button, is able to play immediately. It doesn't have to download anything. There's no data that needs to be loaded anymore. And that's really good for games, that's really good for sort of interactive experiences where you don't want any latency, you don't want any lag between clicking and hearing the audio.

And it's also good if you just wanna play a sound over and over again. You don't have to download it each time you play it, you just download it one time and then you can can play it hundreds of times without having to download any more data. And the way that's gonna look is a bit like this.

It's a little bit more complicated, it requires some asynchronous code. Because we're just loading the sound once and then having to reuse it. And I'll walk through this one, I might not code it all just from scratch. But I'll walk through this, so on mousePressed we play the sound, this function here playSound.

And if I go down to the playSound function, so in the playSound function, we first ensure that everything is loaded. So we first have to say await, loadSound, and that function here will do something that we did in the last demo. Which is just to create a new audio context if it doesn't yet exist just to make sure that we're only using one audio context.

It's generally a good idea to just stick with one audio context for all of your sounds within an application and just reuse that context. And then we're gonna actually create the audio buffer. So this is the thing that holds the audio data that we just need to load once and the way that we load that is a little bit odd.

We first have to fetch the mp3 or the wav file just using fetch, just like this. So I'm fetching the chime, we get a response and then we turn that response into an array buffer, that's what we're doing here. And then finally we have an array buffer, which is some binary data of an mp3 file.

But we have to decode that mp3 file or whatever the format is, OGG or WebM or something. We decode that into audio data that can just be played immediately through the Web Audio API. And that's what we're gonna be doing here with the audioContext.decodeAudioData. We pass in the array buffer there.

And then we get back an audioBuffer. And I've declared that as a global variable here as well. And so if we go back to our little playSound function, we've now loaded up the sound. And so the next part is to just make sure that we're resumed. This is something that you'll see in some of my demos.

It's not always needed. It's one of these situations where, during the course of me developing these applications over the last few years. I sometimes run into some issues where, especially with something like Safari, sometimes the audio context will become in a suspended state. And it's one of these sort of nebulous things where, [LAUGH] you just end up writing this code here to make sure that it's always resumed, no matter whether it's suspended or not.

It suspends itself sometimes if, for example, the user in some way rejects a permission for audio. Or maybe if they haven't yet interacted with the site or if they've interacted with the site, and then they somehow go away from the site and come back. There's some very strange edge cases.

And so a best practice maybe would just be to make sure that the audio context is resumed before you try and play sounds. It's just something I started to put into my code. And then the next thing here we're doing is we're creating a new buffer source. So just like before, we had an mp3 source node, it was a media element source node.

Now we're using a buffer source. So, when they say source, it's the source of the audio, whether it's coming from an audio tag or whether it's coming from this decoded audioBuffer. And again, just like as I was saying with the switchboard, we have to always make sure that any node that we create is hooked up to something.

Cuz if we don't connect the source nodes to the destination or to some other node, then it's not gonna do anything. We're not gonna hear anything. The node will just be there on its own, not sending the signal to anything else. And so we connect the source to the speaker and then we assign the buffer.

So we say, this is the buffer that we've already loaded. We're just gonna use that one. And then we're gonna play the audio. We use 0 here, which just means start the sound immediately. We could use a different variable here, which would give us maybe a delay. So it'll start after some sort of set time.

And so that's that basically. [SOUND] There we go. [SOUND]

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now