Cheat sheets

Audio Features, Classification and Metrics

Sample, frame, window, mel, MFCC, classify and score audio. Stdlib Python from the lessons.

  • Concepts and terms
  • Tasks and commands
  • Annotated code
  • Diagrams
  • Defaults and numbers
  • Troubleshooting
  • Questions and tips

Source

Waveform to label#

magnitudelogDCTcosineclientWaveformfloats in [-1, 1]processFrames400 samples, hop160processSTFTHann window, FFTprocessMel filterbank80 trianglesstoreLog-melWhisper inputprocessMFCCDCT-II, keep 13processPoolmean + var, 26dimsmodelClassifierk-NN, CNN, AST,BEATsmagnitudelogDCTcosineclientWaveformfloats in [-1, 1]processFrames400 samples, hop 160processSTFTHann window, FFTprocessMel filterbank80 trianglesstoreLog-melWhisper inputprocessMFCCDCT-II, keep 13processPoolmean + var, 26 dimsmodelClassifierk-NN, CNN, AST, BEATs

From Lesson 06.02, Lesson 06.03, 06.03 code/main.py

Formulas#

Time
t = n / sr. A 10 s clip at 16 kHz is 160,000 floats.
Nyquist
sr / 2. Energy above it aliases to lower bins.
Alias
a 7 kHz tone sampled at 10 kHz folds to 10 - 7 = 3 kHz.
Bin
bin k is k \cdot sr / N Hz. Resolution is sr / N.
Mel
m = 2595 \cdot \log_{10}(1 + f / 700)
Hann
w(n) = 0.5 (1 - \cos(2 \pi n / (N - 1)))
Frames
1 + (T - L) / hop. 10 s at 16 kHz gives 998 frames.
Mixup
x = \lambda x_1 + (1 - \lambda) x_2, same for y.

From Lesson 06.01, Lesson 06.02, Lesson 06.03

Feature defaults#

SettingDefaultNote
Frame length40025 ms at 16 kHz
Hop16010 ms at 16 kHz
WindowHannTapers frame edges to zero
Mel bins, ASR80Cover 0 to 8 kHz
Mel bins, classification128AST, PANNs, BEATs
MFCC count13Drop coefficient 0, it is energy
Log floor eps1e-10log(mel_spec + 1e-10)
Keyword spotting40 MFCCsFor tiny devices

From Lesson 06.02, Lesson 06.01

Tasks in code#

TaskCode
Synthesize a tonesine(freq_hz, sr, seconds, amp=0.5)
Find the dominant frequencypeak_freq(samples, sr)
Frame a signalframe_signal(signal, frame_len, hop)
STFT magnitudestft_magnitude(signal, frame_len, hop)
Mel filterbankmel_filterbank(n_mels, n_fft, sr)
Log-mellog_transform(mel_spec, eps=1e-10)
MFCCdct_ii(x, n_coeffs)
k-NN voteknn(q, bank, labels, k=3)

From 06.01 code/main.py, 06.02 code/main.py, 06.03 code/main.py

MFCC k-NN baseline#

sr = 8000demo rate in the code
mag = stft_mag(signal, frame_len, hop)Hann, then DFT per frame
fb = mel_filterbank(n_mels, frame_len, sr)n_mels x (n_fft // 2 + 1)
mels = apply_filterbank(mag, fb)weighted sum per mel bin
lm = log_transform(mels)log(max(v, eps))
feats = [dct_ii(f, n_mfcc) for f in lm]13 coefficients per frame
emb = summarize(feats)mean + var, 26 dims
pred = knn(emb, X_train, y_train, k=3)cosine top k, majority vote

From 06.03 code/main.py

Score a model#

from jiwer import wer, Compose, ToLowerCase, RemovePunctuation, Strip
transform = Compose([ToLowerCase(), RemovePunctuation(), Strip()])
score = wer(truth="Please turn on the lights.", hypothesis="please turn on the light",
truth_transform=transform, hypothesis_transform=transform)
sv = EncoderClassifier.from_hparams("speechbrain/spkrec-ecapa-voxceleb")
secs = torch.nn.functional.cosine_similarity(emb_ref, emb_clone, dim=-1).item()SECS
fad = FrechetAudioDistance()
score = fad.get_fad_score("generated_folder/", "reference_folder/")lower is better

From Lesson 06.17

Libraries#

CommandWhat it does
soundfileReads WAV, FLAC, OGG as float32
torchaudio.transforms.ResampleResamples with anti-aliasing built in
numpy.fft.rfftReal FFT for real audio
torch.stftVectorized STFT
librosa.power_to_dbReference-normalized dB
ffprobeReports sr, channels and codec of a file
jiwerWER and CER with normalization
ASTForAudioClassification.from_pretrainedLoads AST to fine-tune

From Lesson 06.01, Lesson 06.02, Lesson 06.03, Lesson 06.17

Pick a classifier#

Under 1000 clips
k-NN on MFCC means plus audio augmentation.
1K to 100K clips
BEATs or AST fine-tune.
Over 100K clips
train from scratch or fine-tune Whisper-encoder.
Real-time, edge
40-MFCC CNN, quantized to int8.
Multi-label
BEATs-iter3 with BCE loss, mixup and SpecAugment.
Exclusive classes
report top-1 and top-5 accuracy.
Imbalanced classes
report per-class recall and macro F1.

From Lesson 06.03

Metrics#

WER
Word Error Rate. (S + D + I) / N after normalization.
CER
Character Error Rate. For tone languages.
RTFx
audio seconds per wall-clock second. Higher is better.
MOS
Mean Opinion Score. 1 to 5, 20+ listeners, 100+ samples.
UTMOS
learned MOS predictor. Correlates ~0.9 with human MOS.
SECS
ECAPA cosine of reference and clone. Above 0.75 is recognizable.
EER
threshold where FAR equals FRR. ECAPA on VoxCeleb1-O: 0.87%.
DER
(FA + Miss + Confusion) / total speaker time.
FAD
Fréchet distance on VGGish embeddings. Lower is better.

From Lesson 06.17

Troubleshooting#

SymptomCauseFix
Garbage that looks like a model bug44.1 kHz stereo into WhisperResample to 16 kHz mono float32
FFT peak at a false frequencyEnergy above Nyquist aliasedLow-pass filter before downsampling
Silent failure after deploy80 mels in training, 128 at inferenceLog the feature shape at both ends
Mels look differentFeaturized at 22.05 kHzFix SR before featurization
Whisper input looks wrongdB-mel, not log-melFeed log-mel. Custom code does not autodetect
WER doubles in productionPer-utterance norm in training, global at inferenceUse the same normalization
Flat trailing framesZero-padding at the clip endPad symmetrically or replicate
5% WER hides 30% on accentsAggregate WERReport by demographic slice

From Lesson 06.01, Lesson 06.02, Lesson 06.17

Questions#

Why mel, not Hz?
Humans hear pitch on a log scale.
Why a window?
It removes spectral leakage at the frame edges.
Why log-magnitude?
Raw magnitudes span 5-6 orders of magnitude.
Bigger FFT?
Better frequency resolution. Worse time resolution.
Why FFT, not DFT?
The DFT is O(N²). The FFT is O(N log N).
Why minDCF?
It weights cost at a chosen operating point.

From Lesson 06.02, Lesson 06.01, Lesson 06.17

Tips#

  • Match sample rate before you match anything else.
  • If you are not working on music, start with 80 log-mels.
  • Start with a frozen backbone, not a fresh model.
  • Use balanced sampling in training, not in evaluation.
  • Normalize text before you score WER. Report the rule.
  • Report P50/P95/P99 for latency.
  • Keep an in-house held-out set. Public benchmarks saturate.

From Lesson 06.01, Lesson 06.02, Lesson 06.03, Lesson 06.17