Forum: Digitale Signalverarbeitung / DSP / Machine Learning Knacken trotz FIR Filter


von Karsten A. (crazyplaya)


Lesenswert?

Hallo an alle,

ich habe einen VOIP Client entwickelt und tu mich gerade schwer mit der 
Implentierung der Sprache.
Ich zeichne die Sprache via Microphone auf und zwar unter DirectSound.

Dann gebe ich die ungefilterten Rohdaten an einen FIR Filter
1
    short* pTmpBuffer = (short*)pBuffer; //pBuffer = unbehandelte Rohdaten
2
    short* pTmpBuffer2 = new short[160];
3
    for(int i = 0; i < (size - m_nCoeffSize); i++)
4
    {
5
        pTmpBuffer[i] = 0;
6
        for(int y = 0; y < m_nCoeffSize; y++)
7
        {
8
            pTmpBuffer[i] += (pBuffer[y + i] * fCoeffs[y]);
9
        }
10
    }

Danach sample ich das ganze runter von 16kHz auf 8kHz indem ich jeden 
2ten Sample einfach wegwerfe.
1
pTmpBuffer2[0] = 0;
2
    int x = 0;
3
    for(int i = 0; i < size; i++)
4
    {
5
        
6
        if((i+1)%2 == 0)
7
        {
8
            pTmpBuffer2[x] = pTmpBuffer[i];
9
            x++;
10
        }
11
    }

Und encodiere das ganze dann noch mal ins uLaw Format
Am anderen Ende bekomme ich dann die Sprache leicht verzerrt mit einem 
störendem Knacken im Hintergrund.

Ich weiß gerade gar nicht mehr weiter. Kann mir evtl jemand helfen?

Die Filterkoeffizienten hole ich mir über dieses Programm
http://www.winfilter.20m.com

Gruß

Karsten

von Unit* (Gast)


Lesenswert?

Welche Bandbreite hat das Signal, das in den Kompressor reingeht?

von Karsten A. (crazyplaya)


Lesenswert?

16kHZ mit 16bit

von Unit* (Gast)


Lesenswert?

Nicht mal das analoge Signal wird gefiltert?
Das Antialiasing-Filter fehlt.

von Anton2 (Gast)


Lesenswert?

... und das Weglassen jedes zweiten Bits ist auch nicht das WAHRE!

Du produzierst so unnötiges Rauschen - Knacken sollte es aber nicht. 
(???)

von Karsten A. (crazyplaya)


Lesenswert?

Ich behandle direkt die Rohdaten nach dem sie über den ADC der 
Soundkarte abgetastet wurden. Also ganz normal PCM.
Was brauch ich für einen Antialiasing Filter?.

Ich muss dazu sagen ich bin absoluter Beginner auf dem Gebiet und froh, 
dass ich den FIR Filter verstanden habe.

@Anton2:
Wie kann man denn besser runtersamplen?

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Das ist im Prinzip schon richtig. Erst mit Tiefpassfilter auf < 4 kHz 
begrenzen, dann jedes zweite Sample wegwerfen. Das Knacken kommt 
wahrscheinlich durch falsches Bufferhandling zustande (wie das bei 
DirectSound funktioniert weiß ich leider nicht), die "Verzerrungen" 
könnten Aliasing durch unzureichende Filterung sein.

Hat DirectSound keine Funktion zum Downsampling auf 8 kHz?

von Karsten A. (crazyplaya)


Lesenswert?

Ich hab leider nichts dazu finden können ob es unter DirectSound eine 
Funktion zum runtersamplen gibt. In der SDK Dokumentation hab ich nichts 
gefunden und unter google ebensowenig.

Als Buffer hab ich einen Ringbuffer. Es wird immer eine Nachricht 
geschickt, wenn genügend Daten im Buffer vorhanden sind die bearbeitet 
werden können. Dann kann man mit den Signalen arbeiten.

Was heißt denn unzureichenden Filterung? Ich filtere derzewit mit 31 
Koeffizienten.

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Ist der Eingangsbuffer gross genug dass er nicht ueberlaueft? Ist der 
Ausgangsbuffer gross genug dass er nicht leer laeuft? Fuellst du den 
Ausgangsbuffer am Anfang und nach einem Leerlaufen immer komplett voll? 
Ich bin sicher dass DirectSound Programmbeispiele bereitstellt die 
solche Fehlerquellen ausschliessen.

Wie hast du den Filter designt (Grenzfrequenz)? Du musst ueber 4 kHz 
eine moeglichst gute Daempfung haben (ich sag mal >30 dB als 
Hausnummer). Winfilter ist uebrigens etwas mit Vorsicht zu geniessen, 
verwende besser Scilab oder Octave (oder, falls vorhanden, MATLAB mit 
fdatool).

von Roland B. (rolandb)


Lesenswert?

Müssen die Abtastwerte sich nicht überlappen? Sprich im Ringpuffer liegt 
ein Wert (der letzte vom vorherigen)? Oder mehr sogar?
Wenn das Stoss an Stoss liegt, dann kann es doch zum knacken kommen?

mfg

von Roland B. (rolandb)


Angehängte Dateien:

Lesenswert?

Roland Bumm wrote:
> Müssen die Abtastwerte sich nicht überlappen? Sprich im Ringpuffer liegt
> ein Wert (der letzte vom vorherigen)? Oder mehr sogar?
> Wenn das Stoss an Stoss liegt, dann kann es doch zum knacken kommen?
>
> mfg

Argh Sorry. Die Ausgangswerte müssen sich überlappen:

If the support of the impulse response, h(n), has length M
and the support of the k-th segment, xk(n), has length L,
then the discrete linear convolution of h and xk has support of length 
L+M-1

For example if  L = 125 and M = 26 then the support of the individual 
discrete linear convolutions each have length

N = L + K - 1
    = 125 + 26 - 1
    = 150

The first 25 elements of the k-th DLC overlap the last 25 elements of 
the previous DLC.

von Karsten A. (crazyplaya)


Lesenswert?

@Andreas:
Wie errechne ich denn welche Werte ich für die Dämpfung benötige?

Warum ist der Winfilter mit Vorsicht zu genießen?

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Der FIR-Filter muss am Anfang eines neuen Blocks auf die letzte Werte 
des alten Blocks zurueckgreifen. Am einfachsten geht das, indem die 
Filterfunktion einen eigenen Buffer fuer die letzten L-1 Samples 
bereithaelt, so dass sie nur mit einem Sample als Argument aufgerufen 
wird und ein Sample zurueckgibt.

Suche mal nach "Winfilter" im Forum. Alternativen fuer Filterdesign habe 
ich oben genannt, gibt aber natuerlich noch mehr.

von Karsten A. (crazyplaya)


Lesenswert?

Wieviele der letzten Werte des alten Blocks sind denn sinnvoll?

Also z.B. habe ich einen Buffer von 320Byte der gefiltert wird.
Kann ich hier berechnen wieviele genommen werden sollen???

von Karsten A. (crazyplaya)


Lesenswert?

Ich schnall es gerade einfach nicht.
Hat irgendwer mal ein Beispiel für mich wie ich meinen Code(s.o.) 
anpassen könnte???

Pseudocode reicht ja schon nur nicht zu mathematisch bitte:D:D

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

> Wieviele der letzten Werte des alten Blocks sind denn sinnvoll?

So viele wie der FIR-Filter braucht (Anzahl der Koeffizienten).

Beispielcode:
http://www.mikrocontroller.net/wikifiles/1/1e/FirAlgs.c

von Karsten A. (crazyplaya)


Lesenswert?

Andreas Schwarz wrote:

> So viele wie der FIR-Filter braucht (Anzahl der Koeffizienten).

Das hatte ich mir schon fast gedacht, dass es die Anzahl er 
Koeffizienten sein muss. Aber sicher ist sicher:D Danke.
Was ich noch nicht so ganz klar verstanden habe, aus deiner Erklärung

> so dass sie nur mit einem Sample als Argument aufgerufen
> wird und ein Sample zurueckgibt

sprich ich arbeite nur mit einem Wert und rechne darauf die letzten 5 
Werte aus meinem Buffer?

Also
pTmpBuffer[0] = Sample[2] //bspw.
y += pTmpBuffer[0]*Coeffs[0];
pTmpBuffer[1] = y //pTmpBuffer wird immer der zuletzt berechnete Wert an
                  //erste Stelle gesetzt

Was mache ich während ich noch die ersten 5 Buffer bearbeite und somit 
vorher zwischen 0 und 4 Werte habe, womit rechne ich das auf?

von Karsten A. (crazyplaya)


Lesenswert?

Jetzt habe ich es mit dem Algorithmus des fir_basics aus deinem Beispiel 
ausprobiert. Die Sprache ist zwar besser aber es ist immer noch ein 
Knistern beim Sprechen und der Sound selbst ist noch ein wenig verzerrt.
1
for(int i = 0; i < size; i++)
2
{
3
     m_pAliasBuffer[0] = pBuffer[i];
4
     /* calc FIR */
5
     accum = 0;
6
     for (ii = 0; ii < m_nCoeffSize; ii++) 
7
     {
8
         accum += fCoeffs[ii] * m_pAliasBuffer[ii];
9
     }
10
     /* shift delay line */
11
     for (ii = m_nCoeffSize - 2; ii >= 0; ii--) 
12
     {
13
         m_pAliasBuffer[ii + 1] = m_pAliasBuffer[ii];
14
     }
15
     pTmpBuffer[i] = accum;
16
}

Ich bin echt langsam überfragt

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

OK, ich sehe gerade dass du mit Integern rechnest. Wenn du das machst, 
dann musst du fuer den Akkumulator eine groessere Wortbreite (z.B. long) 
verwenden und nach dem Aufaddieren einen Rechtsshift durchfuehren, 
entsprechend der Skalierung deiner Filterkoeffizienten. Bessere 
Alternative: lass dir die Koeffizienten in Floating Point ausgeben und 
rechne in Floating Point, dann must du dir darum keine Gedanken machen.

von Karsten A. (crazyplaya)


Lesenswert?

Oh sorry hätte ich vllt. mal anmerken können, die Koeffizienten sind in 
double
1
double fCoeffs[5] = { 
2
        -0.00112053738724361000,
3
        0.00112128133087145220,
4
        0.99999851211274415000,
5
        0.00112128133087145220,
6
        -0.00112053738724361000
7
    };
und accum ist ebenfalls vom Typ double

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

pBuffer ist der Eingang, pTmpBuffer der Ausgang (gib denen doch mal 
sinnvolle Namen)? Dann sollte das eigentlich funktionieren. Probier es 
am besten erst mal ohne DirectSound, Netzwerkuebertragung usw. aus, 
einfach von Buffer zu Buffer, und schau ob das funktioniert.

von Karsten A. (crazyplaya)


Lesenswert?

Ja pBuffer ist der Eingang und pTmpBuffer Ausgang.
Sorry für meine schlechte Namensgebung;)
Wie meinst du das genau von Buffer zu Buffer?
DirectSound liefert mir ja den Buffer oder soll ich den Filter einfach 
mal mit ner normalen WaveDatei, welche ich einlese austesten?

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Genau.

von Karsten A. (crazyplaya)


Lesenswert?

Ah ok, danke.
Sorry für die dummen Fragen aber das Thema macht mich gerade ein wenig 
gar:D

von Karsten A. (crazyplaya)


Lesenswert?

So habe jetzt noch mal ein paar unterschiedliche Koeffizienten 
ausprobiert.
Jetzt ist das Knacken fast weg.
Allerdings hört sich die Sprache noch sehr mechanisch an. Aber sie ist 
mittlerweile sehr deutlich zu verstehen.

Was kann man da noch machen?

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Ein wav-Beispiel posten.

von Karsten A. (crazyplaya)


Lesenswert?

Dann muss ich erst mal ne Methode schreiben die mir ein Wave File 
ausspuckt.

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Ja. Oder zumindest die Rohdaten, in wav umwandeln kannst du sie mit 
Audacity o.ae.

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.