2023-01-07 14:07:39 +03:00
|
|
|
import { useEffect, useMemo, useRef, useState } from "react"
|
2023-01-12 17:01:45 +03:00
|
|
|
import { VoiceChangerClient } from "../VoiceChangerClient"
|
2023-01-12 10:38:45 +03:00
|
|
|
import { ClientSettingState, useClientSetting } from "./useClientSetting"
|
|
|
|
import { ServerSettingState, useServerSetting } from "./useServerSetting"
|
2023-02-19 20:21:51 +03:00
|
|
|
import { useWorkletNodeSetting, WorkletNodeSettingState } from "./useWorkletNodeSetting"
|
2023-01-11 22:52:01 +03:00
|
|
|
import { useWorkletSetting, WorkletSettingState } from "./useWorkletSetting"
|
2023-01-07 14:07:39 +03:00
|
|
|
|
|
|
|
export type UseClientProps = {
|
|
|
|
audioContext: AudioContext | null
|
|
|
|
audioOutputElementId: string
|
|
|
|
}
|
|
|
|
|
|
|
|
export type ClientState = {
|
2023-02-22 01:35:26 +03:00
|
|
|
initialized: boolean
|
2023-02-18 22:56:16 +03:00
|
|
|
// 各種設定I/Fへの参照
|
2023-01-12 10:38:45 +03:00
|
|
|
workletSetting: WorkletSettingState
|
|
|
|
clientSetting: ClientSettingState
|
2023-02-19 20:21:51 +03:00
|
|
|
workletNodeSetting: WorkletNodeSettingState
|
2023-01-12 10:38:45 +03:00
|
|
|
serverSetting: ServerSettingState
|
|
|
|
|
2023-02-18 22:56:16 +03:00
|
|
|
// モニタリングデータ
|
2023-01-07 14:07:39 +03:00
|
|
|
bufferingTime: number;
|
|
|
|
volume: number;
|
2023-02-20 22:07:43 +03:00
|
|
|
performance: PerformanceData
|
2023-01-08 10:18:20 +03:00
|
|
|
|
2023-02-18 22:56:16 +03:00
|
|
|
// 情報取得
|
2023-01-08 10:18:20 +03:00
|
|
|
getInfo: () => Promise<void>
|
2023-02-18 22:56:16 +03:00
|
|
|
// 設定クリア
|
2023-01-29 03:42:45 +03:00
|
|
|
clearSetting: () => Promise<void>
|
2023-01-07 14:07:39 +03:00
|
|
|
}
|
2023-01-11 17:12:29 +03:00
|
|
|
|
2023-02-20 22:07:43 +03:00
|
|
|
export type PerformanceData = {
|
|
|
|
responseTime: number
|
|
|
|
preprocessTime: number
|
|
|
|
mainprocessTime: number
|
|
|
|
postprocessTime: number
|
|
|
|
}
|
|
|
|
const InitialPerformanceData: PerformanceData = {
|
|
|
|
responseTime: 0,
|
|
|
|
preprocessTime: 0,
|
|
|
|
mainprocessTime: 0,
|
|
|
|
postprocessTime: 0
|
|
|
|
}
|
2023-01-11 17:12:29 +03:00
|
|
|
|
2023-01-07 14:07:39 +03:00
|
|
|
export const useClient = (props: UseClientProps): ClientState => {
|
|
|
|
|
2023-02-22 01:35:26 +03:00
|
|
|
const [initialized, setInitialized] = useState<boolean>(false)
|
2023-01-12 10:38:45 +03:00
|
|
|
// (1-1) クライアント
|
2023-01-11 22:52:01 +03:00
|
|
|
const voiceChangerClientRef = useRef<VoiceChangerClient | null>(null)
|
|
|
|
const [voiceChangerClient, setVoiceChangerClient] = useState<VoiceChangerClient | null>(voiceChangerClientRef.current)
|
2023-01-12 10:38:45 +03:00
|
|
|
//// クライアント初期化待ち用フラグ
|
2023-01-08 14:28:57 +03:00
|
|
|
const initializedResolveRef = useRef<(value: void | PromiseLike<void>) => void>()
|
|
|
|
const initializedPromise = useMemo(() => {
|
|
|
|
return new Promise<void>((resolve) => {
|
|
|
|
initializedResolveRef.current = resolve
|
|
|
|
})
|
|
|
|
}, [])
|
2023-01-12 10:38:45 +03:00
|
|
|
|
|
|
|
|
2023-02-18 22:56:16 +03:00
|
|
|
// (1-2) 各種設定I/F
|
2023-01-12 10:38:45 +03:00
|
|
|
const clientSetting = useClientSetting({ voiceChangerClient, audioContext: props.audioContext })
|
2023-02-19 20:21:51 +03:00
|
|
|
const workletNodeSetting = useWorkletNodeSetting({ voiceChangerClient })
|
2023-01-12 10:38:45 +03:00
|
|
|
const workletSetting = useWorkletSetting({ voiceChangerClient })
|
|
|
|
const serverSetting = useServerSetting({ voiceChangerClient })
|
|
|
|
|
2023-02-18 22:56:16 +03:00
|
|
|
// (1-3) モニタリングデータ
|
2023-01-10 16:49:16 +03:00
|
|
|
const [bufferingTime, setBufferingTime] = useState<number>(0)
|
2023-02-20 22:07:43 +03:00
|
|
|
const [performance, setPerformance] = useState<PerformanceData>(InitialPerformanceData)
|
2023-01-10 16:49:16 +03:00
|
|
|
const [volume, setVolume] = useState<number>(0)
|
2023-01-08 14:28:57 +03:00
|
|
|
|
2023-01-16 02:09:53 +03:00
|
|
|
// (1-4) エラーステータス
|
|
|
|
const errorCountRef = useRef<number>(0)
|
|
|
|
|
2023-01-12 10:38:45 +03:00
|
|
|
// (2-1) 初期化処理
|
2023-01-07 14:07:39 +03:00
|
|
|
useEffect(() => {
|
|
|
|
const initialized = async () => {
|
|
|
|
if (!props.audioContext) {
|
|
|
|
return
|
|
|
|
}
|
2023-01-11 22:52:01 +03:00
|
|
|
const voiceChangerClient = new VoiceChangerClient(props.audioContext, true, {
|
2023-01-07 14:07:39 +03:00
|
|
|
notifySendBufferingTime: (val: number) => {
|
|
|
|
setBufferingTime(val)
|
|
|
|
},
|
2023-02-20 22:07:43 +03:00
|
|
|
notifyResponseTime: (val: number, perf?: number[]) => {
|
|
|
|
const responseTime = val
|
|
|
|
const preprocessTime = perf ? Math.ceil(perf[0] * 1000) : 0
|
|
|
|
const mainprocessTime = perf ? Math.ceil(perf[1] * 1000) : 0
|
|
|
|
const postprocessTime = perf ? Math.ceil(perf[2] * 1000) : 0
|
|
|
|
setPerformance({ responseTime, preprocessTime, mainprocessTime, postprocessTime })
|
2023-01-07 14:07:39 +03:00
|
|
|
},
|
|
|
|
notifyException: (mes: string) => {
|
|
|
|
if (mes.length > 0) {
|
|
|
|
console.log(`error:${mes}`)
|
2023-01-16 02:09:53 +03:00
|
|
|
errorCountRef.current += 1
|
|
|
|
if (errorCountRef.current > 100) {
|
|
|
|
alert("エラーが頻発しています。対象としているフレームワークのモデルがロードされているか確認してください。")
|
|
|
|
errorCountRef.current = 0
|
|
|
|
}
|
2023-01-07 14:07:39 +03:00
|
|
|
}
|
2023-02-19 20:21:51 +03:00
|
|
|
},
|
2023-01-07 14:07:39 +03:00
|
|
|
notifyVolume: (vol: number) => {
|
|
|
|
setVolume(vol)
|
|
|
|
}
|
|
|
|
})
|
2023-01-08 14:28:57 +03:00
|
|
|
|
2023-01-07 14:07:39 +03:00
|
|
|
await voiceChangerClient.isInitialized()
|
|
|
|
voiceChangerClientRef.current = voiceChangerClient
|
2023-01-11 22:52:01 +03:00
|
|
|
setVoiceChangerClient(voiceChangerClientRef.current)
|
2023-01-08 10:18:20 +03:00
|
|
|
console.log("[useClient] client initialized")
|
2023-01-07 14:07:39 +03:00
|
|
|
|
|
|
|
const audio = document.getElementById(props.audioOutputElementId) as HTMLAudioElement
|
|
|
|
audio.srcObject = voiceChangerClientRef.current.stream
|
|
|
|
audio.play()
|
2023-01-08 14:28:57 +03:00
|
|
|
initializedResolveRef.current!()
|
2023-02-22 01:35:26 +03:00
|
|
|
setInitialized(true)
|
2023-01-07 14:07:39 +03:00
|
|
|
}
|
|
|
|
initialized()
|
|
|
|
}, [props.audioContext])
|
|
|
|
|
2023-01-08 10:18:20 +03:00
|
|
|
|
2023-01-12 10:38:45 +03:00
|
|
|
// (2-2) 情報リロード
|
2023-01-08 10:18:20 +03:00
|
|
|
const getInfo = useMemo(() => {
|
|
|
|
return async () => {
|
2023-01-08 14:28:57 +03:00
|
|
|
await initializedPromise
|
2023-02-19 00:25:22 +03:00
|
|
|
await clientSetting.reloadClientSetting() // 実質的な処理の意味はない
|
2023-01-12 10:38:45 +03:00
|
|
|
await serverSetting.reloadServerInfo()
|
2023-01-10 20:19:54 +03:00
|
|
|
}
|
2023-01-12 10:38:45 +03:00
|
|
|
}, [clientSetting, serverSetting])
|
2023-01-11 17:12:29 +03:00
|
|
|
|
|
|
|
|
2023-01-29 03:42:45 +03:00
|
|
|
const clearSetting = async () => {
|
|
|
|
await clientSetting.clearSetting()
|
2023-02-19 20:21:51 +03:00
|
|
|
await workletNodeSetting.clearSetting()
|
2023-01-29 03:42:45 +03:00
|
|
|
await workletSetting.clearSetting()
|
|
|
|
await serverSetting.clearSetting()
|
|
|
|
}
|
2023-01-11 22:52:01 +03:00
|
|
|
|
2023-01-07 14:07:39 +03:00
|
|
|
return {
|
2023-02-22 01:35:26 +03:00
|
|
|
initialized,
|
2023-02-18 22:56:16 +03:00
|
|
|
// 各種設定I/Fへの参照
|
|
|
|
clientSetting,
|
2023-02-19 20:21:51 +03:00
|
|
|
workletNodeSetting,
|
2023-02-18 22:56:16 +03:00
|
|
|
workletSetting,
|
|
|
|
serverSetting,
|
|
|
|
|
|
|
|
// モニタリングデータ
|
2023-01-07 14:07:39 +03:00
|
|
|
bufferingTime,
|
|
|
|
volume,
|
2023-02-20 22:07:43 +03:00
|
|
|
performance,
|
2023-01-07 14:07:39 +03:00
|
|
|
|
2023-02-18 22:56:16 +03:00
|
|
|
// 情報取得
|
2023-01-08 10:18:20 +03:00
|
|
|
getInfo,
|
2023-01-11 22:52:01 +03:00
|
|
|
|
2023-02-18 22:56:16 +03:00
|
|
|
// 設定クリア
|
2023-01-29 03:42:45 +03:00
|
|
|
clearSetting,
|
2023-01-07 14:07:39 +03:00
|
|
|
}
|
|
|
|
}
|