πŸ“Œ preface

Why is it restart? Because the problem I have is I hit play and I hit play again anyway, and it says wrong

(index):41 Uncaught DOMException: Failed to execute ‘start’ on ‘AudioBufferSourceNode’: cannot call start more than once.Β at HTMLButtonElement.Β 

πŸ“Œ Problem recurring

I’ve defined two buttons on the page (a play button and a pause button) and an input for the selection file, and what I want to do is hit play to play, and hit Pause to pause, so I’ve defined two click events (play and pause).

The next step is to use audioContext to implement music playback. To be compatible with browsers, I first wrote a method for each browser to get the audioContext

var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
Copy the code

Then creating the createBufferSource() object is necessary for the audio playback function, so I have the following error code. I then create the createBufferSource variable after the audioCtx variable

var AudioBufferSourceNode = audioCtx.createBufferSource()
​
var play = document.getElementById("play")
var pause = document.getElementById("pause")
var bufferData = null
Copy the code

Note: The AudioBufferSourceNode above is the problem described in this article

Then listen for the change event on the input and execute the code in the callback function when the user selects the audio file

document.getElementById("loadfile").addEventListener("change", Function () {var file = this.files[0] // Get the audio file object //... Other code}Copy the code

After getting the audio file object, create a FileReader object to asynchronously read the contents of the file (or raw data buffer) stored on the user’s computer. Then listen for the load event. When the audio file is loaded, use decodeAudioData to decode it. There are two parameters in decodeAudioData, the first is audioData audioData; The second is a callback function that returns a buffer. When you get a successful buffer, the audio is loaded and you can click play and pause

document.getElementById("loadfile").addEventListener("change", function () { var file = this.files[0] var fr = new FileReader() fr.addEventListener("load", function(e) { audioCtx.decodeAudioData(e.target.result, function(buffer){ // playFun(buffer); // Pass the AudioBuffer returned after decoding as an argument to console.log(" Music loaded "); BufferData = buffer /* write inside the decodeAudioData event, Play.addeventlistener ("click", function () {console.log(" play "); AudioBufferSourceNode. Buffer = bufferData / / AudioBuffer data assigned to buffer properties AudioBufferSourceNode.connect(audioCtx.destination); / / if only play audio, this place is directly connect the AudioBufferSourceNode AudioDestinationNode AudioBufferSourceNode. Start (0); Console. log(" Music status :", audioctx.state); }) // Pause pause.addeventListener ("click", function () {console.log(" pause "); AudioBufferSourceNode. Stop (0) / / stop playing music the console. The log (" state: music, "audioCtx. State); }) },function(err){ console.log(err); }) }) fr.readAsArrayBuffer(file); })Copy the code

Note: The above code is bug code, please copy with caution

πŸ“Œ Problem solved

After looking through most of the sources, I again didn’t find the right answer, but I was inspired by the fact that if I hit play repeatedly and the current AudioBufferSourceNode is still the old one (not updated or reassigned), the error mentioned in this article will occur. Or can’t find a red error like buffer, so I should re-assign AudioBufferSourceNode when I hit play

Let’s do it together

<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta  name="viewport" content="width=device-width, Initial -scale=1.0"> <title>Document</title> </head> <body> <div> <button id="play"> </button> <button Suspension id = "pause" > < / button > < input type = "file" id = "loadfile" > < / div > < script > var audioCtx = new (window. AudioContext | | window.webkitAudioContext)(); var AudioBufferSourceNode = null var play = document.getElementById("play") var pause = document.getElementById("pause")  var bufferData = null document.getElementById("loadfile").addEventListener("change", function () { var file = this.files[0] var fr = new FileReader() fr.addEventListener("load", function(e) { audioCtx.decodeAudioData(e.target.result, function(buffer){ // playFun(buffer); // Pass the AudioBuffer returned after decoding as an argument to console.log(" Music loaded "); BufferData = buffer /* write inside the decodeAudioData event, Play.addeventlistener ("click", function () {console.log(" play "); AudioBufferSourceNode = audioCtx. CreateBufferSource () / / when he has to play to create AudioBufferSourceNode object, Can appear otherwise can't play again question AudioBufferSourceNode. Buffer = bufferData / / AudioBuffer data assigned to buffer properties AudioBufferSourceNode.connect(audioCtx.destination); / / if only play audio, this place is directly connect the AudioBufferSourceNode AudioDestinationNode AudioBufferSourceNode. Start (0); Console. log(" Music status :", audioctx.state); }) // Pause pause.addeventListener ("click", function () {console.log(" pause "); AudioBufferSourceNode. Stop (0) / / stop playing music the console. The log (" state: music, "audioCtx. State); }) },function(err){ console.log(err); }) }) fr.readAsArrayBuffer(file); }) </script> </body> </html>Copy the code

πŸ“Œ rendering