2023-01-12 10:38:45 +03:00
|
|
|
import { useState, useMemo, useRef, useEffect } from "react"
|
2023-02-14 16:32:25 +03:00
|
|
|
|
|
|
|
import { VoiceChangerClientSetting, Protocol, BufferSize, VoiceChangerMode, SampleRate, Speaker, DefaultVoiceChangerClientSetting, INDEXEDDB_KEY_CLIENT, Correspondence, DownSamplingMode } from "../const"
|
2023-01-12 17:01:45 +03:00
|
|
|
import { createDummyMediaStream } from "../util"
|
|
|
|
import { VoiceChangerClient } from "../VoiceChangerClient"
|
2023-01-29 03:42:45 +03:00
|
|
|
import { useIndexedDB } from "./useIndexedDB"
|
2023-01-12 10:38:45 +03:00
|
|
|
|
|
|
|
export type UseClientSettingProps = {
|
|
|
|
voiceChangerClient: VoiceChangerClient | null
|
|
|
|
audioContext: AudioContext | null
|
|
|
|
}
|
|
|
|
|
|
|
|
export type ClientSettingState = {
|
|
|
|
setting: VoiceChangerClientSetting;
|
2023-01-29 03:42:45 +03:00
|
|
|
clearSetting: () => Promise<void>
|
2023-01-12 10:38:45 +03:00
|
|
|
setServerUrl: (url: string) => void;
|
|
|
|
setProtocol: (proto: Protocol) => void;
|
|
|
|
setAudioInput: (audioInput: string | MediaStream | null) => Promise<void>
|
|
|
|
setBufferSize: (bufferSize: BufferSize) => Promise<void>
|
2023-02-14 23:02:51 +03:00
|
|
|
setEchoCancel: (voiceFocus: boolean) => Promise<void>
|
|
|
|
setNoiseSuppression: (voiceFocus: boolean) => Promise<void>
|
|
|
|
setNoiseSuppression2: (voiceFocus: boolean) => Promise<void>
|
2023-01-12 10:38:45 +03:00
|
|
|
setInputChunkNum: (num: number) => void;
|
|
|
|
setVoiceChangerMode: (mode: VoiceChangerMode) => void
|
2023-02-14 16:32:25 +03:00
|
|
|
setDownSamplingMode: (mode: DownSamplingMode) => void
|
2023-01-12 10:38:45 +03:00
|
|
|
setSampleRate: (num: SampleRate) => void
|
|
|
|
setSpeakers: (speakers: Speaker[]) => void
|
2023-02-12 06:25:57 +03:00
|
|
|
setCorrespondences: (file: File | null) => Promise<void>
|
2023-02-12 12:19:22 +03:00
|
|
|
setInputGain: (val: number) => void
|
|
|
|
setOutputGain: (val: number) => void
|
2023-01-12 10:38:45 +03:00
|
|
|
start: () => Promise<void>
|
|
|
|
stop: () => Promise<void>
|
|
|
|
reloadClientSetting: () => Promise<void>
|
|
|
|
}
|
|
|
|
|
|
|
|
export const useClientSetting = (props: UseClientSettingProps): ClientSettingState => {
|
|
|
|
const settingRef = useRef<VoiceChangerClientSetting>(DefaultVoiceChangerClientSetting)
|
|
|
|
const [setting, _setSetting] = useState<VoiceChangerClientSetting>(settingRef.current)
|
2023-01-29 03:42:45 +03:00
|
|
|
const { setItem, getItem, removeItem } = useIndexedDB()
|
|
|
|
|
|
|
|
// 初期化 その1 DBから取得
|
|
|
|
useEffect(() => {
|
|
|
|
const loadCache = async () => {
|
|
|
|
const setting = await getItem(INDEXEDDB_KEY_CLIENT)
|
|
|
|
if (!setting) {
|
|
|
|
// デフォルト設定
|
|
|
|
console.log("No Chache",)
|
|
|
|
const params = new URLSearchParams(location.search);
|
|
|
|
const colab = params.get("colab")
|
|
|
|
if (colab == "true") {
|
|
|
|
settingRef.current.protocol = "rest"
|
|
|
|
settingRef.current.inputChunkNum = 64
|
|
|
|
} else {
|
|
|
|
settingRef.current.protocol = "sio"
|
|
|
|
settingRef.current.inputChunkNum = 32
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
settingRef.current = setting as VoiceChangerClientSetting
|
|
|
|
}
|
|
|
|
_setSetting({ ...settingRef.current })
|
|
|
|
}
|
|
|
|
|
|
|
|
loadCache()
|
|
|
|
}, [])
|
|
|
|
// 初期化 その2 クライアントに設定
|
|
|
|
useEffect(() => {
|
|
|
|
if (!props.voiceChangerClient) return
|
|
|
|
props.voiceChangerClient.setServerUrl(settingRef.current.mmvcServerUrl)
|
|
|
|
props.voiceChangerClient.setInputChunkNum(settingRef.current.inputChunkNum)
|
|
|
|
props.voiceChangerClient.setProtocol(settingRef.current.protocol)
|
|
|
|
props.voiceChangerClient.setVoiceChangerMode(settingRef.current.voiceChangerMode)
|
2023-02-12 12:19:22 +03:00
|
|
|
props.voiceChangerClient.setInputGain(settingRef.current.inputGain)
|
2023-01-29 03:42:45 +03:00
|
|
|
|
|
|
|
// Input, bufferSize, VoiceFocus Disableは_setInputで設定
|
|
|
|
_setInput()
|
|
|
|
}, [props.voiceChangerClient])
|
|
|
|
|
|
|
|
|
|
|
|
const setSetting = async (setting: VoiceChangerClientSetting) => {
|
|
|
|
const storeData = { ...setting }
|
|
|
|
if (typeof storeData.audioInput != "string") {
|
|
|
|
storeData.audioInput = null
|
|
|
|
}
|
|
|
|
setItem(INDEXEDDB_KEY_CLIENT, storeData)
|
|
|
|
_setSetting(setting)
|
|
|
|
}
|
|
|
|
|
|
|
|
const clearSetting = async () => {
|
|
|
|
await removeItem(INDEXEDDB_KEY_CLIENT)
|
|
|
|
}
|
2023-01-12 10:38:45 +03:00
|
|
|
|
|
|
|
//////////////
|
|
|
|
// 設定
|
|
|
|
/////////////
|
|
|
|
const setServerUrl = useMemo(() => {
|
|
|
|
return (url: string) => {
|
|
|
|
if (!props.voiceChangerClient) return
|
2023-01-12 10:47:09 +03:00
|
|
|
props.voiceChangerClient.setServerUrl(url, true)
|
2023-01-12 10:38:45 +03:00
|
|
|
settingRef.current.mmvcServerUrl = url
|
2023-01-29 03:42:45 +03:00
|
|
|
setSetting({ ...settingRef.current })
|
2023-01-12 10:38:45 +03:00
|
|
|
}
|
|
|
|
}, [props.voiceChangerClient])
|
|
|
|
|
|
|
|
const setProtocol = useMemo(() => {
|
|
|
|
return (proto: Protocol) => {
|
|
|
|
if (!props.voiceChangerClient) return
|
|
|
|
props.voiceChangerClient.setProtocol(proto)
|
|
|
|
settingRef.current.protocol = proto
|
2023-01-29 03:42:45 +03:00
|
|
|
setSetting({ ...settingRef.current })
|
2023-01-12 10:38:45 +03:00
|
|
|
}
|
|
|
|
}, [props.voiceChangerClient])
|
|
|
|
|
|
|
|
const _setInput = async () => {
|
|
|
|
if (!props.voiceChangerClient) return
|
|
|
|
if (!settingRef.current.audioInput || settingRef.current.audioInput == "none") {
|
2023-01-29 03:42:45 +03:00
|
|
|
// console.log("[useClient] setup!(1)", settingRef.current.audioInput)
|
2023-01-12 10:38:45 +03:00
|
|
|
const ms = createDummyMediaStream(props.audioContext!)
|
2023-02-14 23:02:51 +03:00
|
|
|
await props.voiceChangerClient.setup(ms, settingRef.current.bufferSize, settingRef.current.echoCancel, settingRef.current.noiseSuppression, settingRef.current.noiseSuppression2)
|
2023-01-12 10:38:45 +03:00
|
|
|
} else {
|
2023-01-29 03:42:45 +03:00
|
|
|
// console.log("[useClient] setup!(2)", settingRef.current.audioInput)
|
2023-02-14 23:02:51 +03:00
|
|
|
await props.voiceChangerClient.setup(settingRef.current.audioInput, settingRef.current.bufferSize, settingRef.current.echoCancel, settingRef.current.noiseSuppression, settingRef.current.noiseSuppression2)
|
2023-01-12 10:38:45 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const setAudioInput = useMemo(() => {
|
|
|
|
return async (audioInput: string | MediaStream | null) => {
|
|
|
|
if (!props.voiceChangerClient) return
|
|
|
|
settingRef.current.audioInput = audioInput
|
|
|
|
await _setInput()
|
2023-01-29 03:42:45 +03:00
|
|
|
setSetting({ ...settingRef.current })
|
2023-01-12 10:38:45 +03:00
|
|
|
}
|
|
|
|
}, [props.voiceChangerClient])
|
|
|
|
|
|
|
|
const setBufferSize = useMemo(() => {
|
|
|
|
return async (bufferSize: BufferSize) => {
|
|
|
|
if (!props.voiceChangerClient) return
|
|
|
|
settingRef.current.bufferSize = bufferSize
|
|
|
|
await _setInput()
|
2023-01-29 03:42:45 +03:00
|
|
|
setSetting({ ...settingRef.current })
|
2023-01-12 10:38:45 +03:00
|
|
|
}
|
|
|
|
}, [props.voiceChangerClient])
|
|
|
|
|
2023-02-14 23:02:51 +03:00
|
|
|
const setEchoCancel = useMemo(() => {
|
|
|
|
return async (val: boolean) => {
|
|
|
|
if (!props.voiceChangerClient) return
|
|
|
|
settingRef.current.echoCancel = val
|
|
|
|
await _setInput()
|
|
|
|
setSetting({ ...settingRef.current })
|
|
|
|
}
|
|
|
|
}, [props.voiceChangerClient])
|
|
|
|
|
|
|
|
const setNoiseSuppression = useMemo(() => {
|
|
|
|
return async (val: boolean) => {
|
|
|
|
if (!props.voiceChangerClient) return
|
|
|
|
settingRef.current.noiseSuppression = val
|
|
|
|
await _setInput()
|
|
|
|
setSetting({ ...settingRef.current })
|
|
|
|
}
|
|
|
|
}, [props.voiceChangerClient])
|
|
|
|
|
|
|
|
const setNoiseSuppression2 = useMemo(() => {
|
|
|
|
return async (val: boolean) => {
|
2023-01-12 10:38:45 +03:00
|
|
|
if (!props.voiceChangerClient) return
|
2023-02-14 23:02:51 +03:00
|
|
|
settingRef.current.noiseSuppression2 = val
|
2023-01-12 10:38:45 +03:00
|
|
|
await _setInput()
|
2023-01-29 03:42:45 +03:00
|
|
|
setSetting({ ...settingRef.current })
|
2023-01-12 10:38:45 +03:00
|
|
|
}
|
|
|
|
}, [props.voiceChangerClient])
|
|
|
|
|
|
|
|
const setInputChunkNum = useMemo(() => {
|
|
|
|
return (num: number) => {
|
|
|
|
if (!props.voiceChangerClient) return
|
|
|
|
props.voiceChangerClient.setInputChunkNum(num)
|
|
|
|
settingRef.current.inputChunkNum = num
|
2023-01-29 03:42:45 +03:00
|
|
|
setSetting({ ...settingRef.current })
|
2023-01-12 10:38:45 +03:00
|
|
|
}
|
|
|
|
}, [props.voiceChangerClient])
|
|
|
|
|
|
|
|
const setVoiceChangerMode = useMemo(() => {
|
|
|
|
return (mode: VoiceChangerMode) => {
|
|
|
|
if (!props.voiceChangerClient) return
|
|
|
|
props.voiceChangerClient.setVoiceChangerMode(mode)
|
|
|
|
settingRef.current.voiceChangerMode = mode
|
2023-01-29 03:42:45 +03:00
|
|
|
setSetting({ ...settingRef.current })
|
2023-01-12 10:38:45 +03:00
|
|
|
}
|
|
|
|
}, [props.voiceChangerClient])
|
|
|
|
|
2023-02-14 16:32:25 +03:00
|
|
|
const setDownSamplingMode = useMemo(() => {
|
|
|
|
return (mode: DownSamplingMode) => {
|
|
|
|
if (!props.voiceChangerClient) return
|
|
|
|
props.voiceChangerClient.setDownSamplingMode(mode)
|
|
|
|
settingRef.current.downSamplingMode = mode
|
|
|
|
setSetting({ ...settingRef.current })
|
|
|
|
}
|
|
|
|
}, [props.voiceChangerClient])
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-01-12 10:38:45 +03:00
|
|
|
const setSampleRate = useMemo(() => {
|
|
|
|
return (num: SampleRate) => {
|
|
|
|
if (!props.voiceChangerClient) return
|
|
|
|
//props.voiceChangerClient.setSampleRate(num) // Not Implemented
|
|
|
|
settingRef.current.sampleRate = num
|
2023-01-29 03:42:45 +03:00
|
|
|
setSetting({ ...settingRef.current })
|
2023-01-12 10:38:45 +03:00
|
|
|
}
|
|
|
|
}, [props.voiceChangerClient])
|
|
|
|
|
|
|
|
const setSpeakers = useMemo(() => {
|
|
|
|
return (speakers: Speaker[]) => {
|
|
|
|
if (!props.voiceChangerClient) return
|
|
|
|
settingRef.current.speakers = speakers
|
2023-01-29 03:42:45 +03:00
|
|
|
setSetting({ ...settingRef.current })
|
2023-01-12 10:38:45 +03:00
|
|
|
}
|
|
|
|
}, [props.voiceChangerClient])
|
|
|
|
|
2023-02-12 06:25:57 +03:00
|
|
|
const setCorrespondences = useMemo(() => {
|
|
|
|
return async (file: File | null) => {
|
|
|
|
if (!props.voiceChangerClient) return
|
|
|
|
if (!file) {
|
|
|
|
settingRef.current.correspondences = []
|
|
|
|
} else {
|
|
|
|
const correspondenceText = await file.text()
|
|
|
|
const cors = correspondenceText.split("\n").map(line => {
|
|
|
|
const items = line.split("|")
|
|
|
|
if (items.length != 3) {
|
|
|
|
console.warn("Invalid Correspondence Line:", line)
|
|
|
|
return null
|
|
|
|
} else {
|
|
|
|
const cor: Correspondence = {
|
|
|
|
sid: Number(items[0]),
|
|
|
|
correspondence: Number(items[1]),
|
|
|
|
dirname: items[2]
|
|
|
|
}
|
|
|
|
return cor
|
|
|
|
}
|
|
|
|
}).filter(x => { return x != null }) as Correspondence[]
|
|
|
|
settingRef.current.correspondences = cors
|
|
|
|
}
|
|
|
|
setSetting({ ...settingRef.current })
|
|
|
|
}
|
|
|
|
}, [props.voiceChangerClient])
|
|
|
|
|
2023-02-12 12:19:22 +03:00
|
|
|
const setInputGain = useMemo(() => {
|
|
|
|
return (val: number) => {
|
|
|
|
if (!props.voiceChangerClient) return
|
|
|
|
props.voiceChangerClient.setInputGain(val)
|
|
|
|
settingRef.current.inputGain = val
|
|
|
|
setSetting({ ...settingRef.current })
|
|
|
|
}
|
|
|
|
}, [props.voiceChangerClient])
|
|
|
|
const setOutputGain = useMemo(() => {
|
|
|
|
return (val: number) => {
|
|
|
|
if (!props.voiceChangerClient) return
|
|
|
|
props.voiceChangerClient.setOutputGain(val)
|
|
|
|
settingRef.current.outputGain = val
|
|
|
|
setSetting({ ...settingRef.current })
|
|
|
|
}
|
|
|
|
}, [props.voiceChangerClient])
|
|
|
|
|
2023-01-12 10:38:45 +03:00
|
|
|
//////////////
|
|
|
|
// 操作
|
|
|
|
/////////////
|
|
|
|
// (1) start
|
|
|
|
const start = useMemo(() => {
|
|
|
|
return async () => {
|
|
|
|
if (!props.voiceChangerClient) return
|
|
|
|
props.voiceChangerClient.setServerUrl(setting.mmvcServerUrl, true)
|
|
|
|
props.voiceChangerClient.start()
|
|
|
|
}
|
|
|
|
}, [setting.mmvcServerUrl, props.voiceChangerClient])
|
|
|
|
// (2) stop
|
|
|
|
const stop = useMemo(() => {
|
|
|
|
return async () => {
|
|
|
|
if (!props.voiceChangerClient) return
|
|
|
|
props.voiceChangerClient.stop()
|
|
|
|
}
|
|
|
|
}, [props.voiceChangerClient])
|
|
|
|
const reloadClientSetting = useMemo(() => {
|
|
|
|
return async () => {
|
|
|
|
if (!props.voiceChangerClient) return
|
|
|
|
await props.voiceChangerClient.getClientSettings()
|
|
|
|
}
|
|
|
|
}, [props.voiceChangerClient])
|
|
|
|
|
|
|
|
return {
|
|
|
|
setting,
|
2023-01-29 03:42:45 +03:00
|
|
|
clearSetting,
|
2023-01-12 10:38:45 +03:00
|
|
|
setServerUrl,
|
|
|
|
setProtocol,
|
|
|
|
setAudioInput,
|
|
|
|
setBufferSize,
|
2023-02-14 23:02:51 +03:00
|
|
|
setEchoCancel,
|
|
|
|
setNoiseSuppression,
|
|
|
|
setNoiseSuppression2,
|
2023-01-12 10:38:45 +03:00
|
|
|
setInputChunkNum,
|
|
|
|
setVoiceChangerMode,
|
2023-02-14 16:32:25 +03:00
|
|
|
setDownSamplingMode,
|
2023-01-12 10:38:45 +03:00
|
|
|
setSampleRate,
|
|
|
|
setSpeakers,
|
2023-02-12 06:25:57 +03:00
|
|
|
setCorrespondences,
|
2023-02-12 12:19:22 +03:00
|
|
|
setInputGain,
|
|
|
|
setOutputGain,
|
2023-01-12 10:38:45 +03:00
|
|
|
|
|
|
|
start,
|
|
|
|
stop,
|
|
|
|
reloadClientSetting
|
|
|
|
}
|
|
|
|
}
|