| 7 | |
| 8 | |
| 9 | def load_audio(wav_path, rate: int = None, offset: float = 0, duration: float = None): |
| 10 | with sf.SoundFile(wav_path) as f: |
| 11 | start_frame = int(offset * f.samplerate) |
| 12 | if duration is None: |
| 13 | frames_to_read = f.frames - start_frame |
| 14 | else: |
| 15 | frames_to_read = int(duration * f.samplerate) |
| 16 | f.seek(start_frame) |
| 17 | audio_data = f.read(frames_to_read, dtype="float32") |
| 18 | audio_tensor = torch.from_numpy(audio_data) |
| 19 | if rate is not None and f.samplerate != rate: |
| 20 | if audio_tensor.ndim == 1: |
| 21 | audio_tensor = audio_tensor.unsqueeze(0) |
| 22 | else: |
| 23 | audio_tensor = audio_tensor.T |
| 24 | resampler = torchaudio.transforms.Resample(orig_freq=f.samplerate, new_freq=rate) |
| 25 | audio_tensor = resampler(audio_tensor) |
| 26 | if audio_tensor.shape[0] == 1: |
| 27 | audio_tensor = audio_tensor.squeeze(0) |
| 28 | return audio_tensor, rate if rate is not None else f.samplerate |
| 29 | |
| 30 | |
| 31 | def forced_align(log_probs: torch.Tensor, targets: torch.Tensor, blank: int = 0): |