JSFiddle - React, Tailwind, and code Playground
by juberti
HTML
<p>When you click Play, random noise will play for 1 second and then the source will be disconnected.</p>
<p>On browsers other than Safari 14, sound will accordingly stop. On Safari 14, what appears to be the last sample will continue to play. Hit the third button to make it stop.
</p>
<button id="playButton"
onclick="play()">
▶
</button>
<button id="stopButton"
onclick="stop()"
disabled>
Stop
</button>
<br><br>
<button id="stopTheNoiseButton"
onclick="stopTheNoise()">
If it gets annoying press this button
<audio>
JavaScript
const playButton = document.querySelector('#playButton');
const stopButton = document.querySelector('#stopButton');
const audioElement = document.querySelector('audio');
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
let mediaStreamDstNode = null;
let bufferSource = null;
function createBufferSource() {
const frameCount = 48000; // 1.0s at 48 kHz.
const channelCount = 2;
const buffer = audioCtx.createBuffer(channelCount, frameCount, audioCtx.sampleRate);
for (let channel = 0; channel < channelCount; channel++) {
const channelData = buffer.getChannelData(channel);
for (let i = 0; i < frameCount; i++) {
// Random values on [-0.1, 0.1].
channelData[i] = Math.random() * 0.2 - 0.1;
}
}
const source = audioCtx.createBufferSource();
source.buffer = buffer;
// Wire up source all the way to the output.
mediaStreamDstNode = mediaStreamDstNode || audioCtx.createMediaStreamDestination();
audioElement.srcObject = mediaStreamDstNode.stream;
source.connect(mediaStreamDstNode);
return source;
}
function play() {
bufferSource = createBufferSource();
bufferSource.onended = () => {
stop();
}
audioElement.play();
bufferSource.start();
playButton.setAttribute('disabled', true);
stopButton.removeAttribute('disabled');
}
function stop() {
if (!bufferSource) { return; }
bufferSource.stop();
bufferSource.disconnect();
bufferSource = null;
// After 1 sec, Safari iOS 14 produces noise unless either:
// audioElement.srcObject = null;
// audioElement.pause();
//
// But these steps shouldn't be needed.
// We've already stopped and disconnected bufferSource.
//
// In contrast, the following browsers work fine:
// Safari 13.1.2 (MacOS)
// Chrome 85
playButton.removeAttribute('disabled');
stopButton.setAttribute('disabled', true);
}
function stopTheNoise() {
audioElement.srcObject = null;
}