File size: 1,970 Bytes
1919bbe | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | """
===============================================================================
preprocessing/normalization.py — Volume / Amplitude Normalization
===============================================================================
"""
import numpy as np
def normalize_volume(audio, method="rms", target_rms=0.1):
"""
Normalize the volume of an audio signal.
Parameters
----------
audio : np.ndarray
1D array of audio samples.
method : str, optional
Normalization method: "peak" or "rms". Default is "rms".
target_rms : float, optional
Target RMS value when method="rms". Default is 0.1.
Returns
-------
np.ndarray
Volume-normalized audio signal.
Notes
-----
- Always check for silence (all zeros) before dividing — division by zero
will produce NaN/Inf values that corrupt the entire pipeline.
- The normalized audio should be clipped to [-1.0, 1.0] to avoid clipping
artifacts when writing back to WAV (if needed for debugging).
"""
if method == "peak":
peak = np.max(np.abs(audio))
if peak < 1e-6: # Silence check to prevent division by zero
return audio
normalized = audio / peak
# --- RMS Normalization ---
# RMS will be better because it won't consider sudden pop in loudness
# as machine 3 is like 100 times louder machine 2
elif method == "rms":
rms = np.sqrt(np.mean(audio ** 2))
if rms < 1e-6: # Silence check to prevent division by zero safety if the silience was too aggressive but it shouldn't be as we will use dp 40 like we said
return audio
normalized = audio * (target_rms / rms)
else:
raise ValueError(f"Unknown normalization method: '{method}'. Please use 'peak' or 'rms'.")
# Clip to [-1.0, 1.0] to prevent audio distortion/clipping artifacts
normalized = np.clip(normalized, -1.0, 1.0)
return normalized
|