This project demonstrates how to reduce background noise from an audio recording using frequency-domain filtering techniques based on Fast Fourier Transform (FFT) in MATLAB.
In real-world environments, audio recordings are often contaminated by background noise, such as wind, crowd chatter, or natural ambient sounds. This project implements a simple but effective method for denoising such audio using MATLAB and frequency analysis via FFT.
The goals of the project are:
- Record a voice sample that contains background noise.
- Apply FFT-based filtering to reduce noise and improve clarity.
- Compare the signal before and after filtering both visually and analytically.
- MATLAB (R2020b or newer recommended)
-
Launch MATLAB and open the project script.
-
Adjust the values of the alpha and beta parameters in the code
alpha = 100; % Oversubtraction factor beta = 0.0000001; % Noise floor
-
Run the main script:
denoising.m
make sure there is an audio input named
record.wav
placed in the working directory -
The script will generate:
- Cleaned audio file:
record_filtered.wav
- Time-domain and frequency-domain plots of original vs filtered signals
- SNR improvement log
- Cleaned audio file:
The workspace and figures are cleared to avoid conflicts:
clear all;
close all;
clc;
The audio is read using audioread
, and stereo audio is converted to mono if needed:
[audioIn, Fs] = audioread('record.wav');
if size(audioIn, 2) > 1
audioIn = mean(audioIn, 2); % Convert stereo to mono
end
Several parameters are defined for efficient FFT processing:
- Frame length:
2048
samples (a power of 2) - Hop size:
frameLength / 4
→ 75% overlap - Window function: Hanning window to reduce spectral leakage
frameLength = 2048;
hopSize = frameLength / 4;
window = hann(frameLength, 'periodic');
Noise is estimated from the first 5 frames of audio under the assumption that they contain only noise:
Noise Profile Calculation:
noiseProfile = mean(abs(fft(noiseFrames .* window)));
The core parameters used for spectral subtraction:
- Oversubtraction factor
α = 100
- Noise floor
β = 1e-7
- Minimum gain
G_min = 0.05
Each frame undergoes the following steps:
Convert frame to frequency domain:
frameFFT = fft(frame);
mag = abs(frameFFT);
phase = angle(frameFFT);
Subtract estimated noise from magnitude spectrum:
magEnhanced = max(mag - α * noiseProfile, β * mag);
With limiting:
gainMask = max(magEnhanced ./ max(mag, eps), G_min);
Smooth the gain mask using moving average:
smoothFilter = ones(5,1)/5;
gainMask = filter(smoothFilter, 1, gainMask);
The second half of the spectrum mirrors the first (due to real-valued signals):
gainMask(half+1:end) = flipud(gainMask(2:end-1));
Apply gain to the original spectrum and perform inverse FFT:
enhancedFFT = gainMask .* frameFFT;
enhancedFrame = real(ifft(enhancedFFT));
audioOut(startIdx:startIdx+frameLength-1) += enhancedFrame .* window;
After all frames are processed, normalization compensates for overlapping windows:
audioOut(validIdx) = audioOut(validIdx) ./ normalizeCoeff(validIdx);
Final RMS normalization:
audioOut = audioOut * (rms(audioIn) / max(eps, rms(audioOut)));
Compare raw and denoised signals to observe amplitude smoothing:
Observe reduction in high-frequency noise:
The improvement is evaluated using:
SNR formula:
Where:
P_signal = mean(audioIn.^2)
P_noise = mean((audioIn - audioOut).^2)
Results:
- Original SNR ≈ ~low
- Enhanced SNR ≈ ~higher
- Improvement logged in the console