mirror of
https://github.com/captbaritone/webamp.git
synced 2026-07-22 17:47:16 +00:00
78 lines
2 KiB
JavaScript
78 lines
2 KiB
JavaScript
// Get the max value from an array-like
|
|
const max = arr => arr.reduce((acc, val) => Math.max(acc, val));
|
|
|
|
function createAnalysers(source) {
|
|
const { context } = source;
|
|
const splitter = context.createChannelSplitter();
|
|
const leftGain = context.createGain();
|
|
const rightGain = context.createGain();
|
|
const leftAnalyser = context.createAnalyser();
|
|
const rightAnalyser = context.createAnalyser();
|
|
|
|
source.connect(splitter);
|
|
splitter.connect(
|
|
leftGain,
|
|
0
|
|
);
|
|
splitter.connect(
|
|
rightGain,
|
|
1
|
|
);
|
|
leftGain.connect(leftAnalyser);
|
|
rightGain.connect(rightAnalyser);
|
|
|
|
function destroy() {
|
|
// TODO: Safari, and maybe Firefox, don't support passing the destination
|
|
// argument which means in Safari, this will disconnect `source` completely,
|
|
// which will silence the audio.
|
|
source.disconnect(splitter);
|
|
splitter.disconnect();
|
|
leftGain.disconnect();
|
|
rightGain.disconnect();
|
|
}
|
|
|
|
return { left: leftAnalyser, right: rightAnalyser, destroy };
|
|
}
|
|
|
|
const POLL_INTERVAL = 20;
|
|
const MAX_CALLS = 100;
|
|
|
|
export default async function detectChannels(source) {
|
|
return new Promise((resolve, reject) => {
|
|
const analysers = createAnalysers(source);
|
|
|
|
const dataArray = new Uint8Array(analysers.left.frequencyBinCount);
|
|
let maxLeft = 0;
|
|
let maxRight = 0;
|
|
let calls = 0;
|
|
|
|
const unsubscribe = () => {
|
|
// eslint-disable-next-line no-use-before-define
|
|
clearInterval(intervalHandle);
|
|
analysers.destroy();
|
|
};
|
|
|
|
const intervalHandle = setInterval(() => {
|
|
analysers.left.getByteFrequencyData(dataArray);
|
|
maxLeft = Math.max(maxLeft, max(dataArray));
|
|
analysers.right.getByteFrequencyData(dataArray);
|
|
maxRight = Math.max(maxRight, max(dataArray));
|
|
|
|
if (maxLeft > 0) {
|
|
if (maxRight > 0) {
|
|
resolve(2);
|
|
} else {
|
|
resolve(1);
|
|
}
|
|
unsubscribe();
|
|
}
|
|
|
|
if (calls >= MAX_CALLS) {
|
|
reject();
|
|
unsubscribe();
|
|
}
|
|
|
|
calls++;
|
|
}, POLL_INTERVAL);
|
|
});
|
|
}
|