Digitaler Tiefpassfilter



  • @NoobTracker Wovon sprichst du?
    Hast du dir mal die 5 Koeffizienten angesehen die da ausgerechnet werden? Und ist dir aufgefallen dass sich die ändern wenn du den Q Wert änderst?
    Eieiei...

    Was meinst du wofür so ein Koeffizienten-Berechnungsprogramm da ist? Wenn man die Parameter (Frequenz, Q, ...) einfach so verwenden könnte, dann bräuchte man sowas ja überhaupt nicht.

    Wie gesagt, das ist nur ein virtueller ElKo, das Programm.

    Echt? Mit einem ElKo und sonst nix kann man Hochpass, Tiefpass, Peak, Notch, Shelving und EQ (aka. "Bandpass") Filter machen? Das muss aber ein cooler Elko sein.

    BTW kleiner Tip: Mit einem Kondensator alleine (Elko oder nicht) kannst du überhaupt keinen Filter machen. Dazu brauchst du noch mindestens ein weiteres Bauteil wie z.B. einen Widerstand oder eine Spule. Siehe RC Glied bzw. LC Glied.



  • @hustbaer Also mit einem ElKo alleine nicht, ich habe noch einen Lautspreher dazu genommen.
    Und mit einem ElKo geht Tiefpass und Hochpass. Mit beidem wahrscheinlich Bandpass.
    Bei diesem einen Pythonprogramm auf halber Höhe ist kein Q zu finden.



  • @NoobTracker sagte in Digitaler Tiefpassfilter:

    Bei diesem einen Pythonprogramm auf halber Höhe ist kein Q zu finden.

    OK, nochmal langsam.
    Mach https://arachnoid.com/BiQuadDesigner/index.html auf
    Quasi ganz oben ist ein Bereich der mit "The Program" beschriftet ist. Da kannst du einstellen welchen Filter-Typ du haben willst, die Eckfrequenz und den Q Wert. Dieses Ding gibt dir dann 5 Koeffizienten aus: a1, a2, b0, b1 und b2.

    Was diese Koeffizienten sind/sollen findest du auch auf der Seite (weiter unten) beschrieben, bzw. in dem von mir bereits verlinkten Wikipedia-Artikel.

    Ändere den Q Wert und guck zu wie sich die Koeffizienten ändern. D.h. der Q Wert geht in die Koeffizienten ein.

    Der Graph in diesem Bereich zeigt dir dabei an welche Frequenzen wie stark verstärkt bzw. abgeschwächt werden. Wenn du Q > 1 einstellst wirst du sehen dass es im Bereich der Eckfrequenz zu einer Verstärkung kommt - die von dir gewünschte Resonanz.

    Die Python Programme vergiss, die sind uninteressant. Die beschreiben bloss wie man ein einfaches RC Glied simuliert. Als "Einleitung" sozusagen.

    Weiter unten findest du dann aber die Funktion mit der du den vom "The Program" berechneten Filter umsetzen kannst:

    public double filter(double x) {
        y = b0 * x + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2;
        x2 = x1;
        x1 = x;
        y2 = y1;
        y1 = y;
        return (y);
    }
    

    x1, x2, y, y1, y2 sind hier Member-Variablen die den inneren Zustand des Filters speichern. Wenn du das ganze in C implementierst und nur einen Filter hast nimmst du einfach globale oder statische Variablen. Ansonsten nen struct wo du die reinpackst. Wie auch immer. Die Werte müssen auf jeden Fall zwischen den Aufrufen der Filterfunktion erhalten bleiben. (OK, y genaugenommen nicht, keine Ahnung wieso das in dem Beispiel ne Member-Variable ist.)

    Und a1, a2, b0, b1, b2 sind die Koeffizienten in die bei der Berechnung vorher der Q Wert eingeflossen ist.



  • @NoobTracker sagte in Digitaler Tiefpassfilter:

    @hustbaer Also mit einem ElKo alleine nicht, ich habe noch einen Lautspreher dazu genommen.

    Siehste.

    Und mit einem ElKo geht Tiefpass und Hochpass.

    Jain. Du kannst mit einem Kondensator + Lautsprecher einen Hochpass machen.

    Aber ein Tiefpass wird da nicht draus - nicht mit einem idealen Kondensator und einer idealen Signalquelle. Für einen Tiefpass brauchst du den Kondensator + (Innenwiderstand der Signalquelle / Innenwiderstand des Kondensators). Weil R und C beim RC Glied immer in Serie sein müssen. Und diese Variante ist auch übelst böse. Du belastest damit die Signalquelle extrem, und der Kondensator wird auch hübsch heiss werden. Und du willst nicht dass dir ein (Elektrolyt-)Kondensator um die ohren fliegt. Such mal auf YouTube nach exploding electrolytic capacitor oder so.



  • @NoobTracker sagte in Digitaler Tiefpassfilter:

    wellenformwert = berechneWellenform
    filterhüllkurve = berechneFilterhüllkurve
    filtergeschwindigkeit = (((wellenformwert - gefilterterWert) * filterhüllkurve) + filtergeschwindigkeit) / (filterhüllkurve + 1)
    gefilterterWert += filtergeschwindigkeit / resonanzwert

    Hehe, ich bin vielleicht lustig: Wenn ich abends einschlafen will, dann muss ich über Programme nachdenken. Und da kommen meine ganzen Lösungen für Probleme her. Gefördert wird dieses abendliche Nachdenken durch einen vor wenigen Tagen veröffentlichten, verzweifelten Forenpost. Tja, dieses Programm scheint die Resonanz mit dem Cutoffwert zu vertauschen. Klar, dass das dann nicht wird, wie's soll.

    wellenformwert = berechneWellenform
    filterhüllkurve = berechneFilterhüllkurve
    filtergeschwindigkeit = ((wellenformwert - gefilterterWert) + (filtergeschwindigkeit * resonanzwert)) / (resonanzwert + 1)
    gefilterterWert += filtergeschwindigkeit / filterhüllkurve 
    

    So dürfte das Programm eher sein. Wenn man die Resonanz völlig weglässt (also auf 0 setzt), dann hat man nur den typischen ElKo. Das heißt, es entsteht keine Geschwindigkeit, weil die Geschwindigkeit direkt auf den Abstand gesetzt wird. Wenn dann die Wellenform "geglättet" werden soll, dann fügt man einfach nur einen Teil des Abstands hinzu. Ich muss das mal gleich ausprobieren, dürfte aber stimmen.



  • Das scheint geholfen zu haben. Ein paar kleine Modifikationen und es läuft.



  • Prima, eines der wenigen Male, bei denen wenige Modifikationen auch bei wenigen Modifikationen bleiben: Es klappt. Hier das cpp-Programm, bin gerade zu faul, um es in Pseudocode zu übertragen.

    
        uint16_t cutoffPos = (NoobTracker.oscs[i].dcf.pos >> 24);
    #define cIntense 0x80
        NoobTracker.oscs[i].osc1.targetValue = NoobTracker.getWfVal(NoobTracker.oscs[i].osc1.pos >> 16, NoobTracker.oscs[i].osc1.waveform);
        NoobTracker.oscs[i].osc2.targetValue = NoobTracker.getWfVal(NoobTracker.oscs[i].osc2.pos >> 16, NoobTracker.oscs[i].osc2.waveform);
    #define reso     0x1000
        
        NoobTracker.oscs[i].osc1.cutoffSpeed = (((NoobTracker.oscs[i].osc1.targetValue - NoobTracker.oscs[i].osc1.cutoffValue) * cutoffPos) + (NoobTracker.oscs[i].osc1.cutoffSpeed * reso)) / (cutoffPos + reso);
        NoobTracker.oscs[i].osc2.cutoffSpeed = (((NoobTracker.oscs[i].osc2.targetValue - NoobTracker.oscs[i].osc2.cutoffValue) * cutoffPos) + (NoobTracker.oscs[i].osc2.cutoffSpeed * reso)) / (cutoffPos + reso);
        
        NoobTracker.oscs[i].osc1.cutoffValue += (NoobTracker.oscs[i].osc1.cutoffSpeed / 0xFF) * cutoffPos;
        NoobTracker.oscs[i].osc2.cutoffValue += (NoobTracker.oscs[i].osc2.cutoffSpeed / 0xFF) * cutoffPos;
    


  • Dieses Programm kann mit der richtigen Resonanz Sägezahn in Sinus verwandeln.



  • @NoobTracker Würde mich sehr wundern wenn es das kann. Das Ergebnis sieht vermutlich etwas aus wie eine Sinusschwingung, aber es sind vermutlich noch gut Oberwellen dabei. Bloss halt so schwach dass man sie nicht sieht wenn man sich bloss die Kurve ansieht.



  • @hustbaer Möglich, aber der DAC hat nur 8 bit, das geht also unter.


Log in to reply