Why does my FFT return all zeros for certain sound files?
    8 visualizaciones (últimos 30 días)
  
       Mostrar comentarios más antiguos
    
    LJC
 el 24 de Mzo. de 2021
  
    
    
    
    
    Comentada: Mathieu NOE
      
 el 25 de Mzo. de 2021
            Hi!
I've been working on a Equaliser and I want it to display a frequency-domain graph from an audio file that is read. I had it working, at least so I thought, so I was experimenting with all the sound files I could find. (The application allows .wav, .flac, .m4a and .mp3 files). 
For almost all of the files I have tried the code (shown below) works, as seen in this picture.

Then this is the ouput I get with one of two .mp3 files. The matlab code plays the file, and it clearly reads it correctly due to the top display showing the waveform. 

Below is the code that I am using:
                file = app.SelectFileDropDown.Value;
                [y,Fs] = audioread(file);
                n = length(y);
                t = 0:seconds(1/Fs):seconds(n/Fs);
                t = t(1:end-1);
                plot(app.VisualiserDisplay,t, y); % This displays the waveform at the top
                N = 2^12;
                j = 0:N-1;
                f = (Fs/N).*j;
                X = fft(y,N); % This is _supposed_ to display the graph at the bottom
                semilogx(app.EqualiserDisplay, f(1:round(20000/(Fs/N))),20*log(abs(X(1:round(20000/(Fs/N))))));
I was playing around to try and determine why it wasn't working and discovered that for the files that don't work the 'double' X is filled with all zeros but y is not! For the working files, X is filled with complex numbers, as it should be. Can anyone suggest why this might be happening? It seems rather random that some files return all zeros and others work as intended?
Thanks in advance!   
2 comentarios
Respuesta aceptada
  Mathieu NOE
      
 el 24 de Mzo. de 2021
        Luke - see above 
again : 
I found where the issue is on the OP code - 
  N = 2^12;
  j = 0:N-1;
  f = (Fs/N).*j;
  X = fft(y,N); % This is _supposed_ to display the graph at the bottom
the issue is that this is not an averaged fft for the entire signal duration !! 
this takes only the first N samples of data and display the fft of that single data buffer 
read the fft help : 
  %   FFT(X,N) is the N-point FFT, 
  %  padded with zeros if X has less   than N points and truncated if it has more.
in the case of that specific audio file , the first N samples are  zero (indeed the first 10,000 samples are zero) , so the fft = 0 all the same.

if one would do an averaged fft for the entire signal , this is my home made fft  function : 
  function  [freq_vector,fft_spectrum] = myfft_peak(signal, Fs, nfft, Overlap)
% FFT peak spectrum of signal  (example sinus amplitude 1   = 0 dB after fft).
% Linear averaging
%   signal - input signal, 
%   Fs - Sampling frequency (Hz).
%   nfft - FFT window size
%   Overlap - buffer percentage of overlap % (between 0 and 0.95)
signal = signal(:);
samples = length(signal);
% fill signal with zeros if its length is lower than nfft
if samples<nfft
    s_tmp = zeros(nfft,1);
    s_tmp((1:samples)) = signal;
    signal = s_tmp;
    samples = nfft;
end
% window : hanning
window = hanning(nfft);
window = window(:);
%    compute fft with overlap 
 offset = fix((1-Overlap)*nfft);
 spectnum = 1+ fix((samples-nfft)/offset); % Number of windows
%     % for info is equivalent to : 
%     noverlap = Overlap*nfft;
%     spectnum = fix((samples-noverlap)/(nfft-noverlap));	% Number of windows
    % main loop
    fft_spectrum = 0;
    for i=1:spectnum
        start = (i-1)*offset;
        sw = signal((1+start):(start+nfft)).*window;
        fft_spectrum = fft_spectrum + (abs(fft(sw))*4/nfft);     % X=fft(x.*hanning(N))*4/N; % hanning only 
    end
    fft_spectrum = fft_spectrum/spectnum; % to do linear averaging scaling
% one sidded fft spectrum  % Select first half 
    if rem(nfft,2)    % nfft odd
        select = (1:(nfft+1)/2)';
    else
        select = (1:nfft/2+1)';
    end
fft_spectrum = fft_spectrum(select);
freq_vector = (select - 1)*Fs/nfft;
end
4 comentarios
Más respuestas (0)
Ver también
Categorías
				Más información sobre Discrete Fourier and Cosine Transforms en Help Center y File Exchange.
			
	Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!

