Forum: Digitale Signalverarbeitung / DSP / Machine Learning Wie Hilbert-Transformator berechnen


von Manfred M. (bittbeisser)


Angehängte Dateien:

Lesenswert?

Als Funkamateur und Hobby Programmierer versuche ich mich seit einiger 
Zeit in der digitalen Signalverarbeitung.

Dafür hätte ich gerne einen Hilbert Trasformator als Phasenschieber.

In dem Buch "Einführung in die digitale Signalverarbeitung" von H. Götze 
auf Seite 272ff habe ich dazu ein Beispiel gefunden. Das Beispiel geht 
jedoch von einer Phasendrehung von -90° aus. Leider sind meine 
mathematischen Kenntnisse nicht besonders ausgeprägt, weswegen ich 
bisher noch nicht herausgefunden habe, wie man eine Phasendrehung um 
+90° erreicht.

Ich weiss zwar, das man das einfach durch invertieren der Vorzeichen 
erreichen kann, aber das ist programmtechnisch blöd umzusetzen. Daher 
hätte ich gerne die richtige Formel dafür.

Im Buch ist für -90° folgende Formel angegeben:
bi = (1-cos(i-(k/2)π))/i-(k/2))π

Dabei ist k=10 (Anzahl der Koeffizienten = 11) und i geht von 0 bis 10.

Die im Buch angegebenen Koeffizienten konnte ich anhand der Formel 
nachvollziehen und habe sie manuell in mein Testprogramm eingegeben 
(siehe Anhang).

Ein Blockdiagramm in ein Programm umzusetzen fällt mir leichter als 
Formeln abzuwandeln. Daher benötige ich etwas Hilfe.

von Christoph db1uq K. (christoph_kessler)


Lesenswert?

<jean pütz> Ich hab da mal was vorbereitet </jean pütz>

https://www.mikrocontroller.net/articles/Hilbert-Transformator_%28Phasenschieber%29_mit_ATmega

In Matlab kann man FIR-Filter direkt für Hilpert-Trafo berechnen lassen, 
das sind immer zwei parallel, deren Ausgänge gegeneinander breitbandig 
um 90 Grad verschoben sind.

Mit IIR gibt es Näherungen, die Musikelektroniker machen das gern so.

von Helmut L. (helmi1)


Lesenswert?

Hier gibt es ein passendes Tool zu, da kannst du die Phasen einstellen.

http://iowahills.com/

von Martin O. (ossi-2)


Lesenswert?

90 Grad=-90 Grad + 180 Grad
Man muss also das Ausgangssignals eines -90 Grad Hilbert-transformators
einfach mit -1 multiplizieren um den 90 Grad Transformator zu erreichen.

von Manfred M. (bittbeisser)


Lesenswert?

Ich hätte vielleicht noch erwähnen sollen, dass alle meine Rechner mit 
Linux laufen und ich kein Windows habe. Damit entfällt Matlab.

Den Beitrag auf Iowahills kenne ich auch. Das ist der Grund weswegen ich 
2 Filter einsetzen will. Die müssen dann im Durchlassbereich nicht 
absolut flach sein, es genügt wenn sie symmetrisch sind.

Aber ich glaube die Lösung gefunden zu haben. Es scheint auszureichen, 
wenn man in der Formel über dem Bruchstrich
 1 - cos(iπ)
gegen
 cos(iπ) - 1
tauscht.

> Mit IIR gibt es Näherungen, die Musikelektroniker machen das gern so.
Auf die Idee wäre ich nicht gekommen. Mal sehen ob ich daraus weitere 
Anregungen bekomme.

Ich habe übrigens mal versuchsweise die Anzahl der Taps um 4 erhöht. Der 
Durchlassbereich wird etwas breiter und eine Welle kommt hinzu. Aber die 
Amplitude der Welligkeit bleibt erhalten, es wird also nicht flacher.

von Jan K. (jan_k)


Lesenswert?

Deine Ordnung ist etwas zu niedrig, erst bei höherer Ordnung wird die 
Amplitude schön flach. So Größenordnung 40 taps macht etwa +-0.2 dB 
ripple.

Btw, Matlab gibts auch für Linux.

: Bearbeitet durch User
von Manfred M. (bittbeisser)


Lesenswert?

Ich habe die Anzahl der Taps mal auf 19 erhöht (manuell gerechnet) und 
siehe da, die Amplitude des mittleren Höckers ist tatsächlich von +0.9 
auf +0.6 zurückgegangen. Aber die Höcker an den Bandenden sind in 
gleicher Höhe geblieben.

Bevor ich das jetzt weiter untersuche, will ich das erstmal als Programm 
umsetzen. Die manuelle Übertragung der Werte ist mir auf Dauer zu 
umständlich.

Interessant ist auch, das der cos-Term immer +1 oder -1 liefert (wg. 
n*π), den muss ich also nicht wirklich berechnen.

Ich war dann auch mal etwas übermütig, und habe die Tabs auf die 
mittlere 3 reduziert.
1
int numtaps = 3;
2
3
double b_coeff[] = {
4
   -0.636,
5
    0,
6
    0.636
7
};
Das Ergebnis ist ein Durchlassbereich, der wie eine positive Sinus 
Halbwelle aussieht. Ich erinnere mich dunkel, das hier so etwas vor ca. 
einem Jahr schon eimal diskutiert wurde, allerdings mit den Werten -1, 
0, +1.

Die Sache fängt an interessant zu werden.

: Bearbeitet durch User
von Dergute W. (derguteweka)


Lesenswert?

Moin,

Die Welligkeit koennte damit zu tun haben, dass die Koeffizienten nicht 
gefenstert wurden, sondern "roh" aus der Formel kommen.

Statt Matlab nehm' ich gerne GNU Octave mit dem Package Signal. Sollte 
bei haushaltsueblichen Linuxdistributionen installierbar sein.

Damit kann man sich z.B. so die Koeffizienten fuer ein Hilbertfilter 
berechnen lassen:
1
n=5; d=[zeros(1,n) 1 zeros(1,n)]; h=imag(hilbert (d,length(d)));freqz(h);

dabei ist n nicht die Anzahl der Koeffizienten, sondern die Anzahl ist 
dann 2*n+1; hier also 11.

Es gibt auch die Moeglichkeit mit der Octave-Funktion "remez" sowas zu 
machen, aber ich hab' so den Eindruck, dass da noch was in der Numerik 
klemmt. Das tut bei mir nicht so, wie's sollte (error: remez: 
insufficient extremals--cannot continue).

Gruss
WK

von Manfred M. (bittbeisser)


Angehängte Dateien:

Lesenswert?

Danke für den Hinweis mit der Fensterung. Ich werde diese Möglichkeit 
bei der Umsetzung berücksichtigen. Ich werde dann ja sehen welche 
Auswirkungen das hat und ob danach eine neue Normierung erforderlich 
ist.

> dabei ist n nicht die Anzahl der Koeffizienten, sondern die Anzahl ist
> dann 2*n+1; hier also 11.

Ja, diese Formulierung für die Koeffizienten macht Sinn, denn ausgehend 
vom mittleren Wert (=0) ist jeder ungerade Index-Wert vorhanden und 
jeder gerade Wert gleich 0 und macht somit als Endwert keinen Sinn.

> Es gibt auch die Moeglichkeit mit der Octave-Funktion "remez" sowas zu
> machen,...
Ups, ich dachte bisher das "remez" nur bei Matlab verfügbar ist. Und ich 
habe das immer mit dem "Parks–McClellan filter design algorithm" für 
eine Tschebyscheff Approximation in Verbindung gebracht. Den Code dafür 
habe ich zwar heruntergeladen, aber noch nicht ernsthaft daran gedacht 
damit etwas zu machen, da im hier mehrfach verlinktem DSP-Guide die 
Berechnung entsprechender IIR Filter gezeigt wird.

p.s. Ich habe so etwas wie eine Fensterfunktion jetzt einfach mal 
"gefühlsmäßig" aus der Hand simuliert, indem ich die weiter ab liegenden 
Werte einfach mal halbiert habe. Das Ergebnis überrascht mich. Die 
Welligkeit ist reduziert! Siehe Anhang.

: Bearbeitet durch User
von Dergute W. (derguteweka)


Lesenswert?

Moin,

Ja, das Gibbssche Phaenomen kommt immer und ueberall um die Ecke 
geschlichen, wenn man es nicht brauchen kann. Da hilft dann evtl. noch 
fenstern.
Ist aber bei der "hilbert" Funktion in Octave schon miteingebaut, 
zumindest sehen die Ergebnisse danach aus.

Gruss
WK

von Manfred M. (bittbeisser)


Lesenswert?

Ich habe die Hilbert Funktion jetzt mal provisorisch in mein Programm 
eingebaut, also ohne irgendwelche Fehlerprüfungen.

Bei 43 Taps ist die Welligkeit in der Mitte weniger geworden, aber die 
Überschwinger an den Enden bleiben. Aber jede beliebige Fensterfunktion 
bringt eine Besserung.

Auf den ersten Blick würde ich sagen ,dass Gauß und Blackman die besten 
Ergebnisse bringen, wobei Gauß einen steileren Übergangsbereich hat. Bei 
einem einfachen Cosinus Fenster sind aber noch deutliche Überschwinger 
an den Enden erkennbar.

Ich habe aber keine Ahnung, wie ich mit einfachen Mitteln überprüfen 
kann, ob die Phasendrehung nach der Fensterung erhalten geblieben ist.

von Dergute W. (derguteweka)


Angehängte Dateien:

Lesenswert?

Moin,

Naja, welches Fenster jetzt das tollste ist, das ist so aehnlich wie mit 
ein paar Tellern mit Kacke, und welcher schmeckt am besten... ;-)

Manfred M. schrieb:
> Ich habe aber keine Ahnung, wie ich mit einfachen Mitteln überprüfen
> kann, ob die Phasendrehung nach der Fensterung erhalten geblieben ist.

Eigentlich duerfte die Fensterung nix an der Phase drehen, wenn die 
Fensterkoeffizienten symmetrisch sind - also z.b. sowas [0 0.5 1 0.5 0]

Mal mit deinem Beispiel mit 43 Koeffizienten:

Erzeugung der Filterkoeffizenten; Ausgabe des Filters:
1
n=21; d=[zeros(1,n) 1 zeros(1,n)]; h=imag(hilbert (d,length(d)));freqz(h);

Test auf Phasenverschiebung:
1
(unwrap(arg(freqz(h))-arg(freqz(d))))
2
3
ans =
4
5
   0.00000
6
  -1.57080
7
  -1.57080
8
  -1.57080
9
  -1.57080
10
  -1.57080
11
  -1.57080
12
  -1.57080
13
  -1.57080
14
  -1.57080
15
  ....

Bis auf bei der Frequenz 0 sieht das doch recht konstant und pi/2 artig 
aus. Und der Ripple bleibt bis die meiste Zeit < +/- 0.5 dB; das ist 
doch schonmal was.

Gruss
WK

von Manfred M. (bittbeisser)


Angehängte Dateien:

Lesenswert?

> ... das ist doch schonmal was.
Das ist super. Eine Sache weniger, über die ich nachdenken muss. Die 
Filterkoeffizienten sind zwar nicht wirklich symmetrisch, denn sie 
unterscheiden sich durch die Vorzeichen. Bei -90° sind alle Vorzeichen 
links von der Mitte negativ und rechts positiv.

Und das mit dem Ripple passt in etwa. Mein Programm probiert das ja nur 
aus. Von daher sind meine Ergebnisse immer etwas ungenau, zumal ich auch 
immer die Mauskoordinaten (+/-1 Pixel) auf die Skalierung umrechnen 
muss.

Aber etwas irritiert bin ich von der Sprungantwort. Da habe ich 
möglicherweise noch einen Programmfehler. Ich finde einfach nicht 
heraus, warum die "Eiffeltürme" diese Stufen haben. Bei anderen Filtern 
sieht das immer glatt aus. Aber zumindest sieht die Sprungantwort fuer 
das +90° Filter spiegelbildlich aus. Das kann schonmal nicht ganz 
verkehrt sein.

Gruß
MM

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Manfred M. schrieb:
> Die
> Filterkoeffizienten sind zwar nicht wirklich symmetrisch, denn sie
> unterscheiden sich durch die Vorzeichen.

Man kann bei FIR Koeffizienten von Achsensymmetrie oder auch 
Punktsymmetrie sprechen. Der Hilbert ist Punktsymmetrisch.
Angenehm ist, dass bei FIR Filtern, deren Koeffizienten eine der beiden 
Symmetrien aufweisen, automatisch die Phase linear ist, bzw. die 
Gruppenlaufzeit konstant.

Das mit deinen gestufen Eiffeltuermen kann schon so passen.

Gruss
WK

von Manfred M. (bittbeisser)


Lesenswert?

Das mit der Punktsymmetrie ist wohl irgendwie an mir vorbei gegangen, 
wohl weil das bei meinen bisherigen Anwendungen nicht auftrat. 
Jedenfalls kann ich jetzt wieder an der Signalaufbereitung fuer meinen 
Morsedecoder basteln.

Übrigens habe ich festgestellt, dass bei einigen Fensterfunktionen 
(Cosinus, Von-Hann, Lanczos) der erste und der letzte Koeffizient mit 
geringer Abweichung (10E-17) Null werden. Und da sowieso jeder 2. 
Koeffizient 0 ist, kann man nochmal 4 davon einspaaren. Das erscheint 
mir deutlich effektiver, als wenn man einen normalen FIR Bandpass nimmt 
und nur die Vorzeichen invertiert (wie das z.B.  beim Programm Fldigi 
gemacht wird).

einen schönen Abend noch
MM

von Manfred M. (bittbeisser)


Lesenswert?

Mir gehen die Stufen am "Eiffelturm" nicht aus dem Kopf. Ich habe 2 
Dinge festgestellt:
 1) Die Stufen resultieren daraus, dass das aus dem Filter tatsächlich
    2 mal nacheinander der gleiche Wert herauskommt, was ich mit einem
    Debugger überprüft habe.

 2) Dieser Effekt tritt bei allen Filtern mit Null-Koeffizienten
    auf, z.B. auch bei Halbband-Filtern mit ungerader Tap Anzahl.

Es scheint mir, das dies System bedingt ist und nur mit analogen Filtern 
beseitigt werden kann. Sehe ich das richtig oder bin ich jetzt völlig 
auf dem Holzweg?

von Dergute W. (derguteweka)


Angehängte Dateien:

Lesenswert?

Moin,

Manfred M. schrieb:
> Es scheint mir, das dies System bedingt ist und nur mit analogen Filtern
> beseitigt werden kann. Sehe ich das richtig oder bin ich jetzt völlig
> auf dem Holzweg?

Ja klar ist das "systembedingt". Du willst ja was haben, was dir ueber 
einen moeglichst weiten Frequenzbereich eine moeglichst gleichbleibende 
90 Grad Phasenverschiebung macht. Das ist doch der Ausgangspunkt. Und 
dabei kommt dann halt ein Filter raus,  das bei einem niederfrequenten, 
rechteckfoermigen Eingangssignal "stufige Eiffeltuerme" als 
Filterantwort hat. Ist halt so.

Wenn du ein Filter haben willst, dass "schoene Eiffeltuerme" am Ausgang 
hat, dann bau's dir. Das ist dann aber kein Hilbert mehr, sondern 
irgendwas anderes, was vielleicht noch so aehnliche Eigenschaften hat.

Hier sind zwar die Eiffeltuerme nicht mehr stufig, aber dafuer der 
Frequenzgang alles andere als betragskonstant...

Gruss
WK

von Reinhard M. (Gast)


Lesenswert?

Die Hilbert Transformierte eines Rechtecks schaut genau so aus,
wie Du beschrieben hast.

Siehe gleich erstes Bild auf:

https://de.wikipedia.org/wiki/Hilbert-Transformation

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Dort steht aber auch weiter unten:

"Zu beachten ist, dass die zeitdiskrete Impulsantwort h[k] nicht der 
abgetasteten, kontinuierlichen Impulsantwort h(t) entspricht."

Gruss
WK

von Manfred M. (bittbeisser)


Lesenswert?

Die Bedeutung des Satzes hatte ich nicht erkannt.

Dabei hätte ich die Ursache der Stufen auch anhand des (vollständigen) 
Blockbildes erkennen können. Im Wikipedia Artikel sind 2 
Verzögerungsglieder zusammen gefasst. Dadurch ist nicht sofort 
ersichtlich, dass z.B. beim zweiten Arbeitstakt der weiter geschobene 
erste Wert auf den Koeffizienten 0 trifft und somit noch keinen Beitrag 
zur Ausgabe leistet.

Jedenfalls bin ich froh, dass sich alles aufgeklärt hat.
Gruß
MM

von Claus W. (Gast)


Lesenswert?

Formel im ersten Beitrag:

i geht von null bis k-1.

In der Formel wird durch i dividiert, das NULL sein kann. Es scheint 
eine Klammer zu fehlen.

von W.S. (Gast)


Lesenswert?

Claus W. schrieb:
> Es scheint
> eine Klammer zu fehlen.

Klar, Adlerauge.

bi = (1-cos(i-(k/2)π))/i-(k/2))π

das hat 4x '('  und 5x ')'
folglich stimmt das so nicht. Ist aber niemandem bislang aufgefallen, 
was ein Hinweis auf den Grad der Gründlichkeit ist.

W.S.

von Manfred M. (bittbeisser)


Lesenswert?

Da fehlt tatsächlich eine Klammer damit unter'm Bruchstrich alles 
zusammenbleibt.

bi = (1-cos(i-(k/2)π))/(i-(k/2))π

Und hier zur Kontrolle noch der (überarbeitungsbedürftige) Programmcode 
von damals:
1
void
2
FilterFactory::createFIR_Hilbert( InData_t * inp, Fdata_t * fdata ) {
3
    int     k2;
4
    int     n;
5
    int     cix;        // coefficient index
6
    double  arg;
7
    double *b;
8
    int     p_flag = 0;
9
    int     num_taps = inp->taps;
10
11
    b = new double[num_taps];
12
    k2 = (num_taps - 1) / 2;
13
    cix = num_taps - 1;     // tap coefficients are stored in reversed order!
14
    for( n = 0; n < num_taps; n++ ) {
15
        if( n == k2 ) {     // avoid division by zero
16
            b[cix] = 0.0;
17
        } else {
18
            arg = (n - k2) * M_PI;
19
            b[cix] = (1.0 - cos( arg )) / arg;
20
        }
21
        cix--;
22
    }
23
    fdata->a_coeff = 0;
24
    fdata->b_coeff = b;
25
}

von W.S. (Gast)


Lesenswert?

Manfred M. schrieb:
> Da fehlt tatsächlich eine Klammer damit unter'm Bruchstrich alles
> zusammenbleibt.
>
> bi = (1-cos(i-(k/2)π))/(i-(k/2))π

Ja was denn nun?

Normalerweise sind Division und Multiplikation gleichberechtigt. Da 
fragt man sich, wie du das mit dem schlußendlichen PI meinst. Soll das 
so gerechnet werden, wie du es darstellst oder soll es mit in den 
Nenner?

W.S.

von Christoph db1uq K. (christoph_kessler)


Lesenswert?

Der Tipp mit Iowa Hills ist gut
http://iowahills.com/A5HilbertPhasePage.html

Claus hat in meinem 10 Jahre alten Artikel ein Zusatzkapitel eingefügt
(ich habe eine e-mail bekommen "Mikrocontroller.net-Seite 
Hilbert-Transformator (Phasenschieber) mit ATmega wurde von Claus w 
geändert")

Bei der Gelegenheit habe ich ein paar verwaiste Links korrigiert, das 
meiste ist noch im Webarchiv zu finden.

> Kann man zu einem Sinussignal das Cosinus-Signal auch ohne synthetisches
> Filter erhalten? Genau weiß ich es nicht.

Wir hatten es neulich von der alten analogtechnischen Methode
Beitrag "Direktmisch-Empfänger: ungewolltes Seitenband passiv unterdrücken"
Nur mit R und C aufgebaut. Es gibt entweder einer sehr kompakte 
Schaltung, die aber hochpräzise Bauteile braucht oder das 
Polyphasen-Netzwerk.

Und es gibt ebenfalls analog die "dritte Methode" durch I/Q-Umsetzung 
auf eine Zwischenfrequenz, dazu sind nur schmalbandige Phasenschieber 
nötig.

Zu der Aussage "ermittelt zu einem Sinus-Signal das um 90° verschobene 
Cosinus-Signal" sollte man noch anmerken, dass jeder praktische 
Hilbert-Transformator eine Zeitverschiebung für beide Signale 
verursacht. Die FIR-Filter-Version hat wenigstens eine ebene 
Gruppenlaufzeit (konstante Zeitverzögerung für alle Frequenzen) , für 
die anderen ist die wellig. Dann haben die beiden Ausgangssignale 
gegenüber dem Eingang eine undefinierte frequenzabhängige 
Phasenverschiebung.

von Manfred M. (bittbeisser)


Lesenswert?

> Ja was denn nun?
Ja, da muss ich wohl noch zwei Klammern spendieren. Im Buch war das 
klassisch mit Bruchstrich abgedruckt, was ich leider falsch umgesetzt 
hatte. Im Programm ist das aber richtig.

bi = (1-cos(i-(k/2)π))/((i-(k/2))π)

> Der Tipp mit Iowa Hills ist gut
Die Idee ist Gut, aber leider hatte ich damals keine Anleitung für die 
Berechnung gefunden.

Im Programm FLDIGI wird das Problem auf andere Weise gelöst. Da werden 
zwei (fast) identische Filter verwendet. Allerdings wird bei einem bei 
der Berechnung der Koeffizienten anstatt eines Sinus der Cosinus 
verwendet. Das ergibt dann auch einen Phasenunterschied von 90°.

von Christoph db1uq K. (christoph_kessler)


Lesenswert?

>FLDIGI
http://www.w1hkj.com/FldigiHelp/index_of_contents_page.html
Ich suche überall nach der Beschreibung dieser Filterberechnung, ein 
ziemlich umfangreiches Programm. Wo soll das genau stehen?

Das Laden von PDFs von der Seite dauert anscheinend Stunden. Er zitiert 
eine Arbeit, die ich im Original schneller gefunden habe:
https://www.il-pib.pl/czasopisma/JTIT/2006/1/76.pdf
ist es das?

Iowa Hills schreibt
"Notice however, that this waveform starts before t = 0. ... (it is 
non-causal)"

Das ist das Problem der Hilbert-Transformation, ideal ist sie nicht 
möglich. Wie in den Neutrino-Witzen von 2011 ("wir bedienen hier keine 
überlichtschnellen Neutrinos" sagte der Barkeeper. Ein Neutrino betritt 
eine Bar.)

Man macht gleich zwei Zugeständnisse, die Zeitverzögerung rückt die 
Impulsantwort nach rechts, und links von t=0 wird deren 
Einschwingvorgang zu Null gesetzt.

: Bearbeitet durch User
von Dergute W. (derguteweka)


Lesenswert?

Moin,

Christoph db1uq K. schrieb:
> Wo soll das genau stehen?

Ich wuerd' mal mutmassen, dass es da drinnen steht:

fldigi-4.1.17/src/filters/filters.cxx

Gruss
WK

von W.S. (Gast)


Lesenswert?

Manfred M. schrieb:
>> Der Tipp mit Iowa Hills ist gut
> Die Idee ist Gut, aber leider hatte ich damals keine Anleitung für die
> Berechnung gefunden.

Willkommen im Club.

Ich hab auch schon seit ewig nach sowas gesucht, aber bislang rein 
garnichts zum Thema gefunden. Nun ja, da bei mir der Störpegel auf der 
KW unerträglich hoch ist, ist mir auch die Lust ziemlich vergangen, da 
weiter zu machen. Daher hab ich das Thema in letzter Zeit nicht wirklich 
weiter verfolgt.

Meine Idee ist allerdings etwas anders, als ich das bei dir sehe: ich 
würde allemal zwei gleiche Filterkernel verwenden, die jeweils um 45° 
drehen: das eine von vorn nach hinten, das andere von hinten nach vorn, 
sprich für I und Q die Koeffizienten gespiegelt (Tap[0]<-->Tap[N] usw.). 
Damit sind die beiden Filter von ihrer Art her recht gleich, sollten 
also keine unvorhergesehenen Unterschiede bringen außer der 
Drehrichtung: eines +45°, das andere -45°.

Im Prinzip sehe ich da nur 2 Wege der Berechnung:
1. ein fertiges Filter berechnen und als Realteil eines komplexen 
Filters ansehen, dann per Hilbert den zugehörigen Imaginärteil 
berechnen, dann alle Koeffizienten per Cordic um rund 45° (einstellbar 
bzw. justierbar zum Ausgleich etwaiger Toleranzen weiter vorn im 
Analogteil) drehen und davon dann den resultierenden Realteil als 
Filterkernel nehmen.
2. sowas wie den sin(x)/x auf komplexe x erweitern und das Ganze erstmal 
rein analytisch zu rechentechnisch benutzbaren Funktionen reduzieren. 
Ist aber nur eine vage Idee.

W.S.

von W.S. (Gast)


Lesenswert?

Christoph db1uq K. schrieb:
> Man macht gleich zwei Zugeständnisse, die Zeitverzögerung rückt die
> Impulsantwort nach rechts

Im Grunde hast du das doch bei allen symmetrischen Filtern. Jedes 
braucht die gleiche Anzahl von Samples in der Vergangenheit wie in der 
Zukunft. Daher füllt man die neuen Samples in die Zukunft ein, wo sie 
dann mit jedem Sample ein Stück Richtung Gegenwart rutschen und danach 
in der Vergangenheit verschwinden. Deshalb ist JETZT eben nicht am 
gerade gelesenen Sample, sondern in der Mitte des Filters. Und das eben 
ganz gleich, ob das Filter nun die Phase dreht oder nicht.

Und asymmetrische Filter (also n(Zukunft) <> n(Vergangenheit)) willst du 
bestimmt nicht einsetzen.

W.S.

von Christoph db1uq K. (christoph_kessler)


Lesenswert?

Das ist die komplette Adresse:
https://sourceforge.net/p/fldigi/fldigi/ci/master/tree/src/filters/filters.cxx

hier?
Zeile 149 // Filter will (be) the Hilbert form
Zeile 103-108:
    if (!hilbert) {
      x = (2  f2  sinc(2  f2  t) -
           2  f1  sinc(2  f1  t)) * hamming(h);
    } else {
      x = (2  f2  cosc(2  f2  t) -
           2  f1  cosc(2  f1  t)) * hamming(h);

https://de.wikipedia.org/wiki/Sinc-Funktion
der cosc ist anscheinend seltener

von Dergute W. (derguteweka)


Lesenswert?

Christoph db1uq K. schrieb:
> der cosc ist anscheinend seltener

Ja, der ist auch "nur" in der src/include/filters.h als inline function 
definiert.

Das scheint mir so aehnlich gemacht zu werden, wie ich hier mal schrub:
https://embdev.net/topic/368003#4149218

Gruss
WK

von Manfred M. (bittbeisser)


Lesenswert?

> Das ist die komplette Adresse:
Ich wollte gerade die komplette Funktion posten, was sich jetzt erübrigt 
hat.
Ich hatte mir seinerzeit den kompletten Quältext heruntergeladen. Ist 
wirklich umfangreich aber auch interessant. Da sind einige interessante 
Tricks dabei.

Die Synchronisation bei PSK31 habe ich aber nicht verstanden (das greife 
ich vielleicht später noch einmal auf).

von Christoph db1uq K. (christoph_kessler)


Lesenswert?

https://sourceforge.net/p/fldigi/fldigi/ci/master/tree/src/include/filters.h

Die hatte ich gesucht, Zeilen 59-70 sind sinc und cosc, in guter 
Gesellschaft von mac (multiply-accumulate), Moving average filter, 
Sliding FFT (was macht man damit?) und einem Goertzel.

von Manfred M. (bittbeisser)


Lesenswert?

> Sliding FFT (was macht man damit?)
Ich tippe mal auf das Wasserfalldiagramm.

> und einem Goertzel
Der taucht in dtmf.cxx auf. Was damit codiert wird weiß ich aber nicht.

von Burkhard K. (buks)


Lesenswert?

W.S. schrieb:
> als ich das bei dir sehe: ich
> würde allemal zwei gleiche Filterkernel verwenden, die jeweils um 45°
> drehen:

Die Idee ist nicht ganz neu: Clay S. Turner, "An Efficient Analytic 
Signal Generator": 
https://www.iro.umontreal.ca/~mignotte/IFT3205/Documents/TipsAndTricks/AnEfficientAnalyticSignalGenerator.pdf

von Christoph db1uq K. (christoph_kessler)


Lesenswert?

Den Artikel gibt es auch vom Autor:
http://www.claysturner.com/dsp/
http://www.claysturner.com/dsp/ASG.pdf

Der Artikel ist auch in einem Buch abgedruckt, ISBN 9781118278383
(nur ab der 2.Auflage von 2012, das habe ich hier vorliegen)
dort ist auch eine aktuelle Downloadadresse für den Matlab-Code dazu. 
Die Adresse im PDF existiert nicht mehr:
https://wiley.mpstechnologies.com/wiley/BOBContent/searchLPBobContent.do
ISBN:9781118278383 eintragen und "Chap 38 Analytic Sig Gen.zip" 
downloaden
Filename:                            Function
"ASG Notes Ver-1.1.doc"            Mathematical Derivations
"AnalyticSignalGenerator.mcd"      MathCAD code
QuadFilterCoeffs_Turner_test.m:     MATLAB Main routine for testing.
                                   Run this first.
QuadFilterCoeffs_Turner.m          MATLAB: Generates complex filter's 
coefficients.
QuadFilterCoeffs_Turner_plots.m     MATLAB: Generates complex filter's 
coefficients
                                   plus many plots showing the 
performance
                                   of the filters.

Der Herausgeber dieses Buchs Rick Lyons erwähnt Clay Turner in einer 
Übersicht
"Complex baseband and analytic bandpass signal generation methods"
mit Blockdiagrammen zu den verschiedenen Möglichkeiten.
https://www.dsprelated.com/showarticle/153.php

: Bearbeitet durch User
von W.S. (Gast)


Angehängte Dateien:

Lesenswert?

Burkhard K. schrieb:
> Die Idee ist nicht ganz neu

Ja kenn ich. Aber auch bei seinem Artikel sind Fehler drin. Entweder 
Druckfehler oder Schusselfehler oder mißverständlich sich ausgedrückt.
Ich hatte das vor so etwa 4 Jahren schon mal simuliert.
Ergebnis: Sperrtiefe mangelhaft und Sperrtiefe sinkt mit Breite des 
Durchlaßbereiches.
Ich häng dir mal ein paar Bilder und den Filterkernel dran. Guck dir den 
Artikel nochmal an, vielleicht findest du den Knackpunkt, den ich damals 
nicht gefunden hatte.

W.S.

von Manfred M. (bittbeisser)


Angehängte Dateien:

Lesenswert?

Die neu verlinkten Dokumente sehen interessant aus. Allerdings hatte ich 
noch nicht die Zeit, mich damit intensiver zu beschäftigen.

Aber ich konnte es nicht lassen, die geposteten Koeffizienten mal an 
mein altes Programm zu verfüttern. Das Ergebnis ist so gut wie identisch 
(siehe Anhang).

Allerdings sind die Koeffizienten nicht symmetrisch angeordnet (falls da 
kein Fehler passiert ist). Wie wurden die Werte berechnet?

Meine Impulsantwort sieht ähnlich aus, ist aber etwas flacher, was 
vermutlich mit der Skalierung zu tun hat.

von W.S. (Gast)


Lesenswert?

Manfred M. schrieb:
> Allerdings sind die Koeffizienten nicht symmetrisch angeordnet

Jahahaha.. das ist der eigentliche Knackpunkt. Bei einer Phasendrehung 
von Null ist der Filterkernel spiegelsymmetrisch um das mittlere 
Element. Wenn man die Phase dreht, dann wachsen die Taps auf einer Seite 
und schrumpfen auf der anderen, bis der ganze Filterkernel bei 90 Grad 
punktsymmetrisch um das mittlere Element ist.

Stell dir den Filterkernel mal vor als eine im Raum liegende Spirale. 
Abszisse sind die Taps von 0 (links) bis N (rechts). Nach oben geht der 
Realanteil und von vorn nach hinten der Imaginäranteil. Und 
normalerweies gucken wir nur von vorn drauf, sehen also nur den 
Realanteil.

Wenn man nun entweder diese Spirale dreht oder schräg von oben oder 
unten guckt, sieht diese Spirale anders aus und wenn man senkrecht von 
oben/unten guckt, sieht man nur den Imaginäranteil und der ist 
punktsymmetrisch.

W.S.

von Burkhard K. (buks)


Angehängte Dateien:

Lesenswert?

W.S. schrieb:
> Sperrtiefe mangelhaft und Sperrtiefe sinkt mit Breite des
> Durchlaßbereiches.

Kann ich so nicht nachvollziehen, ich hatte das Filter vor mehreren 
Jahren mit 2x242 Taps mit 0.240xFs Durchlass berechnet und dann in einem 
FPGA-Projekt eingesetzt. Optimal wäre ein symmetrisch um Fs/4 
angeordnetes Filter, das wird von Turner auch so beschrieben. Das ging 
in meinem Fall nicht, daher musste ich die Anzahl der Taps hochdrehen.

Manfred M. schrieb:
> Allerdings sind die Koeffizienten nicht symmetrisch angeordnet (falls da
> kein Fehler passiert ist). Wie wurden die Werte berechnet?

Wie bereits gesagt, kein Fehler. Dafür sind die beiden 
In-Phase/Quad-Kernel zueinander symmetrisch. Die Berechnung ist in ASG 
Notes Ver-1.1.doc (siehe Beitrag von Christoph) abgeleitet und dann in 
Formel (22) zusammengefasst.

von W.S. (Gast)


Angehängte Dateien:

Lesenswert?

Burkhard K. schrieb:
> Kann ich so nicht nachvollziehen,

Macht nix. So wie ich das in deinen Bildern sehe, hattest du da ein ganz 
anderes Anliegen als ich es habe.

Aber dein Beitrag hat was Gutes. Ich hab mich nämlich grad vorhin 
aufgerafft, das ganze alte Zeugs nochmal durchzusehen. Ist alles von 
2015..2016.

OK, eine Bemerkung von W.Kiefer dazu hat auch ihr übriges getan. 
Halleluja sag ich.

Ich häng dir mal 2 Dateien dran: zuerst ein gesammelter Vergleich 
zwischen Filterkerneln von IOWA Hills und von Turner, beide unter 
gleichen Randbedingungen, die einem üblichen SSB-Empfänger entsprechen. 
Also ein FIR-Bandpass von etwa 100..300Hz bis etwa 2.7..3.0 kHz und 
Filterlänge von 201 Taps.
Ich hab das ganze vorhin nochmal durchexerziert und dabei ein paar 
Marken gesetzt. Im Archiv sind für beide Kandidaten:
- die Daten, also Textdateien mit den Koeffizienten.
- die Filterkernel als JPG, in Stufen zu 5 Grad Phasendrehung
- die zugehörigen Filter im Frequenzverlauf
Die Kernel von IOWA Hills sind (wenn ich mich recht erinnere) per 
Blackman gefenstert. Kaiser wäre da schöner.

So, und obendrein hab ich mal die weiter oben von mir genannte 2. 
Version der Filter-Berechnung als Pascalquelle drangehängt. Das ist die 
mit der Erweiterung der Berechnung von Real auf Komplex. Ist platzmäßig 
aufwendig für das Durchziehen auf einem µC, weil man eine Reihe von 
Arrays braucht. Aber vielleicht kann man den Platzbedarf deutlich 
senken, wenn man Re und Im schön nacheinander berechnet. Mal sehen.

Den abschließenden Teil zum Drehen per Cordic hab ich noch nicht 
gemacht, aber das ist schlußendlich nur noch eine Fleißaufgabe.

Die Idee, den ganzen Filter zuerst nur Real zu berechnen und dann per 
Hilbert um 90° zu drehen, um den Imginärteil zu kriegen, können wir 
getrost in die Tonne werfen. Das ist mir jetzt endgültig klar geworden. 
Die Geradeaus-Berechnung braucht zwar mehr an RAM, aber das sollte sich 
bei einem etwas dickeren µC noch unterbringen lassen.

Ach ja: ich hatte auch mal getestet, wie sehr die Kernel degradieren, 
wenn man nicht double filtert, sondern single filtert oder gar integer 
filtert. Naja, so wenigstens 22 Bit sollten es schon sein, sonst 
gefällt's mir nicht mehr wirklich. Da werde ich demnächst auch mal 
testen, wie breit man den Kernel berechnen muß, ohne daß er schlecht 
wird.

W.S.

von Manfred M. (bittbeisser)


Lesenswert?

Ich finde die Erklärung von W.S. recht anschaulich. So etwas vermisse 
ich in der deutschen Literatur. Da wird einem oft nur eine Formel 
vorgesetzt, was wenig einsteigerfreundlich ist (ich bin ja nur 
Funkamateur).

Zum Pascal Code: Mein (Linux-) Editor stört sich da an der Windows 
Zeichenkodierung und will, das ich die einstelle. Aber der Programmcode 
sieht ja recht übersichtlich aus. Danke dafür. Ich komme allerdings 
momentan nicht dazu das umzusetzen, da ich seit Tagen gegen einen 
Programmfehler kämpfe.

von W.S. (Gast)



Lesenswert?

Manfred M. schrieb:
> Zum Pascal Code: Mein (Linux-) Editor stört sich da an der Windows
> Zeichenkodierung

Ich benutze den Notetab pro, der hat zwar auch seine Eigenheiten, aber 
er stört sich nicht an den fehlenden CR bei Unixquellen. Abgesehen davon 
habe ich Pascal aus mehreren wichtigen Gründen gewählt. Zum einen, weil 
ich selber damit programmiere, zum anderen, weil gerade Pascal noch 
immer das leserlichste ist, was eigentlich jeder verstehen kann. C 
hingegen bedarf einiger Vorkenntnisse.

Wolfgang Kiefer hat mich am Wochenende dazu angeregt, meinen alten Kram 
hervorzuholen und endlich fertig zu machen, wozu eben auch eine 
möglichst lesbare Dokumentation gehört. Also hab ich das Ganze mal 
niedergeschrieben, siehe Anhang. Ein erstes Ausprobieren ging auch 
zufriedenstellend, ist jedenfalls mMn besser als das von Turner.

W.S.

von bubu (Gast)


Lesenswert?

wie oben jemand schon sagte, musiker nehmen dazu einfach zwei biquad 
oder einen FIR und erzeugen 2 filtereinstellungen, die sich genau um 90 
grad verschoben zueinander verhalten, ohne dass man über die 
verscheibung zum eingangssignal bescheid wissen müsste, denn bei 
musiksignalen ist sehr häufig die "phase" in diesem sinn vollkommen egal 
da man sie ehnicht hört; hauptsache, ich kann das signal jetzt erst mal 
symetrisch verarbeiten.

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.