mirror of
https://github.com/w-okada/voice-changer.git
synced 2025-01-23 13:35:12 +03:00
refactoring
This commit is contained in:
parent
5b85d58b8b
commit
46e7a64185
File diff suppressed because one or more lines are too long
@ -1,5 +1,3 @@
|
||||
import { FixedUserData } from "../002_hooks/013_useAudioControllerState";
|
||||
|
||||
export const fetchTextResource = async (url: string): Promise<string> => {
|
||||
const res = await fetch(url, {
|
||||
method: "GET"
|
||||
@ -7,107 +5,3 @@ export const fetchTextResource = async (url: string): Promise<string> => {
|
||||
const text = res.text()
|
||||
return text;
|
||||
}
|
||||
|
||||
export const postVoice = async (title: string, prefix: string, index: number, blob: Blob) => {
|
||||
// const url = `./api/voice/${title}/${prefix}/${index}`
|
||||
// const url = `./api/voice`
|
||||
// !!!!!!!!!!! COLABのプロキシがRoot直下のパスしか通さない??? !!!!!!
|
||||
// !!!!!!!!!!! Bodyで参照、設定コマンドを代替する。 !!!!!!
|
||||
const url = `/api`
|
||||
|
||||
const blobBuffer = await blob.arrayBuffer()
|
||||
const obj = {
|
||||
command: "POST_VOICE",
|
||||
data: Buffer.from(blobBuffer).toString("base64"),
|
||||
title: title,
|
||||
prefix: prefix,
|
||||
index: index
|
||||
};
|
||||
const body = JSON.stringify(obj);
|
||||
|
||||
const res = await fetch(`${url}`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: body
|
||||
})
|
||||
|
||||
const receivedJson = await res.json()
|
||||
const message = receivedJson["message"]
|
||||
console.debug("POST VOICE RES:", message)
|
||||
return
|
||||
}
|
||||
|
||||
export const getVoice = async (title: string, prefix: string, index: number) => {
|
||||
if (!title || !prefix) {
|
||||
return null
|
||||
}
|
||||
|
||||
const url = `/api`
|
||||
const obj = {
|
||||
command: "GET_VOICE",
|
||||
title: title,
|
||||
prefix: prefix,
|
||||
index: index
|
||||
};
|
||||
const body = JSON.stringify(obj);
|
||||
|
||||
const res = await fetch(`${url}`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: body
|
||||
})
|
||||
|
||||
|
||||
const receivedJson = await res.json()
|
||||
// const message = receivedJson["message"]
|
||||
const dataBase64 = receivedJson["data"]
|
||||
// console.log("GET VOICE RES:", message, dataBase64)
|
||||
if (!dataBase64) {
|
||||
return null;
|
||||
}
|
||||
const buf = Buffer.from(dataBase64, "base64")
|
||||
const blob = new Blob([buf.buffer])
|
||||
return blob
|
||||
}
|
||||
|
||||
export const postVoice__ = async (title: string, index: number, userData: FixedUserData) => {
|
||||
const url = `/api/voice/${title}/${index}`
|
||||
const micWavBlob = await userData.micWavBlob!.arrayBuffer()
|
||||
const vfWavBlob = await userData.vfWavBlob!.arrayBuffer()
|
||||
const micF32 = await userData.micWavSamples!
|
||||
const vfF32 = await userData.vfWavSamples!
|
||||
|
||||
const obj = {
|
||||
micWavBlob: Buffer.from(micWavBlob).toString("base64"),
|
||||
vfWavBlob: Buffer.from(vfWavBlob).toString("base64"),
|
||||
micF32: Buffer.from(micF32).toString("base64"),
|
||||
vfF32: Buffer.from(vfF32).toString("base64")
|
||||
};
|
||||
const body = JSON.stringify(obj);
|
||||
|
||||
const res = await fetch(`${url}`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: body
|
||||
})
|
||||
|
||||
const receivedJson = await res.json()
|
||||
const changedVoiceBase64 = receivedJson["changedVoiceBase64"]
|
||||
const buf = Buffer.from(changedVoiceBase64, "base64")
|
||||
const ab = new ArrayBuffer(buf.length);
|
||||
const view = new Uint8Array(ab);
|
||||
for (let i = 0; i < buf.length; ++i) {
|
||||
view[i] = buf[i];
|
||||
}
|
||||
return ab
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ApplicationSetting } from "../001_clients_and_managers/000_ApplicationSettingLoader"
|
||||
import { generateWavNameForLocalStorage } from "../const"
|
||||
import { generateDataNameForLocalStorage } from "../const"
|
||||
import { IndexedDBStateAndMethod } from "./001_useIndexedDB"
|
||||
import { FixedUserData } from "./013_useAudioControllerState"
|
||||
export type UseAppStateStorageProps = {
|
||||
@ -17,13 +17,13 @@ export type AppStateStorageStateAndMethod = AppStateStorageState & {
|
||||
|
||||
export const useAppStateStorage = (props: UseAppStateStorageProps): AppStateStorageStateAndMethod => {
|
||||
const saveUserData = async (_title: string, prefix: string, index: number, userData: FixedUserData) => {
|
||||
const { micString } = generateWavNameForLocalStorage(prefix, index)
|
||||
props.indexedDBState.setItem(micString, userData)
|
||||
const { dataName } = generateDataNameForLocalStorage(prefix, index)
|
||||
props.indexedDBState.setItem(dataName, userData)
|
||||
}
|
||||
|
||||
const loadUserData = async (_title: string, prefix: string, index: number): Promise<FixedUserData | null> => {
|
||||
const { micString } = generateWavNameForLocalStorage(prefix, index)
|
||||
const obj = await props.indexedDBState.getItem(micString) as FixedUserData
|
||||
const { dataName } = generateDataNameForLocalStorage(prefix, index)
|
||||
const obj = await props.indexedDBState.getItem(dataName) as FixedUserData
|
||||
return obj
|
||||
}
|
||||
|
||||
|
@ -4,9 +4,6 @@ import { Duplex, DuplexOptions } from "readable-stream";
|
||||
import MicrophoneStream from "microphone-stream";
|
||||
import { useAppSetting } from "../003_provider/AppSettingProvider";
|
||||
|
||||
|
||||
|
||||
|
||||
export type MediaRecorderState = {
|
||||
micMediaStream: MediaStream | undefined,
|
||||
vfMediaStream: MediaStream | undefined
|
||||
@ -27,6 +24,8 @@ export type MediaRecorderStateAndMethod = MediaRecorderState & {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// AudioInputデータを蓄積するAudiowStreamer
|
||||
class AudioStreamer extends Duplex {
|
||||
chunks: Float32Array[] = []
|
||||
SampleRate: number
|
||||
@ -45,18 +44,14 @@ class AudioStreamer extends Duplex {
|
||||
this.initializeData()
|
||||
}
|
||||
|
||||
// 蓄積したデータをWavに変換して返す
|
||||
getRecordedData = () => {
|
||||
const sampleSize = this.chunks.reduce((prev, cur) => {
|
||||
return prev + cur.length
|
||||
}, 0)
|
||||
const samples = new Float32Array(sampleSize);
|
||||
let sampleIndex = 0
|
||||
// this.chunks.forEach(floatArray => {
|
||||
// floatArray.forEach(val => {
|
||||
// samples[sampleIndex] = val
|
||||
// sampleIndex++;
|
||||
// })
|
||||
// })
|
||||
|
||||
for (let i = 0; i < this.chunks.length; i++) {
|
||||
for (let j = 0; j < this.chunks[i].length; j++) {
|
||||
samples[sampleIndex] = this.chunks[i][j];
|
||||
@ -64,14 +59,6 @@ class AudioStreamer extends Duplex {
|
||||
}
|
||||
}
|
||||
|
||||
// console.log("samples:c2", this.chunks[0][0])
|
||||
// console.log("samples:c2", this.chunks[0][1])
|
||||
// console.log("samples:c2", this.chunks[0])
|
||||
// console.log("samples:s", samples[0])
|
||||
// console.log("samples:s", samples[1])
|
||||
// console.log("samples:s", samples[2])
|
||||
// console.log("samples:s", samples)
|
||||
|
||||
const writeString = (view: DataView, offset: number, string: string) => {
|
||||
for (var i = 0; i < string.length; i++) {
|
||||
view.setUint8(offset + i, string.charCodeAt(i));
|
||||
@ -107,28 +94,14 @@ class AudioStreamer extends Duplex {
|
||||
const audioBlob = new Blob([view], { type: 'audio/wav' });
|
||||
const duration = samples.length / this.SampleRate
|
||||
|
||||
// audioBlob.arrayBuffer().then((buffer) => {
|
||||
// console.log("DATALENGTH1", samples.length * 2)
|
||||
// const oldView = new DataView(buffer);
|
||||
// console.log("DATALENGTH2", view.getUint32(40, true))
|
||||
// console.log("DATALENGTH3", oldView.getUint32(40, true))
|
||||
// })
|
||||
|
||||
|
||||
return { audioBlob, duration, samples }
|
||||
|
||||
// var url = URL.createObjectURL(audioBlob);
|
||||
// // var a = document.createElement('a');
|
||||
// // a.href = url;
|
||||
// // a.download = 'test.wav';
|
||||
// // a.click();
|
||||
// // return this.chunks
|
||||
// return url
|
||||
}
|
||||
|
||||
// AudioInputを蓄積
|
||||
public _write(chunk: AudioBuffer, _encoding: any, callback: any) {
|
||||
const buffer = chunk.getChannelData(0);
|
||||
console.log("SAMPLERATE:", chunk.sampleRate, chunk.numberOfChannels, chunk.length)
|
||||
// console.log("SAMPLERATE:", chunk.sampleRate, chunk.numberOfChannels, chunk.length)
|
||||
var bufferData = new Float32Array(chunk.length);
|
||||
for (var i = 0; i < chunk.length; i++) {
|
||||
bufferData[i] = buffer[i];
|
||||
@ -152,6 +125,7 @@ export const useMediaRecorder = (): MediaRecorderStateAndMethod => {
|
||||
const [micMediaStream, setMicMediaStream] = useState<MediaStream>()
|
||||
const [vfMediaStream, setVfMediaStream] = useState<MediaStream>()
|
||||
|
||||
// 生の(ノイキャンなしの)データ蓄積用Streamer
|
||||
const micAudioStreamer = useMemo(() => {
|
||||
return new AudioStreamer({ objectMode: true, SampleRate: applicationSetting.applicationSetting.sample_rate })
|
||||
}, [])
|
||||
@ -165,6 +139,7 @@ export const useMediaRecorder = (): MediaRecorderStateAndMethod => {
|
||||
return s
|
||||
}, [])
|
||||
|
||||
// ノイキャンしたデータの蓄積用Streamer
|
||||
const vfAudioStreamer = useMemo(() => {
|
||||
return new AudioStreamer({ objectMode: true, SampleRate: applicationSetting.applicationSetting.sample_rate })
|
||||
}, [])
|
||||
@ -179,6 +154,12 @@ export const useMediaRecorder = (): MediaRecorderStateAndMethod => {
|
||||
}, [])
|
||||
|
||||
|
||||
// AudioInput変更のトリガー
|
||||
useEffect(() => {
|
||||
setNewAudioInputDevice(deviceManagerState.audioInputDeviceId || "")
|
||||
}, [deviceManagerState.audioInputDeviceId])
|
||||
|
||||
// AudioInput変更のトリガーによりinputのパイプラインを再生成する
|
||||
const setNewAudioInputDevice = async (deviceId: string) => {
|
||||
console.log("setNewAudioInputDevice", deviceId)
|
||||
let vf = voiceFocusDeviceTransformer
|
||||
@ -231,9 +212,7 @@ export const useMediaRecorder = (): MediaRecorderStateAndMethod => {
|
||||
vfStream.setStream(outputNode.stream)
|
||||
vfStream.pauseRecording()
|
||||
}
|
||||
useEffect(() => {
|
||||
setNewAudioInputDevice(deviceManagerState.audioInputDeviceId || "")
|
||||
}, [deviceManagerState.audioInputDeviceId])
|
||||
|
||||
|
||||
const startRecord = () => {
|
||||
console.log("start record")
|
||||
@ -242,6 +221,7 @@ export const useMediaRecorder = (): MediaRecorderStateAndMethod => {
|
||||
vfAudioStreamer.clearRecordedData()
|
||||
vfStream!.playRecording()
|
||||
}
|
||||
|
||||
const pauseRecord = () => {
|
||||
micStream!.pauseRecording()
|
||||
vfStream!.pauseRecording()
|
||||
|
@ -11,11 +11,10 @@ export const generateTextFileName = (prefix: string, index: number) => {
|
||||
return `${prefix}${indexString}.txt`
|
||||
}
|
||||
|
||||
export const generateWavNameForLocalStorage = (prefix: string, index: number) => {
|
||||
export const generateDataNameForLocalStorage = (prefix: string, index: number) => {
|
||||
const indexString = String(index + 1).padStart(3, '0')
|
||||
const vfString = `${prefix}${indexString}_vf`
|
||||
const micString = `${prefix}${indexString}_mic`
|
||||
return { micString, vfString }
|
||||
const dataName = `${prefix}${indexString}_mic`
|
||||
return { dataName }
|
||||
}
|
||||
export const generateRegionNameForLocalStorage = (prefix: string, index: number) => {
|
||||
const indexString = String(index + 1).padStart(3, '0')
|
||||
|
Loading…
Reference in New Issue
Block a user