From 47489571da6762618b168c35e999c90f6c00fabf Mon Sep 17 00:00:00 2001 From: wataru Date: Wed, 15 Feb 2023 07:18:05 +0900 Subject: [PATCH] quality control update --- client/demo/dist/index.js | 4 +- client/demo/src/107_qulity_control.tsx | 119 +++++++++++++++++++++---- client/demo/src/css/App.css | 14 ++- server/voice_changer/VoiceChanger.py | 45 ++++++++++ 4 files changed, 162 insertions(+), 20 deletions(-) diff --git a/client/demo/dist/index.js b/client/demo/dist/index.js index 30d9edbe..14cf7548 100644 --- a/client/demo/dist/index.js +++ b/client/demo/dist/index.js @@ -114,7 +114,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"useQualityControl\": () => (/* binding */ useQualityControl)\n/* harmony export */ });\n/* harmony import */ var _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/helpers/slicedToArray */ \"./node_modules/@babel/runtime/helpers/esm/slicedToArray.js\");\n/* harmony import */ var _dannadori_voice_changer_client_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @dannadori/voice-changer-client-js */ \"./node_modules/@dannadori/voice-changer-client-js/dist/index.js\");\n/* harmony import */ var _dannadori_voice_changer_client_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_dannadori_voice_changer_client_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_2__);\n\n\n\nvar useQualityControl = function useQualityControl(props) {\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_2__.useState)(false),\n _useState2 = (0,_babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(_useState, 2),\n showQualityControl = _useState2[0],\n setShowQualityControl = _useState2[1];\n var noiseControlRow = (0,react__WEBPACK_IMPORTED_MODULE_2__.useMemo)(function () {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"div\", {\n className: \"body-row split-3-2-2-2-1 left-padding-1 guided\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"div\", {\n className: \"body-item-title left-padding-1 \"\n }, \"Noise Suppression\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"div\", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"input\", {\n type: \"checkbox\",\n checked: props.clientState.clientSetting.setting.echoCancel,\n onChange: function onChange(e) {\n props.clientState.clientSetting.setEchoCancel(e.target.checked);\n }\n }), \" echo cancel\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"div\", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"input\", {\n type: \"checkbox\",\n checked: props.clientState.clientSetting.setting.noiseSuppression,\n onChange: function onChange(e) {\n props.clientState.clientSetting.setNoiseSuppression(e.target.checked);\n }\n }), \" suppression1\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"div\", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"input\", {\n type: \"checkbox\",\n checked: props.clientState.clientSetting.setting.noiseSuppression2,\n onChange: function onChange(e) {\n props.clientState.clientSetting.setNoiseSuppression2(e.target.checked);\n }\n }), \" suppression2\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"div\", {\n className: \"body-button-container\"\n }));\n }, [props.clientState.clientSetting.setting.echoCancel, props.clientState.clientSetting.setEchoCancel, props.clientState.clientSetting.setting.noiseSuppression, props.clientState.clientSetting.setNoiseSuppression, props.clientState.clientSetting.setting.noiseSuppression2, props.clientState.clientSetting.setNoiseSuppression2]);\n var gainControlRow = (0,react__WEBPACK_IMPORTED_MODULE_2__.useMemo)(function () {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"div\", {\n className: \"body-row split-3-2-2-3 left-padding-1 guided\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"div\", {\n className: \"body-item-title left-padding-1 \"\n }, \"Gain Control\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"div\", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"span\", {\n className: \"body-item-input-slider-label\"\n }, \"in\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"input\", {\n type: \"range\",\n className: \"body-item-input-slider\",\n min: \"0.0\",\n max: \"1.0\",\n step: \"0.1\",\n value: props.clientState.clientSetting.setting.inputGain,\n onChange: function onChange(e) {\n props.clientState.clientSetting.setInputGain(Number(e.target.value));\n }\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"span\", {\n className: \"body-item-input-slider-val\"\n }, props.clientState.clientSetting.setting.inputGain)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"div\", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"span\", {\n className: \"body-item-input-slider-label\"\n }, \"out\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"input\", {\n type: \"range\",\n className: \"body-item-input-slider\",\n min: \"0.0\",\n max: \"1.0\",\n step: \"0.1\",\n value: props.clientState.clientSetting.setting.outputGain,\n onChange: function onChange(e) {\n props.clientState.clientSetting.setOutputGain(Number(e.target.value));\n }\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"span\", {\n className: \"body-item-input-slider-val\"\n }, props.clientState.clientSetting.setting.outputGain)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"div\", {\n className: \"body-button-container\"\n }));\n }, [props.clientState.clientSetting.setting.inputGain, props.clientState.clientSetting.setting.inputGain, props.clientState.clientSetting.setting.outputGain, props.clientState.clientSetting.setOutputGain]);\n var f0DetectorRow = (0,react__WEBPACK_IMPORTED_MODULE_2__.useMemo)(function () {\n var desc = {\n \"harvest\": \"High Quality\",\n \"dio\": \"Light Weight\"\n };\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"div\", {\n className: \"body-row split-3-7 left-padding-1 guided\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"div\", {\n className: \"body-item-title left-padding-1 \"\n }, \"F0 Detector\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"div\", {\n className: \"body-select-container\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"select\", {\n className: \"body-select\",\n value: props.clientState.serverSetting.setting.f0Detector,\n onChange: function onChange(e) {\n props.clientState.serverSetting.setF0Detector(e.target.value);\n }\n }, Object.values(_dannadori_voice_changer_client_js__WEBPACK_IMPORTED_MODULE_1__.F0Detector).map(function (x) {\n //@ts-ignore\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"option\", {\n key: x,\n value: x\n }, x, \"(\", desc[x], \")\");\n }))));\n }, [props.clientState.serverSetting.setting.f0Detector, props.clientState.serverSetting.setF0Detector]);\n var recordIORow = (0,react__WEBPACK_IMPORTED_MODULE_2__.useMemo)(function () {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"div\", {\n className: \"body-row split-3-7 left-padding-1 guided\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"div\", {\n className: \"body-item-title left-padding-1 \"\n }, \"recordIO\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"div\", {\n className: \"body-select-container\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"select\", {\n className: \"body-select\",\n value: props.clientState.serverSetting.setting.recordIO,\n onChange: function onChange(e) {\n props.clientState.serverSetting.setRecordIO(Number(e.target.value));\n }\n }, Object.values([0, 1]).map(function (x) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"option\", {\n key: x,\n value: x\n }, x);\n }))));\n }, [props.clientState.serverSetting.setting.recordIO, props.clientState.serverSetting.setRecordIO]);\n var QualityControlContent = (0,react__WEBPACK_IMPORTED_MODULE_2__.useMemo)(function () {\n if (!showQualityControl) return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement((react__WEBPACK_IMPORTED_MODULE_2___default().Fragment), null);\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement((react__WEBPACK_IMPORTED_MODULE_2___default().Fragment), null, noiseControlRow, gainControlRow, f0DetectorRow, recordIORow);\n }, [showQualityControl, gainControlRow, noiseControlRow, f0DetectorRow, recordIORow]);\n var qualityControl = (0,react__WEBPACK_IMPORTED_MODULE_2__.useMemo)(function () {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement((react__WEBPACK_IMPORTED_MODULE_2___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"div\", {\n className: \"body-row split-3-7 left-padding-1\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"div\", {\n className: \"body-sub-section-title\"\n }, \"Quality Control\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"div\", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(\"input\", {\n type: \"checkbox\",\n checked: showQualityControl,\n onChange: function onChange(e) {\n setShowQualityControl(e.target.checked);\n }\n }), \" show\")), QualityControlContent);\n }, [showQualityControl, QualityControlContent]);\n return {\n qualityControl: qualityControl\n };\n};\n\n//# sourceURL=webpack://demo/./src/107_qulity_control.tsx?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"useQualityControl\": () => (/* binding */ useQualityControl)\n/* harmony export */ });\n/* harmony import */ var _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/helpers/slicedToArray */ \"./node_modules/@babel/runtime/helpers/esm/slicedToArray.js\");\n/* harmony import */ var _babel_runtime_helpers_asyncToGenerator__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @babel/runtime/helpers/asyncToGenerator */ \"./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js\");\n/* harmony import */ var _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @babel/runtime/regenerator */ \"./node_modules/@babel/runtime/regenerator/index.js\");\n/* harmony import */ var _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _dannadori_voice_changer_client_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @dannadori/voice-changer-client-js */ \"./node_modules/@dannadori/voice-changer-client-js/dist/index.js\");\n/* harmony import */ var _dannadori_voice_changer_client_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_dannadori_voice_changer_client_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_4__);\n\n\n\n\n\nvar reloadDevices = /*#__PURE__*/function () {\n var _ref = (0,_babel_runtime_helpers_asyncToGenerator__WEBPACK_IMPORTED_MODULE_1__[\"default\"])( /*#__PURE__*/_babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_2___default().mark(function _callee() {\n var ms, mediaDeviceInfos, audioOutputs;\n return _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_2___default().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n _context.prev = 0;\n _context.next = 3;\n return navigator.mediaDevices.getUserMedia({\n video: false,\n audio: true\n });\n case 3:\n ms = _context.sent;\n ms.getTracks().forEach(function (x) {\n x.stop();\n });\n _context.next = 10;\n break;\n case 7:\n _context.prev = 7;\n _context.t0 = _context[\"catch\"](0);\n console.warn(\"Enumerate device error::\", _context.t0);\n case 10:\n _context.next = 12;\n return navigator.mediaDevices.enumerateDevices();\n case 12:\n mediaDeviceInfos = _context.sent;\n audioOutputs = mediaDeviceInfos.filter(function (x) {\n return x.kind == \"audiooutput\";\n });\n return _context.abrupt(\"return\", audioOutputs);\n case 15:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[0, 7]]);\n }));\n return function reloadDevices() {\n return _ref.apply(this, arguments);\n };\n}();\nvar useQualityControl = function useQualityControl(props) {\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_4__.useState)(false),\n _useState2 = (0,_babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(_useState, 2),\n showQualityControl = _useState2[0],\n setShowQualityControl = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_4__.useState)([]),\n _useState4 = (0,_babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(_useState3, 2),\n outputAudioDeviceInfo = _useState4[0],\n setOutputAudioDeviceInfo = _useState4[1];\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_4__.useState)(\"none\"),\n _useState6 = (0,_babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(_useState5, 2),\n audioOutputForGUI = _useState6[0],\n setAudioOutputForGUI = _useState6[1];\n (0,react__WEBPACK_IMPORTED_MODULE_4__.useEffect)(function () {\n var initialize = /*#__PURE__*/function () {\n var _ref2 = (0,_babel_runtime_helpers_asyncToGenerator__WEBPACK_IMPORTED_MODULE_1__[\"default\"])( /*#__PURE__*/_babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_2___default().mark(function _callee2() {\n var audioInfo;\n return _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_2___default().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n _context2.next = 2;\n return reloadDevices();\n case 2:\n audioInfo = _context2.sent;\n setOutputAudioDeviceInfo(audioInfo);\n case 4:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2);\n }));\n return function initialize() {\n return _ref2.apply(this, arguments);\n };\n }();\n initialize();\n }, []);\n var noiseControlRow = (0,react__WEBPACK_IMPORTED_MODULE_4__.useMemo)(function () {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", {\n className: \"body-row split-3-2-2-2-1 left-padding-1 guided\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", {\n className: \"body-item-title left-padding-1 \"\n }, \"Noise Suppression\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"input\", {\n type: \"checkbox\",\n checked: props.clientState.clientSetting.setting.echoCancel,\n onChange: function onChange(e) {\n props.clientState.clientSetting.setEchoCancel(e.target.checked);\n }\n }), \" echo cancel\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"input\", {\n type: \"checkbox\",\n checked: props.clientState.clientSetting.setting.noiseSuppression,\n onChange: function onChange(e) {\n props.clientState.clientSetting.setNoiseSuppression(e.target.checked);\n }\n }), \" suppression1\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"input\", {\n type: \"checkbox\",\n checked: props.clientState.clientSetting.setting.noiseSuppression2,\n onChange: function onChange(e) {\n props.clientState.clientSetting.setNoiseSuppression2(e.target.checked);\n }\n }), \" suppression2\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", {\n className: \"body-button-container\"\n }));\n }, [props.clientState.clientSetting.setting.echoCancel, props.clientState.clientSetting.setEchoCancel, props.clientState.clientSetting.setting.noiseSuppression, props.clientState.clientSetting.setNoiseSuppression, props.clientState.clientSetting.setting.noiseSuppression2, props.clientState.clientSetting.setNoiseSuppression2]);\n var gainControlRow = (0,react__WEBPACK_IMPORTED_MODULE_4__.useMemo)(function () {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", {\n className: \"body-row split-3-2-2-3 left-padding-1 guided\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", {\n className: \"body-item-title left-padding-1 \"\n }, \"Gain Control\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"span\", {\n className: \"body-item-input-slider-label\"\n }, \"in\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"input\", {\n type: \"range\",\n className: \"body-item-input-slider\",\n min: \"0.0\",\n max: \"1.0\",\n step: \"0.1\",\n value: props.clientState.clientSetting.setting.inputGain,\n onChange: function onChange(e) {\n props.clientState.clientSetting.setInputGain(Number(e.target.value));\n }\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"span\", {\n className: \"body-item-input-slider-val\"\n }, props.clientState.clientSetting.setting.inputGain)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"span\", {\n className: \"body-item-input-slider-label\"\n }, \"out\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"input\", {\n type: \"range\",\n className: \"body-item-input-slider\",\n min: \"0.0\",\n max: \"1.0\",\n step: \"0.1\",\n value: props.clientState.clientSetting.setting.outputGain,\n onChange: function onChange(e) {\n props.clientState.clientSetting.setOutputGain(Number(e.target.value));\n }\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"span\", {\n className: \"body-item-input-slider-val\"\n }, props.clientState.clientSetting.setting.outputGain)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", {\n className: \"body-button-container\"\n }));\n }, [props.clientState.clientSetting.setting.inputGain, props.clientState.clientSetting.setting.inputGain, props.clientState.clientSetting.setting.outputGain, props.clientState.clientSetting.setOutputGain]);\n var f0DetectorRow = (0,react__WEBPACK_IMPORTED_MODULE_4__.useMemo)(function () {\n var desc = {\n \"harvest\": \"High Quality\",\n \"dio\": \"Light Weight\"\n };\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", {\n className: \"body-row split-3-7 left-padding-1 guided\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", {\n className: \"body-item-title left-padding-1 \"\n }, \"F0 Detector\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", {\n className: \"body-select-container\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"select\", {\n className: \"body-select\",\n value: props.clientState.serverSetting.setting.f0Detector,\n onChange: function onChange(e) {\n props.clientState.serverSetting.setF0Detector(e.target.value);\n }\n }, Object.values(_dannadori_voice_changer_client_js__WEBPACK_IMPORTED_MODULE_3__.F0Detector).map(function (x) {\n //@ts-ignore\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"option\", {\n key: x,\n value: x\n }, x, \"(\", desc[x], \")\");\n }))));\n }, [props.clientState.serverSetting.setting.f0Detector, props.clientState.serverSetting.setF0Detector]);\n var recordIORow = (0,react__WEBPACK_IMPORTED_MODULE_4__.useMemo)(function () {\n var setReocrdIO = /*#__PURE__*/function () {\n var _ref3 = (0,_babel_runtime_helpers_asyncToGenerator__WEBPACK_IMPORTED_MODULE_1__[\"default\"])( /*#__PURE__*/_babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_2___default().mark(function _callee3(val) {\n var imageContainer, image, image2, wavContainer, media1, media2;\n return _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_2___default().wrap(function _callee3$(_context3) {\n while (1) switch (_context3.prev = _context3.next) {\n case 0:\n _context3.next = 2;\n return props.clientState.serverSetting.setRecordIO(val);\n case 2:\n if (val == 0) {\n imageContainer = document.getElementById(\"quality-control-analyze-image-container\");\n imageContainer.innerHTML = \"\";\n image = document.createElement(\"img\");\n image.src = \"/tmp/analyze-dio.png?\" + new Date().getTime();\n imageContainer.appendChild(image);\n image2 = document.createElement(\"img\");\n image2.src = \"/tmp/analyze-harvest.png?\" + new Date().getTime();\n imageContainer.appendChild(image2);\n wavContainer = document.getElementById(\"quality-control-analyze-wav-container\");\n wavContainer.innerHTML = \"\";\n media1 = document.createElement(\"audio\");\n media1.src = \"/tmp/in.wav?\" + new Date().getTime();\n media1.controls = true;\n // @ts-ignore\n media1.setSinkId(audioOutputForGUI);\n wavContainer.appendChild(media1);\n media2 = document.createElement(\"audio\");\n media2.src = \"/tmp/out.wav?\" + new Date().getTime();\n media2.controls = true;\n // @ts-ignore\n media2.setSinkId(audioOutputForGUI);\n wavContainer.appendChild(media2);\n }\n case 3:\n case \"end\":\n return _context3.stop();\n }\n }, _callee3);\n }));\n return function setReocrdIO(_x) {\n return _ref3.apply(this, arguments);\n };\n }();\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement((react__WEBPACK_IMPORTED_MODULE_4___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", {\n className: \"body-row split-3-7 left-padding-1 guided\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", {\n className: \"body-item-title left-padding-1 \"\n }, \"recordIO\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", {\n className: \"body-select-container\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"select\", {\n className: \"body-select\",\n value: props.clientState.serverSetting.setting.recordIO,\n onChange: function onChange(e) {\n setReocrdIO(Number(e.target.value));\n }\n }, Object.values([0, 1]).map(function (x) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"option\", {\n key: x,\n value: x\n }, x);\n })))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", {\n className: \"body-row split-3-7 left-padding-1 guided\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", {\n className: \"body-item-title left-padding-1 \"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", null, \"Spectrogram\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"span\", null, \"(left: dio, right:harvest)\"))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", {\n className: \"body-image-container-quality-analyze\",\n id: \"quality-control-analyze-image-container\"\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", {\n className: \"body-row split-3-7 left-padding-1 guided\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", {\n className: \"body-item-title left-padding-1 \"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", null, \"wav (left:input, right:output)\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"select\", {\n className: \"body-select\",\n value: audioOutputForGUI,\n onChange: function onChange(e) {\n setAudioOutputForGUI(e.target.value);\n var wavContainer = document.getElementById(\"quality-control-analyze-wav-container\");\n wavContainer.childNodes.forEach(function (x) {\n if (x instanceof HTMLAudioElement) {\n //@ts-ignore\n x.setSinkId(e.target.value);\n }\n });\n }\n }, outputAudioDeviceInfo.map(function (x) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"option\", {\n key: x.deviceId,\n value: x.deviceId\n }, x.label);\n }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", {\n className: \"body-wav-container-quality-analyze\",\n id: \"quality-control-analyze-wav-container\"\n })));\n }, [props.clientState.serverSetting.setting.recordIO, props.clientState.serverSetting.setRecordIO, outputAudioDeviceInfo, audioOutputForGUI]);\n var QualityControlContent = (0,react__WEBPACK_IMPORTED_MODULE_4__.useMemo)(function () {\n if (!showQualityControl) return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement((react__WEBPACK_IMPORTED_MODULE_4___default().Fragment), null);\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement((react__WEBPACK_IMPORTED_MODULE_4___default().Fragment), null, noiseControlRow, gainControlRow, f0DetectorRow, recordIORow);\n }, [showQualityControl, gainControlRow, noiseControlRow, f0DetectorRow, recordIORow]);\n var qualityControl = (0,react__WEBPACK_IMPORTED_MODULE_4__.useMemo)(function () {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement((react__WEBPACK_IMPORTED_MODULE_4___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", {\n className: \"body-row split-3-7 left-padding-1\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", {\n className: \"body-sub-section-title\"\n }, \"Quality Control\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"div\", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4___default().createElement(\"input\", {\n type: \"checkbox\",\n checked: showQualityControl,\n onChange: function onChange(e) {\n setShowQualityControl(e.target.checked);\n }\n }), \" show\")), QualityControlContent);\n }, [showQualityControl, QualityControlContent]);\n return {\n qualityControl: qualityControl\n };\n};\n\n//# sourceURL=webpack://demo/./src/107_qulity_control.tsx?"); /***/ }), @@ -136,7 +136,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/noSourceMaps.js */ \"./node_modules/css-loader/dist/runtime/noSourceMaps.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);\n// Imports\n\n\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));\n___CSS_LOADER_EXPORT___.push([module.id, \"@import url(https://fonts.googleapis.com/css2?family=Chicle&family=Poppins:ital,wght@0,200;0,400;0,600;1,200;1,400;1,600&display=swap);\"]);\n___CSS_LOADER_EXPORT___.push([module.id, \"@import url(https://fonts.googleapis.com/css2?family=Yusei+Magic&display=swap);\"]);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \":root {\\n --text-color: #333;\\n --company-color1: rgba(64, 119, 187, 1);\\n --company-color2: rgba(29, 47, 78, 1);\\n --company-color3: rgba(255, 255, 255, 1);\\n --company-color1-alpha: rgba(64, 119, 187, 0.3);\\n --company-color2-alpha: rgba(29, 47, 78, 0.3);\\n --company-color3-alpha: rgba(255, 255, 255, 0.3);\\n --global-shadow-color: rgba(0, 0, 0, 0.4);\\n\\n --sidebar-transition-time: 0.3s;\\n --sidebar-transition-time-quick: 0.1s;\\n --sidebar-transition-animation: ease-in-out;\\n\\n --header-height: 1.5rem;\\n --right-sidebar-width: 320px;\\n\\n --dialog-border-color: rgba(100, 100, 100, 1);\\n --dialog-shadow-color: rgba(0, 0, 0, 0.3);\\n --dialog-background-color: rgba(255, 255, 255, 1);\\n --dialog-primary-color: rgba(19, 70, 209, 1);\\n --dialog-active-color: rgba(40, 70, 209, 1);\\n --dialog-input-border-color: rgba(200, 200, 200, 1);\\n --dialog-submit-button-color: rgba(180, 190, 230, 1);\\n --dialog-cancel-button-color: rgba(235, 80, 80, 1);\\n\\n --body-video-seeker-height: 3rem;\\n}\\n\\n* {\\n margin: 0;\\n padding: 0;\\n box-sizing: border-box;\\n font-family: \\\"Poppins\\\", sans-serif;\\n}\\nhtml {\\n font-size: 16px;\\n}\\nbody {\\n height: 100%;\\n width: 100%;\\n overflow-y: scroll;\\n overflow-x: hidden;\\n color: var(--text-color);\\n /* background: linear-gradient(45deg, var(--company-color1) 0, 5%, var(--company-color2) 5% 10%, var(--company-color3) 10% 80%, var(--company-color1) 80% 85%, var(--company-color2) 85% 100%); */\\n background: linear-gradient(45deg, var(--company-color1) 0, 1%, var(--company-color2) 1% 5%, var(--company-color3) 5% 80%, var(--company-color1) 80% 85%, var(--company-color2) 85% 100%);\\n}\\n#app {\\n height: 100%;\\n width: 100%;\\n}\\n.main-body {\\n height: 100%;\\n width: 100%;\\n padding: 2rem;\\n font-family: \\\"Yusei Magic\\\", sans-serif;\\n display: flex;\\n flex-direction: column;\\n font-size: 1rem;\\n}\\n.body-row {\\n}\\n.split-6-4 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n.split-6-4 > div:nth-child(1) {\\n left: 0px;\\n width: 60%;\\n }\\n.split-6-4 > div:nth-child(2) {\\n left: 60%;\\n width: 40%;\\n }\\n\\n.split-4-6 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n\\n.split-4-6 > div:nth-child(1) {\\n left: 0px;\\n width: 40%;\\n }\\n\\n.split-4-6 > div:nth-child(2) {\\n left: 40%;\\n width: 60%;\\n }\\n.split-3-7 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n.split-3-7 > div:nth-child(1) {\\n left: 0px;\\n width: 30%;\\n }\\n.split-3-7 > div:nth-child(2) {\\n left: 30%;\\n width: 70%;\\n }\\n\\n.split-3-3-4 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n\\n.split-3-3-4 > div:nth-child(1) {\\n left: 0px;\\n width: 30%;\\n }\\n\\n.split-3-3-4 > div:nth-child(2) {\\n left: 30%;\\n width: 30%;\\n }\\n\\n.split-3-3-4 > div:nth-child(3) {\\n left: 60%;\\n width: 40%;\\n }\\n\\n.split-2-5-3 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n\\n.split-2-5-3 > div:nth-child(1) {\\n left: 0px;\\n width: 20%;\\n }\\n\\n.split-2-5-3 > div:nth-child(2) {\\n left: 20%;\\n width: 50%;\\n }\\n\\n.split-2-5-3 > div:nth-child(3) {\\n left: 70%;\\n width: 30%;\\n }\\n.split-4-4-2 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n.split-4-4-2 > div:nth-child(1) {\\n left: 0px;\\n width: 40%;\\n }\\n.split-4-4-2 > div:nth-child(2) {\\n left: 40%;\\n width: 40%;\\n }\\n.split-4-4-2 > div:nth-child(3) {\\n left: 80%;\\n width: 20%;\\n }\\n.split-3-2-2-3 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n.split-3-2-2-3 > div:nth-child(1) {\\n left: 0px;\\n width: 30%;\\n }\\n.split-3-2-2-3 > div:nth-child(2) {\\n left: 30%;\\n width: 20%;\\n }\\n.split-3-2-2-3 > div:nth-child(3) {\\n left: 50%;\\n width: 20%;\\n }\\n.split-3-2-2-3 > div:nth-child(4) {\\n left: 70%;\\n width: 30%;\\n }\\n.split-3-2-3-2 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n.split-3-2-3-2 > div:nth-child(1) {\\n left: 0px;\\n width: 30%;\\n }\\n.split-3-2-3-2 > div:nth-child(2) {\\n left: 30%;\\n width: 20%;\\n }\\n.split-3-2-3-2 > div:nth-child(3) {\\n left: 50%;\\n width: 30%;\\n }\\n.split-3-2-3-2 > div:nth-child(4) {\\n left: 80%;\\n width: 20%;\\n }\\n.split-3-1-2-4 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n.split-3-1-2-4 > div:nth-child(1) {\\n left: 0px;\\n width: 30%;\\n }\\n.split-3-1-2-4 > div:nth-child(2) {\\n left: 30%;\\n width: 10%;\\n }\\n.split-3-1-2-4 > div:nth-child(3) {\\n left: 40%;\\n width: 20%;\\n }\\n.split-3-1-2-4 > div:nth-child(4) {\\n left: 60%;\\n width: 40%;\\n }\\n.split-3-2-1-4 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n.split-3-2-1-4 > div:nth-child(1) {\\n left: 0px;\\n width: 30%;\\n }\\n.split-3-2-1-4 > div:nth-child(2) {\\n left: 30%;\\n width: 20%;\\n }\\n.split-3-2-1-4 > div:nth-child(3) {\\n left: 50%;\\n width: 10%;\\n }\\n.split-3-2-1-4 > div:nth-child(4) {\\n left: 60%;\\n width: 40%;\\n }\\n.split-3-2-2-2-1 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n.split-3-2-2-2-1 > div:nth-child(1) {\\n left: 0px;\\n width: 30%;\\n }\\n.split-3-2-2-2-1 > div:nth-child(2) {\\n left: 30%;\\n width: 20%;\\n }\\n.split-3-2-2-2-1 > div:nth-child(3) {\\n left: 50%;\\n width: 20%;\\n }\\n.split-3-2-2-2-1 > div:nth-child(4) {\\n left: 70%;\\n width: 20%;\\n }\\n.split-3-2-2-2-1 > div:nth-child(5) {\\n left: 90%;\\n width: 10%;\\n }\\n.split-3-1-1-1-4 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n.split-3-1-1-1-4 > div:nth-child(1) {\\n left: 0px;\\n width: 30%;\\n }\\n.split-3-1-1-1-4 > div:nth-child(2) {\\n left: 30%;\\n width: 10%;\\n }\\n.split-3-1-1-1-4 > div:nth-child(3) {\\n left: 40%;\\n width: 10%;\\n }\\n.split-3-1-1-1-4 > div:nth-child(4) {\\n left: 50%;\\n width: 10%;\\n }\\n.split-3-1-1-1-4 > div:nth-child(5) {\\n left: 60%;\\n width: 40%;\\n }\\n.underline {\\n border-bottom: 3px solid #333;\\n}\\n.left-padding-1 {\\n padding-left: 1rem;\\n}\\n.left-padding-2 {\\n padding-left: 2rem;\\n}\\n.left-margin-1 {\\n margin-left: 1rem;\\n}\\n.left-margin-2 {\\n margin-left: 2rem;\\n}\\n.highlight {\\n background-color: rgba(200, 200, 255, 0.3);\\n}\\n.guided {\\n /* background-color: rgba(9, 133, 67, 0.3); */\\n background-color: rgba(159, 165, 162, 0.1);\\n /* border-bottom: 1px solid rgba(9, 133, 67, 0.3); */\\n}\\n\\n.divider {\\n height: 4px;\\n /* background-color: rgba(16, 210, 113, 0.1); */\\n background-color: rgba(31, 42, 36, 0.1);\\n}\\n\\n.body-top-title {\\n font-size: 3rem;\\n}\\n.body-top-title-version {\\n margin-left: 2rem;\\n font-size: 1.2rem;\\n background: linear-gradient(transparent 60%, yellow 30%);\\n}\\n.body-top-title-belongings {\\n display: flex;\\n align-items: flex-end;\\n justify-content: flex-start;\\n}\\n.body-top-title-belongings > div {\\n margin-left: 10px;\\n margin-right: 10px;\\n }\\n.body-top-title-belongings > .belonging-item > .link {\\n text-decoration: none;\\n }\\n.body-top-title-belongings > .belonging-item > .link > span {\\n font-size: small;\\n }\\n\\n.body-section-title {\\n font-size: 1.5rem;\\n color: rgb(51, 49, 49);\\n}\\n.body-sub-section-title {\\n font-size: 1.1rem;\\n font-weight: 700;\\n color: rgb(3, 53, 12);\\n}\\n\\n.body-item-title {\\n color: rgb(51, 99, 49);\\n}\\n.body-item-text {\\n color: rgb(30, 30, 30);\\n overflow: hidden;\\n text-overflow: ellipsis;\\n white-space: nowrap;\\n}\\n.body-item-text .body-item-text-item {\\n padding-left: 1rem;\\n }\\n.body-item-text-small {\\n color: rgb(30, 30, 30);\\n font-size: 0.7rem;\\n}\\n.body-input-container {\\n display: flex;\\n}\\n.body-item-input {\\n width: 60%;\\n}\\n.body-item-input-slider {\\n width: 60%;\\n}\\n.body-item-input-slider-label {\\n margin-right: 1rem;\\n}\\n.body-item-input-slider-val {\\n margin-left: 1rem;\\n}\\n\\n.body-button-container {\\n display: flex;\\n flex-direction: row;\\n align-items: center;\\n}\\n\\n.body-button-container > div {\\n margin-left: 5px;\\n margin-right: 5px;\\n padding-left: 20px;\\n padding-right: 20px;\\n }\\n\\n.body-button-container .body-button {\\n -webkit-user-select: none;\\n -moz-user-select: none;\\n user-select: none;\\n border: solid 1px #999;\\n border-radius: 2px;\\n cursor: pointer;\\n vertical-align: middle;\\n }\\n\\n.body-button-container .body-button:hover {\\n border: solid 1px #000;\\n }\\n\\n.body-button-container .body-button-disabled {\\n -webkit-user-select: none;\\n -moz-user-select: none;\\n user-select: none;\\n border: solid 1px #999;\\n border-radius: 2px;\\n vertical-align: middle;\\n background: #ddd;\\n }\\n\\n.body-button-container .body-button-active {\\n -webkit-user-select: none;\\n -moz-user-select: none;\\n user-select: none;\\n border: solid 1px #333;\\n border-radius: 2px;\\n background: #ada;\\n }\\n\\n.body-button-container .body-button-stanby {\\n -webkit-user-select: none;\\n -moz-user-select: none;\\n user-select: none;\\n border: solid 1px #999;\\n border-radius: 2px;\\n background: #aba;\\n cursor: pointer;\\n }\\n\\n.body-button-container .body-button-stanby:hover {\\n border: solid 1px #000;\\n }\\n.body-select-container .body-select {\\n color: rgb(30, 30, 30);\\n }\\n\", \"\"]);\n// Exports\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);\n\n\n//# sourceURL=webpack://demo/./src/css/App.css?./node_modules/css-loader/dist/cjs.js??ruleSet%5B1%5D.rules%5B2%5D.use%5B1%5D!./node_modules/postcss-loader/dist/cjs.js"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/noSourceMaps.js */ \"./node_modules/css-loader/dist/runtime/noSourceMaps.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);\n// Imports\n\n\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));\n___CSS_LOADER_EXPORT___.push([module.id, \"@import url(https://fonts.googleapis.com/css2?family=Chicle&family=Poppins:ital,wght@0,200;0,400;0,600;1,200;1,400;1,600&display=swap);\"]);\n___CSS_LOADER_EXPORT___.push([module.id, \"@import url(https://fonts.googleapis.com/css2?family=Yusei+Magic&display=swap);\"]);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \":root {\\n --text-color: #333;\\n --company-color1: rgba(64, 119, 187, 1);\\n --company-color2: rgba(29, 47, 78, 1);\\n --company-color3: rgba(255, 255, 255, 1);\\n --company-color1-alpha: rgba(64, 119, 187, 0.3);\\n --company-color2-alpha: rgba(29, 47, 78, 0.3);\\n --company-color3-alpha: rgba(255, 255, 255, 0.3);\\n --global-shadow-color: rgba(0, 0, 0, 0.4);\\n\\n --sidebar-transition-time: 0.3s;\\n --sidebar-transition-time-quick: 0.1s;\\n --sidebar-transition-animation: ease-in-out;\\n\\n --header-height: 1.5rem;\\n --right-sidebar-width: 320px;\\n\\n --dialog-border-color: rgba(100, 100, 100, 1);\\n --dialog-shadow-color: rgba(0, 0, 0, 0.3);\\n --dialog-background-color: rgba(255, 255, 255, 1);\\n --dialog-primary-color: rgba(19, 70, 209, 1);\\n --dialog-active-color: rgba(40, 70, 209, 1);\\n --dialog-input-border-color: rgba(200, 200, 200, 1);\\n --dialog-submit-button-color: rgba(180, 190, 230, 1);\\n --dialog-cancel-button-color: rgba(235, 80, 80, 1);\\n\\n --body-video-seeker-height: 3rem;\\n}\\n\\n* {\\n margin: 0;\\n padding: 0;\\n box-sizing: border-box;\\n font-family: \\\"Poppins\\\", sans-serif;\\n}\\nhtml {\\n font-size: 16px;\\n}\\nbody {\\n height: 100%;\\n width: 100%;\\n overflow-y: scroll;\\n overflow-x: hidden;\\n color: var(--text-color);\\n /* background: linear-gradient(45deg, var(--company-color1) 0, 5%, var(--company-color2) 5% 10%, var(--company-color3) 10% 80%, var(--company-color1) 80% 85%, var(--company-color2) 85% 100%); */\\n background: linear-gradient(45deg, var(--company-color1) 0, 1%, var(--company-color2) 1% 5%, var(--company-color3) 5% 80%, var(--company-color1) 80% 85%, var(--company-color2) 85% 100%);\\n}\\n#app {\\n height: 100%;\\n width: 100%;\\n}\\n.main-body {\\n height: 100%;\\n width: 100%;\\n padding: 2rem;\\n font-family: \\\"Yusei Magic\\\", sans-serif;\\n display: flex;\\n flex-direction: column;\\n font-size: 1rem;\\n}\\n.body-row {\\n}\\n.split-6-4 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n.split-6-4 > div:nth-child(1) {\\n left: 0px;\\n width: 60%;\\n }\\n.split-6-4 > div:nth-child(2) {\\n left: 60%;\\n width: 40%;\\n }\\n\\n.split-4-6 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n\\n.split-4-6 > div:nth-child(1) {\\n left: 0px;\\n width: 40%;\\n }\\n\\n.split-4-6 > div:nth-child(2) {\\n left: 40%;\\n width: 60%;\\n }\\n.split-3-7 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n.split-3-7 > div:nth-child(1) {\\n left: 0px;\\n width: 30%;\\n }\\n.split-3-7 > div:nth-child(2) {\\n left: 30%;\\n width: 70%;\\n }\\n\\n.split-3-3-4 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n\\n.split-3-3-4 > div:nth-child(1) {\\n left: 0px;\\n width: 30%;\\n }\\n\\n.split-3-3-4 > div:nth-child(2) {\\n left: 30%;\\n width: 30%;\\n }\\n\\n.split-3-3-4 > div:nth-child(3) {\\n left: 60%;\\n width: 40%;\\n }\\n\\n.split-2-5-3 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n\\n.split-2-5-3 > div:nth-child(1) {\\n left: 0px;\\n width: 20%;\\n }\\n\\n.split-2-5-3 > div:nth-child(2) {\\n left: 20%;\\n width: 50%;\\n }\\n\\n.split-2-5-3 > div:nth-child(3) {\\n left: 70%;\\n width: 30%;\\n }\\n.split-4-4-2 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n.split-4-4-2 > div:nth-child(1) {\\n left: 0px;\\n width: 40%;\\n }\\n.split-4-4-2 > div:nth-child(2) {\\n left: 40%;\\n width: 40%;\\n }\\n.split-4-4-2 > div:nth-child(3) {\\n left: 80%;\\n width: 20%;\\n }\\n.split-3-2-2-3 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n.split-3-2-2-3 > div:nth-child(1) {\\n left: 0px;\\n width: 30%;\\n }\\n.split-3-2-2-3 > div:nth-child(2) {\\n left: 30%;\\n width: 20%;\\n }\\n.split-3-2-2-3 > div:nth-child(3) {\\n left: 50%;\\n width: 20%;\\n }\\n.split-3-2-2-3 > div:nth-child(4) {\\n left: 70%;\\n width: 30%;\\n }\\n.split-3-2-3-2 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n.split-3-2-3-2 > div:nth-child(1) {\\n left: 0px;\\n width: 30%;\\n }\\n.split-3-2-3-2 > div:nth-child(2) {\\n left: 30%;\\n width: 20%;\\n }\\n.split-3-2-3-2 > div:nth-child(3) {\\n left: 50%;\\n width: 30%;\\n }\\n.split-3-2-3-2 > div:nth-child(4) {\\n left: 80%;\\n width: 20%;\\n }\\n.split-3-1-2-4 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n.split-3-1-2-4 > div:nth-child(1) {\\n left: 0px;\\n width: 30%;\\n }\\n.split-3-1-2-4 > div:nth-child(2) {\\n left: 30%;\\n width: 10%;\\n }\\n.split-3-1-2-4 > div:nth-child(3) {\\n left: 40%;\\n width: 20%;\\n }\\n.split-3-1-2-4 > div:nth-child(4) {\\n left: 60%;\\n width: 40%;\\n }\\n.split-3-2-1-4 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n.split-3-2-1-4 > div:nth-child(1) {\\n left: 0px;\\n width: 30%;\\n }\\n.split-3-2-1-4 > div:nth-child(2) {\\n left: 30%;\\n width: 20%;\\n }\\n.split-3-2-1-4 > div:nth-child(3) {\\n left: 50%;\\n width: 10%;\\n }\\n.split-3-2-1-4 > div:nth-child(4) {\\n left: 60%;\\n width: 40%;\\n }\\n.split-3-2-2-2-1 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n.split-3-2-2-2-1 > div:nth-child(1) {\\n left: 0px;\\n width: 30%;\\n }\\n.split-3-2-2-2-1 > div:nth-child(2) {\\n left: 30%;\\n width: 20%;\\n }\\n.split-3-2-2-2-1 > div:nth-child(3) {\\n left: 50%;\\n width: 20%;\\n }\\n.split-3-2-2-2-1 > div:nth-child(4) {\\n left: 70%;\\n width: 20%;\\n }\\n.split-3-2-2-2-1 > div:nth-child(5) {\\n left: 90%;\\n width: 10%;\\n }\\n.split-3-1-1-1-4 {\\n display: flex;\\n width: 100%;\\n justify-content: center;\\n margin: 1px 0px 1px 0px;\\n}\\n.split-3-1-1-1-4 > div:nth-child(1) {\\n left: 0px;\\n width: 30%;\\n }\\n.split-3-1-1-1-4 > div:nth-child(2) {\\n left: 30%;\\n width: 10%;\\n }\\n.split-3-1-1-1-4 > div:nth-child(3) {\\n left: 40%;\\n width: 10%;\\n }\\n.split-3-1-1-1-4 > div:nth-child(4) {\\n left: 50%;\\n width: 10%;\\n }\\n.split-3-1-1-1-4 > div:nth-child(5) {\\n left: 60%;\\n width: 40%;\\n }\\n.underline {\\n border-bottom: 3px solid #333;\\n}\\n.left-padding-1 {\\n padding-left: 1rem;\\n}\\n.left-padding-2 {\\n padding-left: 2rem;\\n}\\n.left-margin-1 {\\n margin-left: 1rem;\\n}\\n.left-margin-2 {\\n margin-left: 2rem;\\n}\\n.highlight {\\n background-color: rgba(200, 200, 255, 0.3);\\n}\\n.guided {\\n /* background-color: rgba(9, 133, 67, 0.3); */\\n background-color: rgba(159, 165, 162, 0.1);\\n /* border-bottom: 1px solid rgba(9, 133, 67, 0.3); */\\n}\\n\\n.divider {\\n height: 4px;\\n /* background-color: rgba(16, 210, 113, 0.1); */\\n background-color: rgba(31, 42, 36, 0.1);\\n}\\n\\n.body-top-title {\\n font-size: 3rem;\\n}\\n.body-top-title-version {\\n margin-left: 2rem;\\n font-size: 1.2rem;\\n background: linear-gradient(transparent 60%, yellow 30%);\\n}\\n.body-top-title-belongings {\\n display: flex;\\n align-items: flex-end;\\n justify-content: flex-start;\\n}\\n.body-top-title-belongings > div {\\n margin-left: 10px;\\n margin-right: 10px;\\n }\\n.body-top-title-belongings > .belonging-item > .link {\\n text-decoration: none;\\n }\\n.body-top-title-belongings > .belonging-item > .link > span {\\n font-size: small;\\n }\\n\\n.body-section-title {\\n font-size: 1.5rem;\\n color: rgb(51, 49, 49);\\n}\\n.body-sub-section-title {\\n font-size: 1.1rem;\\n font-weight: 700;\\n color: rgb(3, 53, 12);\\n}\\n\\n.body-item-title {\\n color: rgb(51, 99, 49);\\n}\\n.body-item-text {\\n color: rgb(30, 30, 30);\\n overflow: hidden;\\n text-overflow: ellipsis;\\n white-space: nowrap;\\n}\\n.body-item-text .body-item-text-item {\\n padding-left: 1rem;\\n }\\n.body-item-text-small {\\n color: rgb(30, 30, 30);\\n font-size: 0.7rem;\\n}\\n.body-input-container {\\n display: flex;\\n}\\n.body-item-input {\\n width: 60%;\\n}\\n.body-item-input-slider {\\n width: 60%;\\n}\\n.body-item-input-slider-label {\\n margin-right: 1rem;\\n}\\n.body-item-input-slider-val {\\n margin-left: 1rem;\\n}\\n\\n.body-button-container {\\n display: flex;\\n flex-direction: row;\\n align-items: center;\\n}\\n\\n.body-button-container > div {\\n margin-left: 5px;\\n margin-right: 5px;\\n padding-left: 20px;\\n padding-right: 20px;\\n }\\n\\n.body-button-container .body-button {\\n -webkit-user-select: none;\\n -moz-user-select: none;\\n user-select: none;\\n border: solid 1px #999;\\n border-radius: 2px;\\n cursor: pointer;\\n vertical-align: middle;\\n }\\n\\n.body-button-container .body-button:hover {\\n border: solid 1px #000;\\n }\\n\\n.body-button-container .body-button-disabled {\\n -webkit-user-select: none;\\n -moz-user-select: none;\\n user-select: none;\\n border: solid 1px #999;\\n border-radius: 2px;\\n vertical-align: middle;\\n background: #ddd;\\n }\\n\\n.body-button-container .body-button-active {\\n -webkit-user-select: none;\\n -moz-user-select: none;\\n user-select: none;\\n border: solid 1px #333;\\n border-radius: 2px;\\n background: #ada;\\n }\\n\\n.body-button-container .body-button-stanby {\\n -webkit-user-select: none;\\n -moz-user-select: none;\\n user-select: none;\\n border: solid 1px #999;\\n border-radius: 2px;\\n background: #aba;\\n cursor: pointer;\\n }\\n\\n.body-button-container .body-button-stanby:hover {\\n border: solid 1px #000;\\n }\\n.body-select {\\n color: rgb(30, 30, 30);\\n max-width: 100%;\\n}\\n\\n.body-image-container-quality-analyze,\\n.body-wav-container-quality-analyze {\\n display: flex;\\n width: 100%;\\n}\\n\\n.body-image-container-quality-analyze > img, .body-wav-container-quality-analyze > img {\\n width: 50%;\\n }\\n\", \"\"]);\n// Exports\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);\n\n\n//# sourceURL=webpack://demo/./src/css/App.css?./node_modules/css-loader/dist/cjs.js??ruleSet%5B1%5D.rules%5B2%5D.use%5B1%5D!./node_modules/postcss-loader/dist/cjs.js"); /***/ }), diff --git a/client/demo/src/107_qulity_control.tsx b/client/demo/src/107_qulity_control.tsx index ab769ff6..f1d15784 100644 --- a/client/demo/src/107_qulity_control.tsx +++ b/client/demo/src/107_qulity_control.tsx @@ -1,5 +1,5 @@ import { BufferSize, DownSamplingMode, F0Detector, Protocol, SampleRate, VoiceChangerMode } from "@dannadori/voice-changer-client-js" -import React, { useMemo, useState } from "react" +import React, { useEffect, useMemo, useState } from "react" import { ClientState } from "@dannadori/voice-changer-client-js"; @@ -10,9 +10,31 @@ export type UseQualityControlProps = { export type QualityControlState = { qualityControl: JSX.Element; } +const reloadDevices = async () => { + try { + const ms = await navigator.mediaDevices.getUserMedia({ video: false, audio: true }); + ms.getTracks().forEach(x => { x.stop() }) + } catch (e) { + console.warn("Enumerate device error::", e) + } + const mediaDeviceInfos = await navigator.mediaDevices.enumerateDevices(); + const audioOutputs = mediaDeviceInfos.filter(x => { return x.kind == "audiooutput" }) + + return audioOutputs +} + export const useQualityControl = (props: UseQualityControlProps): QualityControlState => { const [showQualityControl, setShowQualityControl] = useState(false) + const [outputAudioDeviceInfo, setOutputAudioDeviceInfo] = useState([]) + const [audioOutputForGUI, setAudioOutputForGUI] = useState("none") + useEffect(() => { + const initialize = async () => { + const audioInfo = await reloadDevices() + setOutputAudioDeviceInfo(audioInfo) + } + initialize() + }, []) const noiseControlRow = useMemo(() => { @@ -94,23 +116,90 @@ export const useQualityControl = (props: UseQualityControlProps): QualityControl const recordIORow = useMemo(() => { + const setReocrdIO = async (val: number) => { + await props.clientState.serverSetting.setRecordIO(val) + if (val == 0) { + const imageContainer = document.getElementById("quality-control-analyze-image-container") as HTMLDivElement + imageContainer.innerHTML = "" + const image = document.createElement("img") + image.src = "/tmp/analyze-dio.png?" + new Date().getTime() + imageContainer.appendChild(image) + const image2 = document.createElement("img") + image2.src = "/tmp/analyze-harvest.png?" + new Date().getTime() + imageContainer.appendChild(image2) + + const wavContainer = document.getElementById("quality-control-analyze-wav-container") as HTMLDivElement + wavContainer.innerHTML = "" + const media1 = document.createElement("audio") as HTMLAudioElement + media1.src = "/tmp/in.wav?" + new Date().getTime() + media1.controls = true + // @ts-ignore + media1.setSinkId(audioOutputForGUI) + wavContainer.appendChild(media1) + const media2 = document.createElement("audio") as HTMLAudioElement + media2.src = "/tmp/out.wav?" + new Date().getTime() + media2.controls = true + // @ts-ignore + media2.setSinkId(audioOutputForGUI) + wavContainer.appendChild(media2) + } + } return ( -
-
recordIO
-
- + <> +
+
recordIO
+
+ +
-
+
+
+
+ Spectrogram +
+
+ (left: dio, right:harvest) +
+
+
+
+
+
+
+
+ wav (left:input, right:output) +
+ +
+
+
+
+ ) - }, [props.clientState.serverSetting.setting.recordIO, props.clientState.serverSetting.setRecordIO]) + }, [props.clientState.serverSetting.setting.recordIO, props.clientState.serverSetting.setRecordIO, outputAudioDeviceInfo, audioOutputForGUI]) const QualityControlContent = useMemo(() => { if (!showQualityControl) return <> diff --git a/client/demo/src/css/App.css b/client/demo/src/css/App.css index ce00b378..e3064ac5 100644 --- a/client/demo/src/css/App.css +++ b/client/demo/src/css/App.css @@ -444,8 +444,16 @@ body { } } } -.body-select-container { - .body-select { - color: rgb(30, 30, 30); +.body-select { + color: rgb(30, 30, 30); + max-width: 100%; +} + +.body-image-container-quality-analyze, +.body-wav-container-quality-analyze { + display: flex; + width: 100%; + & > img { + width: 50%; } } diff --git a/server/voice_changer/VoiceChanger.py b/server/voice_changer/VoiceChanger.py index b1eedae3..f3c5117f 100755 --- a/server/voice_changer/VoiceChanger.py +++ b/server/voice_changer/VoiceChanger.py @@ -22,6 +22,13 @@ providers = ['OpenVINOExecutionProvider', "CUDAExecutionProvider", "DmlExecution import wave +import matplotlib +matplotlib.use('Agg') +import pylab +import librosa +import librosa.display +SAMPLING_RATE = 24000 + class MockStream: """ @@ -194,6 +201,18 @@ class VoiceChanger(): return data + def _get_f0_dio(self, y, sr=SAMPLING_RATE): + _f0, time = pw.dio(y, sr, frame_period=5) + f0 = pw.stonemask(y, _f0, time, sr) + time = np.linspace(0, y.shape[0] / sr, len(time)) + return f0, time + + def _get_f0_harvest(self, y, sr=SAMPLING_RATE): + _f0, time = pw.harvest(y, sr, frame_period=5) + f0 = pw.stonemask(y, _f0, time, sr) + time = np.linspace(0, y.shape[0] / sr, len(time)) + return f0, time + def update_setteings(self, key: str, val: any): if key == "onnxExecutionProvider" and self.onnx_session != None: if val == "CUDAExecutionProvider": @@ -215,6 +234,32 @@ class VoiceChanger(): self.unpackedData_length = 0 if key == "recordIO" and val == 1: self._setupRecordIO() + if key == "recordIO" and val == 0: + try: + stream_input_file = os.path.join(TMP_DIR, "in.wav") + analyze_file_dio = os.path.join(TMP_DIR, "analyze-dio.png") + analyze_file_harvest = os.path.join(TMP_DIR, "analyze-harvest.png") + y, sr = librosa.load(stream_input_file, SAMPLING_RATE) + y = y.astype(np.float64) + spec = librosa.amplitude_to_db(np.abs(librosa.stft(y, n_fft=2048, win_length=2048, hop_length=128)), ref=np.max) + f0_dio, times = self._get_f0_dio(y) + f0_harvest, times = self._get_f0_harvest(y) + + pylab.close() + HOP_LENGTH = 128 + img = librosa.display.specshow(spec, sr=SAMPLING_RATE, hop_length=HOP_LENGTH, x_axis='time', y_axis='log', ) + pylab.plot(times, f0_dio, label='f0', color=(0, 1, 1, 0.6), linewidth=3) + pylab.savefig(analyze_file_dio) + + pylab.close() + HOP_LENGTH = 128 + img = librosa.display.specshow(spec, sr=SAMPLING_RATE, hop_length=HOP_LENGTH, x_axis='time', y_axis='log', ) + pylab.plot(times, f0_harvest, label='f0', color=(0, 1, 1, 0.6), linewidth=3) + pylab.savefig(analyze_file_harvest) + + except Exception as e: + print("recordIO exception", e) + elif key in self.settings.floatData: setattr(self.settings, key, float(val)) elif key in self.settings.strData: