DSP FIR Filter mit Downsampling entwickeln



  • Hi an alle,

    weiß nicht in welches Forum dieses Thema besser gepasst hätte. Darum hab ich mich für C++ allgemein entschieden.

    Ich bräuchte einen FIR Filter welcher auch gleichzeitig die Abtastrate reduziert. Bspw. von 16kHz auf 8kHz.

    Die Quellen die ich dazu gefunden habe, ich weiß es gibt einige, sind mir zu mathematisch. Ich kapiere irgendwie noch nicht so ganz wie ich das ganz in C++ implementiere.

    Könnte mir vllt. jemand Schritt für Schritt erklären wie man an so eine FIR Filter rangeht? Also für den normalsterblichen Anwendungsentwickler ohne Mathe Diplom .

    Ich weiß ich muss dem Filter Parameter übergeben.
    Da wäre meine erste Frage, was für Parameter müssen dass sein?
    Dann muss ich die Koeefizienten berechnen aber wie?
    Und wie reduziere ich dann noch die Abtastrate ohne zuviel Störungen mit reinzubringen?

    Mit freundlichem Gruß

    Karsten





  • Danke den hab ich auch bereits gefunden.

    Allerdings macht der ja keine Reduktion der Abtastrate.

    Und wie komm ich an die Filterkoeefizienten ran.



  • Was soll das Filter erreichen? Warum überhaupt ein FIR-Filter? Wie sollen wir konkrete Antworten geben wenn du keine konkreten Fragen stellst?



  • Ok da hast du schon irgendwo recht.
    Also das Ziel ist es aufgezeichnete Sprache via RTP Protokoll zu versenden.

    Also Live Sampling.
    Ich capture Sprache mit DirectSound. Und alle 20ms wird eine Event abgerufen, der den aufgezeichneten Sample von 16 auf 8kHz runtersamplet und dann in das uLaw Format konvertiert.

    Momentan mache ich das runtersamplen folgendermaßen.

    int filter_state = 0:
    /* input_buf can be equal to output_buf */
    void downsample(const short *input_buf, short *output_buf, int output_count ) 
    {
        int input_idx, input_end, output_idx, output_sam;
        input_idx = output_idx = 0;
        input_end = output_count * 2;
        while( input_idx < input_end ) 
        {
            filter_state = ( filter_state + input_buf[ input_idx ] ) >> 1;
            output_buf[ output_idx ] = filter_state;
            filter_state = ( filter_state + input_buf[ input_idx + 1 ] ) >> 1;
            input_idx += 2;
            output_idx += 1;
        }
    }
    

    Die übertragende Sprache ist aber noch ziemlich verzerrt und es existieren Knackgeräusche im Hintergrund.

    Der FIR Filter soll nun das ganze entzerren und die Knackgeräusche entfernen und gleichzeitig das ganze auf 8kHz reduzieren.
    Und genau da liegt mein Problem. Wie erzeuge ich einen solchen Filter?



  • Tim schrieb:

    Was soll das Filter erreichen? Warum überhaupt ein FIR-Filter? Wie sollen wir konkrete Antworten geben wenn du keine konkreten Fragen stellst?

    Hat er doch. Er will eine Abtastratenreduktion 2:1.
    Dafür nimmst Du am besten ein FIR-Filter, dass die Bandbreite halbiert, und dann schmeisst Du jedes zweite Sample weg.



  • Tachyon schrieb:

    Dafür nimmst Du am besten ein FIR-Filter, dass die Bandbreite halbiert, und dann schmeisst Du jedes zweite Sample weg.

    oder einfach den mittelwert von 2 benachbarten samples.
    🙂



  • Also ich bin noch gar nicht so richtig drin in dem Thema Filterdesign, daher meine Fragen.

    Mir wurde halt gesagt nimm nen FIR Filter mit ner Faltung.
    Und ab dem Wort Faltung war bei mir Bahnhof. :D.

    Und was auch noch eine meiner Fragen war, was benötige ich alles
    um einen solchen Filter zu designen?
    Welche Werte brauche ich alles dafür?

    @ fricky
    Das hab ich schon getan mit dem Ergebnis dass die ganze Sache sich noch übler anhört



  • Hier die mittelwertsberechung

    const int RATIO = (SAMPLERATE/8000); //Samplerate = 16000
        const int size2 = (nBytesToReduce/RATIO); //bytes to reduce = 320
    
        short* downsampledAudio = pBuffer; //pBuffer = raw Speech Data
        signed long summe = 0;
        for(int i = 0; i < nBytesToReduce; i++)
        {
            summe += pBuffer[i];
            if(((i+1)%RATIO) == 0)
            {
                downsampledAudio[i/RATIO] = summe/RATIO;
                summe = 0;
            }
        }
        return downsampledAudio;
    


  • ~fricky schrieb:

    Tachyon schrieb:

    Dafür nimmst Du am besten ein FIR-Filter, dass die Bandbreite halbiert, und dann schmeisst Du jedes zweite Sample weg.

    oder einfach den mittelwert von 2 benachbarten samples.
    🙂

    Das kannst Du vergessen, wenn Du auch nur einen minimalen Anspruch an die Qualität hast. Dadurch hast Du übelste Artefakte.



  • Wie gesagt, dass hab ich auch schon gemerkt



  • Diskrete Faltung läuft in etwa so ab:

    1. Beginne bei einem Sample n aus dem Signal
    2. Multipliziere Sample beginnend bei n mit jedem Coeff bis zu maximalen Coeff-Länge (C) und addiere die Werte. Beispiel(n1*c1) + (n2*c2)+...+(nC*cC)
    3. Gehe ein Sample im Signal weiter
    4. Wiederhole 1..3


  • Also ist n meine Laufvariable korrekt?
    und c ist dann mein ein Sample aus meinem puffer?



  • Jetzt mal gerade ne kleine Zwischenfrage worüber ich gerade nachdenke.

    Wie bereits gesagt ich habe ein Sample mit der Größe 320byte bei 16kHz also 20ms.
    Wende ich den Filter auf dieses Sample auf jedes einzelene Byte an oder auf den gesamten 20ms - Sample?



  • Tachyon schrieb:

    ~fricky schrieb:

    Tachyon schrieb:

    Dafür nimmst Du am besten ein FIR-Filter, dass die Bandbreite halbiert, und dann schmeisst Du jedes zweite Sample weg.

    oder einfach den mittelwert von 2 benachbarten samples.
    🙂

    Das kannst Du vergessen, wenn Du auch nur einen minimalen Anspruch an die Qualität hast. Dadurch hast Du übelste Artefakte.

    ok, ich hab' mir eine saubere sinuswelle vorgestellt. bei 'nem audiosignal, mit vielen frequenzen drin, kann ich mir schon vorstellen, dass sich das mies anhört. da klingt deine 'jedes_2_te_sample_weglösch'-methode sicher besser.
    🙂



  • CrazyPlaya schrieb:

    Jetzt mal gerade ne kleine Zwischenfrage worüber ich gerade nachdenke.

    Wie bereits gesagt ich habe ein Sample mit der Größe 320byte bei 16kHz also 20ms.
    Wende ich den Filter auf dieses Sample auf jedes einzelene Byte an oder auf den gesamten 20ms - Sample?

    Du musst für jedes Sample, das Du haben willst, filtern.
    Wenn Du z.B. ein Filter mit 16 Koeffizienten hast, dann rechnest Du s1*c1+s2*c2+...+s16*c16 (s sind die Samples, c die Koeffizienten).
    Danach bekommst Du genau ein neues Sample, nämlich die Summe der ganzen Produkte. Dann gehst Du ein Sample weiter und wiederholst das Ganze, also



  • Also mal für ganz dumme wie mich:D

    Ich habe einen 20ms langen Sample

    jetzt benötige ich einen Filter mit 320 Koeffizienten?

    Und dann muss ich alle einzelnen Werte mit allen einzelnen Koeffs Multipliziern und addieren und dieser Wert ergibt dann meinen neuen Sample. Woher weiß ich welchen Wert die einzelnen Koeffs haben müssen?

    Ich sag ja ich tue mich da gerade echt schwer mit.

    Und schmeiß ich vorher jeden 2.ten Sample raus oder nach der Berechnung?



  • Nein, Du benötigst so viele Koeffizienten, dass Du die gewünschte Flankensteilheit für Dein Filter erreichst. Je höher die Ordung des Filters, desto schneller geht dein Filter vom Durchlassband ins Stopband über.
    Noch mal für Deine 320 Werte und ein Filter mit 16 Koeffizienten:
    Du fängest beim ersten Sample an und gehst das bis zum 16. Dann Fängst Du beim zweiten Sample an und gehst bis zum 17. Dann das 3. bis zum 18. usw.
    Die Koeffiziententabelle läuft dabei immer nur von 1..16.

    Und lösch die Tabelle bitte wieder raus.



  • Tachyon schrieb:

    Tim schrieb:

    Was soll das Filter erreichen? Warum überhaupt ein FIR-Filter? Wie sollen wir konkrete Antworten geben wenn du keine konkreten Fragen stellst?

    Hat er doch.

    Hat er nicht. Er schrieb etwas von einem Filter _und_ von der Abtastratenreduktion. Dass gescheite Abtastratenreduktion einen Filter impliziert hat damit nichts zu tun.



  • Ok Tabelle ist wieder gelöscht:D.

    Gut soweit hab ich das jetzt verstanden.
    Sind noch 2 Fragen offen.
    Wie weiß ich welche Werte die Koeffizienten besitzen müssen und
    zum runtersamplen erst jeden 2 Sample rausschmeißen und dann Filtern oder umgekehrt?


Anmelden zum Antworten