I am trying to execute a function related to analyzer upon different elements in slicer selection.
After Page load, when I make first selection there is no issue but on subsequent selection, I am getting error in console.
I can't figure out why.
This is what I have tried and the console prints out the error from 2nd selection onwards.
// Audio DB
const audioDB = [
{ index: 0, src: 'https://s.cdpn.io/1202/Star_Wars_original_opening_crawl_1977.mp3' },
{ index: 1, src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/128337/ongoing-thing-crop.ogg' }
];
const indexString = ['Please select a track', ...audioDB.map(a => a.index.toString())];
let audioCtx;
let analyzer;
let audioSourceNode;
const audio = document.querySelector('audio');
const select = document.querySelector('.slicer');
select.addEventListener('change', function () {
if (audioCtx && audioCtx.state !== 'closed') {
audioCtx.close().then(function () {
createNewContextAndPlay();
});
} else {
createNewContextAndPlay();
}
function createNewContextAndPlay() {
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
play();
}
function play() {
const index = select.selectedIndex;
if (audioSourceNode) {
audioSourceNode.disconnect();
}
if (index !== 0) {
const managedIndex = index - 1;
const val = audioDB.find(a => a.index === managedIndex)?.src;
if (val) {
audio.src = val;
audio.play();
if (audioSourceNode) {
audioSourceNode.disconnect();
}
if (audioCtx && audioCtx.state !== 'closed') {
audioSourceNode = audioCtx.createMediaElementSource(audio);
analyzer = audioCtx.createAnalyser();
if (audioSourceNode && analyzer) {
audioSourceNode.connect(analyzer);
analyzer.connect(audioCtx.destination);
console.log(1);
}
}
}
}
}
});
<!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">
<title>Document</title>
</head>
<body>
<audio id="audio" crossorigin="anonymous"></audio>
<div class="slcr">
<label for="Tracks" style="font-size: 16px; font-family: Oswald, sans-serif; color: red;"> Tracks :- <select class="slicer" id="slicer" style="font-family: Oswald, sans-serif; background-color: aqua;">
<option>Please select a track</option>
<option>Track1</option>
<option>Track2</option>
</select>
</label>
</div>
</body>
</html>
As the error says createMediaElementSource()
can only be called once with the same <audio/>
element on the same AudioContext
.
Re-using the existing MediaElementAudioSourceNode
should fix the problem. Just make sure to only call createMediaElementSource()
if audioSourceNode
is still undefined
.
if (audioSourceNode === undefined) {
audioSourceNode = audioCtx.createMediaElementSource(audio);
}