Greetings All
I have an fft function in matlab/octave that works great on an imported mono wav/audio signal that is 1 second long, but when the signal imported is more than 1 second the frequency values become incorrect. To check this I created a 2 second signal using audacity the first half of the 2 second signal (1 second of it) was 500hz at 0.3 amplitude and the second half of the 2 second signal (1 second of it) was 200hz at 0.8 amplitude. I also checked it with audacity's analyse spectrum option.
When I use the function on this 2 second signal it shows that the max frequency is at 999.95hz when it should show the max frequency is at 200hz. Can anyone help me get this function to work with signals greater than just 1 second.
I've included the function along with the code that calls the function.
**The FUNCTION:**
function [freq,amp,ampinv,phase,phase_radtodeg,phase_degtorad,phase_adjindeg,phase_adjinrad,sigfft,sigifft,sigphase]=rtfftphase(vp_sig_orig,Fs,phase_goal)
vp_sig_orig = vp_sig_orig - mean(vp_sig_orig); %remove the mean of your signal due to dc offset
vp_sig_orig=vp_sig_orig';
vp_sig_len=length(vp_sig_orig); %get sample rate from vp fs_rate needs to be an even number?
% Use next highest power of 2 greater than or equal to length(x) to calculate FFT.
nfft= 2^(nextpow2(length(vp_sig_orig)));
% Take fft, padding with zeros so that length(fftx) is equal to nfft
fftx = fft(vp_sig_orig,nfft);
sigfft= fft(vp_sig_orig);
sigifft=ifft(sigfft);
sigphase = unwrap(angle(sigfft')); %get phase of orginal signal
% Calculate the number of unique points
NumUniquePts = ceil((nfft+1)/2);
% FFT is symmetric, throw away second half
fftx = fftx(1:NumUniquePts);
% Take the magnitude of fft of x and scale the fft so that it is not a function of the length of x
mx = abs(fftx)/length(vp_sig_orig); %replaced for testing from stackexchage
% Since we dropped half the FFT, we multiply mx by 2 to keep the same energy.
% The DC component and Nyquist component, if it exists, are unique and should not be multiplied by 2.
if rem(nfft, 2) % odd nfft excludes Nyquist point
mx(2:end) = mx(2:end)*2;
else
mx(2:end -1) = mx(2:end -1)*2;
end
%yamp=(mx(1,:)/max(abs(mx(1,:)))*1); % keep at 1, dont use in function use in script file directly
amp=mx;
ampinv=abs(amp-max(amp));
% This is an evenly spaced frequency vector with NumUniquePts points.
freq_vect = (0:NumUniquePts-1)*vp_sig_len/nfft;
freq=(freq_vect'); %take of round if you want exact numbers
%get phase of new signal
phase = unwrap(angle(fftx)); %get phase of orginal signal
%phase stuff phase adj stuff not fully done yet I don't know the correct way to use it leave at 0 for now
phase_radtodeg=rtrad2deg(phase); %also check sigphase to see if it's the same.
phase_degtorad=rtdeg2rad(phase_radtodeg); %for checking
phase_adjindeg=phase_goal-phase_radtodeg; %used to create new phase to get to goal phase
phase_adjinrad=rtdeg2rad(phase_adjindeg);
**Example: that calls the function**
imported_sig_L=imported_sig(:,1)';
[xfreq_orig,yamp_orig,yamp_inv,phase_orig,phase_in_deg,phase_in_rad,phase_adjindeg,phase_adjinrad,sigfft,sigifft,sigphase]=rtfftphase(imported_sig_L,fs_rate,0);
array1=[xfreq_orig,yamp_orig,yamp_inv,phase_orig,mod(phase_in_deg,360),phase_in_rad,phase_adjindeg,phase_adjinrad]; %have degs only go up to 360
%Sort Array Section
array1_sort_amp_norm=sortrows(array1,-2); %sort by amplitude
array1_sort_amp_inv=sortrows(array1,-3); %sort by amplitude inverse
%get max freq checking to make sure freq isn't zero if so go to next row
if (array1_sort_amp_norm(1,1)>0); % To get max amplitude
maxfreq_normA=array1_sort_amp_norm(1,1)
elseif (array1_sort_amp_norm(1,1)<=0); %
maxfreq_normA=array1_sort_amp_norm(2,1)
end
if (array1_sort_amp_inv(1,1)>0); % To get inverted max amplitude
maxfreq_invA=array1_sort_amp_inv(1,1)
elseif (array1_sort_amp_inv(1,1)<=0); %
maxfreq_invA=array1_sort_amp_inv(2,1)
end
Thanks
I have an fft function in matlab/octave that works great on an imported mono wav/audio signal that is 1 second long, but when the signal imported is more than 1 second the frequency values become incorrect. To check this I created a 2 second signal using audacity the first half of the 2 second signal (1 second of it) was 500hz at 0.3 amplitude and the second half of the 2 second signal (1 second of it) was 200hz at 0.8 amplitude. I also checked it with audacity's analyse spectrum option.
When I use the function on this 2 second signal it shows that the max frequency is at 999.95hz when it should show the max frequency is at 200hz. Can anyone help me get this function to work with signals greater than just 1 second.
I've included the function along with the code that calls the function.
**The FUNCTION:**
function [freq,amp,ampinv,phase,phase_radtodeg,phase_degtorad,phase_adjindeg,phase_adjinrad,sigfft,sigifft,sigphase]=rtfftphase(vp_sig_orig,Fs,phase_goal)
vp_sig_orig = vp_sig_orig - mean(vp_sig_orig); %remove the mean of your signal due to dc offset
vp_sig_orig=vp_sig_orig';
vp_sig_len=length(vp_sig_orig); %get sample rate from vp fs_rate needs to be an even number?
% Use next highest power of 2 greater than or equal to length(x) to calculate FFT.
nfft= 2^(nextpow2(length(vp_sig_orig)));
% Take fft, padding with zeros so that length(fftx) is equal to nfft
fftx = fft(vp_sig_orig,nfft);
sigfft= fft(vp_sig_orig);
sigifft=ifft(sigfft);
sigphase = unwrap(angle(sigfft')); %get phase of orginal signal
% Calculate the number of unique points
NumUniquePts = ceil((nfft+1)/2);
% FFT is symmetric, throw away second half
fftx = fftx(1:NumUniquePts);
% Take the magnitude of fft of x and scale the fft so that it is not a function of the length of x
mx = abs(fftx)/length(vp_sig_orig); %replaced for testing from stackexchage
% Since we dropped half the FFT, we multiply mx by 2 to keep the same energy.
% The DC component and Nyquist component, if it exists, are unique and should not be multiplied by 2.
if rem(nfft, 2) % odd nfft excludes Nyquist point
mx(2:end) = mx(2:end)*2;
else
mx(2:end -1) = mx(2:end -1)*2;
end
%yamp=(mx(1,:)/max(abs(mx(1,:)))*1); % keep at 1, dont use in function use in script file directly
amp=mx;
ampinv=abs(amp-max(amp));
% This is an evenly spaced frequency vector with NumUniquePts points.
freq_vect = (0:NumUniquePts-1)*vp_sig_len/nfft;
freq=(freq_vect'); %take of round if you want exact numbers
%get phase of new signal
phase = unwrap(angle(fftx)); %get phase of orginal signal
%phase stuff phase adj stuff not fully done yet I don't know the correct way to use it leave at 0 for now
phase_radtodeg=rtrad2deg(phase); %also check sigphase to see if it's the same.
phase_degtorad=rtdeg2rad(phase_radtodeg); %for checking
phase_adjindeg=phase_goal-phase_radtodeg; %used to create new phase to get to goal phase
phase_adjinrad=rtdeg2rad(phase_adjindeg);
**Example: that calls the function**
imported_sig_L=imported_sig(:,1)';
[xfreq_orig,yamp_orig,yamp_inv,phase_orig,phase_in_deg,phase_in_rad,phase_adjindeg,phase_adjinrad,sigfft,sigifft,sigphase]=rtfftphase(imported_sig_L,fs_rate,0);
array1=[xfreq_orig,yamp_orig,yamp_inv,phase_orig,mod(phase_in_deg,360),phase_in_rad,phase_adjindeg,phase_adjinrad]; %have degs only go up to 360
%Sort Array Section
array1_sort_amp_norm=sortrows(array1,-2); %sort by amplitude
array1_sort_amp_inv=sortrows(array1,-3); %sort by amplitude inverse
%get max freq checking to make sure freq isn't zero if so go to next row
if (array1_sort_amp_norm(1,1)>0); % To get max amplitude
maxfreq_normA=array1_sort_amp_norm(1,1)
elseif (array1_sort_amp_norm(1,1)<=0); %
maxfreq_normA=array1_sort_amp_norm(2,1)
end
if (array1_sort_amp_inv(1,1)>0); % To get inverted max amplitude
maxfreq_invA=array1_sort_amp_inv(1,1)
elseif (array1_sort_amp_inv(1,1)<=0); %
maxfreq_invA=array1_sort_amp_inv(2,1)
end
Thanks