mirror of
https://github.com/w-okada/voice-changer.git
synced 2025-01-23 21:45:00 +03:00
WIP: support v1.5.x, add recording output function 1
This commit is contained in:
parent
ea7690c2cd
commit
449f5a55d1
4
client/demo/dist/index.js
vendored
4
client/demo/dist/index.js
vendored
File diff suppressed because one or more lines are too long
@ -29,6 +29,13 @@ const reloadDevices = async () => {
|
|||||||
toJSON: () => { }
|
toJSON: () => { }
|
||||||
})
|
})
|
||||||
const audioOutputs = mediaDeviceInfos.filter(x => { return x.kind == "audiooutput" })
|
const audioOutputs = mediaDeviceInfos.filter(x => { return x.kind == "audiooutput" })
|
||||||
|
audioOutputs.push({
|
||||||
|
deviceId: "record",
|
||||||
|
groupId: "record",
|
||||||
|
kind: "audiooutput",
|
||||||
|
label: "record",
|
||||||
|
toJSON: () => { }
|
||||||
|
})
|
||||||
return [audioInputs, audioOutputs]
|
return [audioInputs, audioOutputs]
|
||||||
}
|
}
|
||||||
export type UseDeviceSettingProps = {
|
export type UseDeviceSettingProps = {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
export declare const RequestType: {
|
export declare const RequestType: {
|
||||||
readonly voice: "voice";
|
readonly voice: "voice";
|
||||||
readonly config: "config";
|
readonly config: "config";
|
||||||
|
readonly startRecording: "startRecording";
|
||||||
|
readonly stopRecording: "stopRecording";
|
||||||
};
|
};
|
||||||
export type RequestType = typeof RequestType[keyof typeof RequestType];
|
export type RequestType = typeof RequestType[keyof typeof RequestType];
|
||||||
export type VoiceChangerWorkletProcessorRequest = {
|
export type VoiceChangerWorkletProcessorRequest = {
|
||||||
|
@ -225,15 +225,23 @@ export class VoiceChangerClient {
|
|||||||
|
|
||||||
// configure worklet
|
// configure worklet
|
||||||
configureWorklet = (setting: WorkletSetting) => {
|
configureWorklet = (setting: WorkletSetting) => {
|
||||||
const req: VoiceChangerWorkletProcessorRequest = {
|
// const req: VoiceChangerWorkletProcessorRequest = {
|
||||||
requestType: "config",
|
// requestType: "config",
|
||||||
voice: new ArrayBuffer(1),
|
// voice: new ArrayBuffer(1),
|
||||||
numTrancateTreshold: setting.numTrancateTreshold,
|
// numTrancateTreshold: setting.numTrancateTreshold,
|
||||||
volTrancateThreshold: setting.volTrancateThreshold,
|
// volTrancateThreshold: setting.volTrancateThreshold,
|
||||||
volTrancateLength: setting.volTrancateLength
|
// volTrancateLength: setting.volTrancateLength
|
||||||
}
|
// }
|
||||||
this.vcNode.postReceivedVoice(req)
|
// this.vcNode.postReceivedVoice(req)
|
||||||
|
this.vcNode.configure(setting)
|
||||||
}
|
}
|
||||||
|
startOutputRecordingWorklet = () => {
|
||||||
|
|
||||||
|
}
|
||||||
|
stopOutputRecordingWorklet = () => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Configurator Method
|
// Configurator Method
|
||||||
uploadFile = (buf: ArrayBuffer, filename: string, onprogress: (progress: number, end: boolean) => void) => {
|
uploadFile = (buf: ArrayBuffer, filename: string, onprogress: (progress: number, end: boolean) => void) => {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { VoiceChangerWorkletProcessorRequest } from "./@types/voice-changer-worklet-processor";
|
import { VoiceChangerWorkletProcessorRequest } from "./@types/voice-changer-worklet-processor";
|
||||||
|
import { WorkletSetting } from "./const";
|
||||||
|
|
||||||
export type VolumeListener = {
|
export type VolumeListener = {
|
||||||
notifyVolume: (vol: number) => void
|
notifyVolume: (vol: number) => void
|
||||||
@ -21,6 +22,45 @@ export class VoiceChangerWorkletNode extends AudioWorkletNode {
|
|||||||
|
|
||||||
handleMessage(event: any) {
|
handleMessage(event: any) {
|
||||||
// console.log(`[Node:handleMessage_] `, event.data.volume);
|
// console.log(`[Node:handleMessage_] `, event.data.volume);
|
||||||
this.listener.notifyVolume(event.data.volume as number)
|
if (event.data.responseType === "volume") {
|
||||||
|
this.listener.notifyVolume(event.data.volume as number)
|
||||||
|
} else if (event.data.responseType === "recordData") {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
console.warn(`[worklet_node][voice-changer-worklet-processor] unknown response ${event.data.responseType}`, event.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configure = (setting: WorkletSetting) => {
|
||||||
|
const req: VoiceChangerWorkletProcessorRequest = {
|
||||||
|
requestType: "config",
|
||||||
|
voice: new ArrayBuffer(1),
|
||||||
|
numTrancateTreshold: setting.numTrancateTreshold,
|
||||||
|
volTrancateThreshold: setting.volTrancateThreshold,
|
||||||
|
volTrancateLength: setting.volTrancateLength
|
||||||
|
}
|
||||||
|
this.port.postMessage(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
startOutputRecordingWorklet = () => {
|
||||||
|
const req: VoiceChangerWorkletProcessorRequest = {
|
||||||
|
requestType: "startRecording",
|
||||||
|
voice: new ArrayBuffer(1),
|
||||||
|
numTrancateTreshold: 0,
|
||||||
|
volTrancateThreshold: 0,
|
||||||
|
volTrancateLength: 0
|
||||||
|
}
|
||||||
|
this.port.postMessage(req)
|
||||||
|
|
||||||
|
}
|
||||||
|
stopOutputRecordingWorklet = () => {
|
||||||
|
const req: VoiceChangerWorkletProcessorRequest = {
|
||||||
|
requestType: "stopRecording",
|
||||||
|
voice: new ArrayBuffer(1),
|
||||||
|
numTrancateTreshold: 0,
|
||||||
|
volTrancateThreshold: 0,
|
||||||
|
volTrancateLength: 0
|
||||||
|
}
|
||||||
|
this.port.postMessage(req)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,9 +1,20 @@
|
|||||||
export const RequestType = {
|
export const RequestType = {
|
||||||
"voice": "voice",
|
"voice": "voice",
|
||||||
"config": "config"
|
"config": "config",
|
||||||
|
"startRecording": "startRecording",
|
||||||
|
"stopRecording": "stopRecording"
|
||||||
} as const
|
} as const
|
||||||
export type RequestType = typeof RequestType[keyof typeof RequestType]
|
export type RequestType = typeof RequestType[keyof typeof RequestType]
|
||||||
|
|
||||||
|
|
||||||
|
export const ResponseType = {
|
||||||
|
"volume": "volume",
|
||||||
|
"recordData": "recordData"
|
||||||
|
} as const
|
||||||
|
export type ResponseType = typeof ResponseType[keyof typeof ResponseType]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export type VoiceChangerWorkletProcessorRequest = {
|
export type VoiceChangerWorkletProcessorRequest = {
|
||||||
requestType: RequestType,
|
requestType: RequestType,
|
||||||
voice: ArrayBuffer,
|
voice: ArrayBuffer,
|
||||||
@ -12,6 +23,12 @@ export type VoiceChangerWorkletProcessorRequest = {
|
|||||||
volTrancateLength: number
|
volTrancateLength: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type VoiceChangerWorkletProcessorResponse = {
|
||||||
|
responseType: ResponseType,
|
||||||
|
volume?: number,
|
||||||
|
recordData?: Float32Array[]
|
||||||
|
}
|
||||||
|
|
||||||
class VoiceChangerWorkletProcessor extends AudioWorkletProcessor {
|
class VoiceChangerWorkletProcessor extends AudioWorkletProcessor {
|
||||||
private BLOCK_SIZE = 128
|
private BLOCK_SIZE = 128
|
||||||
private initialized = false;
|
private initialized = false;
|
||||||
@ -21,7 +38,10 @@ class VoiceChangerWorkletProcessor extends AudioWorkletProcessor {
|
|||||||
private volTrancateLength = 32
|
private volTrancateLength = 32
|
||||||
private volTrancateCount = 0
|
private volTrancateCount = 0
|
||||||
|
|
||||||
|
private isRecording = false
|
||||||
|
|
||||||
playBuffer: Float32Array[] = []
|
playBuffer: Float32Array[] = []
|
||||||
|
recordingBuffer: Float32Array[] = []
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
@ -47,6 +67,28 @@ class VoiceChangerWorkletProcessor extends AudioWorkletProcessor {
|
|||||||
this.volTrancateThreshold = request.volTrancateThreshold
|
this.volTrancateThreshold = request.volTrancateThreshold
|
||||||
console.log("[worklet] worklet configured", request)
|
console.log("[worklet] worklet configured", request)
|
||||||
return
|
return
|
||||||
|
} else if (request.requestType === "startRecording") {
|
||||||
|
if (this.isRecording) {
|
||||||
|
console.warn("[worklet] recoring is already started")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.isRecording = true
|
||||||
|
this.recordingBuffer = []
|
||||||
|
return
|
||||||
|
} else if (request.requestType === "stopRecording") {
|
||||||
|
if (!this.isRecording) {
|
||||||
|
console.warn("[worklet] recoring is not started")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.isRecording = false
|
||||||
|
const recordResponse: VoiceChangerWorkletProcessorResponse = {
|
||||||
|
responseType: ResponseType.recordData,
|
||||||
|
recordData: this.recordingBuffer
|
||||||
|
|
||||||
|
}
|
||||||
|
this.port.postMessage(recordResponse);
|
||||||
|
this.recordingBuffer = []
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const arrayBuffer = request.voice
|
const arrayBuffer = request.voice
|
||||||
@ -80,6 +122,9 @@ class VoiceChangerWorkletProcessor extends AudioWorkletProcessor {
|
|||||||
f32Block![frameIndexInBlock + 1] = (currentFrame + nextFrame) / 2
|
f32Block![frameIndexInBlock + 1] = (currentFrame + nextFrame) / 2
|
||||||
if (f32Block!.length === frameIndexInBlock + 2) {
|
if (f32Block!.length === frameIndexInBlock + 2) {
|
||||||
this.playBuffer.push(f32Block!)
|
this.playBuffer.push(f32Block!)
|
||||||
|
if (this.isRecording) {
|
||||||
|
this.recordingBuffer.push(f32Block!)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,7 +164,11 @@ class VoiceChangerWorkletProcessor extends AudioWorkletProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (voice) {
|
if (voice) {
|
||||||
this.port.postMessage({ volume: this.volume });
|
const volumeResponse: VoiceChangerWorkletProcessorResponse = {
|
||||||
|
responseType: ResponseType.volume,
|
||||||
|
volume: this.volume
|
||||||
|
}
|
||||||
|
this.port.postMessage(volumeResponse);
|
||||||
outputs[0][0].set(voice)
|
outputs[0][0].set(voice)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user