Download backend/app/features/spectrogram.py from vipan-kumar/Audio_Deepfake_Detection: direct link, hf CLI and curl.
- Browser
- Download file 1.98 kB
-
https://huggingface.co/spaces/vipan-kumar/Audio_Deepfake_Detection/resolve/main/backend/app/features/spectrogram.py
- Command line
-
hf download hf://spaces/vipan-kumar/Audio_Deepfake_Detection/backend/app/features/spectrogram.py
-
curl -L -o spectrogram.py https://huggingface.co/spaces/vipan-kumar/Audio_Deepfake_Detection/resolve/main/backend/app/features/spectrogram.py
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() | |