| """ |
| =============================================================================== |
| 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: |
| return audio |
| normalized = audio / peak |
|
|
| |
| |
| |
| elif method == "rms": |
| rms = np.sqrt(np.mean(audio ** 2)) |
| if rms < 1e-6: |
| return audio |
| normalized = audio * (target_rms / rms) |
| |
| else: |
| raise ValueError(f"Unknown normalization method: '{method}'. Please use 'peak' or 'rms'.") |
|
|
| |
| normalized = np.clip(normalized, -1.0, 1.0) |
|
|
| return normalized |
|
|