import os import glob import random import torch import numpy as np from torch.utils import data from suno_utils.audio import Audio from torchaudio_augmentations import ( RandomApply, Noise, Gain, PitchShift, Compose, ) class SelfSimDataset(data.Dataset): def __init__( self, metadata, task_indices, split="train", input_length_s=30.0, sample_rate=24000, num_samples=-1, ): assert split in ["train", "valid"] self.metadata = metadata self.indices = task_indices["self_sim"][split] self.input_length_s = input_length_s self.sample_rate = sample_rate self.num_samples = num_samples self.split = split # get augmentation if split == "train": self._get_augmentations() print(f"{len(self.indices)} files are available for self_sim {split} set") def _get_augmentations(self): # Stochastic data augmentation transforms = [ RandomApply([Noise(min_snr=0.1, max_snr=0.5)], p=0.3), RandomApply([Gain()], p=0.2), RandomApply( [ PitchShift( n_samples=int(self.input_length_s * self.sample_rate), sample_rate=self.sample_rate, pitch_shift_min=-3.0, pitch_shift_max=3.0, ) ], p=0.4, ), ] self.augmentation = Compose(transforms=transforms) def __getitem__(self, index): # read data if self.split == "train": audio_path = self.metadata[random.choice(self.indices)]["filepath"] elif self.split == "valid": audio_path = self.metadata[self.indices[index]]["filepath"] audio = Audio.from_file(audio_path, sample_rate=self.sample_rate) if self.split == "train": # random crop try: start_ms_1 = random.randint( 0, (audio.duration_ms - int(1000 * self.input_length_s) - 1) ) start_ms_2 = random.randint( 0, (audio.duration_ms - int(1000 * self.input_length_s) - 1) ) start_s_1 = start_ms_1 / 1000 start_s_2 = start_ms_2 / 1000 except ValueError: start_s_1 = 0.0 start_s_2 = 0.0 wav_1 = audio.get_segment( from_s=start_s_1, to_s=start_s_1 + self.input_length_s ).array_float wav_2 = audio.get_segment( from_s=start_s_2, to_s=start_s_2 + self.input_length_s ).array_float # augmentation wav_1 = ( self.augmentation(torch.from_numpy(wav_1).unsqueeze(0)) .squeeze(0) .numpy() ) wav_2 = ( self.augmentation(torch.from_numpy(wav_2).unsqueeze(0)) .squeeze(0) .numpy() ) elif self.split == "valid": # crop first and last 30s start_s_1 = 0.0 start_s_2 = max(audio.duration_s - self.input_length_s, 0.0) wav_1 = audio.get_segment( from_s=start_s_1, to_s=start_s_1 + self.input_length_s ).array_float wav_2 = audio.get_segment( from_s=start_s_2, to_s=start_s_2 + self.input_length_s ).array_float # zero padding if len(wav_1) < int(self.sample_rate * self.input_length_s): pad = int(self.sample_rate * self.input_length_s) - len(wav_1) wav_1 = np.pad(wav_1, (0, pad), mode="constant", constant_values=0) if len(wav_2) < int(self.sample_rate * self.input_length_s): pad = int(self.sample_rate * self.input_length_s) - len(wav_2) wav_2 = np.pad(wav_2, (0, pad), mode="constant", constant_values=0) return wav_1, wav_2 def __len__(self): if self.num_samples > 0: return self.num_samples else: return len(self.indices)