async internal process

This commit is contained in:
w-okada 2023-11-23 16:44:23 +09:00
parent 0e7c0daebc
commit b24c781a72

View File

@ -1,5 +1,11 @@
import { VoiceChangerWorkletProcessorRequest } from "../@types/voice-changer-worklet-processor";
import { DefaultClientSettng, DownSamplingMode, VOICE_CHANGER_CLIENT_EXCEPTION, WorkletNodeSetting, WorkletSetting } from "../const";
import {
DefaultClientSettng,
DownSamplingMode,
VOICE_CHANGER_CLIENT_EXCEPTION,
WorkletNodeSetting,
WorkletSetting,
} from "../const";
import { io, Socket } from "socket.io-client";
import { DefaultEventsMap } from "@socket.io/component-emitter";
import { ServerRestClient } from "./ServerRestClient";
@ -8,7 +14,10 @@ export type VoiceChangerWorkletListener = {
notifyVolume: (vol: number) => void;
notifySendBufferingTime: (time: number) => void;
notifyResponseTime: (time: number, perf?: number[]) => void;
notifyException: (code: VOICE_CHANGER_CLIENT_EXCEPTION, message: string) => void;
notifyException: (
code: VOICE_CHANGER_CLIENT_EXCEPTION,
message: string
) => void;
};
export type InternalCallback = {
@ -29,8 +38,12 @@ export class VoiceChangerWorkletNode extends AudioWorkletNode {
private outputNode: VoiceChangerWorkletNode | null = null;
// Promises
private startPromiseResolve: ((value: void | PromiseLike<void>) => void) | null = null;
private stopPromiseResolve: ((value: void | PromiseLike<void>) => void) | null = null;
private startPromiseResolve:
| ((value: void | PromiseLike<void>) => void)
| null = null;
private stopPromiseResolve:
| ((value: void | PromiseLike<void>) => void)
| null = null;
// InternalCallback
private internalCallback: InternalCallback | null = null;
@ -49,9 +62,16 @@ export class VoiceChangerWorkletNode extends AudioWorkletNode {
// 設定
updateSetting = (setting: WorkletNodeSetting) => {
console.log(`[WorkletNode] Updating WorkletNode Setting,`, this.setting, setting);
console.log(
`[WorkletNode] Updating WorkletNode Setting,`,
this.setting,
setting
);
let recreateSocketIoRequired = false;
if (this.setting.serverUrl != setting.serverUrl || this.setting.protocol != setting.protocol) {
if (
this.setting.serverUrl != setting.serverUrl ||
this.setting.protocol != setting.protocol
) {
recreateSocketIoRequired = true;
}
this.setting = setting;
@ -80,7 +100,10 @@ export class VoiceChangerWorkletNode extends AudioWorkletNode {
if (this.setting.protocol === "sio") {
this.socket = io(this.setting.serverUrl + "/test");
this.socket.on("connect_error", (err) => {
this.listener.notifyException(VOICE_CHANGER_CLIENT_EXCEPTION.ERR_SIO_CONNECT_FAILED, `[SIO] rconnection failed ${err}`);
this.listener.notifyException(
VOICE_CHANGER_CLIENT_EXCEPTION.ERR_SIO_CONNECT_FAILED,
`[SIO] rconnection failed ${err}`
);
});
this.socket.on("connect", () => {
console.log(`[SIO] connect to ${this.setting.serverUrl}`);
@ -102,12 +125,18 @@ export class VoiceChangerWorkletNode extends AudioWorkletNode {
// Quick hack for server device mode
if (response[0] == 0) {
this.listener.notifyResponseTime(Math.round(perf[0] * 1000), perf.slice(1, 4));
this.listener.notifyResponseTime(
Math.round(perf[0] * 1000),
perf.slice(1, 4)
);
return;
}
if (result.byteLength < 128 * 2) {
this.listener.notifyException(VOICE_CHANGER_CLIENT_EXCEPTION.ERR_SIO_INVALID_RESPONSE, `[SIO] recevied data is too short ${result.byteLength}`);
this.listener.notifyException(
VOICE_CHANGER_CLIENT_EXCEPTION.ERR_SIO_INVALID_RESPONSE,
`[SIO] recevied data is too short ${result.byteLength}`
);
} else {
if (this.outputNode != null) {
this.outputNode.postReceivedVoice(response[1]);
@ -158,7 +187,11 @@ export class VoiceChangerWorkletNode extends AudioWorkletNode {
}
};
private _averageDownsampleBuffer(buffer: Float32Array, originalSampleRate: number, destinationSamplerate: number) {
private _averageDownsampleBuffer(
buffer: Float32Array,
originalSampleRate: number,
destinationSamplerate: number
) {
if (originalSampleRate == destinationSamplerate) {
return buffer;
}
@ -175,7 +208,11 @@ export class VoiceChangerWorkletNode extends AudioWorkletNode {
// Use average value of skipped samples
var accum = 0,
count = 0;
for (var i = offsetBuffer; i < nextOffsetBuffer && i < buffer.length; i++) {
for (
var i = offsetBuffer;
i < nextOffsetBuffer && i < buffer.length;
i++
) {
accum += buffer[i];
count++;
}
@ -221,7 +258,11 @@ export class VoiceChangerWorkletNode extends AudioWorkletNode {
} else {
//////// (Kind 2) 平均 //////////
// downsampledBuffer = this._averageDownsampleBuffer(buffer, 48000, 24000)
downsampledBuffer = this._averageDownsampleBuffer(inputData, 48000, this.setting.sendingSampleRate);
downsampledBuffer = this._averageDownsampleBuffer(
inputData,
48000,
this.setting.sendingSampleRate
);
}
// Float to Int16 (internalの場合はfloatのまま行く。)
@ -264,7 +305,10 @@ export class VoiceChangerWorkletNode extends AudioWorkletNode {
this.listener.notifySendBufferingTime(Date.now() - this.bufferStart);
this.bufferStart = Date.now();
} else {
console.warn(`[worklet_node][voice-changer-worklet-processor] unknown response ${event.data.responseType}`, event.data);
console.warn(
`[worklet_node][voice-changer-worklet-processor] unknown response ${event.data.responseType}`,
event.data
);
}
}
@ -281,7 +325,10 @@ export class VoiceChangerWorkletNode extends AudioWorkletNode {
const restClient = new ServerRestClient(this.setting.serverUrl);
const res = await restClient.postVoice(timestamp, newBuffer.buffer);
if (res.byteLength < 128 * 2) {
this.listener.notifyException(VOICE_CHANGER_CLIENT_EXCEPTION.ERR_REST_INVALID_RESPONSE, `[REST] recevied data is too short ${res.byteLength}`);
this.listener.notifyException(
VOICE_CHANGER_CLIENT_EXCEPTION.ERR_REST_INVALID_RESPONSE,
`[REST] recevied data is too short ${res.byteLength}`
);
} else {
if (this.outputNode != null) {
this.outputNode.postReceivedVoice(res);
@ -292,10 +339,22 @@ export class VoiceChangerWorkletNode extends AudioWorkletNode {
}
} else if (this.setting.protocol == "internal") {
if (!this.internalCallback) {
this.listener.notifyException(VOICE_CHANGER_CLIENT_EXCEPTION.ERR_INTERNAL_AUDIO_PROCESS_CALLBACK_IS_NOT_INITIALIZED, `[AudioWorkletNode] internal audio process callback is not initialized`);
this.listener.notifyException(
VOICE_CHANGER_CLIENT_EXCEPTION.ERR_INTERNAL_AUDIO_PROCESS_CALLBACK_IS_NOT_INITIALIZED,
`[AudioWorkletNode] internal audio process callback is not initialized`
);
return;
}
const res = await this.internalCallback.processAudio(newBuffer);
// const res = await this.internalCallback.processAudio(newBuffer);
// if (res.length < 128 * 2) {
// return;
// }
// if (this.outputNode != null) {
// this.outputNode.postReceivedVoice(res.buffer);
// } else {
// this.postReceivedVoice(res.buffer);
// }
this.internalCallback.processAudio(newBuffer).then((res) => {
if (res.length < 128 * 2) {
return;
}
@ -304,6 +363,7 @@ export class VoiceChangerWorkletNode extends AudioWorkletNode {
} else {
this.postReceivedVoice(res.buffer);
}
});
} else {
throw "unknown protocol";
}