CoolFace
Apppublic

DD0101/VITS

sourceHugging Faceupdated 2y agoView on Hugging Face
1likes
data_utils.py393 linesDownload Raw Back to root
1import time2import os3import random4import numpy as np5import torch6import torch.utils.data7 8import commons 9from mel_processing import spectrogram_torch10from utils import load_wav_to_torch, load_filepaths_and_text11from text import text_to_sequence, cleaned_text_to_sequence12 13 14class TextAudioLoader(torch.utils.data.Dataset):15    """16        1) loads audio, text pairs17        2) normalizes text and converts them to sequences of integers18        3) computes spectrograms from audio files.19    """20    def __init__(self, audiopaths_and_text, hparams):21        self.audiopaths_and_text = load_filepaths_and_text(audiopaths_and_text)22        self.text_cleaners  = hparams.text_cleaners23        self.max_wav_value  = hparams.max_wav_value24        self.sampling_rate  = hparams.sampling_rate25        self.filter_length  = hparams.filter_length 26        self.hop_length     = hparams.hop_length 27        self.win_length     = hparams.win_length28        self.sampling_rate  = hparams.sampling_rate 29 30        self.cleaned_text = getattr(hparams, "cleaned_text", False)31 32        self.add_blank = hparams.add_blank33        self.min_text_len = getattr(hparams, "min_text_len", 1)34        self.max_text_len = getattr(hparams, "max_text_len", 190)35 36        random.seed(1234)37        random.shuffle(self.audiopaths_and_text)38        self._filter()39 40 41    def _filter(self):42        """43        Filter text & store spec lengths44        """45        # Store spectrogram lengths for Bucketing46        # wav_length ~= file_size / (wav_channels * Bytes per dim) = file_size / (1 * 2)47        # spec_length = wav_length // hop_length48 49        audiopaths_and_text_new = []50        lengths = []51        for audiopath, text in self.audiopaths_and_text:52            if self.min_text_len <= len(text) and len(text) <= self.max_text_len:53                audiopaths_and_text_new.append([audiopath, text])54                lengths.append(os.path.getsize(audiopath) // (2 * self.hop_length))55        self.audiopaths_and_text = audiopaths_and_text_new56        self.lengths = lengths57 58    def get_audio_text_pair(self, audiopath_and_text):59        # separate filename and text60        audiopath, text = audiopath_and_text[0], audiopath_and_text[1]61        text = self.get_text(text)62        spec, wav = self.get_audio(audiopath)63        return (text, spec, wav)64 65    def get_audio(self, filename):66        audio, sampling_rate = load_wav_to_torch(filename)67        if sampling_rate != self.sampling_rate:68            raise ValueError("{} {} SR doesn't match target {} SR".format(69                sampling_rate, self.sampling_rate))70        audio_norm = audio / self.max_wav_value71        audio_norm = audio_norm.unsqueeze(0)72        spec_filename = filename.replace(".wav", ".spec.pt")73        if os.path.exists(spec_filename):74            spec = torch.load(spec_filename)75        else:76            spec = spectrogram_torch(audio_norm, self.filter_length,77                self.sampling_rate, self.hop_length, self.win_length,78                center=False)79            spec = torch.squeeze(spec, 0)80            torch.save(spec, spec_filename)81        return spec, audio_norm82 83    def get_text(self, text):84        if self.cleaned_text:85            text_norm = cleaned_text_to_sequence(text)86        else:87            text_norm = text_to_sequence(text, self.text_cleaners)88        if self.add_blank:89            text_norm = commons.intersperse(text_norm, 0)90        text_norm = torch.LongTensor(text_norm)91        return text_norm92 93    def __getitem__(self, index):94        return self.get_audio_text_pair(self.audiopaths_and_text[index])95 96    def __len__(self):97        return len(self.audiopaths_and_text)98 99 100class TextAudioCollate():101    """ Zero-pads model inputs and targets102    """103    def __init__(self, return_ids=False):104        self.return_ids = return_ids105 106    def __call__(self, batch):107        """Collate's training batch from normalized text and aduio108        PARAMS109        ------110        batch: [text_normalized, spec_normalized, wav_normalized]111        """112        # Right zero-pad all one-hot text sequences to max input length113        _, ids_sorted_decreasing = torch.sort(114            torch.LongTensor([x[1].size(1) for x in batch]),115            dim=0, descending=True)116 117        max_text_len = max([len(x[0]) for x in batch])118        max_spec_len = max([x[1].size(1) for x in batch])119        max_wav_len = max([x[2].size(1) for x in batch])120 121        text_lengths = torch.LongTensor(len(batch))122        spec_lengths = torch.LongTensor(len(batch))123        wav_lengths = torch.LongTensor(len(batch))124 125        text_padded = torch.LongTensor(len(batch), max_text_len)126        spec_padded = torch.FloatTensor(len(batch), batch[0][1].size(0), max_spec_len)127        wav_padded = torch.FloatTensor(len(batch), 1, max_wav_len)128        text_padded.zero_()129        spec_padded.zero_()130        wav_padded.zero_()131        for i in range(len(ids_sorted_decreasing)):132            row = batch[ids_sorted_decreasing[i]]133 134            text = row[0]135            text_padded[i, :text.size(0)] = text136            text_lengths[i] = text.size(0)137 138            spec = row[1]139            spec_padded[i, :, :spec.size(1)] = spec140            spec_lengths[i] = spec.size(1)141 142            wav = row[2]143            wav_padded[i, :, :wav.size(1)] = wav144            wav_lengths[i] = wav.size(1)145 146        if self.return_ids:147            return text_padded, text_lengths, spec_padded, spec_lengths, wav_padded, wav_lengths, ids_sorted_decreasing148        return text_padded, text_lengths, spec_padded, spec_lengths, wav_padded, wav_lengths149 150 151"""Multi speaker version"""152class TextAudioSpeakerLoader(torch.utils.data.Dataset):153    """154        1) loads audio, speaker_id, text pairs155        2) normalizes text and converts them to sequences of integers156        3) computes spectrograms from audio files.157    """158    def __init__(self, audiopaths_sid_text, hparams):159        self.audiopaths_sid_text = load_filepaths_and_text(audiopaths_sid_text)160        self.text_cleaners = hparams.text_cleaners161        self.max_wav_value = hparams.max_wav_value162        self.sampling_rate = hparams.sampling_rate163        self.filter_length  = hparams.filter_length164        self.hop_length     = hparams.hop_length165        self.win_length     = hparams.win_length166        self.sampling_rate  = hparams.sampling_rate167 168        self.cleaned_text = getattr(hparams, "cleaned_text", False)169 170        self.add_blank = hparams.add_blank171        self.min_text_len = getattr(hparams, "min_text_len", 1)172        self.max_text_len = getattr(hparams, "max_text_len", 190)173 174        random.seed(1234)175        random.shuffle(self.audiopaths_sid_text)176        self._filter()177 178    def _filter(self):179        """180        Filter text & store spec lengths181        """182        # Store spectrogram lengths for Bucketing183        # wav_length ~= file_size / (wav_channels * Bytes per dim) = file_size / (1 * 2)184        # spec_length = wav_length // hop_length185 186        audiopaths_sid_text_new = []187        lengths = []188        for audiopath, sid, text in self.audiopaths_sid_text:189            if self.min_text_len <= len(text) and len(text) <= self.max_text_len:190                audiopaths_sid_text_new.append([audiopath, sid, text])191                lengths.append(os.path.getsize(audiopath) // (2 * self.hop_length))192        self.audiopaths_sid_text = audiopaths_sid_text_new193        self.lengths = lengths194 195    def get_audio_text_speaker_pair(self, audiopath_sid_text):196        # separate filename, speaker_id and text197        audiopath, sid, text = audiopath_sid_text[0], audiopath_sid_text[1], audiopath_sid_text[2]198        text = self.get_text(text)199        spec, wav = self.get_audio(audiopath)200        sid = self.get_sid(sid)201        return (text, spec, wav, sid)202 203    def get_audio(self, filename):204        audio, sampling_rate = load_wav_to_torch(filename)205        if sampling_rate != self.sampling_rate:206            raise ValueError("{} {} SR doesn't match target {} SR".format(207                sampling_rate, self.sampling_rate))208        audio_norm = audio / self.max_wav_value209        audio_norm = audio_norm.unsqueeze(0)210        spec_filename = filename.replace(".wav", ".spec.pt")211        if os.path.exists(spec_filename):212            spec = torch.load(spec_filename)213        else:214            spec = spectrogram_torch(audio_norm, self.filter_length,215                self.sampling_rate, self.hop_length, self.win_length,216                center=False)217            spec = torch.squeeze(spec, 0)218            torch.save(spec, spec_filename)219        return spec, audio_norm220 221    def get_text(self, text):222        if self.cleaned_text:223            text_norm = cleaned_text_to_sequence(text)224        else:225            text_norm = text_to_sequence(text, self.text_cleaners)226        if self.add_blank:227            text_norm = commons.intersperse(text_norm, 0)228        text_norm = torch.LongTensor(text_norm)229        return text_norm230 231    def get_sid(self, sid):232        sid = torch.LongTensor([int(sid)])233        return sid234 235    def __getitem__(self, index):236        return self.get_audio_text_speaker_pair(self.audiopaths_sid_text[index])237 238    def __len__(self):239        return len(self.audiopaths_sid_text)240 241 242class TextAudioSpeakerCollate():243    """ Zero-pads model inputs and targets244    """245    def __init__(self, return_ids=False):246        self.return_ids = return_ids247 248    def __call__(self, batch):249        """Collate's training batch from normalized text, audio and speaker identities250        PARAMS251        ------252        batch: [text_normalized, spec_normalized, wav_normalized, sid]253        """254        # Right zero-pad all one-hot text sequences to max input length255        _, ids_sorted_decreasing = torch.sort(256            torch.LongTensor([x[1].size(1) for x in batch]),257            dim=0, descending=True)258 259        max_text_len = max([len(x[0]) for x in batch])260        max_spec_len = max([x[1].size(1) for x in batch])261        max_wav_len = max([x[2].size(1) for x in batch])262 263        text_lengths = torch.LongTensor(len(batch))264        spec_lengths = torch.LongTensor(len(batch))265        wav_lengths = torch.LongTensor(len(batch))266        sid = torch.LongTensor(len(batch))267 268        text_padded = torch.LongTensor(len(batch), max_text_len)269        spec_padded = torch.FloatTensor(len(batch), batch[0][1].size(0), max_spec_len)270        wav_padded = torch.FloatTensor(len(batch), 1, max_wav_len)271        text_padded.zero_()272        spec_padded.zero_()273        wav_padded.zero_()274        for i in range(len(ids_sorted_decreasing)):275            row = batch[ids_sorted_decreasing[i]]276 277            text = row[0]278            text_padded[i, :text.size(0)] = text279            text_lengths[i] = text.size(0)280 281            spec = row[1]282            spec_padded[i, :, :spec.size(1)] = spec283            spec_lengths[i] = spec.size(1)284 285            wav = row[2]286            wav_padded[i, :, :wav.size(1)] = wav287            wav_lengths[i] = wav.size(1)288 289            sid[i] = row[3]290 291        if self.return_ids:292            return text_padded, text_lengths, spec_padded, spec_lengths, wav_padded, wav_lengths, sid, ids_sorted_decreasing293        return text_padded, text_lengths, spec_padded, spec_lengths, wav_padded, wav_lengths, sid294 295 296class DistributedBucketSampler(torch.utils.data.distributed.DistributedSampler):297    """298    Maintain similar input lengths in a batch.299    Length groups are specified by boundaries.300    Ex) boundaries = [b1, b2, b3] -> any batch is included either {x | b1 < length(x) <=b2} or {x | b2 < length(x) <= b3}.301  302    It removes samples which are not included in the boundaries.303    Ex) boundaries = [b1, b2, b3] -> any x s.t. length(x) <= b1 or length(x) > b3 are discarded.304    """305    def __init__(self, dataset, batch_size, boundaries, num_replicas=None, rank=None, shuffle=True):306        super().__init__(dataset, num_replicas=num_replicas, rank=rank, shuffle=shuffle)307        self.lengths = dataset.lengths308        self.batch_size = batch_size309        self.boundaries = boundaries310  311        self.buckets, self.num_samples_per_bucket = self._create_buckets()312        self.total_size = sum(self.num_samples_per_bucket)313        self.num_samples = self.total_size // self.num_replicas314  315    def _create_buckets(self):316        buckets = [[] for _ in range(len(self.boundaries) - 1)]317        for i in range(len(self.lengths)):318            length = self.lengths[i]319            idx_bucket = self._bisect(length)320            if idx_bucket != -1:321                buckets[idx_bucket].append(i)322  323        for i in range(len(buckets) - 1, 0, -1):324            if len(buckets[i]) == 0:325                buckets.pop(i)326                self.boundaries.pop(i+1)327  328        num_samples_per_bucket = []329        for i in range(len(buckets)):330            len_bucket = len(buckets[i])331            total_batch_size = self.num_replicas * self.batch_size332            rem = (total_batch_size - (len_bucket % total_batch_size)) % total_batch_size333            num_samples_per_bucket.append(len_bucket + rem)334        return buckets, num_samples_per_bucket335  336    def __iter__(self):337      # deterministically shuffle based on epoch338      g = torch.Generator()339      g.manual_seed(self.epoch)340  341      indices = []342      if self.shuffle:343          for bucket in self.buckets:344              indices.append(torch.randperm(len(bucket), generator=g).tolist())345      else:346          for bucket in self.buckets:347              indices.append(list(range(len(bucket))))348  349      batches = []350      for i in range(len(self.buckets)):351          bucket = self.buckets[i]352          len_bucket = len(bucket)353          ids_bucket = indices[i]354          num_samples_bucket = self.num_samples_per_bucket[i]355  356          # add extra samples to make it evenly divisible357          rem = num_samples_bucket - len_bucket358          ids_bucket = ids_bucket + ids_bucket * (rem // len_bucket) + ids_bucket[:(rem % len_bucket)]359  360          # subsample361          ids_bucket = ids_bucket[self.rank::self.num_replicas]362  363          # batching364          for j in range(len(ids_bucket) // self.batch_size):365              batch = [bucket[idx] for idx in ids_bucket[j*self.batch_size:(j+1)*self.batch_size]]366              batches.append(batch)367  368      if self.shuffle:369          batch_ids = torch.randperm(len(batches), generator=g).tolist()370          batches = [batches[i] for i in batch_ids]371      self.batches = batches372  373      assert len(self.batches) * self.batch_size == self.num_samples374      return iter(self.batches)375  376    def _bisect(self, x, lo=0, hi=None):377      if hi is None:378          hi = len(self.boundaries) - 1379  380      if hi > lo:381          mid = (hi + lo) // 2382          if self.boundaries[mid] < x and x <= self.boundaries[mid+1]:383              return mid384          elif x <= self.boundaries[mid]:385              return self._bisect(x, lo, mid)386          else:387              return self._bisect(x, mid + 1, hi)388      else:389          return -1390 391    def __len__(self):392        return self.num_samples // self.batch_size393