Playing a varying frequency in Hertz in matlab? - matlab

I have some matlab code which produces frequency (in hertz) of a sound over 5 seconds. The code as it stands outputs 100 samples per second, and I want to play the 5 second block to see what this sounds like, but I'm having issues with sampling rate and sound / soundsc commands.
My frequency oscillates (data here ) and I'd be very grateful if someone could help me convert this data into some kind of real-time approximation of what it should sound like.

Something like this may be helpful
Fs=2000; %sample rate, Hz
t=0:1/Fs:5; %time vector
F=298+sin(2*pi*t); %put your own F here
S=sin(2*pi*F.*t); %here is the sound vector
%visual check
figure(1);
plot(t,S)
figure(2);
plot(t,F)
%listen
wavplay(S,Fs)
This is like FM modulation, but different. If you have an Fold vector with a different sample rate, you can convert it with the command
F=interp1(told,Fold,t); %told and Fold are F at a different sample rate
%check it
plot(told,Fold,t,F)

First, your sampling rate should be at least twice the maximum frequency according the Nyquist–Shannon sampling theorem.
Next, you need to generate a sinusoid:
Signal = sin(2*pi*Phi);
where Phi is the phase corresponding to the desired frequency pattern, which is simply an integral of the frequency (which you can do numerically or analytically).

Related

How can i use fft to find the maximum frequency of a periodic signal?

I'm trying to find the maximum frequency of a periodic signal in Matlab and as i know when you convert a periodic signal to the frequency spectrum you get only delta functions however i get a few curves between the produced delta functions. Here is the code :
t=[-0.02:10^-3:0.02];
s=5.*(1+cos(2*pi*10*t)).*cos(2*pi*100*t);
figure, subplot(211), plot(t,s);
y=fft(s);
subplot(212), plot(t,y);
Here is a code-snippet to help you understand how to get the frequency-spectrum using fft in matlab.
Things to remember are:
You need to decide on a sampling frequency, which should be high enough, as per the Nyquist Criterion (You need the number of samples, at least more than twice the highest frequency or else we will have aliasing). That means, fs in this example cannot be below 2 * 110. Better to have it even higher to see a have a better appearance of the signal.
For a real signal, what you want is the power-spectrum obtained as the square of the absolute of the output of the fft() function. The imaginary part, which contains the phase should contain nothing but noise. (I didn't plot the phase here, but you can do this to check for yourself.)
Finally, we need to use fftshift to shift the signal such that we get the mirrored spectrum around the zero-frequency.
The peaks would be at the correct frequencies. Now considering only the positive frequencies, as you can see, we have the largest peak at 100Hz and two further lobs around 100Hz +- 10Hz i.e. 90Hz and 110Hz.
Apparently, 110Hz is the highest frequency, in your example.
The code:
fs = 500; % sampling frequency - Should be high enough! Remember Nyquist!
t=[-.2:1/fs:.2];
s= 5.*(1+cos(2*pi*10*t)).*cos(2*pi*100*t);
figure, subplot(311), plot(t,s);
n = length(s);
y=fft(s);
f = (0:n-1)*(fs/n); % frequency range
power = abs(y).^2/n;
subplot(312), plot(f, power);
Y = fftshift(y);
fshift = (-n/2:n/2-1)*(fs/n); % zero-centered frequency range
powershift = abs(Y).^2/n;
subplot(313), plot(fshift, powershift);
The output plots:
The first plot is the signal in the time domain
The signal in the frequency domain
The shifted fft signal

MATLAB: Apply lowpass filter on sound signal [duplicate]

I've only used MATLAB as a calculator, so I'm not as well versed in the program. I hope a kind person may be able to guide me on the way since Google currently is not my friend.
I have a wav file in the link below, where there is a human voice and some noise in the background. I want the noise removed. Is there anyone who can tell me how to do it in MATLAB?
https://www.dropbox.com/s/3vtd5ehjt2zfuj7/Hold.wav
This is a pretty imperfect solution, especially since some of the noise is embedded in the same frequency range as the voice you hear on the file, but here goes nothing. What I was talking about with regards to the frequency spectrum is that if you hear the sound, the background noise has a very low hum. This resides in the low frequency range of the spectrum, whereas the voice has a more higher frequency. As such, we can apply a bandpass filter to get rid of the low noise, capture most of the voice, and any noisy frequencies on the higher side will get cancelled as well.
Here are the steps that I did:
Read in the audio file using audioread.
Play the original sound so I can hear what it sounds like using. Do this by creating an audioplayer object.
Plotted both the left and right channels to take a look at the sound signal in time domain... if it gives any clues. Looking at the channels, they both seem to be the same, so it looks like it was just a single microphone being mapped to both channels.
I took the Fourier Transform and saw the frequency distribution.
Using (4) I figured out the rough approximation of where I should cut off the frequencies.
Designed a bandpass filter that cuts off these frequencies.
Filtered the signal then played it by constructing another audioplayer object.
Let's go then!
Step #1
%% Read in the file
clearvars;
close all;
[f,fs] = audioread('Hold.wav');
audioread will read in an audio file for you. Just specify what file you want within the ''. Also, make sure you set your working directory to be where this file is being stored. clearvars, close all just do clean up for us. It closes all of our windows (if any are open), and clears all of our variables in the MATLAB workspace. f would be the signal read into MATLAB while fs is the sampling frequency of your signal. f here is a 2D matrix. The first column is the left channel while the second is the right channel. In general, the total number of channels in your audio file is denoted by the total number of columns in this matrix read in through audioread.
Step #2
%% Play original file
pOrig = audioplayer(f,fs);
pOrig.play;
This step will allow you to create an audioplayer object that takes the signal you read in (f), with the sampling frequency fs and outputs an object stored in pOrig. You then use pOrig.play to play the file in MATLAB so you can hear it.
Step #3
%% 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');
stem is a way to plot discrete points in MATLAB. Each point in time has a circle drawn at the point with a vertical line drawn from the horizontal axis to that point in time. subplot is a way to place multiple figures in the same window. I won't get into it here, but you can read about how subplot works in detail by referencing this StackOverflow post I wrote here. The above code produces the plot shown below:
The above code is quite straight forward. I'm just plotting each channel individually in each subplot.
Step #4
%% 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));
The code that will look the most frightening is the code above. If you recall from signals and systems, the maximum frequency that is represented in our signal is the sampling frequency divided by 2. This is called the Nyquist frequency. The sampling frequency of your audio file is 48000 Hz, which means that the maximum frequency represented in your audio file is 24000 Hz. fft stands for Fast Fourier Transform. Think of it as a very efficient way of computing the Fourier Transform. The traditional formula requires that you perform multiple summations for each element in your output. The FFT will compute this efficiently by requiring far less operations and still give you the same result.
We are using fft to take a look at the frequency spectrum of our signal. You call fft by specifying the input signal you want as the first parameter, followed by how many points you want to evaluate at with the second parameter. It is customary that you specify the number of points in your FFT to be the length of the signal. I do this by checking to see how many rows we have in our sound matrix. When you plot the frequency spectrum, I just took one channel to make things simple as the other channel is the same. This serves as the first input into fft. Also, bear in mind that I divided by N as it is the proper way of normalizing the signal. However, because we just want to take a snapshot of what the frequency domain looks like, you don't really need to do this. However, if you're planning on using it to compute something later, then you definitely need to.
I wrote some additional code as the spectrum by default is uncentered. I used fftshift so that the centre maps to 0 Hz, while the left spans from 0 to -24000Hz while the right spans from 0 to 24000 Hz. This is intuitively how I see the frequency spectrum. You can think of negative frequencies as frequencies that propagate in the opposite direction. Ideally, the frequency distribution for a negative frequency should equal the positive frequency. When you plot the frequency spectrum, it tells you how much contribution that frequency has to the output. That is defined by the magnitude of the signal. You find this by taking the abs function. The output that you get is shown below.
If you look at the plot, there are a lot of spikes around the low frequency range. This corresponds to your humming whereas the voice probably maps to the higher frequency range and there isn't that much of it as there isn't that much of a voice heard.
Step #5
By trial and error and looking at Step #5, I figured everything from 700 Hz and down corresponds to the humming noise while the higher noise contributions go from 12000 Hz and higher.
Step #6
You can use the butter function from the Signal Processing Toolbox to help you design a bandpass filter. However, if you don't have this toolbox, refer to this StackOverflow post on how user-made function that achieves the same thing. However, the order for that filter is only 2. Assuming you have the butter function available, you need to figure out what order you want your filter. The higher the order, the more work it'll do. I choose n = 7 to start off. You also need to normalize your frequencies so that the Nyquist frequency maps to 1, while everything else maps between 0 and 1. Once you do that, you can call butter like so:
[b,a] = butter(n, [beginFreq, endFreq], 'bandpass');
The bandpass flag means you want to design a bandpass filter, beginFreq and endFreq map to the normalized beginning and ending frequency you want to for the bandpass filter. In our case, that's beginFreq = 700 / Nyquist and endFreq = 12000 / Nyquist. b,a are the coefficients used for a filter that will help you perform this task. You'll need these for the next step.
%% 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');
Step #7
%% Filter the signal
fOut = filter(b, a, f);
%% Construct audioplayer object and play
p = audioplayer(fOut, fs);
p.play;
You use filter to filter your signal using what you got from Step #6. fOut will be your filtered signal. If you want to hear it played, you can construct and audioplayer based on this output signal at the same sampling frequency as the input. You then use p.play to hear it in MATLAB.
Give this all a try and see how it all works. You'll probably need to play around the most in Step #6 and #7. This isn't a perfect solution, but enough to get you started I hope.
Good luck!

Add noise to speech with different sampling rates in matlab

I am trying to add a noise file (.wav) file to a speech signal(.wav).
[b fs]=audioread('AzBio_01-01_S60.wav');
[babble fs1]=audioread('cafeteria_babble.wav');
The issue is that both the files have different sampling rates (fs=22050, fs1=44100).
When i add them it distorts the other signal since the sampling rate is different. How do i solve this. I am playing the sound via
p=audioplayer (total,fs)
play (p)
The distortion will be due to the sample values summing to more than 1 not the sample rate differences. To deal with that risk divide both vectors by two before summing them.
That said, you do still need to deal with the sample rate difference. There are two ways of doing this: either reduce the sampling rate of the signal with the higher sampling rate or increase the sampling rate of the other signal.
Reducing the sampling rate of the signal with the higher rate is easier but comes with the disadvantage that you are actually losing data. You could do this by using resample. resample(babble, fs, fs1)
Alternatively you can upsample the signal with the lower sampling frequency. This won't give you any more data but it will mean the sample rates match. You can do this with interp1. b = interp1(1:length(b),b,0.5:0.5:length(b))
So in summary
[b fs]=audioread('AzBio_01-01_S60.wav');
[babble fs1]=audioread('cafeteria_babble.wav');
b = interp1(1:length(b),b,0.5:0.5:length(b)); % interpolate b to fs1
total = b/2 + babble/2; % sum at half the sample values
p=audioplayer (total,fs1);
play (p)

Why doesn't matlab give me an 8KHz sinewave for 16KHz sampling frequency?

I have the following matlab code, and I am trying to get 64 samples of various sinewave frequencies at 16KHz sampling frequency:
close all; clear; clc;
dt=1/16000;
freq = 8000;
t=-dt;
for i=1:64,
t=t+dt;a(i)=sin(2*pi*freq*t);
end
plot(a,'-o'); grid on;
for freq = 1000, the output graph is
The graph seems normal upto 2000, but at 3000, the graph is
We can see that the amplitude changes during every cycle
Again, at 4000 the graph is
Not exactly a sinewave, but the amplitude is as expected during every cycle and if I play it out it sounds like a single frequency tone
But again at 6000 we have
and at 8000 we have
Since the sampling frequency is 16000 I was assuming that I should be able to generate sinewave samples for upto 8000, and I was expecting the graph I got at 4000 to appear at 8000. Instead, even at 3000, the graph starts to look weird
If I change the sampling frequency to 32000 and the sinewave frequency to 16000, I get the same graph that I am getting now at 8000. Why does matlab behave this way?
EDIT:
at freq = 7900
This is just an artifact of aliasing. Notice how the vertical axis for the 8kHz graph only goes up to 1.5E-13? Ideally the graph should be all zeros; what you're seeing is rounding error.
Looking at the expression for computing the samples at 16kHz:
x(n) = sin(2 * pi * freq * n / 16000)
Where x is the signal, n is the integer sample number, and freq is the frequency in hertz. So, when freq is 8kHz, it's equivalent to:
x(n) = sin(2 * pi * 8000 * n / 16000) = sin(pi * n)
Because n is an integer, sin(pi * n) will always be zero. 8kHz is called the Nyquist frequency for a sampling rate of 16kHz for this reason; in general, the Nyquist frequency is always half the sample frequency.
At 3kHz, the signal "looks weird" because some of the peaks are at non-integer multiples of 16kHz, because 16 is not evenly divisible by 3. Same goes for the 6kHz signal.
The reason they still sound like pure sine tones is because of how the amplitude is interpolated between samples. The graph uses simple linear interpolation, which gives the impression of harsh edges at the samples. However, a physical loudspeaker (more precisely, the circuitry which drives it) does not use linear interpolation directly. Instead, a small filter circuit is used to smooth out those harsh edges (aka anti-aliasing) which removes the artificial frequencies above the aforementioned Nyquist frequency.
That is problem of matlab but a nature of sampling.
16KHz sampling makes 16K (16,000) sampled data per second. 8KHz signal has 8K (8000) cycles per second. So two sample data per a cycle.
Two is minimum number of data per cycle. This is know a part of "sampling theorem".
Let try to show two cycles with three points on graph, you may understand that its impossible to show two cycles by three points. In the same way, you can't show 2N cycles by (2N-1) points.
The effect seen for 8 kHz is as all other answers already mention aliasing effects and arises due to that the sine wave for 8 kHz is sin(2*pi*n*8000*1/16000) = sin(n*pi), which is explained in Drew McGovens answer. Luckily the amplitude is not the only parameter that defines the signal. The other parameter that is required to completely define the signal is the phase. This means that when doing for fourier analysis of the signal, it is still possible to find the right frequency. Try:
close all; clear; clc;
dt=1/16000;
freq = 7300;
t=-dt;
for i=1:64,
t=t+dt;a(i)=sin(2*pi*freq*t);
end
plot(a,'-o'); grid on;
figure; plot( linspace(1,16000,1000), abs(fft(a)) );
A side comment: some people might argue against using i as index variable since that can also be used as the imagiary number i. Personally I have nothing against using i since the runtime and overhead only is affected slightly and I always uses 1i. However, just make sure to use 1i consistently for the imaginary unit then.

Remove noise from wav file, MATLAB

I've only used MATLAB as a calculator, so I'm not as well versed in the program. I hope a kind person may be able to guide me on the way since Google currently is not my friend.
I have a wav file in the link below, where there is a human voice and some noise in the background. I want the noise removed. Is there anyone who can tell me how to do it in MATLAB?
https://www.dropbox.com/s/3vtd5ehjt2zfuj7/Hold.wav
This is a pretty imperfect solution, especially since some of the noise is embedded in the same frequency range as the voice you hear on the file, but here goes nothing. What I was talking about with regards to the frequency spectrum is that if you hear the sound, the background noise has a very low hum. This resides in the low frequency range of the spectrum, whereas the voice has a more higher frequency. As such, we can apply a bandpass filter to get rid of the low noise, capture most of the voice, and any noisy frequencies on the higher side will get cancelled as well.
Here are the steps that I did:
Read in the audio file using audioread.
Play the original sound so I can hear what it sounds like using. Do this by creating an audioplayer object.
Plotted both the left and right channels to take a look at the sound signal in time domain... if it gives any clues. Looking at the channels, they both seem to be the same, so it looks like it was just a single microphone being mapped to both channels.
I took the Fourier Transform and saw the frequency distribution.
Using (4) I figured out the rough approximation of where I should cut off the frequencies.
Designed a bandpass filter that cuts off these frequencies.
Filtered the signal then played it by constructing another audioplayer object.
Let's go then!
Step #1
%% Read in the file
clearvars;
close all;
[f,fs] = audioread('Hold.wav');
audioread will read in an audio file for you. Just specify what file you want within the ''. Also, make sure you set your working directory to be where this file is being stored. clearvars, close all just do clean up for us. It closes all of our windows (if any are open), and clears all of our variables in the MATLAB workspace. f would be the signal read into MATLAB while fs is the sampling frequency of your signal. f here is a 2D matrix. The first column is the left channel while the second is the right channel. In general, the total number of channels in your audio file is denoted by the total number of columns in this matrix read in through audioread.
Step #2
%% Play original file
pOrig = audioplayer(f,fs);
pOrig.play;
This step will allow you to create an audioplayer object that takes the signal you read in (f), with the sampling frequency fs and outputs an object stored in pOrig. You then use pOrig.play to play the file in MATLAB so you can hear it.
Step #3
%% 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');
stem is a way to plot discrete points in MATLAB. Each point in time has a circle drawn at the point with a vertical line drawn from the horizontal axis to that point in time. subplot is a way to place multiple figures in the same window. I won't get into it here, but you can read about how subplot works in detail by referencing this StackOverflow post I wrote here. The above code produces the plot shown below:
The above code is quite straight forward. I'm just plotting each channel individually in each subplot.
Step #4
%% 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));
The code that will look the most frightening is the code above. If you recall from signals and systems, the maximum frequency that is represented in our signal is the sampling frequency divided by 2. This is called the Nyquist frequency. The sampling frequency of your audio file is 48000 Hz, which means that the maximum frequency represented in your audio file is 24000 Hz. fft stands for Fast Fourier Transform. Think of it as a very efficient way of computing the Fourier Transform. The traditional formula requires that you perform multiple summations for each element in your output. The FFT will compute this efficiently by requiring far less operations and still give you the same result.
We are using fft to take a look at the frequency spectrum of our signal. You call fft by specifying the input signal you want as the first parameter, followed by how many points you want to evaluate at with the second parameter. It is customary that you specify the number of points in your FFT to be the length of the signal. I do this by checking to see how many rows we have in our sound matrix. When you plot the frequency spectrum, I just took one channel to make things simple as the other channel is the same. This serves as the first input into fft. Also, bear in mind that I divided by N as it is the proper way of normalizing the signal. However, because we just want to take a snapshot of what the frequency domain looks like, you don't really need to do this. However, if you're planning on using it to compute something later, then you definitely need to.
I wrote some additional code as the spectrum by default is uncentered. I used fftshift so that the centre maps to 0 Hz, while the left spans from 0 to -24000Hz while the right spans from 0 to 24000 Hz. This is intuitively how I see the frequency spectrum. You can think of negative frequencies as frequencies that propagate in the opposite direction. Ideally, the frequency distribution for a negative frequency should equal the positive frequency. When you plot the frequency spectrum, it tells you how much contribution that frequency has to the output. That is defined by the magnitude of the signal. You find this by taking the abs function. The output that you get is shown below.
If you look at the plot, there are a lot of spikes around the low frequency range. This corresponds to your humming whereas the voice probably maps to the higher frequency range and there isn't that much of it as there isn't that much of a voice heard.
Step #5
By trial and error and looking at Step #5, I figured everything from 700 Hz and down corresponds to the humming noise while the higher noise contributions go from 12000 Hz and higher.
Step #6
You can use the butter function from the Signal Processing Toolbox to help you design a bandpass filter. However, if you don't have this toolbox, refer to this StackOverflow post on how user-made function that achieves the same thing. However, the order for that filter is only 2. Assuming you have the butter function available, you need to figure out what order you want your filter. The higher the order, the more work it'll do. I choose n = 7 to start off. You also need to normalize your frequencies so that the Nyquist frequency maps to 1, while everything else maps between 0 and 1. Once you do that, you can call butter like so:
[b,a] = butter(n, [beginFreq, endFreq], 'bandpass');
The bandpass flag means you want to design a bandpass filter, beginFreq and endFreq map to the normalized beginning and ending frequency you want to for the bandpass filter. In our case, that's beginFreq = 700 / Nyquist and endFreq = 12000 / Nyquist. b,a are the coefficients used for a filter that will help you perform this task. You'll need these for the next step.
%% 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');
Step #7
%% Filter the signal
fOut = filter(b, a, f);
%% Construct audioplayer object and play
p = audioplayer(fOut, fs);
p.play;
You use filter to filter your signal using what you got from Step #6. fOut will be your filtered signal. If you want to hear it played, you can construct and audioplayer based on this output signal at the same sampling frequency as the input. You then use p.play to hear it in MATLAB.
Give this all a try and see how it all works. You'll probably need to play around the most in Step #6 and #7. This isn't a perfect solution, but enough to get you started I hope.
Good luck!