mirror of
https://github.com/lewismoten/data-over-audio.git
synced 2026-04-03 02:06:50 +08:00
Separate microphone
This commit is contained in:
150
Panels/MicrophonePanel.js
Normal file
150
Panels/MicrophonePanel.js
Normal file
@@ -0,0 +1,150 @@
|
||||
import BasePanel from './BasePanel';
|
||||
|
||||
const media = {
|
||||
audio: {
|
||||
mandatory: {
|
||||
autoGainControl: false,
|
||||
echoCancellation: false,
|
||||
noiseSuppression: false,
|
||||
suppressLocalAudioPlayback: false,
|
||||
voiceIsolation: false
|
||||
},
|
||||
optional: []
|
||||
}
|
||||
};
|
||||
|
||||
class MicrophonePanel extends BasePanel {
|
||||
constructor() {
|
||||
super('Microphone');
|
||||
|
||||
this.addCheckboxes('receive-via', [
|
||||
{text: 'Listen', id: 'listen', eventName: 'listenChange'}
|
||||
]);
|
||||
this.addCanvas('canvas', 100, 25);
|
||||
|
||||
this.addEventListener('listenChange', (e) => {
|
||||
if(e.checked) {
|
||||
this.error = undefined;
|
||||
navigator.mediaDevices.getUserMedia(media)
|
||||
.then(stream => {
|
||||
this.stream = stream;
|
||||
this.connectStream();
|
||||
this.dispatcher.emit('on', stream);
|
||||
})
|
||||
.catch(error => {
|
||||
this.error = error;
|
||||
console.log(error);
|
||||
this.setListening(false);
|
||||
this.disconnectStream();
|
||||
this.stopSampling();
|
||||
})
|
||||
} else {
|
||||
if(this.stream) {
|
||||
this.error = undefined;
|
||||
this.disconnectStream();
|
||||
this.dispatcher.emit('off');
|
||||
}
|
||||
this.stopSampling();
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
setAnalyser = analyser => {
|
||||
if(analyser) {
|
||||
this.analyser = analyser;
|
||||
this.connectStream();
|
||||
} else {
|
||||
this.disconnectStream();
|
||||
this.analyser = analyser;
|
||||
}
|
||||
}
|
||||
setAudioContext = audioContext => {
|
||||
if(audioContext) {
|
||||
this.audioContext = audioContext;
|
||||
this.connectStream();
|
||||
} else {
|
||||
this.disconnectStream();
|
||||
this.audioContext = audioContext;
|
||||
}
|
||||
}
|
||||
connectStream = () => {
|
||||
if(this.stream) {
|
||||
if(this.audioContext) {
|
||||
if(!this.streamNode) {
|
||||
this.streamNode = this.audioContext.createMediaStreamSource(this.stream);
|
||||
}
|
||||
if(this.analyser) {
|
||||
this.streamNode.connect(this.analyser);
|
||||
}
|
||||
if(this.getListening()) {
|
||||
this.startSampling();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
disconnectStream = () => {
|
||||
if(this.streamNode) {
|
||||
if(this.analyser) {
|
||||
this.streamNode.disconnect(this.analyser);
|
||||
this.streamNode = undefined;
|
||||
}
|
||||
}
|
||||
if(this.stream) {
|
||||
this.stream.getTracks().forEach(track => track.stop());
|
||||
this.stream = undefined;
|
||||
}
|
||||
this.stopSampling();
|
||||
}
|
||||
|
||||
isSampling = () => !!this.samplingId;
|
||||
startSampling = () => {
|
||||
if(this.isSampling()) return;
|
||||
// nothing to analyse
|
||||
if(!this.stream) return;
|
||||
// nothing to analyse with
|
||||
if(!this.analyser) return;
|
||||
this.samplingId = window.requestAnimationFrame(this.drawSpectrumAnalyzer);
|
||||
}
|
||||
stopSampling = () => {
|
||||
if(!this.isSampling()) return;
|
||||
window.cancelAnimationFrame(this.samplingId);
|
||||
this.samplingId = undefined;
|
||||
}
|
||||
|
||||
getListening = () => this.getCheckedById('listen');
|
||||
setListening = checked => {
|
||||
if(this.getListening() !== checked) {
|
||||
this.setCheckedById('listen', checked)
|
||||
this.dispatcher.emit('listenChange', {checked});
|
||||
}
|
||||
};
|
||||
|
||||
getStream = () => this.stream;
|
||||
|
||||
drawSpectrumAnalyzer = () => {
|
||||
const canvas = this.getElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
const width = canvas.width;
|
||||
const height = canvas.height;
|
||||
|
||||
let frequencyResolution = this.audioContext.sampleRate / this.analyser.fftSize;
|
||||
let nyquistFrequency = this.audioContext.sampleRate / 2;
|
||||
let buffer = new Uint8Array(this.analyser.frequencyBinCount);
|
||||
this.analyser.getByteFrequencyData(buffer);
|
||||
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
let barWidth = (1/buffer.length) * width;
|
||||
for(let i = 0; i < buffer.length; i++) {
|
||||
let x = i * barWidth;
|
||||
let y = (1 - (buffer[i] / 255)) * height;
|
||||
const hue = Math.floor(((i * frequencyResolution) / nyquistFrequency) * 360)
|
||||
ctx.fillStyle = `hsl(${hue}, 100%, 50%)`;
|
||||
ctx.fillRect(x, y, barWidth, height-y);
|
||||
}
|
||||
|
||||
this.samplingId = window.requestAnimationFrame(this.drawSpectrumAnalyzer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default MicrophonePanel;
|
||||
Reference in New Issue
Block a user