138 lines
3.6 KiB
TypeScript
138 lines
3.6 KiB
TypeScript
import useMitt from "@/modules/mitt";
|
|
import { useIpc } from '@/modules/ipc';
|
|
import { showRecIcon, hideRecIcon } from "./animations";
|
|
import { onMounted, onUnmounted, ref, Ref } from "vue";
|
|
import keyboardNameMap from "../keyBoardMaps/keyboardNameMap";
|
|
import { renderMessage, clientMessage } from '@/modules/message';
|
|
import { AudioData } from "@/types";
|
|
|
|
|
|
function arrayBufferToBase64 (buffer: any) {
|
|
var binary = '';
|
|
var bytes = new Uint8Array(buffer);
|
|
var len = bytes.byteLength;
|
|
for (var i = 0; i < len; i++) {
|
|
binary += String.fromCharCode( bytes[ i ] );
|
|
}
|
|
return window.btoa( binary );
|
|
}
|
|
|
|
|
|
|
|
export default function useAudioInputController (typing: Ref) {
|
|
|
|
let mediaRecorder: any;
|
|
let buffer = '';
|
|
let sampleRate = 44100; // default
|
|
let channels = 1;
|
|
|
|
// For sending messages.
|
|
const { post, invoke } = useIpc();
|
|
const { emitter } = useMitt();
|
|
|
|
const recording = ref(false);
|
|
|
|
// initiate media recorder
|
|
if (navigator.mediaDevices) {
|
|
console.log("Initializing media recorder.");
|
|
|
|
const usrOptions: any = {
|
|
audio: true,
|
|
video: false
|
|
}
|
|
|
|
navigator.mediaDevices.getUserMedia(usrOptions).then((stream: any) => {
|
|
|
|
const context = new AudioContext();
|
|
const source = context.createMediaStreamSource(stream);
|
|
const processor = context.createScriptProcessor(1024, 1, 1);
|
|
|
|
source.connect(processor);
|
|
processor.connect(context.destination);
|
|
|
|
processor.onaudioprocess = (e: AudioProcessingEvent) => {
|
|
|
|
if (recording.value) {
|
|
|
|
const data = e.inputBuffer.getChannelData(0).buffer;
|
|
|
|
buffer += arrayBufferToBase64(data);
|
|
|
|
sampleRate = e.inputBuffer.sampleRate;
|
|
|
|
} else buffer = '';
|
|
|
|
};
|
|
|
|
});
|
|
|
|
}
|
|
|
|
//---Callbacks-----------------------------------------------
|
|
|
|
const onKeyDown = (e: KeyboardEvent) => {
|
|
const cmd = keyboardNameMap[e.keyCode];
|
|
|
|
// Start recording on space bar.
|
|
if (cmd == "SPACE" && !typing.value && !recording.value) {
|
|
|
|
console.log("INPT:Starting record, filling buffer.")
|
|
recording.value = true;
|
|
showRecIcon();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const onKeyUp = async (e: KeyboardEvent) => {
|
|
const cmd = keyboardNameMap[e.keyCode];
|
|
|
|
// Stop recording on space up.
|
|
if (cmd == "SPACE" && recording.value) {
|
|
|
|
// get audio from buffer then stop recording
|
|
console.log("INPT:Stopping record.")
|
|
recording.value = false;
|
|
hideRecIcon()
|
|
|
|
// render a place holder message
|
|
const message = renderMessage(
|
|
"",
|
|
"",
|
|
"",
|
|
"sf"
|
|
);
|
|
|
|
emitter.emit("self-message", message);
|
|
|
|
// send audio to backend
|
|
const audio: AudioData = {
|
|
content: buffer,
|
|
channels: channels,
|
|
fs: sampleRate
|
|
}
|
|
|
|
console.log("INPT:Sending audio to backend");
|
|
post("client-message", clientMessage("", audio, message.uid));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
onMounted(() => {
|
|
window.addEventListener("keydown", onKeyDown);
|
|
window.addEventListener("keyup", onKeyUp);
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
window.removeEventListener("keydown", onKeyDown);
|
|
window.removeEventListener("keyup", onKeyUp);
|
|
});
|
|
|
|
return {
|
|
recording
|
|
}
|
|
|
|
}
|