Forum: Digitale Signalverarbeitung / DSP / Machine Learning FIR in Octave


von U. B. (ub007)


Angehängte Dateien:

Lesenswert?

Hallo !

Es gab schon mal einen ähnlichen Thread hier aber genau auf die Frage wo 
ich jetzt auch habe wurde leider keine Antwort gegeben.
Ich möchte in Octave einen FIR berechnen aber nicht mit den Funktionen 
die Octave zur Verfügung stellt sondern eben "mit der Hand am Arm".
Ich habe eine Sweep-WAV generiert die ich in Octave einlesen kann. Die 
Frequenz läuft von 50Hz bis 18kHz mit 22050 Samples bei einer Samplerate 
von 44100Hz. Mein LP-Filter soll z.B. bei 2.5KHz dicht machen. Wie 
erwartet zeigt die FFT-Analyse (siehe Bild) wie der Sweep im 
Frequenz-Bereich aussieht. Lass ich aber den Filter mit 20 Tabs drüber 
laufen ergibt sich nur in der Amplitude eine Änderung. Auch mit 100 Tabs 
oder ungeraden oder geraden Anzahl von Tabs sieht das immer gleich aus.
OK, der Code in Octave ist nicht effizient, aber wie gesagt, es sollte 
ja erst mal nur zum testen sein. Die Koeffizienten wurden über Tone FIR 
Designer errechnet und der Code habe ich von
http://www.fh-schmalkalden.de/schmalkaldenmedia/Realisierung_Digitaler_Filter_in_C-p-419.pdf
An was kann es liegen das man ab 2.5kHz keinen Abfall der Frequenz sieht 
?

Gruß Uli

Hier mal der Octave-Code:
1
% Octave  
2
3
%// FilterType = LoPass, fcut1 = 2.5kHz 
4
%// fsample = 44100Hz, Window = Hamming, 
5
nc = 20;
6
b=[
7
  -0.011433, 0.007947, 0.060518, 0.184715, 0.406822, 0.726661,
8
  1.111126, 1.498814, 1.815087, 1.992966, 2.003541, 1.815087,
9
  1.498814, 1.111126, 0.726661, 0.406822, 0.184715, 0.060518,
10
  0.007947, -0.011433,
11
];
12
13
% ---------------------------------------- 
14
function y=G(ys,nc,b,in_buffer) 
15
16
   % alle Werte nach rechts shiften
17
  for i=nc:-1:2          
18
      in_buffer(i) = in_buffer(i-1); 
19
   end 
20
21
   % Schreibe neuen Wert ys in Buffer 
22
   in_buffer(1) = ys; 
23
   
24
   % Berechne neuen Ausgangswert 
25
   y = 0; 
26
   for i=1:+1:nc 
27
      y += ( b(i)*in_buffer(i) ); 
28
   end 
29
endfunction 
30
% ---------------------------------------- 
31
clf
32
t=1; y=0; ys1=0; samplerate=44100;
33
ys = wavread ("ttt.wav");
34
samples=length(ys);
35
36
% in_buffer loeschen
37
for i=1:+1:nc
38
   in_buffer(i) = 0; 
39
end
40
41
for t=1:+1:samples
42
   ym(t)=G(ys(t),nc,b,in_buffer);
43
end 
44
45
ym1=abs(fft(ym));
46
yo1=abs(fft(ys));
47
48
t=1:+1:samples;
49
50
% FFT-Plot
51
subplot(4,1,1)
52
plot(t*(samplerate/samples),yo1);grid on;
53
axis([0 20000])
54
title("FFT ohne Filter")
55
56
subplot(4,1,2)
57
plot(t*(samplerate/samples),ym1);grid on;
58
axis([0 20000])
59
title("FFT nach Filter")
60
61
%Signal-Plot
62
subplot(4,1,3)
63
plot(t,ys(t));grid on;
64
title("Signal ohne Filter")
65
66
subplot(4,1,4)
67
plot(t,ym(t));grid on;
68
title("Signal mit Filter")

von Markus B. (russenbaer)


Angehängte Dateien:

Lesenswert?

Servus Uli,

Ich hab Dir mit Octave (freqz Funktion) den Frequenzgang Deines Filters 
gerechnet.
Willst Du wirklich so ein Filter?

BTW:
Du gibst den State (Gedächtnis) Deines Filters nicht zurück, MATLAB und 
ich nehme an auch OCTAVE übergeben Werte durch kopieren, nicht durch 
Referenz. Im (hab ich mir jetzt nicht angeschaut) Beispiel wo Du den 
C-Code nachgetippt hast wird sicher ein Pointer auf deinen in_buffer 
übergeben.
Das gibts in MATLAB/Octave nicht!

Du musst als zweite Variable den State zurückgeben!
1
function [y, in_buffer] = G(ys,nc,b,in_buffer)
lg
Markus

PS:
Effizientes umkopieren (was Du in einer Schleife erledigst)
1
b(2:end) = b(1:end-1];
Inprodukt zweier Vektoren (Berechnung Deines Ausgangswertes y, Ersatz 
für die zweite Schleife in Deiner Funktion)
1
y = b(:)' * in_buffer(:);
Erzeugen eines Null-Initialisierten Buffers:
1
in_buffer = zeros(numel(b),1);

von U. B. (ub007)


Lesenswert?

Hallo Markus !

Erstmal danke für die Antwort.

Markus B. schrieb:
> Servus Uli,
>
> Ich hab Dir mit Octave (freqz Funktion) den Frequenzgang Deines Filters
> gerechnet.
> Willst Du wirklich so ein Filter?
>
Nein Markus natürlich nicht, aber das ist wie beschrieben eben nur zum 
Test.
>
> BTW:
> Du gibst den State (Gedächtnis) Deines Filters nicht zurück, MATLAB und
> ich nehme an auch OCTAVE übergeben Werte durch kopieren, nicht durch
> Referenz. Im (hab ich mir jetzt nicht angeschaut) Beispiel wo Du den
> C-Code nachgetippt hast wird sicher ein Pointer auf deinen in_buffer
> übergeben.
> Das gibts in MATLAB/Octave nicht!
>
Ebent ;-) Das gibt es nicht. Deshalb hab ich mal abgeprüft ob Variablen 
wie in_buffer oder eben die Koeffizienten b(i) in der Funktion zur 
Verfügung stehen. Ich übergebe sie ja beim Aufruf mit z.B. G(...b,,,)
Und sie stehen auch drin !
>
> Du musst als zweite Variable den State zurückgeben!function [y,
> in_buffer] = G(ys,nc,b,in_buffer)
> lg
> Markus
>
Klar, man hätte korrektehalber y und in_buffer mit einem "return" 
zurückgeben können, aber nachdem die Werte außerhalb und innerhalb der 
Funktion(Scope) identisch sind(hab ich mir durch printf anzeigen 
lassen), hab ich mir das an der Stelle erspart.
Ich weiß das klingt wie hingeschludert, aber ich befürchte selbst wenn 
alles 1000% korrekt programmiert ist, dass das Ergebnis nicht besser 
aussieht als wie oben im Bild ! In dem anderen Thread sagte der 
Thread-Eröffner man muss mit den Koeffizienten einbischen 
herum-experimentieren dann bekommt man den Filter tatsächlich zum 
laufen, aber genau das möchte ich eben nicht.

Gruß Uli

von Detlef _. (detlef_a)


Lesenswert?

Hallo Uli,

das rechtsshiften der Werte kommt nicht zurück. Machs' so wie Markus das 
beschrieben hat, Deine Variante funktioniert nicht.

Cheers
Detlef

von U. B. (ub007)


Angehängte Dateien:

Lesenswert?

Detlef _a schrieb:
> Hallo Uli,
>
> das rechtsshiften der Werte kommt nicht zurück. Machs' so wie Markus das
> beschrieben hat, Deine Variante funktioniert nicht.
>
> Cheers
> Detlef

Ups....da hab ich etwas nicht in Octave nicht gewußt....Shit happens...
denn als ich das von Markus einbaute...sieht das ganze jetzt so 
aus...siehe Bild...und genau das wollte ich !
Dank euch beiden :-)

Grüßle Uli

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.