const _pad = "_";
const _punctuation = ";:,.!?¡¿—…\"«»“” ";
const _letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const _letters_ipa = "ɑɐɒæɓʙβɔɕçɗɖðʤəɘɚɛɜɝɞɟʄɡɠɢʛɦɧħɥʜɨɪʝɭɬɫɮʟɱɯɰŋɳɲɴøɵɸθœɶʘɹɺɾɻʀʁɽʂʃʈʧʉʊʋⱱʌɣɤʍχʎʏʑʐʒʔʡʕʢǀǁǂǃˈˌːˑʼʴʰʱʲʷˠˤ˞↓↑→↗↘'̩'ᵻ";
// below code called Spread syntax
const Symbols = [_pad, ..._punctuation, ..._letters, ..._letters_ipa];
const SpaceId = Symbols.indexOf(' ');
const symbolToId = {};
const idToSymbol = {};
// initialize symbolToId and idToSymbol
for (let i = 0; i < Symbols.length; i++) {
symbolToId[Symbols[i]] = i;
idToSymbol[i] = Symbols[i];
}
class MatchaTTSRaw {
constructor() {
this.processing = false
}
async load_model(model_path,options={}){
this.session = await ort.InferenceSession.create(model_path,options);
console.log(this.session)
const inputNames = this.session.inputNames;
this.need_spks = inputNames.includes("spks")
console.log(`this model need spks = ${this.need_spks}`);
return this.session
}
get_output_names_html(){
if (typeof this.session=='undefined'){
return null
}
let outputNamesString = '[outputNames]
';
const outputNames = this.session.outputNames;
for (let outputName of outputNames) {
console.log(outputName)
outputNamesString+=outputName+"
"
}
return outputNamesString.trim()
}
get_input_names_html(){
if (typeof this.session=='undefined'){
return null
}
let inputNamesString = '[inputNames]
';
const inputNames = this.session.inputNames;
for (let inputName of inputNames) {
console.log(inputName)
inputNamesString+=inputName+"
"
}
return inputNamesString.trim()
}
processText(text) {
const x = this.intersperse(this.textToSequence(text));
const x_phones = this.sequenceToText(x);
const textList = [];
for (let i = 1; i < x_phones.length; i += 2) {
textList.push(x_phones[i]);
}
return {
x: x,
x_length: x.length,
x_phones: x_phones,
x_phones_label: textList.join(""),
};
}
basicCleaners2(text, lowercase = false) {
if (lowercase) {
text = text.toLowerCase();
}
text = text.replace(/\s+/g, " ");
return text;
}
textToSequence(text) {
const sequenceList = [];
const clean_text = this.basicCleaners2(text);
for (let i = 0; i < clean_text.length; i++) {
const symbol = clean_text[i];
sequenceList.push(symbolToId[symbol]);
}
return sequenceList;
}
intersperse(sequence, item = 0) {
const sequenceList = [item];
for (let i = 0; i < sequence.length; i++) {
sequenceList.push(sequence[i]);
sequenceList.push(item);
}
return sequenceList;
}
sequenceToText(sequence) {
const textList = [];
for (let i = 0; i < sequence.length; i++) {
const symbol = idToSymbol[sequence[i]];
textList.push(symbol);
}
return textList.join("");
}
async infer(text, temperature, speed,spks=0) {
if(this.processing){
console.error("already processing")
return null
}
try{
console.log("set processing True")
this.processing = true; // try ブロック内で設定
const dic = this.processText(text);
console.log(`x:${dic.x.join(", ")}`);
console.log(`x_length:${dic.x_length}`);
console.log(`x_phones_label:${dic.x_phones_label}`);
console.log(`temperature=${temperature} speed = ${speed} spks=${spks}`);
const dataX = new BigInt64Array(dic.x.length)
for (let i = 0; i < dic.x.length; i++) {
//console.log(dic.x[i])
dataX[i] = BigInt(dic.x[i]); // Convert each number to a BigInt
}
const data_x_length = new BigInt64Array(1)
data_x_length[0] = BigInt(dic.x_length)
//const dataX = Int32Array.from([dic.x_length])
const tensorX = new ort.Tensor('int64', dataX, [1, dic.x.length]);
// const data_x_length = Int32Array.from([dic.x_length])
const tensor_x_length = new ort.Tensor('int64', data_x_length, [1]);
const data_scale = Float32Array.from( [temperature, speed])
const tensor_scale = new ort.Tensor('float32', data_scale, [2]);
const send_data = {
x: tensorX,
x_lengths: tensor_x_length,
scales: tensor_scale,
}
//for vctk need speaker id
if (this.need_spks){
const data_spks = new BigInt64Array(1)
data_spks[0] = BigInt(spks)
const tensor_spks = new ort.Tensor('int64', data_spks, [1]);
send_data.spks = tensor_spks
}
// Run inference
const output = await this.session.run(send_data);
//If your onnx not connect hifigun difference output return (not tested)
const wav_array = output.wav.data;
const x_lengths_array = output.wav_lengths.data;
return wav_array;
}catch (exception){
console.error("Inference error:", exception);
return null
}finally{
console.log("set processing False")
this.processing = false;
}
}
}
export { MatchaTTSRaw };