Spaces:
Sleeping
Sleeping
File size: 2,915 Bytes
0fea377 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
const SAMPLING_RATE = 16_000;
const Microphone = {
mounted() {
this.mediaRecorder = null;
this.el.addEventListener("mousedown", (event) => {
this.startRecording();
});
this.el.addEventListener("mouseup", (event) => {
this.stopRecording();
});
},
startRecording() {
this.audioChunks = [];
navigator.mediaDevices.getUserMedia({ audio: true }).then((stream) => {
this.mediaRecorder = new MediaRecorder(stream);
this.mediaRecorder.addEventListener("dataavailable", (event) => {
if (event.data.size > 0) {
this.audioChunks.push(event.data);
}
});
this.mediaRecorder.start();
});
},
stopRecording() {
this.mediaRecorder.addEventListener("stop", (event) => {
if (this.audioChunks.length === 0) return;
const audioBlob = new Blob(this.audioChunks);
audioBlob.arrayBuffer().then((buffer) => {
const context = new AudioContext({ sampleRate: SAMPLING_RATE });
context.decodeAudioData(buffer, (audioBuffer) => {
const pcmBuffer = audioBufferToPcm(audioBuffer);
const buffer = convertEndianness32(
pcmBuffer,
getEndianness(),
this.el.dataset.endianness
);
this.upload("audio", [new Blob([buffer])]);
});
});
});
this.mediaRecorder.stop();
},
isRecording() {
return this.mediaRecorder && this.mediaRecorder.state === "recording";
},
};
function audioBufferToPcm(audioBuffer) {
const numChannels = audioBuffer.numberOfChannels;
const length = audioBuffer.length;
const size = Float32Array.BYTES_PER_ELEMENT * length;
const buffer = new ArrayBuffer(size);
const pcmArray = new Float32Array(buffer);
const channelDataBuffers = Array.from({ length: numChannels }, (x, channel) =>
audioBuffer.getChannelData(channel)
);
// Average all channels upfront, so the PCM is always mono
for (let i = 0; i < pcmArray.length; i++) {
let sum = 0;
for (let channel = 0; channel < numChannels; channel++) {
sum += channelDataBuffers[channel][i];
}
pcmArray[i] = sum / numChannels;
}
return buffer;
}
function convertEndianness32(buffer, from, to) {
if (from === to) {
return buffer;
}
// If the endianness differs, we swap bytes accordingly
for (let i = 0; i < buffer.byteLength / 4; i++) {
const b1 = buffer[i];
const b2 = buffer[i + 1];
const b3 = buffer[i + 2];
const b4 = buffer[i + 3];
buffer[i] = b4;
buffer[i + 1] = b3;
buffer[i + 2] = b2;
buffer[i + 3] = b1;
}
return buffer;
}
function getEndianness() {
const buffer = new ArrayBuffer(2);
const int16Array = new Uint16Array(buffer);
const int8Array = new Uint8Array(buffer);
int16Array[0] = 1;
if (int8Array[0] === 1) {
return "little";
} else {
return "big";
}
}
export default Microphone;
|