| 53 | |
| 54 | |
| 55 | def encode_reference_audio(reference_audio_path, temp_dir, checkpoint_path, device="cuda"): |
| 56 | logger.info("Encoding reference audio...") |
| 57 | |
| 58 | # Normalize waveform |
| 59 | waveform, sample_rate = torchaudio.load(reference_audio_path) |
| 60 | waveform = waveform.to(device) |
| 61 | |
| 62 | if waveform.abs().max() > 1.0: |
| 63 | waveform = waveform / waveform.abs().max() |
| 64 | |
| 65 | audio_int16 = (waveform * 32767).to(torch.int16).cpu().numpy() |
| 66 | normalized_path = os.path.join(temp_dir, "normalized_ref.wav") |
| 67 | sf.write(normalized_path, audio_int16.T, sample_rate) |
| 68 | logger.debug(f"Normalized audio saved at: {normalized_path}") |
| 69 | |
| 70 | # Ensure output base path has NO extension, but .npy will be added by inference.py |
| 71 | reference_tokens_base = os.path.join(temp_dir, "reference_tokens") |
| 72 | reference_tokens_path = reference_tokens_base + ".npy" |
| 73 | |
| 74 | # Run VQGAN inference to encode audio into tokens |
| 75 | sys.argv = [ |
| 76 | "inference.py", |
| 77 | "--input-path", normalized_path, |
| 78 | "--output-path", reference_tokens_base + ".wav", # Add .wav to satisfy soundfile |
| 79 | "--checkpoint-path", checkpoint_path, |
| 80 | "--device", device |
| 81 | ] |
| 82 | |
| 83 | try: |
| 84 | vqgan_inference.main() |
| 85 | except SystemExit: |
| 86 | logger.debug("vqgan_inference.main() exited with SystemExit (normal for CLI entrypoints).") |
| 87 | |
| 88 | # Ensure .npy was created |
| 89 | if not os.path.exists(reference_tokens_path): |
| 90 | raise RuntimeError(f"Reference tokens were not generated at: {reference_tokens_path}") |
| 91 | |
| 92 | logger.debug(f"Reference tokens saved at: {reference_tokens_path}") |
| 93 | return reference_tokens_path |
| 94 | |
| 95 | |
| 96 | def generate_semantic_tokens( |