Last active
March 4, 2021 23:49
-
-
Save rnewman/29b7e88f0acbde78c20f32187ee652ea to your computer and use it in GitHub Desktop.
Loopback worklet example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | |
<title>Audio Worklet loopback test</title> | |
</head> | |
<body> | |
<h1>Loopback test</h1> | |
<ol> | |
<li>Make sure your Bluetooth device is your default input and output device.</li> | |
<li>Play music. Verify that you hear high-quality music.</li> | |
<li>Hit one of the buttons below. You should hear a shift to a low-quality mode.</li> | |
<li>Talk: in Chrome you should hear a choppy version of your own voice.</li> | |
</ol> | |
<audio id="output"></audio> | |
<div> | |
<button id="worklet">Start with worklet</button> | |
</div> | |
<div> | |
<button id="noworklet">Start without worklet</button> | |
</div> | |
<script> | |
async function loopback(worklet) { | |
const context = new AudioContext({ | |
latencyHint: 0, | |
}); | |
const input = await window.navigator.mediaDevices.getUserMedia({ | |
audio: { | |
channelCount: 1, | |
}, | |
}); | |
const source = context.createMediaStreamSource(input); | |
const destination = context.createMediaStreamDestination(); | |
if (worklet) { | |
const module = await context.audioWorklet.addModule('https://gistpreview.github.io/?29b7e88f0acbde78c20f32187ee652ea/loopback.js'); | |
console.info('Got module.', module); | |
const node = new AudioWorkletNode(context, 'loopback-worklet', { | |
numberOfInputs: 1, | |
numberOfOutputs: 1, | |
outputChannelCount: [1] | |
}); | |
console.info('Connecting to Audio Worklet.'); | |
source.connect(node); | |
node.connect(destination); | |
} else { | |
console.info('Piping straight through.'); | |
source.connect(destination); | |
} | |
const outputElement = document.getElementById('output'); | |
outputElement.srcObject = destination.stream; | |
outputElement.play(); | |
} | |
document.getElementById('worklet').onclick = () => loopback(true); | |
document.getElementById('noworklet').onclick = () => loopback(false); | |
</script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Loopback extends AudioWorkletProcessor { | |
constructor() { | |
super(); | |
console.info('Constructed loopback'); | |
} | |
process(inputs, outputs, parameters) { | |
if (!inputs) { | |
console.warn('No inputs.'); | |
} | |
// Mono only. | |
const input = inputs[0][0]; | |
const output = outputs[0][0]; | |
if (!input) { | |
console.warn('No input; waiting.'); | |
return true; | |
} | |
for (let i = 0; i < 128; ++i) { | |
output[i] = input[i]; | |
} | |
return true; | |
} | |
} | |
registerProcessor('loopback-worklet', Loopback); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment