UNPKG

@minto-ai/xunfei-tts

Version:

借助“讯飞在线语音合成API”实现浏览器端“文本转语音

65 lines (56 loc) 2.32 kB
import type { TranscodeWorkerReplyWorkerMessage, TranscodeWorkerSendWorkerData, TranscodeWorkerSendWorkerMessage } from './index' function base64ToS16(base64AudioData: string): Int16Array { base64AudioData = atob(base64AudioData) const outputArray = new Uint8Array(base64AudioData.length) for (let i = 0; i < base64AudioData.length; i += 1) { outputArray[i] = base64AudioData.charCodeAt(i) } return new Int16Array(new DataView(outputArray.buffer).buffer) } function transS16ToF32(input: Int16Array): Float32Array { const tmpData = [] for (let i = 0; i < input.length; i += 1) { const d = input[i] < 0 ? input[i] / 0x8000 : input[i] / 0x7FFF tmpData.push(d) } return new Float32Array(tmpData) } function transSamplingRate(data: Float32Array, fromRate: number = 44100, toRate: number = 16000): Float32Array { const fitCount = Math.round(data.length * (toRate / fromRate)) const newData = new Float32Array(fitCount) const springFactor = (data.length - 1) / (fitCount - 1) newData[0] = data[0] for (let i = 1; i < fitCount - 1; i += 1) { const tmp = i * springFactor const before = Math.floor(tmp).toFixed() as unknown as number const after = Math.ceil(tmp).toFixed() as unknown as number const atPoint = tmp - Number(before) newData[i] = data[before] + (data[after] - data[before]) * atPoint } newData[fitCount - 1] = data[data.length - 1] return newData } function transToAudioData(data: TranscodeWorkerSendWorkerData, fromRate: number = 16000, toRate: number = 22505): void { const audioDataStr = data.original as string const outputS16 = base64ToS16(audioDataStr) let output: any = transS16ToF32(outputS16) output = transSamplingRate(output, fromRate, toRate) output = Array.from(output) globalThis.postMessage({ type: 'success', data: { audioData: output, rawAudioData: Array.from(outputS16), uuid: data.uuid, }, } as TranscodeWorkerReplyWorkerMessage) } function handleRun(data: TranscodeWorkerSendWorkerData): void { transToAudioData(data) } globalThis.addEventListener('message', (event: MessageEvent<TranscodeWorkerSendWorkerMessage>) => { const { type, data } = event.data if (type === 'send') { handleRun(data!) } })