WIP: gui commonize 2

This commit is contained in:
wataru 2023-04-05 02:31:06 +09:00
parent 2adfb7c910
commit 604846b0c6
31 changed files with 1335 additions and 28 deletions

View File

@ -18,9 +18,30 @@
"qualityControl": { "qualityControl": {
"F0DetectorEnable": false "F0DetectorEnable": false
}, },
"speakerSetting": [], "speakerSetting": {
"converterSetting": [], "showSpeakerF0": false,
"advancedSetting": [] "srcIdEnable": true,
"editSpeakerIdMappingEnable": true,
"f0FactorEnable": false,
"tuningEnable": false,
"clusterInferRationEnable": false,
"noiseScaleEnable": false,
"silentThresholdEnable": false
},
"converterSetting": {
"extraDataLengthEnable": false
},
"advancedSetting": {
"serverURLEnable": true,
"protocolEnable": true,
"sampleRateEnable": true,
"sendingSampleRateEnable": true,
"crossFadeOverlapSizeEnable": true,
"crossFadeOffsetRateEnable": true,
"crossFadeEndRateEnable": true,
"downSamplingModeEnable": true,
"trancateNumTresholdEnable": true
}
}, },
"dialogs": { "dialogs": {

File diff suppressed because one or more lines are too long

View File

@ -18,9 +18,30 @@
"qualityControl": { "qualityControl": {
"F0DetectorEnable": false "F0DetectorEnable": false
}, },
"speakerSetting": [], "speakerSetting": {
"converterSetting": [], "showSpeakerF0": false,
"advancedSetting": [] "srcIdEnable": true,
"editSpeakerIdMappingEnable": true,
"f0FactorEnable": false,
"tuningEnable": false,
"clusterInferRationEnable": false,
"noiseScaleEnable": false,
"silentThresholdEnable": false
},
"converterSetting": {
"extraDataLengthEnable": false
},
"advancedSetting": {
"serverURLEnable": true,
"protocolEnable": true,
"sampleRateEnable": true,
"sendingSampleRateEnable": true,
"crossFadeOverlapSizeEnable": true,
"crossFadeOffsetRateEnable": true,
"crossFadeEndRateEnable": true,
"downSamplingModeEnable": true,
"trancateNumTresholdEnable": true
}
}, },
"dialogs": { "dialogs": {

View File

@ -1,6 +1,4 @@
import { useState } from "react" import { useState } from "react"
import { AppGuiDemoClearSetting } from "../components/demo/102_ClearSettingRow"
import { AppGuiDemoDialogLicenseSetting } from "../components/demo/901_LicenseDialog"
import { ClientType } from "@dannadori/voice-changer-client-js" import { ClientType } from "@dannadori/voice-changer-client-js"
export type AppGuiSetting = AppGuiDemoSetting export type AppGuiSetting = AppGuiDemoSetting
@ -26,18 +24,36 @@ export type AppGuiDemoSetting = {
"qualityControl": { "qualityControl": {
"F0DetectorEnable": boolean "F0DetectorEnable": boolean
}, },
"speakerSetting": AppGuiDemoComponents[], "speakerSetting": {
"converterSetting": AppGuiDemoComponents[], "showSpeakerF0": boolean
"advancedSetting": AppGuiDemoComponents[] "srcIdEnable": boolean
"editSpeakerIdMappingEnable": boolean
"f0FactorEnable": boolean
"tuningEnable": boolean
"clusterInferRationEnable": boolean
"noiseScaleEnable": boolean
"silentThresholdEnable": boolean
},
"converterSetting": {
"extraDataLengthEnable": boolean
},
"advancedSetting": {
"serverURLEnable": boolean,
"protocolEnable": boolean,
"sampleRateEnable": boolean,
"sendingSampleRateEnable": boolean,
"crossFadeOverlapSizeEnable": boolean,
"crossFadeOffsetRateEnable": boolean,
"crossFadeEndRateEnable": boolean,
"downSamplingModeEnable": boolean,
"trancateNumTresholdEnable": boolean,
}
}, },
dialogs: { dialogs: {
"license": { title: string, auther: string, contact: string, url: string, license: string }[] "license": { title: string, auther: string, contact: string, url: string, license: string }[]
} }
} }
export type AppGuiDemoComponents = AppGuiDemoClearSetting
export type AppGuiDemoDialogComponents = AppGuiDemoDialogLicenseSetting
const InitialAppGuiDemoSetting: AppGuiDemoSetting = { const InitialAppGuiDemoSetting: AppGuiDemoSetting = {
@ -62,9 +78,31 @@ const InitialAppGuiDemoSetting: AppGuiDemoSetting = {
"qualityControl": { "qualityControl": {
"F0DetectorEnable": false "F0DetectorEnable": false
}, },
"speakerSetting": [], "speakerSetting": {
"converterSetting": [], "showSpeakerF0": false,
"advancedSetting": [] "srcIdEnable": false,
"editSpeakerIdMappingEnable": false,
"f0FactorEnable": false,
"tuningEnable": false,
"clusterInferRationEnable": false,
"noiseScaleEnable": false,
"silentThresholdEnable": false
},
"converterSetting": {
"extraDataLengthEnable": false
},
"advancedSetting": {
"serverURLEnable": false,
"protocolEnable": false,
"sampleRateEnable": false,
"sendingSampleRateEnable": false,
"crossFadeOverlapSizeEnable": false,
"crossFadeOffsetRateEnable": false,
"crossFadeEndRateEnable": false,
"downSamplingModeEnable": false,
"trancateNumTresholdEnable": false,
}
}, },
dialogs: { dialogs: {
"license": [{ title: "", auther: "", contact: "", url: "", license: "MIT" }] "license": [{ title: "", auther: "", contact: "", url: "", license: "MIT" }]

View File

@ -62,10 +62,11 @@ export const AppStateProvider = ({ children }: Props) => {
}, [clientState.clientState.initialized]) }, [clientState.clientState.initialized])
useEffect(() => { useEffect(() => {
appGuiSettingState.getAppSetting("/assets/gui_settings/MMVCv13.json") const params = new URLSearchParams(window.location.search);
const modelType = params.get("modelType") || ""
appGuiSettingState.getAppSetting(`/assets/gui_settings/${modelType}.json`)
}, []) }, [])
console.log("appSettingState", appGuiSettingState)
const providerValue: AppStateValue = { const providerValue: AppStateValue = {
audioContext: appRoot.audioContextState.audioContext!, audioContext: appRoot.audioContextState.audioContext!,
...clientState.clientState, ...clientState.clientState,

View File

@ -119,7 +119,6 @@ export const GuiStateProvider = ({ children }: Props) => {
useEffect(() => { useEffect(() => {
const audioInitialize = async () => { const audioInitialize = async () => {
const audioInfo = await reloadDeviceInfo() const audioInfo = await reloadDeviceInfo()
console.log("AUDIO", audioInfo)
setInputAudioDeviceInfo(audioInfo[0]) setInputAudioDeviceInfo(audioInfo[0])
setOutputAudioDeviceInfo(audioInfo[1]) setOutputAudioDeviceInfo(audioInfo[1])
} }

View File

@ -7,6 +7,9 @@ import { ServerControl } from "./200_ServerControl";
import { ModelSetting } from "./300_ModelSetting"; import { ModelSetting } from "./300_ModelSetting";
import { DeviceSetting } from "./400_DeviceSetting"; import { DeviceSetting } from "./400_DeviceSetting";
import { QualityControl } from "./500_QualityControl"; import { QualityControl } from "./500_QualityControl";
import { SpeakerSetting } from "./600_SpeakerSetting";
import { ConverterSetting } from "./700_ConverterSetting";
import { AdvancedSetting } from "./800_AdvancedSetting";
@ -21,13 +24,15 @@ export const Demo = () => {
<ModelSetting /> <ModelSetting />
<DeviceSetting /> <DeviceSetting />
<QualityControl /> <QualityControl />
{/* {guiState.stateControls.openServerControlCheckbox.trigger} */} <SpeakerSetting />
<ConverterSetting />
<AdvancedSetting />
<audio hidden id={AUDIO_ELEMENT_FOR_PLAY_RESULT}></audio> {/* <audio hidden id={AUDIO_ELEMENT_FOR_PLAY_RESULT}></audio>
org:<audio id={AUDIO_ELEMENT_FOR_TEST_ORIGINAL} controls></audio> org:<audio id={AUDIO_ELEMENT_FOR_TEST_ORIGINAL} controls></audio>
<audio id={AUDIO_ELEMENT_FOR_TEST_CONVERTED} controls></audio> <audio id={AUDIO_ELEMENT_FOR_TEST_CONVERTED} controls></audio>
<audio id={AUDIO_ELEMENT_FOR_TEST_CONVERTED_ECHOBACK} controls hidden></audio> <audio id={AUDIO_ELEMENT_FOR_TEST_CONVERTED_ECHOBACK} controls hidden></audio> */}
</div> </div>
</GuiStateProvider> </GuiStateProvider>

View File

@ -0,0 +1,61 @@
import React, { useMemo } from "react"
import { AnimationTypes, HeaderButton, HeaderButtonProps } from "../101_HeaderButton"
import { useGuiState } from "./001_GuiStateProvider"
import { SrcIdRow } from "./601_SrcIdRow"
import { DstIdRow } from "./602_DstIdRow"
import { EditSpeakerIdMappingRow } from "./603_EditSpeakerIdMappingRow"
import { F0FactorRow } from "./604_F0FactorRow"
import { TuneRow } from "./605_TuneRow"
import { ClusterInferRatioRow } from "./606_ClusterInferRatioRow"
import { NoiseScaleRow } from "./607_NoiseScaleRow"
import { SilentThresholdRow } from "./608_SilentThresholdRow"
export const SpeakerSetting = () => {
const guiState = useGuiState()
const accodionButton = useMemo(() => {
const accodionButtonProps: HeaderButtonProps = {
stateControlCheckbox: guiState.stateControls.openSpeakerSettingCheckbox,
tooltip: "Open/Close",
onIcon: ["fas", "caret-up"],
offIcon: ["fas", "caret-up"],
animation: AnimationTypes.spinner,
tooltipClass: "tooltip-right",
};
return <HeaderButton {...accodionButtonProps}></HeaderButton>;
}, []);
const deviceSetting = useMemo(() => {
return (
<>
{guiState.stateControls.openSpeakerSettingCheckbox.trigger}
<div className="partition">
<div className="partition-header">
<span className="caret">
{accodionButton}
</span>
<span className="title" onClick={() => { guiState.stateControls.openSpeakerSettingCheckbox.updateState(!guiState.stateControls.openSpeakerSettingCheckbox.checked()) }}>
Speaker Setting
</span>
<span></span>
</div>
<div className="partition-content">
<SrcIdRow />
<DstIdRow />
<EditSpeakerIdMappingRow />
<F0FactorRow />
<TuneRow />
<ClusterInferRatioRow />
<NoiseScaleRow />
<SilentThresholdRow />
</div>
</div>
</>
)
}, [])
return deviceSetting
}

View File

@ -0,0 +1,78 @@
import React, { useMemo } from "react"
import { useAppState } from "../../001_provider/001_AppStateProvider"
export const SrcIdRow = () => {
const appState = useAppState()
const speakerSetting = appState.appGuiSettingState.appGuiSetting.front.speakerSetting
const srcIdRow = useMemo(() => {
if (!speakerSetting.srcIdEnable) {
return <></>
}
if (speakerSetting.showSpeakerF0) {
return <></>
}
return (
<div className="body-row split-3-2-1-4 left-padding-1 guided">
<div className="body-item-title left-padding-1">Source Speaker Id</div>
<div className="body-select-container">
<select className="body-select" value={appState.serverSetting.serverSetting.srcId} onChange={(e) => {
appState.serverSetting.updateServerSettings({ ...appState.serverSetting.serverSetting, srcId: Number(e.target.value) })
}}>
{
appState.clientSetting.clientSetting.speakers.map(x => {
return <option key={x.id} value={x.id}>{x.name}({x.id})</option>
})
}
</select>
</div>
<div className="body-item-text">
</div>
<div className="body-item-text"></div>
</div>
)
}, [appState.serverSetting.serverSetting, appState.serverSetting.updateServerSettings, appState.clientSetting.clientSetting.speakers])
const srcIdRowWithF0 = useMemo(() => {
if (!speakerSetting.srcIdEnable) {
return <></>
}
if (!speakerSetting.showSpeakerF0) {
return <></>
}
const selected = appState.clientSetting.clientSetting.correspondences?.find(x => {
return x.sid == appState.serverSetting.serverSetting.srcId
})
return (
<div className="body-row split-3-2-1-4 left-padding-1 guided">
<div className="body-item-title left-padding-1">Source Speaker Id</div>
<div className="body-select-container">
<select className="body-select" value={appState.serverSetting.serverSetting.srcId} onChange={(e) => {
// const recF0 = calcDefaultF0Factor(Number(e.target.value), appState.serverSetting.serverSetting.dstId)
// appState.serverSetting.updateServerSettings({ ...appState.serverSetting.serverSetting, srcId: Number(e.target.value), f0Factor: recF0 })
appState.serverSetting.updateServerSettings({ ...appState.serverSetting.serverSetting, srcId: Number(e.target.value) })
}}>
{
appState.clientSetting.clientSetting.correspondences?.map(x => {
return <option key={x.sid} value={x.sid}>{x.dirname}({x.sid})</option>
})
}
</select>
</div>
<div className="body-item-text">
<div>F0: {selected?.correspondence.toFixed(1) || ""}</div>
</div>
<div className="body-item-text"></div>
</div>
)
}, [appState.serverSetting.serverSetting, appState.serverSetting.updateServerSettings, appState.clientSetting.clientSetting.correspondences])
return (
<>
{srcIdRow}
{srcIdRowWithF0}
</>
)
}

View File

@ -0,0 +1,78 @@
import React, { useMemo } from "react"
import { useAppState } from "../../001_provider/001_AppStateProvider"
export const DstIdRow = () => {
const appState = useAppState()
const speakerSetting = appState.appGuiSettingState.appGuiSetting.front.speakerSetting
const dstIdRow = useMemo(() => {
if (speakerSetting.showSpeakerF0) {
return <></>
}
return (
<div className="body-row split-3-2-1-4 left-padding-1 guided">
<div className="body-item-title left-padding-1">Destination Speaker Id</div>
<div className="body-select-container">
<select className="body-select" value={appState.serverSetting.serverSetting.dstId} onChange={(e) => {
appState.serverSetting.updateServerSettings({ ...appState.serverSetting.serverSetting, dstId: Number(e.target.value) })
}}>
{
appState.clientSetting.clientSetting.speakers?.map(x => {
return <option key={x.id} value={x.id}>{x.name}({x.id})</option>
})
}
</select>
</div>
<div className="body-item-text">
</div>
<div className="body-item-text"></div>
</div>
)
}, [appState.serverSetting.serverSetting, appState.clientSetting.clientSetting.speakers, appState.serverSetting.updateServerSettings])
const dstIdRowWithF0 = useMemo(() => {
if (!speakerSetting.showSpeakerF0) {
return <></>
}
const selected = appState.clientSetting.clientSetting.correspondences?.find(x => {
return x.sid == appState.serverSetting.serverSetting.dstId
})
return (
<div className="body-row split-3-2-1-4 left-padding-1 guided">
<div className="body-item-title left-padding-1">Destination Speaker Id</div>
<div className="body-select-container">
<select className="body-select" value={appState.serverSetting.serverSetting.dstId} onChange={(e) => {
// const recF0 = calcDefaultF0Factor(appState.serverSetting.serverSetting.srcId, Number(e.target.value))
// appState.serverSetting.updateServerSettings({ ...appState.serverSetting.serverSetting, dstId: Number(e.target.value), f0Factor: recF0 })
appState.serverSetting.updateServerSettings({ ...appState.serverSetting.serverSetting, dstId: Number(e.target.value) })
}}>
{
appState.clientSetting.clientSetting.correspondences?.map(x => {
return <option key={x.sid} value={x.sid}>{x.dirname}({x.sid})</option>
})
}
</select>
</div>
<div className="body-item-text">
<div>F0: {selected?.correspondence.toFixed(1) || ""}</div>
</div>
<div className="body-item-text"></div>
</div>
)
}, [appState.serverSetting.serverSetting, appState.serverSetting.updateServerSettings, appState.clientSetting.clientSetting.correspondences])
return (
<>
{dstIdRow}
{dstIdRowWithF0}
</>
)
}

View File

@ -0,0 +1,62 @@
import React, { useMemo, useState } from "react"
import { useAppState } from "../../001_provider/001_AppStateProvider"
export const EditSpeakerIdMappingRow = () => {
const appState = useAppState()
const speakerSetting = appState.appGuiSettingState.appGuiSetting.front.speakerSetting
const [editSpeakerTargetId, setEditSpeakerTargetId] = useState<number>(0)
const [editSpeakerTargetName, setEditSpeakerTargetName] = useState<string>("")
const editSpeakerIdMappingRow = useMemo(() => {
if (!speakerSetting.editSpeakerIdMappingEnable) {
return <></>
}
const onSetSpeakerMappingClicked = async () => {
const targetId = editSpeakerTargetId
const targetName = editSpeakerTargetName
const targetSpeaker = appState.clientSetting.clientSetting.speakers.find(x => { return x.id == targetId })
if (targetSpeaker) {
if (targetName.length == 0) { // Delete
const newSpeakers = appState.clientSetting.clientSetting.speakers.filter(x => { return x.id != targetId })
appState.clientSetting.updateClientSetting({ ...appState.clientSetting.clientSetting, speakers: newSpeakers })
} else { // Update
targetSpeaker.name = targetName
appState.clientSetting.updateClientSetting({ ...appState.clientSetting.clientSetting, speakers: [...appState.clientSetting.clientSetting.speakers] })
}
} else {
if (targetName.length == 0) { // Noop
} else {// add
appState.clientSetting.clientSetting.speakers.push({
id: targetId,
name: targetName
})
appState.clientSetting.updateClientSetting({ ...appState.clientSetting.clientSetting, speakers: [...appState.clientSetting.clientSetting.speakers] })
}
}
}
return (
<div className="body-row split-3-1-2-4 left-padding-1 guided">
<div className="body-item-title left-padding-1">Edit Speaker Mapping</div>
<div className="body-input-container">
<input type="number" min={1} max={256} step={1} value={editSpeakerTargetId} onChange={(e) => {
const id = Number(e.target.value)
setEditSpeakerTargetId(id)
setEditSpeakerTargetName(appState.clientSetting.clientSetting.speakers.find(x => { return x.id == id })?.name || "")
}} />
</div>
<div className="body-input-container">
<input type="text" value={editSpeakerTargetName} onChange={(e) => {
setEditSpeakerTargetName(e.target.value)
}} />
</div>
<div className="body-button-container">
<div className="body-button" onClick={onSetSpeakerMappingClicked}>set</div>
</div>
</div>
)
}, [appState.clientSetting.clientSetting.speakers, editSpeakerTargetId, editSpeakerTargetName])
return editSpeakerIdMappingRow
}

View File

@ -0,0 +1,38 @@
import React, { useMemo } from "react"
import { useAppState } from "../../001_provider/001_AppStateProvider"
export const F0FactorRow = () => {
const appState = useAppState()
const speakerSetting = appState.appGuiSettingState.appGuiSetting.front.speakerSetting
const f0FactorRow = useMemo(() => {
if (!speakerSetting.f0FactorEnable) {
return <></>
}
const src = appState.clientSetting.clientSetting.correspondences?.find(x => {
return x.sid == appState.serverSetting.serverSetting.srcId
})
const dst = appState.clientSetting.clientSetting.correspondences?.find(x => {
return x.sid == appState.serverSetting.serverSetting.dstId
})
const recommendedF0Factor = dst && src ? dst.correspondence / src.correspondence : 0
return (
<div className="body-row split-3-2-1-4 left-padding-1 guided">
<div className="body-item-title left-padding-1">F0 Factor</div>
<div className="body-input-container">
<input type="range" className="body-item-input-slider" min="0.1" max="5.0" step="0.1" value={appState.serverSetting.serverSetting.f0Factor || 0} onChange={(e) => {
appState.serverSetting.updateServerSettings({ ...appState.serverSetting.serverSetting, f0Factor: Number(e.target.value) })
}}></input>
<span className="body-item-input-slider-val">{appState.serverSetting.serverSetting.f0Factor?.toFixed(1) || 0}</span>
</div>
<div className="body-item-text"></div>
<div className="body-item-text">recommend: {recommendedF0Factor.toFixed(1)}</div>
</div>
)
}, [appState.serverSetting.serverSetting.f0Factor, appState.serverSetting.serverSetting.srcId, appState.serverSetting.serverSetting.dstId, appState.clientSetting.clientSetting.correspondences, appState.serverSetting.updateServerSettings])
return f0FactorRow
}

View File

@ -0,0 +1,38 @@
import React, { useMemo } from "react"
import { useAppState } from "../../001_provider/001_AppStateProvider"
export const TuneRow = () => {
const appState = useAppState()
const speakerSetting = appState.appGuiSettingState.appGuiSetting.front.speakerSetting
const tuneRow = useMemo(() => {
if (!speakerSetting.tuningEnable) {
return <></>
}
return (
<div className="body-row split-3-2-2-3 left-padding-1 guided">
<div className="body-item-title left-padding-1 ">Tuning</div>
<div>
<input type="range" className="body-item-input-slider" min="-50" max="50" step="1" value={appState.serverSetting.serverSetting.tran} onChange={(e) => {
appState.serverSetting.updateServerSettings({ ...appState.serverSetting.serverSetting, tran: Number(e.target.value) })
}}></input>
<span className="body-item-input-slider-val">{appState.serverSetting.serverSetting.tran}</span>
</div>
<div>
<input type="checkbox" checked={appState.serverSetting.serverSetting.predictF0 == 1} onChange={(e) => {
appState.serverSetting.updateServerSettings({ ...appState.serverSetting.serverSetting, predictF0: e.target.checked ? 1 : 0 })
}} /> predict f0
</div>
<div className="body-button-container">
</div>
</div>
)
}, [
appState.serverSetting.serverSetting,
appState.serverSetting.updateServerSettings
])
return tuneRow
}

View File

@ -0,0 +1,32 @@
import React, { useMemo } from "react"
import { useAppState } from "../../001_provider/001_AppStateProvider"
export const ClusterInferRatioRow = () => {
const appState = useAppState()
const speakerSetting = appState.appGuiSettingState.appGuiSetting.front.speakerSetting
const clusterRatioRow = useMemo(() => {
if (!speakerSetting.clusterInferRationEnable) {
return <></>
}
return (
<div className="body-row split-3-3-4 left-padding-1 guided">
<div className="body-item-title left-padding-1 ">Cluster infer ratio</div>
<div>
<input type="range" className="body-item-input-slider" min="0" max="1" step="0.1" value={appState.serverSetting.serverSetting.clusterInferRatio} onChange={(e) => {
appState.serverSetting.updateServerSettings({ ...appState.serverSetting.serverSetting, clusterInferRatio: Number(e.target.value) })
}}></input>
<span className="body-item-input-slider-val">{appState.serverSetting.serverSetting.clusterInferRatio}</span>
</div>
<div className="body-button-container">
</div>
</div>
)
}, [
appState.serverSetting.serverSetting,
appState.serverSetting.updateServerSettings
])
return clusterRatioRow
}

View File

@ -0,0 +1,33 @@
import React, { useMemo } from "react"
import { useAppState } from "../../001_provider/001_AppStateProvider"
export const NoiseScaleRow = () => {
const appState = useAppState()
const speakerSetting = appState.appGuiSettingState.appGuiSetting.front.speakerSetting
const noiseScaleRow = useMemo(() => {
if (!speakerSetting.noiseScaleEnable) {
return <></>
}
return (
<div className="body-row split-3-3-4 left-padding-1 guided">
<div className="body-item-title left-padding-1 ">Noice Scale</div>
<div>
<input type="range" className="body-item-input-slider" min="0" max="1" step="0.1" value={appState.serverSetting.serverSetting.noiceScale} onChange={(e) => {
appState.serverSetting.updateServerSettings({ ...appState.serverSetting.serverSetting, noiceScale: Number(e.target.value) })
}}></input>
<span className="body-item-input-slider-val">{appState.serverSetting.serverSetting.noiceScale}</span>
</div>
<div className="body-button-container">
</div>
</div>
)
}, [
appState.serverSetting.serverSetting,
appState.serverSetting.updateServerSettings
])
return noiseScaleRow
}

View File

@ -0,0 +1,34 @@
import React, { useMemo } from "react"
import { useAppState } from "../../001_provider/001_AppStateProvider"
export const SilentThresholdRow = () => {
const appState = useAppState()
const speakerSetting = appState.appGuiSettingState.appGuiSetting.front.speakerSetting
const silentThresholdRow = useMemo(() => {
if (!speakerSetting.silentThresholdEnable) {
return <></>
}
return (
<div className="body-row split-3-3-4 left-padding-1 guided">
<div className="body-item-title left-padding-1 ">Silent Threshold</div>
<div>
<input type="range" className="body-item-input-slider" min="0.00000" max="0.001" step="0.00001" value={appState.serverSetting.serverSetting.silentThreshold} onChange={(e) => {
appState.serverSetting.updateServerSettings({ ...appState.serverSetting.serverSetting, silentThreshold: Number(e.target.value) })
}}></input>
<span className="body-item-input-slider-val">{appState.serverSetting.serverSetting.silentThreshold}</span>
</div>
<div className="body-button-container">
</div>
</div>
)
}, [
appState.serverSetting.serverSetting,
appState.serverSetting.updateServerSettings
])
return silentThresholdRow
}

View File

@ -0,0 +1,50 @@
import React, { useMemo } from "react"
import { AnimationTypes, HeaderButton, HeaderButtonProps } from "../101_HeaderButton"
import { useGuiState } from "./001_GuiStateProvider"
import { InputChunkNumRow } from "./701_InputChunkNumRow"
import { ExtraDataLengthRow } from "./702_ExtraDataLengthRow"
import { GPURow } from "./703_GPURow"
export const ConverterSetting = () => {
const guiState = useGuiState()
const accodionButton = useMemo(() => {
const accodionButtonProps: HeaderButtonProps = {
stateControlCheckbox: guiState.stateControls.openConverterSettingCheckbox,
tooltip: "Open/Close",
onIcon: ["fas", "caret-up"],
offIcon: ["fas", "caret-up"],
animation: AnimationTypes.spinner,
tooltipClass: "tooltip-right",
};
return <HeaderButton {...accodionButtonProps}></HeaderButton>;
}, []);
const deviceSetting = useMemo(() => {
return (
<>
{guiState.stateControls.openConverterSettingCheckbox.trigger}
<div className="partition">
<div className="partition-header">
<span className="caret">
{accodionButton}
</span>
<span className="title" onClick={() => { guiState.stateControls.openConverterSettingCheckbox.updateState(!guiState.stateControls.openConverterSettingCheckbox.checked()) }}>
Converter Setting
</span>
<span></span>
</div>
<div className="partition-content">
<InputChunkNumRow />
<ExtraDataLengthRow />
<GPURow />
</div>
</div>
</>
)
}, [])
return deviceSetting
}

View File

@ -0,0 +1,26 @@
import React, { useMemo } from "react"
import { useAppState } from "../../001_provider/001_AppStateProvider"
export const InputChunkNumRow = () => {
const appState = useAppState()
const inputChunkNumRow = useMemo(() => {
return (
<div className="body-row split-3-2-1-4 left-padding-1 guided">
<div className="body-item-title left-padding-1">Input Chunk Num(128sample/chunk)</div>
<div className="body-input-container">
<input type="number" min={1} max={256} step={1} value={appState.workletNodeSetting.workletNodeSetting.inputChunkNum} onChange={(e) => {
appState.workletNodeSetting.updateWorkletNodeSetting({ ...appState.workletNodeSetting.workletNodeSetting, inputChunkNum: Number(e.target.value) })
appState.workletNodeSetting.trancateBuffer()
}} />
</div>
<div className="body-item-text">
<div>buff: {(appState.workletNodeSetting.workletNodeSetting.inputChunkNum * 128 * 1000 / 48000).toFixed(1)}ms</div>
</div>
<div className="body-item-text"></div>
</div>
)
}, [appState.workletNodeSetting.workletNodeSetting, appState.workletNodeSetting.updateWorkletNodeSetting])
return inputChunkNumRow
}

View File

@ -0,0 +1,36 @@
import React, { useMemo } from "react"
import { useAppState } from "../../001_provider/001_AppStateProvider"
export const ExtraDataLengthRow = () => {
const appState = useAppState()
const converterSetting = appState.appGuiSettingState.appGuiSetting.front.converterSetting
const extraDataLengthRow = useMemo(() => {
if (!converterSetting.extraDataLengthEnable) {
return <></>
}
return (
<div className="body-row split-3-2-1-4 left-padding-1 guided">
<div className="body-item-title left-padding-1">Extra Data Length</div>
<div className="body-input-container">
<select className="body-select" value={appState.serverSetting.serverSetting.extraConvertSize} onChange={(e) => {
appState.serverSetting.updateServerSettings({ ...appState.serverSetting.serverSetting, extraConvertSize: Number(e.target.value) })
appState.workletNodeSetting.trancateBuffer()
}}>
{
[1024 * 4, 1024 * 8, 1024 * 16, 1024 * 32, 1024 * 64, 1024 * 128].map(x => {
return <option key={x} value={x}>{x}</option>
})
}
</select>
</div>
<div className="body-item-text">
</div>
<div className="body-item-text"></div>
</div>
)
}, [appState.serverSetting.serverSetting, appState.serverSetting.updateServerSettings])
return extraDataLengthRow
}

View File

@ -0,0 +1,19 @@
import React, { useMemo } from "react"
import { useAppState } from "../../001_provider/001_AppStateProvider"
export const GPURow = () => {
const appState = useAppState()
const gpuRow = useMemo(() => {
return (
<div className="body-row split-3-7 left-padding-1 guided">
<div className="body-item-title left-padding-1">GPU</div>
<div className="body-input-container">
<input type="number" min={-2} max={5} step={1} value={appState.serverSetting.serverSetting.gpu} onChange={(e) => {
appState.serverSetting.updateServerSettings({ ...appState.serverSetting.serverSetting, gpu: Number(e.target.value) })
}} />
</div>
</div>
)
}, [appState.serverSetting.serverSetting, appState.serverSetting.updateServerSettings])
return gpuRow
}

View File

@ -0,0 +1,67 @@
import React, { useMemo } from "react"
import { AnimationTypes, HeaderButton, HeaderButtonProps } from "../101_HeaderButton"
import { useGuiState } from "./001_GuiStateProvider"
import { ServerURLRow } from "./801_ServerURLRow"
import { ProtocolRow } from "./802_ProtocolRow"
import { SampleRateRow } from "./803_SampleRateRow"
import { SendingSampleRateRow } from "./804_SendingSampleRateRow"
import { CrossFadeOverlapSizeRow } from "./805_CrossFadeOverlapSizeRow"
import { CrossFadeOffsetRateRow } from "./806_CrossFadeOffsetRateRow"
import { CrossFadeEndRateRow } from "./807_CrossFadeEndRateRow"
import { DownSamplingModeRow } from "./808_DownSamplingModeRow"
import { TrancateNumTresholdRow } from "./809_TrancateNumTresholdRow"
export const AdvancedSetting = () => {
const guiState = useGuiState()
const accodionButton = useMemo(() => {
const accodionButtonProps: HeaderButtonProps = {
stateControlCheckbox: guiState.stateControls.openAdvancedSettingCheckbox,
tooltip: "Open/Close",
onIcon: ["fas", "caret-up"],
offIcon: ["fas", "caret-up"],
animation: AnimationTypes.spinner,
tooltipClass: "tooltip-right",
};
return <HeaderButton {...accodionButtonProps}></HeaderButton>;
}, []);
const deviceSetting = useMemo(() => {
return (
<>
{guiState.stateControls.openAdvancedSettingCheckbox.trigger}
<div className="partition">
<div className="partition-header">
<span className="caret">
{accodionButton}
</span>
<span className="title" onClick={() => { guiState.stateControls.openAdvancedSettingCheckbox.updateState(!guiState.stateControls.openAdvancedSettingCheckbox.checked()) }}>
Advanced Setting
</span>
<span></span>
</div>
<div className="partition-content">
<div className="body-row divider"></div>
<ServerURLRow />
<ProtocolRow />
<div className="body-row divider"></div>
<SampleRateRow />
<SendingSampleRateRow />
<div className="body-row divider"></div>
<CrossFadeOverlapSizeRow />
<CrossFadeOffsetRateRow />
<CrossFadeEndRateRow />
<div className="body-row divider"></div>
<DownSamplingModeRow />
<div className="body-row divider"></div>
<TrancateNumTresholdRow />
</div>
</div>
</>
)
}, [])
return deviceSetting
}

View File

@ -0,0 +1,30 @@
import React, { useMemo } from "react"
import { useAppState } from "../../001_provider/001_AppStateProvider"
export const ServerURLRow = () => {
const appState = useAppState()
const advancedSetting = appState.appGuiSettingState.appGuiSetting.front.advancedSetting
const serverUrlRow = useMemo(() => {
if (!advancedSetting.serverURLEnable) {
return <></>
}
const onSetServerClicked = async () => {
const input = document.getElementById("mmvc-server-url") as HTMLInputElement
appState.clientSetting.setServerUrl(input.value)
}
return (
<div className="body-row split-3-3-4 left-padding-1 guided">
<div className="body-item-title left-padding-1">MMVC Server</div>
<div className="body-input-container">
<input type="text" defaultValue={appState.workletNodeSetting.workletNodeSetting.serverUrl} id="mmvc-server-url" className="body-item-input" />
</div>
<div className="body-button-container">
<div className="body-button" onClick={onSetServerClicked}>set</div>
</div>
</div>
)
}, [appState.workletNodeSetting.workletNodeSetting, appState.clientSetting.setServerUrl])
return serverUrlRow
}

View File

@ -0,0 +1,36 @@
import React, { useMemo } from "react"
import { useAppState } from "../../001_provider/001_AppStateProvider"
import { Protocol } from "@dannadori/voice-changer-client-js"
export const ProtocolRow = () => {
const appState = useAppState()
const advancedSetting = appState.appGuiSettingState.appGuiSetting.front.advancedSetting
const protocolRow = useMemo(() => {
if (!advancedSetting.protocolEnable) {
return <></>
}
const onProtocolChanged = async (val: Protocol) => {
appState.workletNodeSetting.updateWorkletNodeSetting({ ...appState.workletNodeSetting.workletNodeSetting, protocol: val })
}
return (
<div className="body-row split-3-7 left-padding-1 guided">
<div className="body-item-title left-padding-1">Protocol</div>
<div className="body-select-container">
<select className="body-select" value={appState.workletNodeSetting.workletNodeSetting.protocol} onChange={(e) => {
onProtocolChanged(e.target.value as
Protocol)
}}>
{
Object.values(Protocol).map(x => {
return <option key={x} value={x}>{x}</option>
})
}
</select>
</div>
</div>
)
}, [appState.workletNodeSetting.workletNodeSetting, appState.workletNodeSetting.updateWorkletNodeSetting])
return protocolRow
}

View File

@ -0,0 +1,31 @@
import React, { useMemo } from "react"
import { useAppState } from "../../001_provider/001_AppStateProvider"
import { SampleRate } from "@dannadori/voice-changer-client-js"
export const SampleRateRow = () => {
const appState = useAppState()
const advancedSetting = appState.appGuiSettingState.appGuiSetting.front.advancedSetting
const sampleRateRow = useMemo(() => {
if (!advancedSetting.sampleRateEnable) {
return <></>
}
return (
<div className="body-row split-3-7 left-padding-1 guided">
<div className="body-item-title left-padding-1">Sample Rate</div>
<div className="body-select-container">
<select className="body-select" value={appState.clientSetting.clientSetting.sampleRate} onChange={(e) => {
appState.clientSetting.updateClientSetting({ ...appState.clientSetting.clientSetting, sampleRate: Number(e.target.value) as SampleRate })
}}>
{
Object.values(SampleRate).map(x => {
return <option key={x} value={x}>{x}</option>
})
}
</select>
</div>
</div>
)
}, [appState.clientSetting.clientSetting, appState.clientSetting.updateClientSetting])
return sampleRateRow
}

View File

@ -0,0 +1,34 @@
import React, { useMemo } from "react"
import { useAppState } from "../../001_provider/001_AppStateProvider"
import { InputSampleRate } from "@dannadori/voice-changer-client-js"
export const SendingSampleRateRow = () => {
const appState = useAppState()
const advancedSetting = appState.appGuiSettingState.appGuiSetting.front.advancedSetting
const sendingSampleRateRow = useMemo(() => {
if (!advancedSetting.sendingSampleRateEnable) {
return <></>
}
return (
<div className="body-row split-3-7 left-padding-1 guided">
<div className="body-item-title left-padding-1">Sending Sample Rate</div>
<div className="body-select-container">
<select className="body-select" value={appState.workletNodeSetting.workletNodeSetting.sendingSampleRate} onChange={(e) => {
appState.workletNodeSetting.updateWorkletNodeSetting({ ...appState.workletNodeSetting.workletNodeSetting, sendingSampleRate: Number(e.target.value) as InputSampleRate })
appState.serverSetting.updateServerSettings({ ...appState.serverSetting.serverSetting, inputSampleRate: Number(e.target.value) as InputSampleRate })
}}>
{
Object.values(InputSampleRate).map(x => {
return <option key={x} value={x}>{x}</option>
})
}
</select>
</div>
</div>
)
}, [appState.workletNodeSetting.workletNodeSetting, appState.workletNodeSetting.updateWorkletNodeSetting, appState.serverSetting.updateServerSettings])
return sendingSampleRateRow
}

View File

@ -0,0 +1,32 @@
import React, { useMemo } from "react"
import { useAppState } from "../../001_provider/001_AppStateProvider"
import { CrossFadeOverlapSize } from "@dannadori/voice-changer-client-js"
export const CrossFadeOverlapSizeRow = () => {
const appState = useAppState()
const advancedSetting = appState.appGuiSettingState.appGuiSetting.front.advancedSetting
const crossFadeOverlapSizeRow = useMemo(() => {
if (!advancedSetting.crossFadeOverlapSizeEnable) {
return <></>
}
return (
<div className="body-row split-3-7 left-padding-1 guided">
<div className="body-item-title left-padding-1">Cross Fade Overlap Size</div>
<div className="body-select-container">
<select className="body-select" value={appState.serverSetting.serverSetting.crossFadeOverlapSize} onChange={(e) => {
appState.serverSetting.updateServerSettings({ ...appState.serverSetting.serverSetting, crossFadeOverlapSize: Number(e.target.value) as CrossFadeOverlapSize })
}}>
{
Object.values(CrossFadeOverlapSize).map(x => {
return <option key={x} value={x}>{x}</option>
})
}
</select>
</div>
</div>
)
}, [appState.serverSetting.serverSetting, appState.serverSetting.updateServerSettings])
return crossFadeOverlapSizeRow
}

View File

@ -0,0 +1,25 @@
import React, { useMemo } from "react"
import { useAppState } from "../../001_provider/001_AppStateProvider"
export const CrossFadeOffsetRateRow = () => {
const appState = useAppState()
const advancedSetting = appState.appGuiSettingState.appGuiSetting.front.advancedSetting
const crossFadeOffsetRateRow = useMemo(() => {
if (!advancedSetting.crossFadeOffsetRateEnable) {
return <></>
}
return (
<div className="body-row split-3-7 left-padding-1 guided">
<div className="body-item-title left-padding-1">Cross Fade Offset Rate</div>
<div className="body-input-container">
<input type="number" min={0} max={1} step={0.1} value={appState.serverSetting.serverSetting.crossFadeOffsetRate} onChange={(e) => {
appState.serverSetting.updateServerSettings({ ...appState.serverSetting.serverSetting, crossFadeOffsetRate: Number(e.target.value) })
}} />
</div>
</div>
)
}, [appState.serverSetting.serverSetting.crossFadeOffsetRate, appState.serverSetting.updateServerSettings])
return crossFadeOffsetRateRow
}

View File

@ -0,0 +1,25 @@
import React, { useMemo } from "react"
import { useAppState } from "../../001_provider/001_AppStateProvider"
export const CrossFadeEndRateRow = () => {
const appState = useAppState()
const advancedSetting = appState.appGuiSettingState.appGuiSetting.front.advancedSetting
const crossFadeEndRateRow = useMemo(() => {
if (!advancedSetting.crossFadeEndRateEnable) {
return <></>
}
return (
<div className="body-row split-3-7 left-padding-1 guided">
<div className="body-item-title left-padding-1">Cross Fade End Rate</div>
<div className="body-input-container">
<input type="number" min={0} max={1} step={0.1} value={appState.serverSetting.serverSetting.crossFadeEndRate} onChange={(e) => {
appState.serverSetting.updateServerSettings({ ...appState.serverSetting.serverSetting, crossFadeEndRate: Number(e.target.value) })
}} />
</div>
</div>
)
}, [appState.serverSetting.serverSetting, appState.serverSetting.updateServerSettings])
return crossFadeEndRateRow
}

View File

@ -0,0 +1,32 @@
import React, { useMemo } from "react"
import { useAppState } from "../../001_provider/001_AppStateProvider"
import { DownSamplingMode } from "@dannadori/voice-changer-client-js"
export const DownSamplingModeRow = () => {
const appState = useAppState()
const advancedSetting = appState.appGuiSettingState.appGuiSetting.front.advancedSetting
const downSamplingModeRow = useMemo(() => {
if (!advancedSetting.downSamplingModeEnable) {
return <></>
}
return (
<div className="body-row split-3-7 left-padding-1 guided">
<div className="body-item-title left-padding-1 ">DownSamplingMode</div>
<div className="body-select-container">
<select className="body-select" value={appState.workletNodeSetting.workletNodeSetting.downSamplingMode} onChange={(e) => {
appState.workletNodeSetting.updateWorkletNodeSetting({ ...appState.workletNodeSetting.workletNodeSetting, downSamplingMode: e.target.value as DownSamplingMode })
}}>
{
Object.values(DownSamplingMode).map(x => {
return <option key={x} value={x}>{x}</option>
})
}
</select>
</div>
</div>
)
}, [appState.workletNodeSetting.workletNodeSetting, appState.workletNodeSetting.updateWorkletNodeSetting])
return downSamplingModeRow
}

View File

@ -0,0 +1,28 @@
import React, { useMemo } from "react"
import { useAppState } from "../../001_provider/001_AppStateProvider"
export const TrancateNumTresholdRow = () => {
const appState = useAppState()
const advancedSetting = appState.appGuiSettingState.appGuiSetting.front.advancedSetting
const trancateNumTresholdRow = useMemo(() => {
if (!advancedSetting.trancateNumTresholdEnable) {
return <></>
}
return (
<div className="body-row split-3-7 left-padding-1 guided">
<div className="body-item-title left-padding-1">Trancate Num</div>
<div className="body-input-container">
<input type="number" min={5} max={300} step={1} value={appState.workletSetting.setting.numTrancateTreshold} onChange={(e) => {
appState.workletSetting.setSetting({
...appState.workletSetting.setting,
numTrancateTreshold: Number(e.target.value)
})
}} />
</div>
</div>
)
}, [appState.workletNodeSetting.workletNodeSetting, appState.workletNodeSetting.updateWorkletNodeSetting])
return trancateNumTresholdRow
}

View File

@ -212,7 +212,7 @@ if __name__ == '__main__':
f"http://<IP>:<PORT>/", level=1) f"http://<IP>:<PORT>/", level=1)
if TYPE == "MMVC": if TYPE == "MMVC":
path = "" path = f"?modelType={MODEL_TYPE}"
else: else:
path = "trainer" path = "trainer"