rhotic / test_phonemes.py
IndianChess's picture
Deploy Rivet R Coach to Build Small org
b6ba91b verified
Raw
History Blame Contribute Delete
1.98 kB
import argparse
import os
import sys
import librosa
import numpy as np
import parselmouth
import torch
from transformers import AutoProcessor, AutoModelForCTC
MODEL_ID = "facebook/wav2vec2-lv-60-espeak-cv-ft"
SAMPLE_RATE = 16000
def main():
parser = argparse.ArgumentParser(description="Transcribe IPA phonemes and measure F3 from a .wav file.")
parser.add_argument("wav_path", help="Path to a .wav audio file")
args = parser.parse_args()
if not os.path.isfile(args.wav_path):
print(f"ERROR: file not found: {args.wav_path}", file=sys.stderr)
sys.exit(1)
print(f"[1/4] Loading audio from {args.wav_path} at {SAMPLE_RATE} Hz...")
audio, sr = librosa.load(args.wav_path, sr=SAMPLE_RATE)
duration = len(audio) / sr
print(f" Loaded {len(audio)} samples ({duration:.2f}s)")
print(f"[2/4] Loading model {MODEL_ID}...")
processor = AutoProcessor.from_pretrained(MODEL_ID)
model = AutoModelForCTC.from_pretrained(MODEL_ID)
model.eval()
print(" Model loaded.")
print("[3/4] Running phoneme recognition...")
inputs = processor(audio, sampling_rate=SAMPLE_RATE, return_tensors="pt")
with torch.no_grad():
logits = model(inputs.input_values).logits
predicted_ids = torch.argmax(logits, dim=-1)
transcription = processor.batch_decode(predicted_ids)[0]
print(f" Phonemes: {transcription}")
print("[4/4] Computing F3 formant with parselmouth...")
sound = parselmouth.Sound(args.wav_path)
formants = sound.to_formant_burg()
times = np.linspace(0, sound.duration, num=100)
f3_values = [formants.get_value_at_time(3, t) for t in times]
f3_values = [v for v in f3_values if v is not None and not np.isnan(v)]
if f3_values:
f3_mean = float(np.mean(f3_values))
print(f" Mean F3: {f3_mean:.1f} Hz (from {len(f3_values)} frames)")
else:
print(" No F3 values detected.")
if __name__ == "__main__":
main()