nanoTTS / stable_codec /data /Text2Phone /phone_tokenizer.py
3v324v23's picture
add files
9807699
Raw
History Blame Contribute Delete
1.99 kB
import torch
import logging
from valle.tools.tokenizer.abs_tokenizer import AbsTokenizer
default_phone_dict = "tools/tokenizer/Text2Phone/alignment_dict"
class PhoneTokenizer(AbsTokenizer):
"""
This is the virtual tokenizer class.
Other tokenizers should inherit this class.
typicially:
Text -> BPE
Text -> Phone
Audio -> Codec
Image -> Codec
...
"""
def __init__(self, phone_table=default_phone_dict, duplicate=False, unk_ph=None):
super(PhoneTokenizer, self).__init__()
phone_dict = open(phone_table, encoding="utf-8").readlines()
phone_dict = [line.strip().split() for line in phone_dict]
phone_dict = {line[0]: None for line in phone_dict}
keys = list(phone_dict.keys())
for i, k in enumerate(keys):
phone_dict[k] = i
self.phone_dict = phone_dict
if unk_ph is None:
self.unk_ph = "<UNK>"
logging.info("No unknown phone provided. Set it as <UNK>.")
else:
self.unk_ph = unk_ph
if unk_ph not in self.phone_dict:
logging.info(f"Set unknown phone with number: {len(self.phone_dict)}")
self.phone_dict[unk_ph] = len(self.phone_dict)
self.unk_id = phone_dict[unk_ph]
self.duplicate = duplicate
@property
def is_discrete(self):
return True
@property
def codebook_length(self):
return len(self.phone_dict)
def find_length(self, x):
return len(self.tokenize(x))
def tokenize(self, x, task=None, cache=None):
if isinstance(x, torch.Tensor):
assert x.dim() == 1
x = torch.unique_consequtive(x) if not self.duplicate else x
return x.to(torch.int16)
elif isinstance(x, str):
x = [self.phone_dict.get(ph, self.unk_id) for ph in x.strip().split()]
return torch.Tensor(x).to(torch.int16)
else:
raise NotImplementedError