Noise removal from audio signal - matlab

guys below are my code. I want to remove noise from audio signal which I added up by myself using random function.The following code removes somehow noise but it is still too noisy that I can't hear the sound. I also want to add the audio file for this code but i didn't find any option while posting my question so you can add any two channel .wav sound file . Any comment or hint will be helpful thanks.
close all
clear
clc
[x,fs] = audioread('cello.wav');
whos x;
pOrig = audioplayer(x,fs); %Signal Play
pOrig.play;
N = size(x,1);
figure;
subplot(2,1,1);
stem(1:N, x(:,1));
title('Left Channel of Origional signal');
subplot(2,1,2);
stem(1:N, x(:,2));
title('Right Channel of origional signal');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
df = fs/N;
w = (-(N/2):(N/2)-1)*df;
y1= fft(x(:,1),N)/N;
y2 = fftshift(y1);
figure;
plot(w,abs(y2));
title('Fast Fourier Transform of Origional Signal')
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
pause
y=x;
y = y + randn(size(y));
pOrig = audioplayer(y,fs);
pOrig.play;
figure;
subplot(2,1,1);
stem(1:N, y(:,1));
title('Left Channel with Noise');
subplot(2,1,2);
stem(1:N, y(:,2));
title('Right Channel with Noise');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
df = fs/N;
w = (-(N/2):(N/2)-1)*df;
y1= fft(y(:,1),N)/N;
y2 = fftshift(y1);
figure;
plot(w,abs(y2));
title('Fast Fourier Transform of Noisy Signal')
pause
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% filter design
n = 10;
beginFreq = 100 / (fs/2);
endFreq = 2000 / (fs/2);
%[b,a] = butter(n, endFreq, 'low');
%fout = filter(b,a,y); % input y(noisy signal)
[b,a] = butter(n, endFreq, 'low');
fout = filter(b,a,y); % input y(noisy signal)
figure;
subplot(2,1,1);
stem(1:N, fout(:,1));
title('Left channel after filtering');
subplot(2,1,2);
stem(1:N, fout(:,2));
title(' Right channel after filtering');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%plot(fout);
df = fs/N;
w = (-(N/2):(N/2)-1)*df;
y1= fft(fout(:,1),N)/N;
y2 = fftshift(y1);
figure;
plot(w,abs(y2));
title('Fast Fourier Transform after filtering');
pOrig = audioplayer(fout,fs);
pOrig.play;

You are adding noise using randn() function, which generatares Gaussian noise, i.e. white noise. The white noise has constant power over the spectrum, that means you are adding noise from 0 to 20kHz (only considering the audio spectrum).
Your filter is a bandpass filter between 0.1-2 kHz, so according to what I pointed out above, you still have noise components in these frequency bands. Theoritecally, it is impossible to filter all of the noise components, however you may want to check out Wiener filters to get better results. Actually, it is the optimal filter if you know about the Gaussian noise parameters, which is only the variance of the noise in your case.
If you want to see an example that removes all the noise, you can add out-of-band noise on to your original signal. That is possible by generating a random sequence by rand() and using a filter to make it bandlimited. For example, filter the generated noise sequence with a 3-10kHz bandpass filter then add to the original audio sequence. Finally, apply the same butter filter in your script to see all the noise is removed.

Related

Applying bandpass in the Fourier for my signal in matlab

I'm trying to apply a bandpass around freq 0 without luck. I'd be happy to receive some help please
x=scan11(1,:)*1e-3/3e8; y=scan11(2,:);
plot(x,y) % my function
[XX,ff]=trans_fourier(y,mean(diff(x)));
plot(ff,abs(XX)) % gives the Fourier transform
I want to choose the freq around 0. let's suppose -1e13 till 1e13 and than to make ifft and to plot the signal after this filer.
How should I start doing this? the command
YY=bandpass(y,[-1e13 1e13],1/mean(diff(x)))
didn't help here unfortunately.
Since, i can't upload here files, here is also my question on matlab forum with all the files
matlab link
I am not sure what the contents of the trans_fourier function exactly are, but in 'plain matlab functions', you could attempt something along the lines of the following.
Nt = 1024; % Number of samples
Fs = 10; % Sampling frequency (samples / second)
t = (0:Nt-1)/Fs; % Time array
x = sin(t/10); % Low-frequency signal
x = x + 0.25*randn(1,Nt); % add some noise
X = fftshift(fft(x)); % FFT of signal with 0 Hz centered
fr = (-Nt/2 : Nt/2-1)/(Nt/Fs); % Frequency axis
% Filter: squared cosine (edit as desired)
fsl = 10; % Length of filter slope, in samples
filt = zeros(size(X));
filt(Nt/2+1+(-fsl:fsl)) = cos( linspace(-pi/2,pi/2,2*fsl+1) ).^2;
x_filt = real(ifft(ifftshift( filt.*X ))); % Filtered x
figure();
subplot(2,2,1); plot(t,x); ax=axis; title('original signal');
subplot(2,2,4); plot(t,x_filt); axis(ax); title('Low-pass filtered signal');
subplot(2,2,2); plot(fr,abs(X)); ax=axis; title('original amplitude spectrum');
subplot(2,2,3); plot(fr,abs(X).*filt); axis(ax); title('Filtered amplitude spectrum');
I am not sure what exactly you meant when you said
let's suppose -1e13 till 1e13
, but keep in mind that extracting a single fourier component (essentially setting all values of the spectrum to zero, except the one you are interested in) acts as a brick-wall filter, and you will get considerable artefacts if you take the inverse transform. Refer to this topic or this page if you're interested.

Noise Cancel in Matlab

I am trying to remove noise from a wav file. But I keep getting the following error after run the script.
The wav file I use is https://drive.google.com/file/d/0BzIyOj_KUKufTTNWMFlRMW9fT2c/view?usp=sharing
I use the code from Remove noise from wav file, MATLAB.
>> run sample3
Index exceeds matrix dimensions.
Error in sample3 (line 17)
stem(1:N, f(:,2));
Error in run (line 96)
evalin('caller', [script ';']);
Here is the code:
%% Read in the file
clearvars;
close all;
[f,fs] = audioread('noise.wav');
%% Play original file
pOrig = audioplayer(f,fs);
pOrig.play;
%% Plot both audio channels
N = size(f,1); % Determine total number of samples in audio file
figure;
subplot(2,1,1);
stem(1:N, f(:,1));
title('Left Channel');
subplot(2,1,2);
stem(1:N, f(:,2));
title('Right Channel');
%% Plot the spectrum
df = fs / N;
w = (-(N/2):(N/2)-1)*df;
y = fft(f(:,1), N) / N; % For normalizing, but not needed for our analysis
y2 = fftshift(y);
figure;
plot(w,abs(y2));
[B,A] = butter(n, [beginFreq, endFreq], 'bandpass');
%% Design a bandpass filter that filters out between 700 to 12000 Hz
n = 7;
beginFreq = 700 / (fs/2);
endFreq = 12000 / (fs/2);
[B,A] = butter(n, [beginFreq, endFreq], 'bandpass');
%% Filter the signal
fOut = filter(b, a, f);
%% Construct audioplayer object and play
p = audioplayer(fOut, fs);
p.play;
The code assumes that the signal is stereo (a.k.a. two channels). Your sound file most likely is mono (judging from the way it sounds... a.k.a. one channel), so any references in the code that uses the right channel should be removed.
Simply put, the only part of the code that is affected is displaying the right channel in time-domain. The rest of the code should work as it accesses the left channel in stereo, which is coincidentally the first column of the sound file and the only column in a mono file.
Replace this code:
N = size(f,1); % Determine total number of samples in audio file
figure;
subplot(2,1,1);
stem(1:N, f(:,1));
title('Left Channel');
subplot(2,1,2);
stem(1:N, f(:,2));
title('Right Channel');
with:
N = size(f,1); % Determine total number of samples in audio file
figure;
stem(1:N, f(:,1));
title('Mono Channel');
In the future, try and read the MATLAB errors more carefully. They're very verbose and descriptive on what the problem in your code is. In this case, it's complaining that you are trying to access a column in the sound file f that doesn't exist.
Note: I am the original author of the answer you have linked.

Why are these two plots different?

Here I am plotting a spectrogram twice, once using imagesc and once using the spectrogram automatic plotting. I don't know why I get different scaling results, probably some filtering by the automatic plotting function but I would like to know what exactly and how to transform it so that it matches.
fs = 44100;
% Frequency sweep signal
sw = logspace(log10(500),log10(5000),fs*5);
x = 0.95 * sin(cumsum((2*pi*sw)/fs));
N = 128;
win_size = N;
noverlap = N/2;
win = window(#blackman,win_size);
[s,f,t] = spectrogram(x,win,noverlap,N,fs,'yaxis');
%% IMAGESC --- FIGURE 1
figure(1)
imagesc(t,f/1000,20*log(abs(s)));
title('Spectrogram');
set(gca,'Ydir','Normal');
xlabel('Time (secs)');
ylabel('Frequency (kHz)');
hcb=colorbar;
title(hcb,'Spectral Magnitude (dB)');
%% test with automatic spectrogram plot ---FIGURE2
figure(2)
spectrogram(x,win,noverlap,N,fs,'yaxis');
end
Help is appreciated :)
Change your code "imagesc(t,f/1000,20*log(abs(s)))" as imagesc(t,f/1000,20*log10(abs(s))).
log() is natural logarithm.
When you calculate dB scale, you should use log10(), not log().

Fourier transform and LTI filter and frequency response in Matlab

I'm new to Matlab for LTI signal processing and wondering if anyone can help with something that I'm sure is meant to be basic. I've spent hours and hours researching and obtaining background information and still cannot obtain a clear path to tackle these problems. So far, from scratch, I have generated a signal required and managed to use the fft function to produce the signal's DFT:
function x = fourier_rikki(A,t,O)
Fs = 1000;
t = 0:(1/Fs):1;
A = [0.5,0,0.5];
N = (length(A) - 1)/2;
x = zeros(size(t));
f1 = 85;
O1 = 2*pi*f1;
for k = 1:length(A)
x1 = x + A(k)*exp(1i*O1*t*(k-N-1));
end
f2 = 150;
O2 = 2*pi*f2;
for k = 1:length(A);
x2 = x + A(k)*exp(1i*O2*t*(k-N-1));
end
f3 = 330;
O3 = 2*pi*f3;
for k = 1:length(A);
x3 = x + A(k)*exp(1i*O3*t*(k-N-1));
end
signal = x1 + x2 + x3;
figure(1);
subplot(3,1,1);
plot(t, signal);
title('Signal x(t) in the Time Domain');
xlabel('Time (Seconds)');
ylabel('x(t)');
X = fft(signal); %DFT of the signal
subplot(3,1,2);
plot(t, X);
title('Power Spectrum of Discrete Fourier Transform of x(t)');
xlabel('Time (Seconds)');
ylabel('Power');
f = linspace(0, 1000, length(X)); %?
subplot(3,1,3);
plot(f, abs(X)); %Only want the positive values
title('Spectral Frequency');
xlabel('Frequency (Hz)'); ylabel('Power');
end
At this stage, I'm assuming this is correct for:
"Generate a signal with frequencies 85,150,330Hz using a sampling frequency of 1000Hz - plot 1seconds worth of the signal and its Discrete Fourier Transform."
The next step is to "Find the frequency response of an LTI system that filters out the higher and lower frequencies using the Fourier Transform". I'm stuck trying to create an LTI system that does that! I have to be left with the 150Hz signal, and I'm guessing I perform the filtering on the FFT, perhaps using conv.
My course is not a programming course - we are not assessed on our programming skills and I have minimal Matlab experience - basically we have been left to our own devices to struggle through, so any help would be greatly appreciated! I am sifting through tonnes of different examples and searching Matlab functions using 'help' etc, but since each one is different and does not have a break down of the variables used, explaining why certain parameters/values are chosen etc. it is just adding to the confusion.
Among many (many) others I have looked at:
http://www.ee.columbia.edu/~ronw/adst-spring2010/lectures/matlab/lecture1.html
http://gribblelab.org/scicomp/09_Signals_and_sampling.html section 10.4 especially.
As well as Matlab Geeks examples and Mathworks Matlab function explanations.
I guess the worst that can happen is that nobody answers and I continue burning my eyeballs out until I manage to come up with something :) Thanks in advance.
I found this bandpass filter code as a Mathworks example, which is exactly what needs to be applied to my fft signal, but I don't understand the attenuation values Ast or the amount of ripple Ap.
n = 0:159;
x = cos(pi/8*n)+cos(pi/2*n)+sin(3*pi/4*n);
d = fdesign.bandpass('Fst1,Fp1,Fp2,Fst2,Ast1,Ap,Ast2',1/4,3/8,5/8,6/8,60,1,60);
Hd = design(d,'equiripple');
y = filter(Hd,x);
freq = 0:(2*pi)/length(x):pi;
xdft = fft(x);
ydft = fft(y);
plot(freq,abs(xdft(1:length(x)/2+1)));
hold on;
plot(freq,abs(ydft(1:length(x)/2+1)),'r','linewidth',2);
legend('Original Signal','Bandpass Signal');
Here is something you can use as a reference. I think I got the gist of what you were trying to do. Let me know if you have any questions.
clear all
close all
Fs = 1000;
t = 0:(1/Fs):1;
N = length(t);
% 85, 150, and 330 Hz converted to radian frequency
w1 = 2*pi*85;
w2 = 2*pi*150;
w3 = 2*pi*330;
% amplitudes
a1 = 1;
a2 = 1.5;
a3 = .75;
% construct time-domain signals
x1 = a1*cos(w1*t);
x2 = a2*cos(w2*t);
x3 = a3*cos(w3*t);
% superposition of 85, 150, and 330 Hz component signals
x = x1 + x2 + x3;
figure
plot(t(1:100), x(1:100));
title('unfiltered time-domain signal, amplitude vs. time');
ylabel('amplitude');
xlabel('time (seconds)');
% compute discrete Fourier transform of time-domain signal
X = fft(x);
Xmag = 20*log10(abs(X)); % magnitude spectrum
Xphase = 180*unwrap(angle(X))./pi; % phase spectrum (degrees)
w = 2*pi*(0:N-1)./N; % normalized radian frequency
f = w./(2*pi)*Fs; % radian frequency to Hz
k = 1:N; % bin indices
% plot magnitude spectrum
figure
plot(f, Xmag)
title('frequency-domain signal, magnitude vs. frequency');
xlabel('frequency (Hz)');
ylabel('magnitude (dB)');
% frequency vector of the filter. attenuates undesired frequency components
% and keeps desired components.
H = 1e-3*ones(1, length(k));
H(97:223) = 1;
H((end-223):(end-97)) = 1;
% plot magnitude spectrum of signal and filter
figure
plot(k, Xmag)
hold on
plot(k, 20*log10(H), 'r')
title('frequency-domain signal (blue) and filter (red), magnitude vs. bin index');
xlabel('bin index');
ylabel('magnitude (dB)');
% filtering in frequency domain is just multiplication
Y = X.*H;
% plot magnitude spectrum of filtered signal
figure
plot(f, 20*log10(abs(Y)))
title('filtered frequency-domain signal, magnitude vs. frequency');
xlabel('frequency (Hz)');
ylabel('magnitude (dB)');
% use inverse discrete Fourier transform to obtain the filtered time-domain
% signal. This signal is complex due to imperfect symmetry in the
% frequency-domain, however the imaginary components are nearly zero.
y = ifft(Y);
% plot overlay of filtered signal and desired signal
figure
plot(t(1:100), x(1:100), 'r')
hold on
plot(t(1:100), x2(1:100), 'linewidth', 2)
plot(t(1:100), real(y(1:100)), 'g')
title('input signal (red), desired signal (blue), signal extracted via filtering (green)');
ylabel('amplitude');
xlabel('time (seconds)');
Here is the end result...

apply low-pass analog filter to an analog signal in matlab

Suppose that I'm simulating SAR signal processing in matlab. You know a block diagram like this :
Here's what I have tried up to now.
t = 0:0.01:10;
f0 = 10^(-6);
t1 = 1;
f1 = 100;
y = chirp(t,f0,t1,f1,'linear');
%starting to generate I's
y1Modulated = y.*cos(2*pi*f0*t);
y1ModulatedFrequencyDomain = fft(y1Modulated);
As you see in the diagram the signal entering the low-pass filter is an analog one. So we should use filters in
matlab ---> signal processing toolbox ---> Analog and Digital filters ---> Analog filters
But I don't know which to use or how to obtain parameters of functions like: besselap , cheblap and so on?
There are many ways to implement what you are trying to do.
Here is one way to write the code for your block diagram:
% define some simulation parameters
fs = 80e6; % sample rate of 80 MHz
f0 = 10e6; % frequency of your complex mixer
% generate the chirp with whatever parameters you need
t = 0:1/fs:1000*1/fs;
y = chirp(t,9e6,6.25e-6,11e6);
% add a bit of noise to make the simulation more realistic
% here we make the signal-to-noise ratio approximately 40 dB
y = awgn(y,40,'measured');
% apply the complex mixing
y2 = y.*exp(j.*2.*pi.*f0.*t);
% create an example lowpass filter and filter the signal to remove images
[b,a] = butter(8,0.1);
y3 = filter(b,a,y2);
% plot the signals to see what they look like
figure(1);
plot(t,y);
grid on;
title('Received Chirp Signal (time domain)');
figure(2);
plot(linspace(-fs/2,fs/2,length(y)),20.*log10(abs(fftshift(fft(y)))));
grid on;
title('Received Chirp Signal (frequency domain)');
xlabel('frequency (Hz)');
ylabel('dB');
axis([-fs/2 fs/2 -30 40]);
figure(3); hold on;
plot(t,real(y3));
plot(t,imag(y3),'r');
grid on;
title('Baseband Chirp Signal (time domain)');
figure(4);
plot(linspace(-fs/2,fs/2,length(y3)),20.*log10(abs(fftshift(fft(y3)))));
grid on;
title('Baseband Chirp Signal (frequency domain)');
xlabel('frequency (Hz)');
ylabel('dB');
axis([-fs/2 fs/2 -30 40]);
Now, you also asked which low-pass filter design to use. This depends entirely on what you are trying to achieve, and you need to specify a filter to meet your requirements. In my example above I have used an 8th order Butterworth design. But often an FIR filter is used in order to achieve a linear phase response.