Separating audio file in 3 different frequency areas - matlab

I apologize in advance, if the title is confusing. Basically, i have a Audio-file, on which I perform a STFT every 50ms. My File is about 11 seconds long (10.8526s), which i have cut off from a soundtrack. Btw, i am not allowed to use the built-in function in Matlab for the STFT. I am aware it is much more easier. Anyway, after i run my code, every 50 ms a STFT is performed and the picture is being plotted.
Now i want to seperate it in 3 different plots. In the first plot i have the lower frequencies (0-300Hz), in the second plot medium frequencies(300-5kHz) and in the last plot i have high frequencies(5Khz-fs/2). fs=44100 --> Further explanations below in the code. How can i define now the areas?
%AUDIO-FILE
%______________________________________________________
[y,fs]=audioread('UnchainMyHeart.wav');
% audioread = Reads Audio file
% y = A vector, which contains the audio signal
% fs = sample rate
% 'UnchainMyHeart' = Audio file
%______________________________________________________
% Paramter for the real-time spectral-analysis
%______________________________________________________
NFA=2;
% Every second picture is being plotted
% Don't need every picture
t_seg=0.05;
%Length of the audio signal on which is a STFT performed
fftlen = 4096;
% Length of the FFT, frequency resolution
TPF= 300;
BPF= 5000;
HPF= 22050;
% Trying to define the frequencies areas
% Isn't working right now
LOW=((TPF*fftlen)/fs);
MEDIUM=((BPF*fftlen)/fs);
HIGH=((HPF*fftlen)/fs);
% Contains the number of FFT points in the frequency
%_______________________________________________________
segl =floor(t_seg*fs);
windowshift=segl/2;
window=hann(segl);
window=window.';
si=1;
% Start Index
ei=segl;
% End Index
AOS= length(y)/windowshift - 1;
f1=figure;
f=0:1:fftlen-1;
f=f/(fftlen-1)*fs;
Ya=zeros(1,fftlen);
n=0;
for m= 1:1:AOS
y_a = y(si:ei);
y_a= y_a.*window;
Ya=fft(y_a, fftlen);
n=n+1;
if n==1
Yres=abs(Ya);
else
Yres=Yres+abs(Ya);
end
if n==NFA
Yres=Yres/NFA;
n=0;
drawnow;
%Updates the graphical objects which are being plotted every 50ms
figure(f1);
plot(f(1:end/2), 20*log10(abs(Yres(1:end/2))));
ylim([-90 50]);
title('Spektrum of audio signal');
xlabel('f(Hz)');
ylabel('dB');
grid on;
end
si=si+windowshift;
% Updating Start Index
ei=ei+windowshift;
% Updating End index
end

I am not able to run you code as I do not have your audio file but I will try to explain conceptually, and use pseudo code.
Frequency brick-wall
If you just want to separate the frequencies for visual purposes you can just use brick-wall filters.
Perform an fft of the full signal. Define a frequency vector.
SigFD = fft(signal);
n = length(signal); % number of samples
fs = 44100; % sampling rate
deltaF = fs/n; % frequency resolution
F = [0:floor(n/2)-1, -(floor(n/2)):-1]*deltaF; % frequency vector
Slice the signal based on the frequency range that you want.
lowF = 0;
highF = 500;
part1Range = abs(F)>lowF&abs(F)<highF;
Fpart1 = F(part1Range);
Sig1FD = SigFD(part1Range);
Note that I am unable to test the code on your waveform so this should be considered more of pseudo code!

Related

Changing the pitch of a imported signal logarithmically / exponentially over time

How can I change the pitch of an imported signal logarithmically / exponentially over time?
Please note that the imported signals that will be used are not single frequencies so a simple sweep or a chirp command will not work since I will be importing vocal audio files, I just created the examples below so they would work and could be tested / show the issues I'm having.
I can change the pitch of a signal over time linearly which works great see part 1 of test code and frequency plot below. Thanks to Sheljohn for the code
%Sweep question part 1
clear all,clf reset,tic,clc
pkg load signal %load packages
%%%----create signal
start_freq=500;
end_freq=20;
fs=22050
len_of_sig=7; %in seconds
t=linspace(0,2*pi*len_of_sig,fs*len_of_sig);
orig_sig1=.8*sin(start_freq*t);
wavwrite([orig_sig1(:)] ,fs,16,strcat('/tmp/0_sig.wav')); % export file
%%%---import signal
[ya, fs, nbitsraw] = wavread('/tmp/0_sig.wav');
orig_total_samples=length(ya); %make this the same length as signal wave
t_import=linspace(0,2*pi*(orig_total_samples/fs),orig_total_samples);
%%%%----Begin linsweep
x = ya(:);
fac=(end_freq-start_freq)/length(x); %linear slope
n = numel(x); % number of timepoints
m = mean(x); % average of the signal
k = transpose(0:n-1); %
h = hilbert( x - m ); % analytic signal
env1 = abs(h); % envelope
sweep=fac*pi*k.^2/(fs); %linearly increasing offset original %alter curve here
p = angle(h) + sweep; % phase + linearly increasing offset original
y = m - imag(hilbert( env1 .* sin(p) )); % inverse-transform
wavwrite([y(:)] ,fs,16,strcat('/tmp/0_sweep.wav')); % export file
%%%----------Used for plotting
z = hilbert(y);
instfreq = fs/(2*pi)*diff(unwrap(angle(z))); %orginal
t_new=t_import/(2*pi); %converts it to seconds
plot(t_new(2:end),instfreq,'-r')
xlabel('Time (secnds)')
ylabel('Frequency (Hz)')
grid on
title('Instantaneous Frequency')
Issues with the code I have below are:
1) The frequency doesn't start or end at the correct frequency.
2) It doesn't have the correct slopes
I believe it has to do with the variables fac and sweep I'm just not sure how to calculate them correctly.
fac=log(start_freq/end_freq)/length(x); %slope
sweep=-(start_freq)*exp(fac*k); %alter curve here
-
%-----------------Sweep question part 2
clear all,clf reset,tic,clc
pkg load signal %load packages
%%%----create signal
start_freq=500;
end_freq=20;
fs=22050
len_of_sig=7; %in seconds
t=linspace(0,2*pi*len_of_sig,fs*len_of_sig);
orig_sig1=.8*sin(start_freq*t);
wavwrite([orig_sig1(:)] ,fs,16,strcat('/tmp/0_sig.wav')); % export file
%%%---import signal
[ya, fs, nbitsraw] = wavread('/tmp/0_sig.wav');
orig_total_samples=length(ya); %make this the same length as signal wave
t_import=linspace(0,2*pi*(orig_total_samples/fs),orig_total_samples);
%%%%----Begin linsweep
x = ya(:);
fac=log(start_freq/end_freq)/length(x); %slope
n = numel(x); % number of timepoints
m = mean(x); % average of the signal
k = transpose(0:n-1); %
h = hilbert( x - m ); % analytic signal
env1 = abs(h); % envelope
sweep=-(start_freq)*exp(fac*k); %alter curve here
p = angle(h) + sweep; % phase + increasing offset
y = m - imag(hilbert( env1 .* sin(p) )); % inverse-transform
wavwrite([y(:)] ,fs,16,strcat('/tmp/0_sweep.wav')); % export file
%%%----------Used for plotting
z = hilbert(y);
instfreq = fs/(2*pi)*diff(unwrap(angle(z))); %orginal
t_new=t_import/(2*pi); %converts it to seconds
plot(t_new(2:end),instfreq,'-r')
xlabel('Time (seconds)')
ylabel('Frequency (Hz)')
grid on
title('Instantaneous Frequency')
The slopes I'm trying to get are when the start frequency starts at 500hz and goes to 20hz. And when the start frequency starts at 20hz and it goes to 500hz. See plots below: Note: These frequency will change so I'm trying to get the correct formula / equation that will calculate these slopes when needed.
Ps: I'm using Octave 4.0 which is similar to Matlab.
Please note that the imported signals that will be used are not single frequencies so a simple sweep or a chirp command will not work since I will be importing vocal audio files, I just created the examples below so they would work and could be tested / show the issues I'm having.
I can get the sweep to look like the plot you are interested in by making the following changes to your code. Some of them are just cosmetic for my sake (e.g. I like my time variables to remain in units of seconds throughout).
Relevant changes:
From:
t=linspace(0,2*pi*len_of_sig,fs*len_of_sig);
orig_sig1=.8*sin(start_freq*t);
fac=log(start_freq/end_freq)/length(x); %slope
To:
t=linspace(0,len_of_sig,fs*len_of_sig);
orig_sig1=0.8*sin(start_freq*t*2*pi);
fac=log(end_freq/start_freq)/length(x);
sweep=(start_freq*2*pi/fs)*exp(fac*k); %alter curve here
Here was some other changes I made,
y = env1.*sin(p);
% and later for consistency
t_import=linspace(0,orig_total_samples/fs,orig_total_samples);
t_new=t_import; %t is seconds
The fac, in my mind, is going to be the difference from your start and end, so it would be: log(endFreq)-log(startFreq) or log(endFreq/startFreq) with the additional normalization for the length. This can be flipped with a negative sign in front.
One issue with the sweep may be happening when you use it to calculate p=angle(h)+sweep; where angle(h) is in radians.
The radians vs Hz units issue may be causing some of the difficulty.

Measuring peaks and the distance between them in my plot

I will keep the explanation, how my codes works, very short. I advise you to try this code yourself, so perhaps you understand it better that way. I have an audio-file and read it in my code. Now i switch from the time domain to the frequency domain by using the function FFT. But the only difference is, that i am performing an STFT on my audio signal. I do it every 30ms, until to the length of my signal. I am aware, that there are many different function in matlab, which also can perform this easily, but there are not giving me the results i need. Now, i am plotting many different frequency spectrums every 30ms. But i split up my signal in three frequency bands. They are called LOW, MEDIUM and HIGH. Basically, this means I have 3 different spectrums plotting every 30ms. The next step I do, is summing all the magnitudes from ONE frequency spectrum together, this means I have ONE VALUE per frequency spectrum, which are being squared.
Now, i have the power from every spectrum ! And all of these values are being plotted in my code. I am only plotting the power values, otherwise my code performance time would be extremely slow.
Btw, the code looks long, but there are two for loop. In the first, i read the low spectrum and when it is finished, the second starts with the medium and high spectrum. Basically they are the same. I am aware, i can probably do that with findpeaks or something similar. But how can i write/pull that of? Or what the necessary steps to do that. At the end, i included a file, Hopefully you can see that.
I want to measure the peaks and get the distance between them from the red plot.
EDIT:
Ok, i got the peaks, but not in the way i imagined. I want to show the peaks, which are above 5000-line. Sorry for not being clear at the beginning. See my plot, what i mean. I want to say my code, that only the peaks should be measured, which are above the 5000-line.
[pks, locs] = findpeaks(ValuesOfYc);
p=plot(x,ValuesOfYc,'r-' ,x(locs), pks,'ob');
This is, what I did above, in my first loop. How should i go on from there?
clear;
clc;
%% MATLAB
%% read file
%_________________________________________
[y,fs]=audioread('Undertale - Megalovania.wav');
% audioread = read wav -file
% y = contains the audio signal
% fs = 44100
% 'UnchainMyHeart' = name of the wav-file
%_________________________________________
%% PARAMETER FOR STFT
%_________________________________________
t_seg=0.03; % length of segment in ms
fftlen = 4096; %FFT-Points
% Defining size of frequency bands
f_low= 1:200; %lower frequencies
f_medium= 201:600; %medium frequencies
f_high= 601:1000; %higher frequencies
%__________________________________________
%% CODE
segl =floor(t_seg*fs);
windowshift=segl/2;
% defining the size of the window shift
window=hann(segl);
% apply hann function on segment length (30 ms)
window=window.';
% transpose vector
si=1;
% defining start index
ei=segl;
% defining end index
N=floor( length(y)/windowshift - 1);
% Calculates the number, how often the window has to shift
% until to length of the audio signal
f1=figure;
% Generating new window
f=0:1:fftlen-1;
f=f/fftlen*fs;
% defining frequency vector
Ya=zeros(1,fftlen);
ValuesOfYc = NaN(1,N);
ValuesOfYd = NaN(1,N);
ValuesOfYe = NaN(1,N);
x =(1:N)*windowshift/fs;
% defining x-axis
for m= 1:1:N
y_a = y(si:ei);
% a segment is taken out from audio signal length(30ms)
y_a= y_a.*window;
% multiplying segment with window (hanning)
Ya=fft(y_a, fftlen);
% Applying fft on segment
Yb=abs(Ya(1:end/2)).^2;
% Squaring the magnitudes from one-sided spectrum
drawnow; % Updating the graphical values
figure(f1);
% Showing the power values
%% frequency bands
y_low = Yb(f_low); % LOW frequency spectrum
Yc=sum(y_low);
% Summing all the power values from one frequency spectrum together
% so you get one power value from one spectrum
ValuesOfYc(m) = Yc;
%Output values are being saved here, which are generated from the for
%loop
% m = start variable from for loop
[pks, locs] = findpeaks(ValuesOfYc);
subplot(2,1,1)
p=plot(x,ValuesOfYc,'r-', x(locs(pks>=5000)), pks(pks>=5000),'ob');
p(1).LineWidth =0.5;
xlabel('time (Audio length)')
ylabel('Power')
grid on
si=si+windowshift;
% Updating start index
ei=ei+windowshift;
% Updating end index
end
for o= 1:1:N
y_a = y(si:ei);
% a segment is taken out from audio signal length(30ms)
y_a= y_a.*window;
% multiplying segment with window (hanning)
Ya=fft(y_a, fftlen);
% Applying fft on segment
Yb=abs(Ya(1:end/2)).^2;
% Squaring the magnitudes from one-sided spectrum
drawnow; % Updating the graphical values
figure(f1);
% Showing the power values
[![enter image description here][1]][1]
%% frequency bands
y_medium = Yb(f_medium); % MEDIUM frequency spectrum
y_high = Yb(f_high); % HIGH frequency spectrum
Yd=sum(y_medium);
Ye=sum(y_high);
% Summing all the power values from one frequency spectrum together
% so you get one power value from one spectrum
ValuesOfYd(o) = Yd;
ValuesOfYe(o) = Ye;
%Output values are being saved here, which are generated from the for
%loop
% m = start variable from for loop
subplot(2,1,2)
p=plot(x, ValuesOfYd,'g-', x, ValuesOfYe,'b-' );
p(1).LineWidth =0.5;
xlabel('time (Audio length)')
ylabel('Power')
grid on
si=si+windowshift;
% Updating start index
ei=ei+windowshift;
% Updating end index
end

How to do a frequency band?

Here in this code i am doing a stft on my wav-file. There is no problem with that. At the beginning, i am defining my parameter, afterwards using my wav file and then applying the stft. Basically what i am doing is a real-time spectral analysis. Anyway my question is, how do i a frequency band? I want my signal to be separated in LOW/MEDIUM/HIGH. I want my vector to be saved, from 0-250 Hz in the LOW-Band, 250-5000 Hz in the MEDIUM-Band, 5-22.05k Hz in the HIGH-Band. I advise you, to try my code in Matlab, if you don't understand it. Just take any wav-file. Btw my signal is plotted in the variable "Yres". Any solution is appreciated!
NFA=2; % Number is used for plotting every 2nd picture
t_seg=0.05; % Length of segment in ms
fftlen = 4096;
% Lenght of "fft",because our segment contains 2205 points
[y,fs]=audioread('UnchainMyHeart.wav');
% audioread = functions reads WAV-file
% y = A vector which contains my audio signal
% fs = sample frequency (44100)
% 'UnchainMyHeart' = WAV-file
t=linspace(0,length(y)/fs,length(y));
% linspace = Creating time vector
% 0 = Start time
% length(y)/fs = End time
% length(y) = Number of samples in y
plot(t,y)
% plotting signal in the time domain
segl =floor(t_seg*fs);
% Applying fft function on the variable "segl"
windowshift=segl/2;
% Defining the size of the window, which goes to the next "segl"
window=hann(segl);
% hann function
window=window.';
si=1;
%Start index
ei=segl;
%End index
AOS= length(y)/windowshift - 1;
% AOS is the number of "segl" we use (About 433)
f1=figure;
% Opening new window
f=0:1:fftlen-1;
f=f/(fftlen-1)*fs;
% Defining frequency vector
Ya=zeros(1,fftlen);
plot(f,Ya),axis([0 fs -90 50])
grid on
n=0;
%start variable
for m= 1:1:AOS
y_a = y(si:ei);
y_a= y_a.*window;
Ya=fft(y_a, fftlen);
n=n+1;
if n==1
Yres=abs(Ya);
else
Yres=Yres+abs(Ya);
end
if n==NFA
Yres=Yres/NFA;
n=0;
drawnow;
%Tut die Grafikobjekte immer auf den neuesten Stand updaten
figure(f1);
plot(f(1:end/2), 20*log10(abs(Yres(1:end/2))));
ylim([-90 50]);
title('Spektrum eines Audiosignal');
xlabel('f(Hz)');
ylabel('dB');
grid on;
end
si=si+windowshift;
% Updating start index
ei=ei+windowshift;
% Updating end index
end
This may not be the best answer! But this may help you get started on something. You can use spectrogram() function from MATLAB's Signal Processing Toolbox.
Let's suppose you have an audio file named ''UnchainMyHeart.wav'(in your case) with one channel. The code goes as follows:
% Reading the audio file
[y1,fs] = audioread('UnchainMyHeart.wav');
% Parameters for STFT (or spectrogram)
windowDuration = 30e-3; overlapDuration = 15e-3;
windowLength = round(windowDuration*fs); % window length
overlapLength = round(overlapDuration*fs); % overlapping of windows
nfft = 1024;
% Executing STFT for the signal
[S1,F1,T1,P1] = spectrogram(x1,hanning(windowLength), ...
overlapLength, nfft, fs, 'yaxis');
S1 and P1 contain STFT and Power Spectrum Density(PSD) of the signal for a time interval of each section with a time interval whose estimations are contained in T1.
For your question, you are looking for F1 which is a vector of cyclical frequencies expressed in terms of sampling frequency, fs. For example: if you have a sampling frequency of 48 kHz (fs) and nfft of 1024, then you will have 513 [(1024/2) +1)] frequency values spaced by (fs/nfft). i.e. 46.875. So your frequency components will be 0, 46.875, 46.875*2, ..., 46.875*512. The maximum you will have is 24 kHz due to Nyquist criterion.
Now, you can easily write a simple routine specifying the ranges as you said. The same technique can be used in your code which is an implementation of stft. I would suggest using MATLAB's built-in function unless your problem requires an implementation. Hope this helps!
If needed, I can answer why the parameters for STFT are chosen as included in the code.

Ways to Compute Spectrum Matlab

I have a question while computing the spectrum of a time series in Matlab. I have read the documentations concerning 'fft' function. However I have seen two ways of implementation and both wgive me different results. I would appreciate to have some answer about this difference:
1st Method:
nPoints=length(timeSeries);
Time specifications:
Fs = 1; % samples per second
Fs = 50;
freq = 0:nPoints-1; %Numerators of frequency series
freq = freq.*Fs./nPoints;
% Fourier Transform:
X = fft(timeSeries)/nPoints; % normalize the data
% find find nuquist frequency
cutOff = ceil(nPoints./2);
% take only the first half of the spectrum
X = abs(X(1:cutOff));
% Frequency specifications:
freq = freq(1:cutOff);
%Plot spectrum
semilogy(handles.plotLoadSeries,freq,X);
2nd Method:
NFFT = 2^nextpow2(nPoints); % Next power of 2 from length of y
Y = fft(timeSeries,NFFT)/nPoints;
f = 1/2*linspace(0,1,NFFT/2+1);
% % Plot single-sided amplitude spectrum.
% plot(handles.plotLoadSeries, f,2*abs(Y(1:NFFT/2+1)))
semilogy(handles.plotLoadSeries,f,2*abs(Y(1:NFFT/2+1)));
I thought that it is not necessary to use 'nextpow' function in 'fft' function in Matlab. Finally, which is the good one?
THanks
The short answer: you need windowing for spectrum analysis.
Now for the long answer... In the second approach, you are using an optimised FFT algorithm useful when the length of the input vector is a power of two. Let's assume that your original signal has 401 samples (as in my example below) from an infinitely long signal; nextpow2() will give you NFFT=512 samples. When you feed the shorter, 401-sample signal into the fft() function, it is implicitly zero-padded to match the requested length of 512 (NFFT). But (here comes the tricky part): zero-padding your signal is equivalent to multiplying an infinitely long signal by a rectangular function, an operation that in the frequency domain translates to a convolution with a sinc function. This would be the reason behind the increased noise floor at the bottom of your semilogarithmic plot.
A way to avoid this noise increase is to create manually the 512-sample signal you want to feed into fft(), using a smoother window function instead of the default rectangular one. Windowing means just multiplying your signal by a tapered, symmetric one. There are tons of literature on choosing a good windowing function, but a typically accurate one with low sidelobes (low noise increase) is the Hamming function, implemented in MATLAB as hamming().
Here is a figure illustrating the issue (in the frequency domain and time domain):
...and the code to generate this figure:
clear
% Create signal
fs = 40; % sampling freq.
Ts = 1/fs; % sampling period
t = 0:Ts:10; % time vector
s = sin(2*pi*3*t); % original signal
N = length(s);
% FFT (length not power of 2)
S = abs(fft(s)/N);
freq = fs*(0:N-1)/N;
% FFT (length power of 2)
N2 = 2^nextpow2(N);
S2 = abs(fft(s, N2)/N2);
freq2 = fs*(0:N2-1)/N2;
t2 = (0:N2-1)*Ts; % longer time vector
s2 = [s,zeros(1,N2-N)]; % signal that was implicitly created for this FFT
% FFT (windowing before FFT)
s3 = [s.*hamming(N).',zeros(1,N2-N)];
S3 = abs(fft(s3, N2)/N2);
% Frequency-domain plot
figure(1)
subplot(211)
cla
semilogy(freq,S);
hold on
semilogy(freq2,S2,'r');
semilogy(freq2,S3,'g');
xlabel('Frequency [Hz]')
ylabel('FFT')
grid on
legend( 'FFT[401]', 'FFT[512]', 'FFT[512] with windowing' )
% Time-domain plot
subplot(212)
cla
plot(s)
hold on
plot(s3,'g')
xlabel('Index')
ylabel('Amplitude')
grid on
legend( 'Original samples', 'Windowed samples' )

How would i down-sample a .wav file then reconstruct it using nyquist? - in MATLAB

This is all done in MATLAB 2010
My objective is to show the results of: undersampling, nyquist rate/ oversampling
First i need to downsample the .wav file to get an incomplete/ or impartial data stream that i can then reconstuct.
Heres the flow chart of what im going to be doing So the flow is analog signal -> sampling analog filter -> ADC -> resample down -> resample up -> DAC -> reconstruction analog filter
what needs to be achieved:
F= Frequency
F(Hz=1/s) E.x. 100Hz = 1000 (Cyc/sec)
F(s)= 1/(2f)
Example problem: 1000 hz = Highest
frequency 1/2(1000hz) = 1/2000 =
5x10(-3) sec/cyc or a sampling rate of
5ms
This is my first signal processing project using matlab.
what i have so far.
% Fs = frequency sampled (44100hz or the sampling frequency of a cd)
[test,fs]=wavread('test.wav'); % loads the .wav file
left=test(:,1);
% Plot of the .wav signal time vs. strength
time=(1/44100)*length(left);
t=linspace(0,time,length(left));
plot(t,left)
xlabel('time (sec)');
ylabel('relative signal strength')
**%this is were i would need to sample it at the different frequecys (both above and below and at) nyquist frequency.*I think.***
soundsc(left,fs) % shows the resaultant audio file , which is the same as original ( only at or above nyquist frequency however)
Can anyone tell me how to make it better, and how to do the sampling at verious frequencies?
heres the .wav file http://www.4shared.com/audio/11xvNmkd/piano.html
EDIT:
%Play decimated file ( soundsc(y,fs) )
%Play Original file ( soundsc(play,fs ) )
%Play reconstucted File ( soundsc(final,fs) )
[piano,fs]=wavread('piano.wav'); % loads piano
play=piano(:,1); % Renames the file as "play"
t = linspace(0,time,length(play)); % Time vector
x = play;
y = decimate(x,25);
stem(x(1:30)), axis([0 30 -2 2]) % Original signal
title('Original Signal')
figure
stem(y(1:30)) % Decimated signal
title('Decimated Signal')
%changes the sampling rate
fs1 = fs/2;
fs2 = fs/3;
fs3 = fs/4;
fs4 = fs*2;
fs5 = fs*3;
fs6 = fs*4;
wavwrite(y,fs/25,'PianoDecimation');
%------------------------------------------------------------------
%Downsampled version of piano is now upsampled to the original
[PianoDecimation,fs]=wavread('PianoDecimation.wav'); % loads piano
play2=PianoDecimation(:,1); % Renames the file as "play
%upsampling
UpSampleRatio = 2; % 2*fs = nyquist rate sampling
play2Up=zeros(length(PianoDecimation)*UpSampleRatio, 1);
play2Up(1:UpSampleRatio:end) = play2; % fill in every N'th sample
%low pass filter
ResampFilt = firpm(44, [0 0.39625 0.60938 1], [1 1 0 0]);
fsUp = (fs*UpSampleRatio)*1;
wavwrite(play2Up,fsUp,'PianoUpsampled');
%Plot2
%data vs time plot
time=(1/44100)*length(play2);
t=linspace(0,time,length(play2));
stem(t,play2)
title('Upsampled graph of piano')
xlabel('time(sec)');
ylabel('relative signal strength')
[PianoUpsampled,fs]=wavread('PianoUpsampled.wav'); % loads piano
final=PianoUpsampled(:,1); % Renames the file as "play"
%-------------------------------------------------------------
%resampleing
[piano,fs]=wavread('piano.wav'); % loads piano
x=piano(:,1); % Renames the file as "play"
m = resample(x,3,2);
Original:
http://www.4shared.com/audio/11xvNmkd/piano.html
New:
http://www.4shared.com/audio/nTRBNSld/PianoUs.html
The easiest thing to do is change sample rates by an integer factor. Downsampling consists of running the data through a low-pass filter followed by discarding samples, while upsampling consists of inserting samples then running the data through a low pass filter (also known as a reconstruction filter or interpolating filter). Aliasing occurs when the filtering steps are skipped or poorly done. So, to show the effect of aliasing, I suggest you simply discard or insert samples as required, then create a new WAV file at the new sample rate. To discard samples, you can do:
DownSampleRatio = 2;
%# Normally apply a low pass filter here
leftDown = left(1:DownSampleRatio:end); %# extract every N'th sample
fsDown = fs/DownSampleRatio;
wavwrite(leftDown, fsDown, filename);
To create samples you can do:
UpSampleRatio = 2;
leftUp = zeros(length(left)*UpSampleRatio, 1);
leftUp(1:UpSampleRatio:end) = left; %# fill in every N'th sample
%# Normally apply a low pass filter here
fsUp = fs*UpSampleRatio;
wavwrite(leftUp, fsUp, filename);
You can just play back the written WAV files to hear the effects.
As an aside, you asked for improvements to your code - I prefer to initialize the t vector as t = (0:(length(left)-1))/fs;.
The DSP technique you need is called decimation.