Forum: Digitale Signalverarbeitung / DSP / Machine Learning MatLab: Gesampelte Sinusfunktionen erzeugen


von Delete M. (skywalker)


Angehängte Dateien:

Lesenswert?

Nicht zurückschrecken wegen der Länge. Mein Problem ist vermutlich 
relativ trivial, aber ich muss ertmal etwas drumherum erklären.

Ich möchte in MatLab eine Sprachanalyse/Sprachsynthese machen. Das ganze 
arbeitet übrigends frameweise. Ich lese also beispielsweise 4s vom 
Mikrofon mit 44,1 kHz ein und habe damit 4*44100 Samples. Diese werden 
in Frames mit fester Framegröße eingeteilt, beispielsweise 160 Samples 
sind 1 Frame. Am Ende der Analyse habe ich pro Frame noch max. 40 
Triplets (Amplitude, Phase, Frequenz). Aus diesen muss ich wieder einen 
Frame generieren. Dazu laufen diese zunächst durch einen Peak-Matching 
Algorithmus, welcher frequenzabhängig die Peaks des aktuellen Frames mit 
denen des nachfolgenden Frames "matched". Sinn des Matching ist es die 
Frequenz-Tracks frameübergreifend zu betrachten, damit die Übergänge 
zwischen den Frames weicher klingen.

Soviel zur Vorgeschichte. In der Synthese muss ich nun die Amplituden 
des Frames und die Phasen des Frames durch vorgegebene Formeln 
interpolieren (bei der Interpolierung werden auch die Werte des 
nachfolgenden Frames berücksichtigt, was durch das Peak-Matching 
vorbereitet wurde).
Logischerweise muss die Länge eines Syntheseframes mit der Länge eines 
Analyseframes übereinstimmen. Wäre die Framegröße also 160, dann müsste 
ich aus den max. 40 Triplets 160 Samplewerte machen (die beispielsweise 
in eine Wave-Datei geschrieben werden können).
Dies soll durch die Erzeugung von Sinuswellen in Framelänge geschehen, 
welche dann aufsummiert werden. Ich muss also für jeden einzelnen der 
max. 40 Peaks eine Sinuswelle mit genau 160 Werten erzeugen. Diese max. 
40 Wellen werden dann aufsummiert, sodass am Ende nur eine einzige 
(resultierende) Welle mit 160 Werten übrig bleibt. Diese gehen in den 
Output und das Ganze beginnt von vorn für den nächsten Frame.

Die Interpolation sieht so aus (dieser Codeausschnitt ist vor der 
eigentlichen Problemstelle, dient also nur um das Nachfolgende zu 
verstehen):
1
for j = 0:length(synthframe(:,1))-1
2
        out_int(j+1,1) = interpolate_amp(synthframe(j+1,1),matchframe(j+1,1),length(synthframe(:,1)),j);
3
        out_int(j+1,2) = interpolate_pha(synthframe(j+1,2),matchframe(j+1,2),synthframe(j+1,3),matchframe(j+1,3),length(synthframe(:,1)),j);
4
end;
5
output = [output;out_int];
interpolate_amp ist die Amplitudeninterpolationsfunktion und 
interpolate_pha eben die Phasenint.-Fkt. Relevant für das Problem ist 
eigentlich nur die Phaseninterpolation:
PHI(t) = PHI + w(t) + alpha(M)*t^2 + beta(M)*t^3
alpha und beta sind zwei spezielle Faktoren, die u.a. noch Komponenten 
des nachfolgenden Frames erhalten. Wichtig ist hier nur, dass die 
Phasenfunktion eben auch die Frequenz und die Phase enthält.

Das Problem ist nun die Erzeugung der Sinuswelle. Das geschicht 
folgendermaßen:
1
for j = 1:length(output(:,1))
2
        oooo = [];
3
        oooo = output(j,1)*cos((0:(2*pi)/(framesize-1):2*pi)+output(j,2));
4
        waveform = [waveform;oooo];
5
end;
6
finalwave = sum(waveform);
7
wave = [wave;finalwave];
Die Formel zur Erzeugung der Sinuswelle ist wie folgt vorgegeben:
s(n) = A(n) * cos[PHI(n)]
Wie in dem Ausschnitt zu sehen habe ich noch den Ausdruck
(0:(2*pi)/(framesize-1):2*pi)
in die cos()-Funktion eingefügt damit ich eben die richtige Anzahl an 
Samples als Ergebnis erhalte. Und ich denke deshalb funktioniert die 
Synthese nicht richtig.
Im Anhang sind zwei Diagramme enthalten. Das linke ist die Aufnahme, das 
rechte die Synthese. Das Signal selbst ist ein 1kHz-Sinus bei einer 
Abtastung mit 44,1kHz. Wie man ansatzweise erkennen kann beträgt die 
Periodendauer ca. 44 Samples (entspricht 44/44100 s bzw. 1002 Hz) im 
linken Diagramm. Im rechten hingegen beträgt sie 160 Samples (bzw. 275 
Hz). Die Frequenz meiner erzeugten Wellen ist also fast nur ein Viertel 
so groß wie die ursprüngliche Frequenz. Jede erzeugte Cosinuswelle hat 
also eine Dauer von 160 Samples und eine entsprechende 
Phasenverschiebung.

So wie ich das mache kommt also nicht das gewünschte Resultat raus. Wie 
kann ich die cos()-Funktion unter diesen Rahmenbedingungen in MatLab 
richtig nutzen um die gewünschten Werte zu erzeugen?

Dann noch eine kleine Frage: Die Phaseninterpolierungsfunktion oben ist 
eine Funktion in der Zeitbasis, in die cos()-Funktion setze ich also 
eine gesampelte Version dieser Formel ein. Ist es korrekt t durch n (n = 
0..S-1; S = Länge des Syntheseframes) zu ersetzen? Die gesampelte 
Variante der Phasenfunktion ist:
pha_int = phase+freq*n+alpha*n^2+beta*n^3;
pha_int ist 1 Amplitudenwert für das aktuelle Sample, n entspricht also 
jeweils der Samplenummer.

von Delete M. (skywalker)


Lesenswert?

Man könnte mein Problem auch kürzer formulieren:
Wie erzeuge ich in MatLab eine Sinusfunktion mit beliebiger Frequenz und 
Amplitude mit einer definierbaren Ergebnisarraygröße, ohne dabei mit 
Skalierung der Arraygröße und der Frequenz durcheinander zu kommen?

von Detlef _. (detlef_a)


Lesenswert?

Aha, das war die Frage.

Das geht so:
sinus=amplitude*sin((0:(Ergebnisarraygroesse-1))*2*pi*frequenz/abtastfre 
quenz+phase)

Die Abtastfrequnz hattest Du nicht erwähnt, die spielt natürlich ne 
Rolle, phase ist der Phasenoffset des Sinus zum Fenster.

Cheers
Detlef

btw:
(1)
>>waveform = [waveform;oooo];
nicht tun, Strukturen mit variabler Länge machen Matlab scripts sehr 
langsam. Zu Anfang ein array passender Länge anlegen.
(2) 'for' Schleifen sind in 99% aller Fälle unnötig, siehe oben und sind 
langsam.

Cheers
Detlef

von T. H. (pumpkin) Benutzerseite


Lesenswert?

Aah, Frequency Tracking nach McAulay & co? Wenn du Interesse bzw. 
immernoch Schwierigkeiten hast kann ich dir mit MATLAB Code unter die 
Arme greifen - allerdings angepasst an ein etwas anderes Problem. Bei 
Interesse schreib mir eine Mail - die findest du im Link meines 
Accounts.

Detlef _a wrote:
> Die Abtastfrequnz hattest Du nicht erwähnt

Ganz oben: 44100Hz.

> 2) 'for' Schleifen sind in 99% aller Fälle unnötig, siehe oben und sind
> langsam.

Recht hat er. Wenigstens initialisieren (foo = zeros(sizeX, sizeY, 
...)), dann sind auch for-Schleifen erträglich schnell (mit dem Vorteil 
der imho intuitiveren Lesbarkeit).


Cheers!

von Detlef _. (detlef_a)


Lesenswert?

>>Detlef _a wrote:
>>> Die Abtastfrequnz hattest Du nicht erwähnt
>>
>>  Ganz oben: 44100Hz.

Aha, das hatte ich nicht wahrgenommen. Vermutlich deshalb, weil ich nach 
dem Satz:

>>Mein Problem ist vermutlich relativ trivial, aber ich muss ertmal etwas 
>>drumherum erklären.

schlagartig die Lust zum Weiterlesen verloren hatte ;-)

Kommst Du Mittwoch mal wieder zum Biertrinken mit, würde mich freuen !?

Cheers
Detlef

von Delete M. (skywalker)


Angehängte Dateien:

Lesenswert?

Detlef _a wrote:
> Aha, das war die Frage.
>
> Das geht so:
> sinus=amplitude*sin((0:(Ergebnisarraygroesse-1))*2*pi*frequenz/>abtastfr 
equenz+phase)
>
Vielen Dank, genau das hat mir erstmal weitergeholfen. Ich hab das 
folgendermaßen eingebaut:
1
output = [];
2
out_int = [];
3
waveform = [];
4
finalwave = [];
5
for j = 0:length(synthframe(:,1))-1
6
        out_int(j+1,1) = interpolate_amp(synthframe(j+1,1),matchframe(j+1,1),length(synthframe(:,1)),j);
7
        out_int(j+1,2:framesize+1) = interpolate_pha(synthframe(j+1,2),matchframe(j+1,2),synthframe(j+1,3),matchframe(j+1,3),length(synthframe(:,1)),j,Fs);
8
        out_int(j+1,3) = synthframe(j+1,3);
9
end;
10
output = [output;out_int];
11
for j = 1:length(output(:,1))
12
        oooo = [];
13
        oooo = output(j,1)*cos((0:(framesize-1))*2*pi*output(j,3)/Fs+output(j,2:framesize+1));
14
        waveform = [waveform;oooo];
15
end;
16
finalwave = sum(waveform);
17
wave = [wave;finalwave];
Dazu noch die Phaseninterpolierungsfunktion:
1
function pha_int = interpolate_pha(phase,phase2,freq,freq2,S,n,F)
2
freq = 2*pi*freq;
3
freq2 = 2*pi*freq2;
4
M = round((1/(2*pi))*((phase+freq*S-phase2)+(freq2-freq)*(S/2)));
5
alpha = (3/(S^2))*(phase2-phase-freq*S+2*pi*M)-(1/S)*(freq2-freq);
6
beta = (-2/(S^3))*(phase2-phase-freq*S+2*pi*M)+(1/(S^2))*(freq2-freq);
7
pha_int = [];
8
for i = 1:S
9
    pha_int = [pha_int,phase+alpha*(i/F)^2+beta*(i/F)^3];
10
end;
Wie im Bild zu sehen ist stimmt die Frequenz jetzt. Und tatsächlich kann 
man jetzt auch die synthetisierte Stimme halbwegs verstehen. Vorher 
verstand man Worte nicht, jetzt kann man die Worte verstehen (auch wenn 
es zugegebener Maßen noch sehr grottig klingt; da läuft also noch nicht 
alles so wie es soll).

Die Stimme klingt noch relativ metallisch und verzerrt, was daran liegt, 
dass die synthetisierten Wellen rechteckförmig sind.
Siehe auch Bilder:
http://www.worldofevanescence.de/martin/matlab/basically_working_01.jpg
http://www.worldofevanescence.de/martin/matlab/basically_working_02.jpg

Ich nehme an die Interpolationen laufen noch nicht so wie sie eigentlich 
sollen. Besonders bei der Phase bin ich mir noch unsicher. Die 
Phaseninterpolationsformel lautet ja:
Die Frequenz wäre damit ja im Cosinus enthalten. Den Frequenzteil (w*t) 
hab ich jetzt weggelassen, damit ich die Frequenz separat von der 
Funktion im Cosinus einfügen kann (wie oben). Damit hab ich doch jetzt 
das t unterschlagen, richtig?

Detlef _a wrote:
>btw:
>(1)
>>>waveform = [waveform;oooo];
>nicht tun, Strukturen mit variabler Länge machen Matlab scripts sehr
>langsam. Zu Anfang ein array passender Länge anlegen.
>(2) 'for' Schleifen sind in 99% aller Fälle unnötig, siehe oben und sind
>langsam.
>
>Cheers
>Detlef
Danke für den Hinweis. Ich hätte nicht gedacht, dass das einen 
Unterschied macht. Ich bin noch nicht dazu gekommen das umzusetzen, 
probier ich dann später aus (mir gehts erstmal nur um die 
Funktionalität; um die Performance kümmere ich mich am Ende).

T. H. wrote:
> Aah, Frequency Tracking nach McAulay & co? Wenn du Interesse bzw.
> immernoch Schwierigkeiten hast kann ich dir mit MATLAB Code unter die
> Arme greifen - allerdings angepasst an ein etwas anderes Problem. Bei
> Interesse schreib mir eine Mail - die findest du im Link meines
> Accounts.
Genau darum geht es. ;)
Mail ist gesendet.

von T. H. (pumpkin) Benutzerseite


Lesenswert?

Hallo Martin,

ich antworte mal hier im Forum auf deine Mail - ist sonst unfair anderen 
gegenüber.

Martin Förster wrote:
> Was versteht man unter einem pitchadaptiven Hammingfenster und wozu dient
> es? Ich nehme stark an, dass es wohl unter Umständen noch etwas die
> Datenmenge bei der Analyse reduzieren kann. Momentan arbeite ich mit einem
> Hammingfenster fester Länge. Wenn dem so ist, ist das Fenster also nicht
> essentiell für den Algorithmus.

Ich habe das Paper gerade nochmal überflogen: So wie ich das sehe geht 
es hier speziell um die Restriktion durch die Formel 20 im Paper und um 
eine Fensterlänge von 2 1/2 mal dem Pitch des Signals. Essentiell ist 
das in erster Näherung nicht, vor allem wenn man sich vorerst auf 
stimmenhafte (voiced) Sprache beschränkt. In meiner Applikation (für 
Musik) habe ich immer mit einer festen Analyselänge gearbeitet.

> Ich versuche gerade herauszufinden warum die synthetisierte Sprache so
> rechteckförmig ist. Wenn ich das hinbekomme sollte das die
> Verständlichkeit deutlich besser werden. Entweder stimmt da etwas noch
> nicht mit den ganzen Schleifen und der Funktion oder beim Peak-Matching
> komme komische Werte raus. Seltsamerweise tritt dieser Stufenbildung nur
> bei Sprache auf, jedoch nicht wenn ich einen einfachen Sinus als
> Eingangssignal nehme (obwohl dieser auch etwas kratzig klingt, was
> vermutlich noch an den Phasensprüngen liegen mag).

Ich kann dir nur empfehlen erstmal mit einfachen Signalen zu arbeiten. 
Zum Beispiel mit drei überlagerten Sinussen, meinetwegen mit 200, 400 
und 1000Hz. Dadurch werden Ergebnisse nachvollziehbar, du kannst Phasen, 
Frequenzen und Tracking-Ergebnisse leicht nachvollziehen. Zudem verkürzt 
sich in jedem Fall die Rechenzeit.

> Die Frequenz wäre damit ja im Cosinus enthalten. Den Frequenzteil (w*t)
> hab ich jetzt weggelassen, damit ich die Frequenz separat von der
> Funktion im Cosinus einfügen kann (wie oben). Damit hab ich doch jetzt
> das t unterschlagen, richtig?

Mit dem hier bin ich nicht glücklich:
1
for i = 1:S
2
    pha_int = [pha_int,phase+alpha*(i/F)^2+beta*(i/F)^3];
3
end;

Wie du schon schreibst, ist die Phase

 phi(t) = phase + omega * t + alpha * t² + beta * t³

omega * t kann man schon weglassen, wenn man es bei der Synthese 
berücksichtigt. Die Frage ist nur: Warum?
1
for j = 0:length(synthframe(:,1))-1
2
        out_int(j+1,1) = interpolate_amp(synthframe(j+1,1),matchframe(j+1,1),length(synthframe(:,1)),j);
3
        out_int(j+1,2:framesize+1) = interpolate_pha(synthframe(j+1,2),matchframe(j+1,2),synthframe(j+1,3),matchframe(j+1,3),length(synthframe(:,1)),j,Fs);
4
        out_int(j+1,3) = synthframe(j+1,3);
5
end;

Vllt hab ich gerade einen Knick in der Optik, aber warum ist deine 
Amplitude nicht abhängig von der Zeit (Skalar) aber sehr wohl die Phase 
(Vektor)?

Zum Schluss: Etwas mehr Kommentare in den Quelltexten wäre schön.  :^)

Ede wrote:
> Kommst Du Mittwoch mal wieder zum Biertrinken mit, würde mich freuen !?

Auf jeden Fall!

von T. H. (pumpkin) Benutzerseite


Lesenswert?

Edit geht leider nicht. Nachtrag:

Wenn du Zeit hast guck mal hier rein, das Schema von McAulay wird 
genutzt und etwas modifiziert:

 http://elvera.nue.tu-berlin.de/files/0937Lajmi2003.pdf (S. 119)
 http://www.alice-dsl.net/sound-inside/downloads/TH2008.pdf (S. 52)

von Delete M. (skywalker)


Lesenswert?

T. H. wrote:
> Wie du schon schreibst, ist die Phase
>
>  phi(t) = phase + omega * t + alpha * t² + beta * t³
>
> omega * t kann man schon weglassen, wenn man es bei der Synthese
> berücksichtigt. Die Frage ist nur: Warum?
Sorry, ich war da grad etwas verwirrt. Das omega*t hab ich in der 
Phasenformel weggelassen, da diese ja nun direkt im cos-Argument stehen. 
Die Anzahl der Samples (0:..) entspricht dabei dem t und das 
2*pi*Frequenz entspricht ja dem Omega. Von daher passt das schon so wie 
es sein soll.

T. H. wrote:
> Vllt hab ich gerade einen Knick in der Optik, aber warum ist deine
> Amplitude nicht abhängig von der Zeit (Skalar) aber sehr wohl die Phase
> (Vektor)?
Du hast da keinen Knick in der Otik. ;) Was ich da geschrieben habe ist 
natürlich Murks. Richtig heißt es nun so:
1
for j = 0:length(synthframe(:,1))-1 % !!! 0 to 255 == 1 to 256 in real!
2
   out_int(j+1,1) = interpolate_amp(synthframe(j+1,1),matchframe(j+1,1),length(synthframe(:,1)),j);
3
   out_int(j+1,2) = interpolate_pha(synthframe(j+1,2),matchframe(j+1,2),synthframe(j+1,3),matchframe(j+1,3),length(synthframe(:,1)),j,Fs);
4
   out_int(j+1,3) = synthframe(j+1,3);
5
end;
6
output = [output;out_int];
7
for j = 1:length(output(:,1))
8
   oooo = [];
9
   oooo = output(j,1)*cos((0:(framesize-1))*2*pi*output(j,3)/Fs+output(j,2));
10
   waveform = [waveform;oooo];
11
end;    % waveform: rows = samples in frame; columns = sinuswave with framesize*values
12
   finalwave = sum(waveform);  % finalwave contains now 1 row with framesize* values = sum of all sinewaves of this one frame!
13
   w = triang(length(finalwave(1,:)));     % triangular window
14
   finalwave = finalwave.*w';
15
   wave = [wave;finalwave]; % summed sinewaves of all frames are stacked in rows
Macht ja auch keinen Sinn so wie es vorher war. Die Zeitabhängigkeit 
kommt ja über die Cosinusfunktion für jedes der Samplepaare.
Ich hab jetzt auch schon die Dreiecksfensterung am Ende eingefügt.

T. H. wrote:
> Ich kann dir nur empfehlen erstmal mit einfachen Signalen zu arbeiten.
> Zum Beispiel mit drei überlagerten Sinussen, meinetwegen mit 200, 400
> und 1000Hz. Dadurch werden Ergebnisse nachvollziehbar, du kannst Phasen,
> Frequenzen und Tracking-Ergebnisse leicht nachvollziehen. Zudem verkürzt
> sich in jedem Fall die Rechenzeit.
Ok, hab ich gemacht. Zunächst mit einem 1 kHz Sinus und dann mit drei 
überlagerten Sinussen.
http://www.worldofevanescence.de/martin/matlab/6_sinus.jpg
http://www.worldofevanescence.de/martin/matlab/testsignal.jpg
Auf beiden Bildern sind jeweils mind. 2 Frames dargestellt. Die Signale 
werden nun nicht mehr eckig synthetisiert, sondern so wie sie sein 
sollen. Durch die Dreiecksfensterung am Ende ist die synthetisierte 
Funktion natürlich dreiecksförmig. Sieht etwas seltsam aus, klingt aber 
ziemlich gut. Ich habe jetzt keine Probleme mehr die Originalstimme zu 
erkennen. Selbst die Betonung bleibt erhalten (also man kann anhand der 
synthetisierten Stimme problemlos den Sprecher unterscheiden). Ein paar 
Soundartefakte/anomalien (oder wie man das nennen will) sind zwar 
enthalten und natürlich klingt es etwas synthetisiert, aber im Prinzip 
funktioniert es zufriedenstellend. :D
Im nachfolgenden Bild ist ein Wort dargestellt (links original, rechts 
synthetisiert):
http://www.worldofevanescence.de/martin/matlab/6.jpg
Ist nicht perfekt, aber schon recht gut (nach meinem Verständnis). 
Zumindest macht das Script nun weitestgehend was es soll.

T. H. wrote:
> Zum Schluss: Etwas mehr Kommentare in den Quelltexten wäre schön.  :^)
Ok, ich hatte sie bis jetzt immer bewusst rausgelöscht beim Posten, weil 
ich sie eher verwirrend fand. Stimmt natürlich, ohne Kommentare ist Code 
schwer nachvollziehbar. Man sieht das selbst nicht so wenn man drin 
steckt.
Ich hab gerade an der Stelle im Script bestimmt schon zig mal etwas 
verändert und rauskommentiert, ich muss jetzt erstmal das ganze Script 
überfliegen und alles Unnötige entfernen.

T. H. wrote:
> Edit geht leider nicht. Nachtrag:
>
> Wenn du Zeit hast guck mal hier rein, das Schema von McAulay wird
> genutzt und etwas modifiziert:
>
>  http://elvera.nue.tu-berlin.de/files/0937Lajmi2003.pdf (S. 119)
>  http://www.alice-dsl.net/sound-inside/downloads/TH2008.pdf (S. 52)
Danke für die Links. Ich habs mal kurz überflogen und es klingt 
interessant. Momentan ändere ich aber erstmal nichts. Unser Projektthema 
lautet ja eigentlich, dass wir den McAulay-Algorithmus in einen FPGA 
reinbekommen sollen. Das MatLab-Modell dient dazu nur zum Verständnis 
und natürlich der Simulation des Algorithmus. Soviel Zeit haben wir auch 
nicht mehr. Wenn wir den Algorithmus so in der Form in den FPGA bekommen 
wäre das schon sehr gut. Wenn am Ende noch Zeit bleibt werden wir 
schauen wie man den Algorithmus (qualitativ) noch verbessern kann, aber 
so wie es jetzt ist, ist es erstmal ausreichend.

von T. H. (pumpkin) Benutzerseite


Lesenswert?

Na wunderbar! :^)

Stell doch mal ein oder zwei Beispiele (Original & Synthese) hier rein - 
das würde mich interessieren.

Cheers!

von Delete M. (skywalker)


Lesenswert?

T. H. wrote:
> Na wunderbar! :^)
>
> Stell doch mal ein oder zwei Beispiele (Original & Synthese) hier rein -
> das würde mich interessieren.
>
> Cheers!

Ok. In der nachfolgenden Zip-Datei sind 4 Soundaufnahmen enthalten (2 
mal ich selbst, einmal eine Frauenstimme aus einem Hörbuch, 1 mal 
Rockmusik). Die Rockmusik klingt, wie erwartet, relativ scheiße. Aber 
für sowas war der Algorithmus ja ursprünglich auch nicht vorgesehen. 
Dennoch versteht man noch die Gesangsstimme. :)

http://www.worldofevanescence.de/martin/matlab/sound_examples.zip

von Delete M. (skywalker)


Angehängte Dateien:

Lesenswert?

Ich hab noch eine Frage zur Darstellung. Und zwar möchte ich das 
Eingangssignal (Original) und das synthetisierte Ausgangssignal im Zeit- 
und Frequenzbereich darstellen, sodass man problemlos die Unterschiede 
sehen kann. Welche Darstellungsformen sind dafür am besten geeignet?
Den Zeitbereich kann ich, wie man weiter oben sehen kann, problemlos 
darstellen. Auch der Frequenzbereich geht. Nur hab ich dann eben zwei 
separate Diagramme für ein Signal. Außerdem kommt beim Frequenzbereich 
noch das Problem hinzu, dass ich für jeden Frame eine Linie habe.
Ich weiß, dass man solche Darstellungen beispielsweise mit dem 
surf-Befehl als 3D-Diagramm darstellen kann. Nur irgendwie krieg ich das 
nicht so richtig hin. Es funktioniert zwar, dass ich die Amplituden aus 
der FFT über die Frames (entspräche dem Zeitbereich) und die Frequenz 
hinweg (Frequenzbereich) mit surf darstellen kann, aber das was 
rauskommt sieht relativ dunkel aus, sodass ich nah hinneinzoomen muss. 
Das kann man dann aber nicht in ein Dokument einfügen. (siehe Anhang)
Ich hab auch ein wenig probiert das mit der Farbpalette ansehlicher zu 
machen, nur irgendwie wird das auch nicht besser.

Gibt es noch eine bessere/sinnvollere Darstellungsform oder wie kann ich 
den surf-Befehl so anwenden, dass das Ergebnis auch irgendwie verwendbar 
in einem Schreibprogramm ist?

von T. H. (pumpkin) Benutzerseite


Lesenswert?

Danke für die Beispiele. Es hört sich zwar nicht so gut an wie ich 
erwartet habe, aber man versteht es. Die Tage habe ich ein wenig weiter 
geforscht und bin hierauf gestoßen. Das sieht auch interessant aus.

  http://mtg.upf.edu/files/publications/CMJ-1990-xserra.pdf


Martin F. wrote:
> Den Zeitbereich kann ich, wie man weiter oben sehen kann, problemlos
> darstellen. Auch der Frequenzbereich geht. Nur hab ich dann eben zwei
> separate Diagramme für ein Signal.

Zeitbereich ist klar:

  foo = rand(100, 1);
  bar = rand(100, 1);
  plot(foo);
  hold on;
  plot(bar, 'r');
  hold off;

Für den Frequenzbereich kannst du durchaus mit surf arbeiten...

> Es funktioniert zwar, dass ich die Amplituden aus
> der FFT über die Frames (entspräche dem Zeitbereich) und die Frequenz
> hinweg (Frequenzbereich) mit surf darstellen kann, aber das was
> rauskommt sieht relativ dunkel aus, sodass ich nah hinneinzoomen muss.
> Das kann man dann aber nicht in ein Dokument einfügen.

Allerdings sollte man das drübergelegte Netz ausstellen. Wenn es zwei in 
einem sein sollen kannst du ein wenig mit der Transparenz jonglieren. 
Damit es übersichtlicher wird würde ich es monochrom machen 
(hell/dunkel, evtl. unterschiedliche color maps). Eine andere Variante 
ist, zwei separate Plots mit spectrogram zu erstellen (hier ein wenig 
mit der Auflösung spielen).

Keine Ahnung mit welcher MATLAB Version du arbeitest, meine hat Probleme 
mit dem Export von Oberflächenplots. Vektorgrafik sieht wirklich übel 
aus. Abhilfe schafft

  print -dbmp -r300 'file.bmp'

Cheers!

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Meiner Meinung nach ist eine Darstellung eines Spektrogramms als 
zweidimensionale Grafik viel anschaulicher. Die x-Achse entspricht dabei 
der Zeit, die y-Achse der Frequenz und die Intensität ist farbcodiert. 
Samplitude kann das beispielsweise auch sehr schön in Echtzeit, Audacity 
kann es in einer Audiospur offline. Wie man das in Matlab macht, weiß 
ich aber nicht.


Grüße,

Peter

von Delete M. (skywalker)


Lesenswert?

Sorry für die lange Sendepause, hatte erstmal viel zu tun.

Das mit den Darstellung hab ich noch nicht hinbekommen. Vielleicht hab 
ich mich auch etwas missverständlich ausgedrückt.
Ich habe nun nach der FFT ein Array mit 257 Zeilen (entspricht dem 
halben Spektrum der 512er FFT) und N Spalten. N ist hierbei die Anzahl 
der Frames die ich bearbeite. Somit sind die Spalten/Frames meine 
Zeitbasis (1. Dimension), die Zeilen meine Frequenzbasis (2. Dimension) 
und die Amplitudenwerte meine 3. Dimension. Dargestellt werden soll das 
in 2D.
Ein Beispiel von dem was ich meine findet man unter:
http://cnx.org/content/m0505/latest/spectrum8.png
(ohne die untere blaue Grafik)

Welchen Befehl muss ich dafür ansetzen? surf scheint mir hierfür nicht 
geeignet zu sein; plot ebenso wenig. Im Prinzip muss ich doch einfach 
nur eine x-Achse mit N Werten und eine y-Achse mit 257 Werten haben, in 
welche ich dann das Array scheibchenweise reinlege und die 
Amplitudenwerte einfärbe. Mache ich den Spaß in zwei separaten Grafiken, 
einmal Original und einmal Synthese, dann müsste das ja eine sehr 
anschauliche Darstellung sein, wo man beides vergleichen kann.

> Eine andere Variante
> ist, zwei separate Plots mit spectrogram zu erstellen (hier ein wenig
> mit der Auflösung spielen).
spectrogram scheint es nicht direkt als Befehl zu geben.

von T. H. (pumpkin) Benutzerseite


Angehängte Dateien:

Lesenswert?

spectrogram wäre genau das was du brauchst. Allerdings ist diese 
Funktion Bestandteil der Signal Processing Toolbox. Wenn du die nicht 
hast siehts schlecht aus. In diesem Fall musst du dir das selber bauen. 
Hier würde ich z.B. surf verwenden - LineStyle auf none (in 
graph3d) damit das Gitter verschwindet, azimuth auf 0 und elevation 
auf 90 (in axis - view). Oder man macht sich das Leben leichter und 
verwendet image (Skalierung beachten!).

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Die Funktion für das Spektrogramm heißt specgram, farbige 2D-Darstellung 
geht mit pcolor (das macht sogar intern genau das was T.H. "von Hand" 
beschrieben hat).

von T. H. (pumpkin) Benutzerseite


Lesenswert?

1
help specgram
2
3
SPECGRAM Spectrogram using a Short-Time Fourier Transform (STFT).
4
    SPECGRAM has been replaced by SPECTROGRAM.  SPECGRAM still works but
5
    may be removed in the future. Use SPECTROGRAM instead. Type help
6
    SPECTROGRAM for details.

Andreas Schwarz wrote:
> ... farbige 2D-Darstellung geht mit pcolor ...

Nett, kannte ich noch nicht.

von Delete M. (skywalker)


Lesenswert?

Vielen Dank. Specgram scheint genau das zu sein was ich suche. Werde ich 
dann gleich mal testen.

Es hat sich nun aber ein anderes Problem aufgetan. Wie in einem Beitrag 
weiter oben zu sehen wird aus einem Sinus wieder ein Sinus (siehe auch 
http://www.worldofevanescence.de/martin/matlab/6_sinus.jpg), jedoch 
wegen der Dreiecksfensterung hat man sozusagen eine Art dreieckige 
Einhüllende mit drin. Zum Vergleich auch noch ein Rechtsignal:
http://www.worldofevanescence.de/martin/matlab/int_recht.jpg
Für die Verständlichkeit von Sprache ist das (in der Konstellation) gut, 
da man die Frameübergange quasi mit dem Holzhammer Richtung Null zwingt 
und somit keine Sprünge drin hat. Schlecht ist das natürlich in Bezug 
auf die Gesamtqualität (durch die Dreiecksfensterung hat man natürlich 
gewisse Rausch/Nachhalleffekte) und die Funktionalität des Algorithmus', 
da die Interpolationsformeln nach McAulay eigentlich glatte Übergänge 
ermöglichen sollten, ohne dass man hinterher diese mit dem Holzhammer 
"glättet".
Unser Betreuer meinte jedenfalls, dass wir das so nicht richtig haben.

Mal unabhängig davon habe ich noch zwei andere Varianten getestet:
(zuvor kommt das Peak-Picking)
Variante 1:
1
wave = zeros(fftsize,length(spec(1,:))); %spec contains the peaks with zeros
2
for i = 1:length(spec(1,:))
3
    wave(:,i) = real(ifft(spec(:,i),fftsize));
4
end;      %sine wave generation via IFFT
5
output = [];
6
output(1:framesize,1) = wave(1:framesize,1);    % first frame (without overlap)
7
for i = 1:length(wave(1,:))-1
8
    wavetemp = zeros(framesize,1);
9
    for j = 1:framesize
10
        wavetemp(j,1) = (wave(j+framesize,i)*(framesize-j)/framesize)+(wave(j,i+1)*j/framesize);  %overlap of frames and application of triangular window
11
    end;
12
    output = [output;wavetemp];
13
end;
14
output = [output;wave(framesize+1:2*framesize,length(wave(1,:)))]; %last frame without overlap
Das ganze mit 512er FFT und 256er Framegröße. Diese Idee, dass 
Dreiecksfenster so anzuwenden, hab ich von ein paar Kommilitonen. Nur 
das Resultat klingt sehr schlecht. Dafür wird aber ein Sinussignal 
perfekt synthetisiert. Etwas komplexeres, wie ein Rechteck, jedoch total 
verhunzt (siehe angehängtes Bild im nächsten Beitrag).

Variante 2:
1
for i = length(spec(:,1))+1:fftsize
2
    spec(i,1) = 0;
3
end; %zero padding for ifft
4
5
wave = zeros(fftsize,length(spec(1,:)));
6
waveform = zeros(framesize,length(spec(1,:)));
7
w = triang(framesize);
8
9
for i = 1:length(spec(1,:))
10
    for j=1:length(spec(:,i))
11
        wave(:,i) = real(ifft(spec(:,i),fftsize));
12
    end;
13
    waveform(:,i) = wave(1:framesize,i).*w; %only framesize samples are taken
14
end;
15
output = [];
16
for i = 0:length(waveform(1,:))-1
17
    for j = 1:length(waveform(:,i+1))
18
        output(i*framesize+j,1) = waveform(j,i+1);
19
    end;
20
end;
Variante 2 mit 160er Framegröße und 512er FFT. Diese Variante produziert 
exakt das selbe wie die ursprüngliche Interpolierungsgeschichte, nur mit 
weniger Codezeilen.
Dass von der ifft nur die ersten 160 Realwerte genommen werden ist ok, 
da die Amplituden am Ende wieder auf 1 normalisiert werden (die ersten 
160 Realteile sind amplitudenmäßig zu klein; die Proportionen zwischen 
ihnen sind aber mit dem Originalsignal identisch, sodass dies durch die 
Normalisierung wieder ausgeglichen wird).

Irgendwo muss bei mir ein fundamentaler Denkfehler drin sein. Die 
Interpolierung sollte ohne separates Dreiecksfenster auskommen, da sie, 
laut der Formel im Artikel, ein solches bereits enthält. Somit hab ich 
die Interpolierung fehlerhaft umgesetzt. Variante 1 sollte theoretisch 
auch funktionieren, versagt aber bei allem was komplexer als ein Sinus 
ist. Variante 2 ist im Prinzip eine kürzere Form der Interpolierung; 
benötigt aber auch das Holzhammer-Dreiecksfenster.
Mittlerweile gehen mir auch die Ideen aus, wo in meinem Ansatz jetzt der 
Fehler ist. Dass Variante 2 verständlich klingt ist klar, nur formal 
gesehen ist sie fehlerhaft. Hat Jemand eine Idee was ich noch probieren 
könnte oder wo der Fehler zu suchen ist?

von Delete M. (skywalker)


Angehängte Dateien:

Lesenswert?

Irgendwie will der Dateianhang heut nicht so recht.

von Delete M. (skywalker)


Angehängte Dateien:

Lesenswert?

Neue Erkenntnis: Lasse ich bei der ursprgl. Interpolation vom Anfang die 
Dreiecksfensterung weg, so kommt sowas wie im Anhang raus.
Es sieht so aus als wären die Amplitudenniveaus bei manchen 
Frameübergängen unterschiedlich. Das sollte dank der Interpolierung 
eigentlich nicht passieren. Durch die Dreiecksfensterung wird der Fehler 
verschleiert, aber die Folgen nicht ganz beseitigt. Wenn ich das 
wegbekomme, dann sollte die Sprache deutlich besser klingen.

von T. H. (pumpkin) Benutzerseite


Lesenswert?

Moin moin!

Hab den Code mal überflogen. Das hier
1
for i = length(spec(:,1))+1:fftsize
2
    spec(i,1) = 0;
3
end; %zero padding for ifft

geht so nicht. Jedenfalls macht es nicht das was du scheinbar denkst. Du 
bringst in das Spektrum eine Asymmetrie rein, dein rücktransformiertes 
Ergebniss wird imaginär (und erklärt, warum du nur den Realteil 
verwenden willst). Ich denke nicht, dass das dein Ziel war.

  http://www.mikrocontroller.net/attachment/50846/a01.jpg

Das sieht mir stark nach einem Phasenfehler aus, der unsymmetrisch ist 
(der Offset scheint nicht gleich zu sein - kann aber durchaus sein, 
dass er es doch ist und die Unsymmetrie im Zeitbereich durch die 
Akkumulation der Einzelwellen kommt).

Soweit erstmal, wenn ich etwas mehr Muße habe dann gucke ich mir den 
Code mal genau an.  :^P

Cheers!

von Delete M. (skywalker)


Lesenswert?

T. H. schrieb:
> Moin moin!
>
> Hab den Code mal überflogen. Das hier
>
>
1
> for i = length(spec(:,1))+1:fftsize
2
>     spec(i,1) = 0;
3
> end; %zero padding for ifft
4
>
>
> geht so nicht. Jedenfalls macht es nicht das was du scheinbar denkst. Du
> bringst in das Spektrum eine Asymmetrie rein, dein rücktransformiertes
> Ergebniss wird imaginär (und erklärt, warum du nur den Realteil
> verwenden willst). Ich denke nicht, dass das dein Ziel war.

Du hast Recht. Die Stelle ist murks, hatte aber keine Bedeutung, weil 
vor dem Peak Picking:
1
spec = zeros(fftsize,(fix(size(pla,1)/framesize)));
Ich hatte in dem Script viel rumeditiert und vergessen den Teil 
rauszulöschen.

von Delete M. (skywalker)


Angehängte Dateien:

Lesenswert?

Andreas Schwarz schrieb:
> Die Funktion für das Spektrogramm heißt specgram, farbige 2D-Darstellung
> geht mit pcolor (das macht sogar intern genau das was T.H. "von Hand"
> beschrieben hat).

Nochmal vielen Dank. specgram hat wunderbar funktioniert (siehe Anhang).

Der Code dafür:
1
figure(1)
2
subplot(1,2,1)
3
specgram(inputspeech,fftsize,Fs,hamming(fftsize))
4
title('Spectrogram of Input Speech');
5
subplot(1,2,2)
6
specgram(outputspeech,fftsize,Fs,hamming(fftsize))
7
title('Spectrogram of Output Speech');
Das ist übrigens das Spektrum mit Dreiecksfensterung.

Ohne Dreiecksfensterung siehts so aus:
http://www.worldofevanescence.de/martin/matlab/spectrogram_speech_ow_160-512.jpg
Wenn man das mal in Hinblick auf den Ausschnitt in a01.jpg betrachtet, 
so werden durch den Sprung sehr viele Harmonische hervorgerufen. 
Logisch, idealisiert betrachtet ist er ein Rechteck.

von Delete M. (skywalker)


Lesenswert?

Ich hab jetzt herausgefunden wo der Fehler lag: Ich hab die FFT-Fenster 
nicht halb übereinander geschoben. Dummer Denkfehler, aber so ist es 
nunmal.
Und zwar muss man das FFT-Fenster bei der STFT immer nur 
(beispielsweise) um einen halben Frame verschieben. Dadurch überlappt 
man die Frames sozusagen übereinander. Schiebt man das dann durch die 
IFFT, muss man die Frames am Ende wieder richtig zusammensetzen.

Ich möchte an der Stelle nicht den ganzen Code reintelllen oder 
reinkopieren, aber hier die wirklich wichtigen Stellen:
Fensterung und Short Time Fourier Transform:
1
fftsize = 512;
2
ffthsize= 257;
3
framesize = 256;
4
hfsize = framesize/2;
5
frametotal = fix((n*Fs)/framesize); %only framecount in real time!
6
framecount = fix((length(pla)-framesize)/hfsize)+1;
7
window = hamming(framesize);%0.011636*hamming(framesize);
8
my_spec = [];
9
for i = 0:(framecount-1)
10
    frame = pla((i*hfsize+1):(i*hfsize+framesize)).*window;           % extracts one frame of input and multiplies it with Hamming window
11
    my_spec = [my_spec,(fft(frame,fftsize))];                               % calculation of the STFT
12
end;
13
spectrum = my_spec(1:(fftsize/2)+1,1:framecount);                     % FFT spectrum is mirrored; only one half is needed
14
real_spec = real(spectrum);                                                 % separates real parts
15
imag_spec = imag(spectrum);                                                 % separates imaginary parts
16
amp = sqrt(real_spec.*real_spec+imag_spec.*imag_spec);                      % amplitude calculation
17
phase = atan2(imag_spec,real_spec);                                         % phase calculation
18
freq = [];
19
freqcount= 1;
20
for i = 0:(Fs/2)/(fftsize/2):(Fs/2)                                         % generation of the frequencies
21
    freq = [freq;i,freqcount];
22
    freqcount = freqcount+1;
23
end;
Danach kommt das Peak-Picking. Lässt man es weg, erhöht sich die 
Qualität maßgeblich (das Ganze arbeitet dann als quasi-Loopback).
Hier werden die Frames wieder zusammengesetzt:
1
wave = zeros(fftsize,framecount);
2
for i=1:framecount %framecounter
3
    wave(:,i) = real(ifft(spec(:,i),fftsize));
4
end;
5
waveform = [];
6
for i=1:hfsize   % first half frame
7
    temp = wave(i,1);
8
    waveform = [waveform;temp];
9
end;
10
for i=1:framecount-1   % all frames except first and last half frame
11
    temp2 = [];
12
    for j=1:hfsize
13
        temp = (wave(j+hfsize,i)*(hfsize - j)/hfsize) + (wave(j,i+1)*j/hfsize);
14
        temp2 = [temp2;temp];
15
    end;
16
    waveform = [waveform;temp2];
17
end;
18
for i=(hfsize+1):framesize   % last half frame
19
    temp = wave(j,1);
20
    waveform = [waveform;temp];
21
end;
22
while length(waveform) < length(pla)
23
    waveform = [waveform;0];
24
end;
25
soundsc(waveform,Fs);
26
waveform = waveform./max(waveform);
27
wavwrite(waveform,Fs,'synthetic_wave');
Der Trick beim Zusammensetzen ist, dass ich die Hälften richtig 
überlagern muss.

Ich versuch das mal so zu visualisieren:
Eingangssignal Zeitbasis:
|----|----|----|----|
Ein Frame entspricht 4 x '-'. Das FFT-Fenster ist ebenso groß, wird aber 
nur um eine halbe Framegröße weitergeschoben. Somit sieht es so aus:
|----|----|----|----|   Zeitsignal
   I    II  III  IV     Nummerierung der Zeitframes
|....|....|....|....|   FFT-Frames (ungerade Indizes)
  |....|....|....|....|   FFT-Frames (gerade Indizes)
  1    3    5    7      Nummerierung der FFT-Frames
     2    4    6    8
Da ich eine 512er-FFT anwende, brauche ich nur die Werte 1:257. Das ist 
das komplette Spektrum.
Nach dem Peak-Picking habe ich einen solchen Frame mit 257 Frequenzen 
(falls durch Peak-Picking nicht Null gesetzt). Der wird in die 
512er-IFFT geschoben. Die gibt 512 komplexe Werte raus. Davon betrachte 
ich nur die Realteile und die Werte 1:256 (dies liegt in der Annahme, 
dass die Eingangssignale der FFT periodisch kontinuierlich sind; 
dementsprechend auch die Ausgangswerte der IFFT). Die Frames werden 
halbframeweise zusammengesetzt. Jeder Halbframe besteht so aus 2 
Komponenten, welche beide mit einer Flanke eines Dreiecksfensters 
multipliziert werden. Der erste und der letzte halbe Frame können 
natürlich nicht optimal zusammengesetzt werden.
Somit ergeben sich die Zeitframes wie folgt (.1 und .2 bedeuten 
erste/zweite Hälfte des Frames):
I.1  = 1.1
I.2  = 1.2 + 2.1
II.1 = 2.2 + 3.1
II.2 = 3.2 + 4.1
...

Klingt verwirrend, aber wenn man sich das mal auf einem Blatt Papier 
aufmalt und ein Glas Wein dazu trinkt, dann haut das hin. :)

Ich hab hier nochmal ein paar Soundbeispiele:
http://www.worldofevanescence.de/martin/matlab/sound_examples_2.zip
Die Qualität ist sehr gut, wenn auch nicht perfekt. Sprache ist fast so 
gut wie das Original; Musik klingt etwas arm (logisch, wenn man das 
Peak-Picking hat), aber dennoch überraschend gut verständlich. Mit etwas 
Mühe liese sich das ganze System sicher noch optimieren, aber für unsere 
Zwecke ist das absolut ausreichend.
Ich hab auch noch ein paar Graphen mit angefügt.

Auf jeden Fall nochmal ein großes Danke für die Hilfe hier. :D

von T. H. (pumpkin) Benutzerseite


Angehängte Dateien:

Lesenswert?

Servus Martin!

Ich hatte ganz verpennt nochmal den Code zu beaugapfeln. Aber du hast es 
ja offensichtlich mit eigenem Hirnschmalz sehr gut hinbekommen. Den 
Handstand mit den Realanteilen der iFFT finde ich zwar etwas ulkig, aber 
nun gut.  ;^)

Ich dachte die überlappende DFT (STFT) war klar.  :^D  Btw: hier kann 
man sicher noch an der Fensterform drehen. Man kann z.B. spektral 
günstige Fenster so konstruieren, sodass sich diese bei einer 
überlappenden Addition - wie beim Dreieck - neutral verhalten. Das 
Verfahren MDCT (oder MDST) macht das z.B. so von Hause aus.


Sei's drum! Die Tracks hören sich wirklich gut an! In den Anhang habe 
ich mal ein Vergleich meines Ergebnisses mit FTR gelegt. Hier ging es um 
die Rekonstruktion ganzer weggefallener (null Information) Blöcke mit je 
21ms Länge.

Cheers!

von Delete M. (skywalker)


Lesenswert?

Mhh, das mit den Realteilen ist so ein Ding. Wie würde man es denn 
richtigerweise machen? Ich hatte da echt eine ganze Weile drüber 
nachgedacht, aber am Ende stellte sich das als funktionierend heraus. 
Ich hatte das auch mathematisch betrachtet. Nimmt man die 
Definitionsformel der inversen DFT, so kann man durch Umformung und 
Behalten der Realteile an einer Stelle auf die Interpolierungsformeln 
vom Paper kommen.

Das mit den überlappenden Fenstern ist halt echt ein dämlicher Fehler. 
Aber scheinbar ist dieses Verfahren so selbsterklärend, dass in der 
Literatur nicht wirklich detailiert darauf eingegangen wird. Wenn man 
sich vorher noch nicht mit sowas beschäftigt hat, liegt das nicht immer 
gleich auf der Hand. :P

Dein Beispiel klingt auch sehr interessant. Ich hätte nicht erwartet, 
dass man solche Fehler so gut kompensieren kann.

von T. H. (pumpkin) Benutzerseite


Lesenswert?

Martin F. schrieb:
> Mhh, das mit den Realteilen ist so ein Ding. Wie würde man es denn
> richtigerweise machen?

Wenn ich dich recht verstanden habe hast du nur die erste Hälfte des 
Spektrums invers transformiert? Wenn man nur eine Hälfte vom Spektrum 
mitschleifen möchte dann kann man beispielsweise das Spektrum vor der 
inversen Transformation an der Niquistfrequenz konjugiert spiegeln:

1
sig = sin(0:2*pi/1023:2*pi);
2
spec = fft(sig);
3
recsig = ifft([spec(1:513) fliplr(conj(spec(2:512)))]);
4
plot(sig); hold on; plot(recsig, 'r');

Vllt habe ich auch was falsch verstanden.  8^)

von Delete M. (skywalker)


Lesenswert?

> Wenn ich dich recht verstanden habe hast du nur die erste Hälfte des
> Spektrums invers transformiert?
Jein. Ja, ich nehme nur die eine Hälfte des Spektrums. Aber nach dem 
Peak-Picking ist dieses nicht mehr so wie es vorher war (also die 
Amplituden einiger Frequenzen sind auf Null gestzt). Da kann ja 
naturgemäß schon nicht mehr exakt das Gleiche rauskommen.

Deinen Code könnte man auch so schreiben:
1
sig = sin(0:2*pi/1023:2*pi);
2
sig = sig';
3
spec = fft(sig);
4
recsig = ifft(spec);
5
plot(sig); hold on; plot(recsig, 'r');
Also im Prinzip: Signal->FFT->IFFT->Signal

So wie ich das mache, sieht das so aus:
1
sig = sin(0:2*pi/1023:2*pi);
2
sig = sig';
3
spec = fft(sig,2048);
4
spec = spec';
5
respec = spec(1:1025);
6
respec(1025:2048) = 0;
7
recsig = real(ifft(respec,2048));
8
e = 2*(recsig(1:1024)+fliplr(recsig(1025:2048)));
9
plot(sig); hold on; plot(e, 'r');
Am Ende muss ich mit 2 multiplizieren, damit die Amplituden passen. Das 
mache ich in meinem Script jedoch nicht. Allerdings muss ich sagen, dass 
ich das dort ja auch anders mache, weil ich ja überlappende Fenster 
habe. Ein Framestück setzt sich dann immer aus zwei Teilen zusammen. Am 
Ende passt es ebend. Ich wüsste jetzt nicht so recht wie ich dein 
Beispiel auf mein Script übertragen könnte.
Ist ja auch nicht so wichtig, es funktioniert ja so. ;)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.