2017-01-30 4 views
0

Dies ist die Art von Handlung, die ich mir vorgestellt habe.Visualisierung fft-signal__Waterplot

https://de.mathworks.com/help/matlab/ref/waterfall.html

Ok, ich will nicht zu viel erklären, wie mein Code funktioniert. Es würde zu viel Zeit brauchen. Probieren Sie den zweiten Code einfach selbst aus. Nehmen Sie eine kleine WAV-Datei, die Sie finden können. Wenn Sie den Code kompilieren, können Sie drei Frequenzbänder sehen und sehen, dass viele Spektren alle 30 ms geplottet werden. Wenn Sie eine spezielle Frage zu meinem Code haben, wie es funktioniert, fragen Sie mich in den Kommentaren.

Ich möchte jedes Spektrum, zumindest aus einem Frequenzband, in einem 3-dimensionalen Diagramm plotten. Kurz gesagt, was sind die Koordinaten des ersten Spektrums und der 2., 3., 4. und so weiter. Mein Zeitsegment, auf das ein FFT angewendet wird, ist 30 ms lang. Der erste Punkt auf der x-Achse ist 30 ms, der nächste auf 60 ms und der nächste auf 90 ms und so weiter. Was ist die Y-Koordinate von den 30ms? Dies wäre auf der Frequenzachse oder der Y-Achse. Die z-Achse wäre die Größe einer Frequenzkomponente zu einem bestimmten Zeitpunkt (oder bei einem gegebenen gleitenden Fensterrahmen). Wie kann ich das tun? Wie schreibe ich das? Ich habe große Probleme mit dieser Angelegenheit. Und da jede Erklärung in einer anderen Sprache ist, wird es für mich viel schwieriger.

Wie Sie vielleicht wissen, habe ich ein Audiofile (Musik), auf dem ich eine STFT berechnen. Ich möchte es mir vorstellen. Siehe die folgende Erklärung in meinem Code. Lesen Sie die Kommentare!

Meine erste Idee auf diese Weise war die Verwendung der Funktion "Mesh" oder etwas ähnliches.

Hier mein maschen Code ist:

X=1:10; 
Y=1:15; 
Z = []; 

% Here i would define the number of time segments 
% See the next following code, to understand, what i mean. 
for i = 1:length(X) 

    % Here in this line, i want to compute my short fft 
    % 

    % number of frequencies 
    for j = 1: length(Y) 
     Z(j,i) = 1.0/(i*j); 
    end 
end 

mesh(X,Y,Z) 

Dieser Code zeichnet mich ein Netz, ich wollte nur für mich wissen, wie das funktioniert. Wie dem auch sei, ich bin mir ziemlich sicher, dass ich nicht weiß, wie die Funktion "Mesh" in vollem Umfang funktioniert, aber ich denke, ich habe das meiste verstanden. Eine andere Sache, die ich erwähnen muss ist, dass ich Frequenzbänder in meinem nächsten folgenden Code definiere. Ich tat dies, weil ich bemerkte, dass ich sehr hohe Amplituden in einem Bereich von 1 - 1000Hz habe, weshalb ich 3 Frequenzbänder definiert habe. Es ist nicht notwendig, alle von ihnen zu zeichnen, aber ich möchte mindestens eins visualisieren. Nicht den gesamten Frequenzbereich aus dem Audiosignal sichtbar machen, sondern nur das spezifisch gewählte Band.

%% MATLAB 
%_________________________________________ 
[y,fs]=audioread('dontstopmenow.wav'); 
% audioread = Read WAV-file 
% y = Vector, which contains audio signal 
% fs = Sample Rate 
% 'dontstopmenow' = WAV-file 
%_________________________________________ 


%PARAMETER FOR STFT 
%_________________________________________ 
t_seg=0.03; % Length of segment in ms 

fftlen = 4096; %FFT-Points 

%Defining the length of my frequency bands 
f_LOW= 1:200; % contain lower frequencies 
f_MEDIUM= 201:600; % contain medium frequencies 
f_HIGH= 601:1000; % contain higher frequencies 

%_______________________________________________________ 

segl =floor(t_seg*fs); 
% Length of segment, on which we use the fft 
% "floor" rounds off the result 
windowshift=segl/2; 
% size of window which goes to the next segment 
window=hann(segl); 
%hann function 
window=window.'; 
% From a row vector to a column vector 
si=1; 
%Start index 
ei=segl; 
%End index 

N= length(y)/windowshift - 1; 
% Number of time segements in audio signal 

f1=figure; 
    % New window 

    f=0:1:fftlen-1; 
    f=f/(fftlen-1)*fs; 
    % frequency vector 

    Ya=zeros(1,fftlen); 
    %Plotting time segments!   
for m= 1:1:N 

    y_a = y(si:ei); 
    y_a= y_a.*window; 
    Ya=fft(y_a, fftlen); 
    Ya=abs(Ya(1:end/2)); 
     %One-sided-spectrum 

     drawnow; %Updates graphical objects 

    figure(f1); 
    plot(f(1:end/2), 20*log10(Ya)); 
    %STFT __ plots the whole audio signal after a stft, every 30ms 

    %% L,M,H - Bands 
    subplot(3,1,1) 
    y_low = Ya(f_LOW); 
    plot(f_LOW,y_low); 
    ylim([-20 60]); 
    title('Spektrum (LOW)'); 
    xlabel('f(Hz)'); 
    ylabel('dB'); 
    grid on 

    subplot(3,1,2) 
    y_medium = Ya(f_MEDIUM); 
    plot(f_MEDIUM,y_medium); 
    ylim([-20 30]); 
    title('Spektrum (MEDIUM)'); 
    xlabel('f(Hz)'); 
    ylabel('dB'); 
    grid on 

    subplot(3,1,3) 
    y_high = Ya(f_HIGH); 
    plot(f_HIGH,y_high); 
    ylim([-20 30]); 
    title('Spektrum (HIGH)'); 
    xlabel('f(Hz)'); 
    ylabel('dB'); 
    grid on; 


    si=si+windowshift; 
    % start index updated  
    ei=ei+windowshift; 
    % end index updated 

end 

Antwort

0

Hier ist die Liste von Anweisungen, die Sie in Ihren Code hinzufügen könnte den Wasserfall Plot zu generieren:

Lassen Sie uns speichern alle STFT Ausgänge in einer Matrix Yb benannt. Ordnen Sie zuerst den Speicher zu, indem Sie diese Zeile vor der for-Schleife hinzufügen.

Als nächstes speichern Sie in der for-Schleife das fft-Ergebnis für jedes Segment. Dies kann durch Hinzufügen der folgenden Zeile nach Abschluss der Berechnung von Ya (kurz vor drawnow) erfolgen.

Yb(m,:) = Ya; 

Jetzt können Sie das Wasserfalldiagramm erstellen. Dies kann durch Hinzufügen des folgenden Codes nach dem Ende der for-Schleife erfolgen.

figure; 
waterfall(f(f_LOW), (1:N)*windowshift/fs, Yb(:,f_LOW)); 
xlabel('Frequency (Hz)'); 
ylabel('Time (s)'); 

Hoffe, dies wird erreicht, was Sie wollen.

Es folgt nicht auf die Hauptfrage im Zusammenhang: Ich habe auch die folgenden Vorschläge einige andere Aspekte des Codes zu verbessern:

(1) Die Berechnung des Frequenzraster f hat einen kleinen Skalierungsfehler. Es sollte sein:

f=f/fftlen*fs; 

(2) In Abhängigkeit von der WAV Datei, die Sie verwenden, können Sie Ihren Code Bruchwerte in windowshift und N, aber beide müssen ganze Zahlen sein. Verwenden Sie entsprechende Rundungsmethoden, um sie zu berechnen. Ich würde vorschlagen, die folgende:

(3) In der for-Schleife, können Sie die ganze fft plotten nur sofort, dass mit den Nebenhandlungen zu überschreiben. Diese Zeile sollte entfernt werden.

+0

Hallo! Zuerst, danke, dass Sie das gelesen haben und mir einige Lösungen zur Verfügung gestellt haben. Bevor Sie das tun, können Sie mir ein paar Fragen beantworten? Was bedeutet "NaN" in der ersten Codezeile, die du geschrieben hast? Ich möchte es verstehen, damit ich daraus lernen kann. Zu den von Ihnen vorgeschlagenen Improvisationen bezüglich Nummer 1: Warum ist es ein Skalierungsfehler und warum sollte dies nicht gemacht werden? Es tut mir leid, wenn ich nervig bin, aber für mich ist es sehr wichtig, meine Fehler zu verstehen! – CidelFastro

+0

Kein Problem. Ich habe 'NaN' verwendet, um die Matrix' Yb' zu initialisieren, ähnlich wie man 'Nullen' benutzt, um' Ya' zu initialisieren. Wir hätten auch 'Nullen' für' Yb' verwenden können, aber ich persönlich bevorzuge stattdessen 'NaN'. Es steht für [Not-a-number] (https://www.mathworks.com/help/matlab/ref/nan.html) und hilft mir manchmal, dumme Fehler in meinem Code zu finden. Wenn zum Beispiel irgendein Teil meines Codes 'Yb' verwendet hat, bevor seine Werte tatsächlich berechnet wurden, würde sich 'NaN' auf mehr Variablen ausbreiten, und der Effekt wäre leichter zu bemerken. – aksadv

+0

Bezüglich des Skalierungsfehlers, auf den ich bei der Berechnung der Position von Frequenzbins hingewiesen habe: Beachten Sie, dass aus der Definition von FFT der Abstand zwischen FFT-Bins "fs/fftlen" ist. Die ersten, zweiten und dritten Bins wären also "0", "fs/fftlen" und "2 * fs/fftlen" Hz. Der bin-Abstand in Ihrem Code war gleich "fs/(fftlen-1)". Beachten Sie auch, dass mit der richtigen Formel die Häufigkeit des letzten Bins "Fs-Fs/fftlen" (äquivalent zu "-Fs/fftlen") wäre, während in Ihrem Code "Fs" (entspricht 0, was wäre das gleiche wie der erste bin). – aksadv