WICHTIG: Der Betrieb von goMatlab.de wird privat finanziert fortgesetzt. - Mehr Infos...

Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   

Partner:




Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

iDFT

 

ovib

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 23.08.2011, 10:07     Titel: iDFT
  Antworten mit Zitat      
Hallo zusammen,

ich lese eine Wave audiodatei ein und möchte diese im Frequenzspektrum bearbeiten. Dafür muss ich den Betrag im Frequenzbereich bilden. Die Phase speichere ich vorher ab und füge sie dem Betrag nach der Bearbeitung wieder hinzu. Leider liefert die Rücktransformation nicht das gewünschte Ergebnis.

Hier der Code:

Code:

Fs = 22000;        
W_size = 256;       % Window size (number of samplings)
y = wavread('.....xy.wav');
w = rectwin(W_size);%Rectangular window
L = length(y);      % length of signal
Lw= length(w);      %l ength of window

%% Window and DFT
NFFT = 2^nextpow2(W_size); % Next power of 2 from length of window
f = Fs/2*linspace(0,1,NFFT/2); % dient nur zum plotten
Nframes=floor(L/Lw);        % abrunden, dabei gehen einige Punkte verloren; Ist aber nicht weiter schlimm
for i=1:Nframes
yw(:,i) = w.*y([(1+W_size*(i-1)):(W_size+W_size*(i-1))],1); %In jeder Spalte steht das entsprechende gefensterte Signal
y_jw = fft(yw,NFFT)/Lw;       %DFT frequency domain
end;  

%% Angle and Absolute Value

y_phase = angle(y_jw);  % Phase of y_jw (will be added to the signal at the end
Y_jw = abs(y_jw)

Y_jw = Y_jw(:);  % aus der Matrix wird wieder ein Zeilenvektor
y_phase = y_phase(:);
X_jw = Y_jw.*exp(i*y_phase); % Hinzufügen der Phase

%% iDFT

X = real(ifft(X_jw));
 

Das ich hier ein Rechteckfenster (statt Hanning) nehme liegt daran, dass die Wavedatei eine Abtastfrequenz von 22kHz hat und das Signal mit einem Mikrofon von maximal 5kHz wohl schmalbandig genug sein müsste (Leakage).
Was muss ich verändern damit Ausgangs- und Eingangssignal gleich sind?

Danke


DSP
Forum-Meister

Forum-Meister



Beiträge: 2.117
Anmeldedatum: 28.02.11
Wohnort: ---
Version: R2014b
     Beitrag Verfasst am: 23.08.2011, 12:43     Titel:
  Antworten mit Zitat      
Hiermit sollte es gehen...

Code:

...
y_jw = zeros(NFFT,Nframes); % preallocate
yw = zeros(NFFT,1);
for i=1:Nframes
    yw = w.*y([(1+W_size*(i-1)):W_size*(i)],1); % i. Segment der Länge W-size aus Daten entnehmen und mit Fenster multiplizieren
    y_jw(:,i) = fft(yw,NFFT)/Lw;       %DFT frequency domain
end;  

% Angle and Absolute Value
Phase = angle(y_jw);  % Phase of y_jw (will be added to the signal at the end
Betrag = abs(y_jw);
% Real- und Imaginärteil
Re = Betrag .* cos(Phase);  
Im = Betrag .* sin(Phase);
X_jw = complex(Re,Im);
X = zeros(size(X_jw)); % preallocate
% iDFT - Segmentweise
for i=1:Nframes
   X(:,i) = real(ifft(X_jw(:,i),NFFT));
end
X = X(:)*Lw; % Skalierung von fft rückgängig machen
 


Die ifft musst du auch wieder Segmentweise durchführen. Gibt es einen Grund, warum du dein Signal in Segmente zerlegst? Die Fensterung mit einem Rechteck kann man sich auch sparen...ich vermute aber mal, dass dies für andere Fenstertypen implementiert worden ist. Was ich aber nicht verstehe, warum X am Ende komplex ist, obwohl ich als Testsignal ein reelles Signal genommen habe.
Private Nachricht senden Benutzer-Profile anzeigen
 
ovib

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 24.08.2011, 07:31     Titel:
  Antworten mit Zitat      
Hallo DSP,

es hat geklappt. Danke!
Allerdings habe ich
Code:

for i=1:Nframes
  y_jw(:,i) = fft(yw,NFFT)/Lw;
end

verwandelt in
Code:

for i=1:Nframes
  y_jw = fft(yw,NFFT)/Lw;
end

Damit klappts.
Eine Frage noch wieso muss man das Ausgangssignal mit Lw multiplizieren bzw. wieso muss man das Eingangssignal in der FFT mit Lw normieren?
 
DSP
Forum-Meister

Forum-Meister



Beiträge: 2.117
Anmeldedatum: 28.02.11
Wohnort: ---
Version: R2014b
     Beitrag Verfasst am: 24.08.2011, 08:58     Titel:
  Antworten mit Zitat      
Zu 1) Wenn du dein Zeitsignal in Segmente zerlegst (hier mit einer Länge von 256) dann überschreibst du doch jedesmal die Transformierte und hast am Ende nur noch das letzte Segment im Frequenzbereich. Das Abspeichern jedes Segments hatte schon seinen Sinn...

Code:
y_jw(:,i) = fft(yw,NFFT)/Lw;


Warum zerlegst du dein Signal überhaupt in Segmente...habe ich auch schon gefragt Wink

Zu 2) Die Skalierung erfolgt, damit das Amplitudenspektrum richtig dargestellt wird. Wenn du das Spektrum nicht plotten willst, sondern lediglich das Signal veränderst, kannst du es auch weglassen. Bei einem Sinus mit Amplitude 10 muss ja auch im Frequenzbereich ein Peak der Höhe 10 bei der Freq. des Sinus sein. Das gilt allerdings nur, wenn man nur das positive Frequenzspektrum darstellt und kein Leakage-effekt auftritt. Schau dir mal in der Skript-Ecke das 'umfassende FFT Beispiel' an. Dort werden die verschiedenen Skalierungen gezeigt.

http://www.gomatlab.de/fft-umfassendes-beispiel-t777.html
Private Nachricht senden Benutzer-Profile anzeigen
 
Neues Thema eröffnen Neue Antwort erstellen



Einstellungen und Berechtigungen
Beiträge der letzten Zeit anzeigen:

Du kannst Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.
Du kannst Dateien in diesem Forum posten
Du kannst Dateien in diesem Forum herunterladen
.





 Impressum  | Nutzungsbedingungen  | Datenschutz | FAQ | goMatlab RSS Button RSS

Hosted by:


Copyright © 2007 - 2024 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks

MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.