Abend! Und zwar will ich ein zeitvariantes Filter für Audioanwendungen auf einem FPGA realisieren. Vorerst versuche ich mal meine theoretischen Überlegungen in Matlab zu simulieren. Auf jeden Fall habe ich da folgendes Problem: Mein Filter soll ein Bandpassfilter (einige 100 Hz Bandbreite) sein, aber mit einer variablen Mittenfrequenz, die sich abhängig von der Zeit ändert. Das heißt, dass als Parameter für die Mittenfrequenz ein LFO dienen soll. Nur da scheiterts bei mir, weil ich noch nicht genau weiß wie ich ein zeitvariantes Filter simuliere. Wär toll, wenn mir jemand Antwort geben könnte, kann gerne noch mehr Infos dazu geben. rock on, Johnsn
Ich hab mal in Google "Zeitvariante Filter" eingegeben, da findet sich einiges an Vorlesungsskripten und Übungen, besonders aus der Elekroakustik und Musikelektronik, teilweise wird auch Matlab erwähnt, z.B. hier: http://www.lnt.de/lms/lecture/digsounds/index.php?lang=de
In der Theorie der digitalen Filter scheinen zeitvariante, also leicht über einen oder wenige Parameter in der Frequenz verstellbare Filter selten vorzukommen. Ich habe in meiner Literatur zu DSPs eine einzige Erwähnung gefunden, und das scheint etwas ziemlich exotisches zu sein. Zwei Allpässe, die sich irgendwie "Kongruent" voneinander unterscheiden, in einer "Brückenschaltung", und dann gibt es einen Parameter, den man ändern muß, Das Buch heißt "Digitale Filter", Autor W.Hess im Teubner-Verlag 1993 ISBN 3-519-16121-4 und der kurze Abschnitt heißt "Abstimmbare Filter" S. 196-197. Seither sind natürlich 13 Jahre vergangen, vermutlich hat sich inzwischern einiges getan. Vermutlich berechnet man normalerweise die Parameter für jeden Einstellvorgang neu oder hat eine Tabelle.
Zeitvariante digitale Filter sind weitverbreitet, z.B. als Echocanceller in jedem DSL Modem / Telefon mit Freisprecheinrichtung etc. oder als adaptive Filter zur Systemidentifikation. 'Zeitvariant' hat ja 'mit in der Frequenz verstellbare' Filter erstmal nix zum tun. Anderes Beispiel sind die Rückkopplungskiller für die Bühne, liefen hier im Forum mal unter 'Autonotch' oder so, glaube ich. Standardwerk Adaptive Filter Theory (4th Edition) by Simon Haykin Cheers Detlef
Beim Autonotchen wird ein gegenphasiges Signal addiert, das geht einfacher, als alle Filterparameter ständig umzurechnen und neu zu schreiben. Auch Echocanceller sind so gebaut. LMS-Filter heißt das als Suchbegriff, least mean square, also kleinstes Quadratmittel, mit dem man sich dem Störsignal annähert.
Es ist ja auch in der analogen Filtertechnik nicht einfach, ein mehrkreisiges Filter durchstimmbar aufzubauen. Man muß sich nur mal einen professionellen Funkempfänger aus der Röhrenzeit ansehen, gegeneinander verspannte Zahnräder, Kurvenscheiben, eine teure Feinmechanik um sämtliche Filter gleichlaufend zu verstellen. Die Erfindung des Superhet-Empfängers hat das vereinfacht, das hochselektive Filter ist fest auf die Zwischenfrequenz abgeglichen.
Damit kannst Du für alle möglichen Filter die Filterkoeffizienten Berechnen. Dann mußt die Die Koeffizienten einfach in Deine Biquad- Gleichung einsetzen.
1 | /* Simple implementation of Biquad filters -- Tom St Denis
|
2 | *
|
3 | * Based on the work
|
4 | |
5 | Cookbook formulae for audio EQ biquad filter coefficients
|
6 | ---------------------------------------------------------
|
7 | by Robert Bristow-Johnson, pbjrbj@viconet.com a.k.a. robert@audioheads.com
|
8 | |
9 | * Available on the web at
|
10 | |
11 | http://www.smartelectronix.com/musicdsp/text/filters005.txt
|
12 | |
13 | * Enjoy.
|
14 | *
|
15 | * This work is hereby placed in the public domain for all purposes, whether
|
16 | * commercial, free [as in speech] or educational, etc. Use the code and please
|
17 | * give me credit if you wish.
|
18 | *
|
19 | * Tom St Denis -- http://tomstdenis.home.dhs.org
|
20 | */
|
21 | |
22 | /* this would be biquad.h */
|
23 | #include <math.h> |
24 | #include <stdlib.h> |
25 | |
26 | #ifndef M_LN2
|
27 | #define M_LN2 0.69314718055994530942
|
28 | #endif
|
29 | |
30 | #ifndef M_PI
|
31 | #define M_PI3.14159265358979323846
|
32 | #endif
|
33 | |
34 | /* whatever sample type you want */
|
35 | typedef double smp_type; |
36 | |
37 | /* this holds the data required to update samples thru a filter */
|
38 | typedef struct { |
39 | smp_type a0, a1, a2, a3, a4; |
40 | smp_type x1, x2, y1, y2; |
41 | }
|
42 | biquad; |
43 | |
44 | extern smp_type BiQuad(smp_type sample, biquad * b); |
45 | extern biquad *BiQuad_new(int type, smp_type dbGain, /* gain of filter */ |
46 | smp_type freq, /* center frequency */ |
47 | smp_type srate, /* sampling rate */ |
48 | smp_type bandwidth); /* bandwidth in octaves */ |
49 | |
50 | /* filter types */
|
51 | enum { |
52 | LPF, /* low pass filter */ |
53 | HPF, /* High pass filter */ |
54 | BPF, /* band pass filter */ |
55 | NOTCH, /* Notch Filter */ |
56 | PEQ, /* Peaking band EQ filter */ |
57 | LSH, /* Low shelf filter */ |
58 | HSH /* High shelf filter */ |
59 | };
|
60 | |
61 | /* Below this would be biquad.c */
|
62 | /* Computes a BiQuad filter on a sample */
|
63 | smp_type BiQuad(smp_type sample, biquad * b) |
64 | {
|
65 | smp_type result; |
66 | |
67 | /* compute result */
|
68 | result = b->a0 * sample + b->a1 * b->x1 + b->a2 * b->x2 - |
69 | b->a3 * b->y1 - b->a4 * b->y2; |
70 | |
71 | /* shift x1 to x2, sample to x1 */
|
72 | b->x2 = b->x1; |
73 | b->x1 = sample; |
74 | |
75 | /* shift y1 to y2, result to y1 */
|
76 | b->y2 = b->y1; |
77 | b->y1 = result; |
78 | |
79 | return result; |
80 | }
|
81 | |
82 | /* sets up a BiQuad Filter */
|
83 | biquad *BiQuad_new(int type, smp_type dbGain, smp_type freq, |
84 | smp_type srate, smp_type bandwidth) |
85 | {
|
86 | biquad *b; |
87 | smp_type A, omega, sn, cs, alpha, beta; |
88 | smp_type a0, a1, a2, b0, b1, b2; |
89 | |
90 | b = malloc(sizeof(biquad)); |
91 | if (b == NULL) |
92 | return NULL; |
93 | |
94 | /* setup variables */
|
95 | A = pow(10, dbGain /40); |
96 | omega = 2 * M_PI * freq /srate; |
97 | sn = sin(omega); |
98 | cs = cos(omega); |
99 | alpha = sn * sinh(M_LN2 /2 * bandwidth * omega /sn); |
100 | beta = sqrt(A + A); |
101 | |
102 | switch (type) { |
103 | case LPF: |
104 | b0 = (1 - cs) /2; |
105 | b1 = 1 - cs; |
106 | b2 = (1 - cs) /2; |
107 | a0 = 1 + alpha; |
108 | a1 = -2 * cs; |
109 | a2 = 1 - alpha; |
110 | break; |
111 | case HPF: |
112 | b0 = (1 + cs) /2; |
113 | b1 = -(1 + cs); |
114 | b2 = (1 + cs) /2; |
115 | a0 = 1 + alpha; |
116 | a1 = -2 * cs; |
117 | a2 = 1 - alpha; |
118 | break; |
119 | case BPF: |
120 | b0 = alpha; |
121 | b1 = 0; |
122 | b2 = -alpha; |
123 | a0 = 1 + alpha; |
124 | a1 = -2 * cs; |
125 | a2 = 1 - alpha; |
126 | break; |
127 | case NOTCH: |
128 | b0 = 1; |
129 | b1 = -2 * cs; |
130 | b2 = 1; |
131 | a0 = 1 + alpha; |
132 | a1 = -2 * cs; |
133 | a2 = 1 - alpha; |
134 | break; |
135 | case PEQ: |
136 | b0 = 1 + (alpha * A); |
137 | b1 = -2 * cs; |
138 | b2 = 1 - (alpha * A); |
139 | a0 = 1 + (alpha /A); |
140 | a1 = -2 * cs; |
141 | a2 = 1 - (alpha /A); |
142 | break; |
143 | case LSH: |
144 | b0 = A * ((A + 1) - (A - 1) * cs + beta * sn); |
145 | b1 = 2 * A * ((A - 1) - (A + 1) * cs); |
146 | b2 = A * ((A + 1) - (A - 1) * cs - beta * sn); |
147 | a0 = (A + 1) + (A - 1) * cs + beta * sn; |
148 | a1 = -2 * ((A - 1) + (A + 1) * cs); |
149 | a2 = (A + 1) + (A - 1) * cs - beta * sn; |
150 | break; |
151 | case HSH: |
152 | b0 = A * ((A + 1) + (A - 1) * cs + beta * sn); |
153 | b1 = -2 * A * ((A - 1) + (A + 1) * cs); |
154 | b2 = A * ((A + 1) + (A - 1) * cs - beta * sn); |
155 | a0 = (A + 1) - (A - 1) * cs + beta * sn; |
156 | a1 = 2 * ((A - 1) - (A + 1) * cs); |
157 | a2 = (A + 1) - (A - 1) * cs - beta * sn; |
158 | break; |
159 | default:
|
160 | free(b); |
161 | return NULL; |
162 | }
|
163 | |
164 | /* precompute the coefficients */
|
165 | b->a0 = b0 /a0; |
166 | b->a1 = b1 /a0; |
167 | b->a2 = b2 /a0; |
168 | b->a3 = a1 /a0; |
169 | b->a4 = a2 /a0; |
170 | |
171 | /* zero initial samples */
|
172 | b->x1 = b->x2 = 0; |
173 | b->y1 = b->y2 = 0; |
174 | |
175 | return b; |
176 | }
|
177 | /* crc==3062280887, version==4, Sat Jul 7 00:03:23 2001 */
|
:
Bearbeitet durch Admin
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.