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 = "" logging.info("No unknown phone provided. Set it as .") 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