vipan-kumar's picture
Initial commit: Audio Deepfake Detector with 8 detectors trained on jay15k
e6a1f55
Raw
History Blame Contribute Delete
1.98 kB
"""Mel spectrogram utilities for the UI and BiCrossMamba-ST input."""
from __future__ import annotations
from typing import List
import numpy as np
import torch
import torchaudio
_MEL_TRANSFORM_CACHE: dict = {}
def _get_mel(sr: int, n_mels: int, n_fft: int, hop_length: int) -> torchaudio.transforms.MelSpectrogram:
key = (sr, n_mels, n_fft, hop_length)
if key not in _MEL_TRANSFORM_CACHE:
_MEL_TRANSFORM_CACHE[key] = torchaudio.transforms.MelSpectrogram(
sample_rate=sr,
n_fft=n_fft,
hop_length=hop_length,
n_mels=n_mels,
f_min=0.0,
f_max=sr // 2,
power=2.0,
)
return _MEL_TRANSFORM_CACHE[key]
def mel_spectrogram(
waveform: torch.Tensor,
sample_rate: int = 16000,
n_mels: int = 64,
n_fft: int = 1024,
hop_length: int = 256,
) -> torch.Tensor:
"""Compute a log-mel spectrogram. Returns shape [n_mels, T]."""
mel = _get_mel(sample_rate, n_mels, n_fft, hop_length)
spec = mel(waveform) # [1, n_mels, T]
log_spec = torch.log(spec + 1e-6)
return log_spec.squeeze(0)
def mel_for_ui(
waveform: torch.Tensor,
sample_rate: int = 16000,
n_mels: int = 64,
n_fft: int = 1024,
hop_length: int = 256,
max_time_steps: int = 256,
) -> List[List[float]]:
"""Return a normalised [0,1] list-of-lists suitable for canvas rendering."""
log_spec = mel_spectrogram(waveform, sample_rate, n_mels, n_fft, hop_length)
arr = log_spec.detach().cpu().numpy()
# Down-sample time axis if needed
T = arr.shape[1]
if T > max_time_steps:
bucket = T // max_time_steps
trimmed = arr[:, : bucket * max_time_steps]
arr = trimmed.reshape(arr.shape[0], max_time_steps, bucket).mean(axis=2)
# Per-clip min-max normalize
lo, hi = float(arr.min()), float(arr.max())
rng = max(hi - lo, 1e-6)
arr = (arr - lo) / rng
return arr.astype(np.float32).tolist()