2013-03-18 7 views
5

Ich arbeite an einer App für das iPad, und ich möchte das Audio von einem Video analysieren, das ich gerade spiele. Mit der MTAudioProcessingTap läuft das alles gut. Momentan habe ich einen Testcode zum Testen/Messen der Lautstärke des linken und rechten Kanals. Das wird alles ziemlich gut:Tiefpass-Audiofilter, Berechnung von RMS unter iOS

void process(MTAudioProcessingTapRef tap, CMItemCount numberFrames, 
     MTAudioProcessingTapFlags flags, AudioBufferList *bufferListInOut, 
     CMItemCount *numberFramesOut, MTAudioProcessingTapFlags *flagsOut) 
{ 
    OSStatus err = MTAudioProcessingTapGetSourceAudio(tap, numberFrames, bufferListInOut, 
                flagsOut, NULL, numberFramesOut); 

    if (err) 
     NSLog(@"Error from GetSourceAudio: %ld", err); 

    float leftVolume, rightVolume; 

    for (CMItemCount i = 0; i < bufferListInOut->mNumberBuffers; i++) 
    { 
     AudioBuffer *pBuffer = &bufferListInOut->mBuffers[i]; 
     int cSamples = numberFrames * pBuffer->mNumberChannels; 

     float *pData = (float *)pBuffer->mData; 

     float rms = 0.0f; 

     for (int j = 0; j < cSamples; j++) 
     { 
      rms += pData[j] * pData[j]; 

     } 

     if (cSamples > 0) 
     { 
      rms = sqrtf(rms/cSamples); 
     } 

     if (0 == i) 
     { 
      leftVolume = rms; 
     } 

     if (1 == i || (0 == i && 1 == bufferListInOut->mNumberBuffers)) 
     { 
      rightVolume = rms; 
     } 
    } 

    NSLog(@"Left/Right Volume: %f/%f", leftVolume, rightVolume); 
} 

Aber für die Zwecke dieser App, ich will es nur die RMS messen („Intensität“) des Bereichs von 0-80Hz (als Beispiel). Daher brauche ich einen Tiefpassfilter.

Ich google seit langer Zeit, aber mein Problem ist, dass ich keinen klaren Beitrag, Tutorial oder Lösung finden kann, die offensichtlich ist. Fast jedes Problem, das irgendwie wie mein klingt, hat ein zufälliges Stück Code darunter mit beschissenen oder fehlenden Kommentaren, so dass ich nicht herausfinden kann, was all die magischen Zahlen dort tun und was sie bedeuten.

Könnte jemand Schieb mich hier in die richtige Richtung? Beachten Sie, dass in meinem Fall ich do möchte den Code verstehen und nicht nur mit einem funktionierenden Beispiel ablaufen.

Dank

Antwort

16

Wenn Sie nur mit einem Arbeitsbeispiel ablaufen könnten, würden Sie Glück haben. :-)

Signalverarbeitung ist ein komplizierter und tiefer Bereich. Es ist kompliziert, wenn Sie es theoretisch tun, und es ist auch kompliziert, wenn Sie es praktisch machen wollen.

Sie möchten einen Tiefpassfilter haben. Es gibt viele Möglichkeiten mit verschiedenen Vor- und Nachteilen.

Die meisten grundlegenden Konzepte Sie beschäftigen müssen, wenn man verstehen will, was los ist:

Frequenzbereich und Zeitbereich: Frequenzbereich ist, wenn Sie über Frequenzintervalle wie 0..80Hz sprechen für Beispiel. Der Zeitbereich ist die normale Zeit oder beispielsweise die einzelnen Abtastwerte, die Sie in Ihrem Abtastpuffer haben. Der obige Code berechnet den RMS im Zeitbereich.

Grundregel: Frequenzbereich und Zeitbereich sind vollständig äquivalent.

Sie können viele Operationen in beiden Domänen mit demselben Ergebnis ausführen. Sie können immer zwischen Frequenzbereich und Zeitbereich wechseln. Da einige Operationen in einer bestimmten Domäne trivial sind, ist es oft nützlich, zuerst zur gewünschten Domäne zu wechseln, die triviale Operation auszuführen und dann (falls erforderlich) zur ursprünglichen Domäne zurückzukehren.

Die Umschaltung zwischen Frequenz- und Zeitbereich erfolgt mit einer FT (Fourier-Transformation). Programmatisch verwendet man häufig den Spezialfall von Puffern, die eine Zweierpotenzanzahl von Proben enthalten, und den FFT Algorithmus (Fast Fourier Transformation).

Die andere interessante Eigenschaft ist das Faltungstheorem: Die FT übersetzt zwischen Multiplikation von Funktionen in einer Domäne und Faltung von Funktionen auf der anderen Domäne.

Nun, was hat das alles mit Ihrem Tiefpassfilter zu tun?

Ihr vorgeschlagener Tiefpassfilter 0-80 Hz ist eine Rechteckfunktion im Frequenzbereich. Sie möchten das mit Ihrer Eingabe in der Frequenzdomäne multiplizieren. Dies bedeutet, dass alle Frequenzteile unter 80 Hz durchgelassen werden und alle anderen auf Null gesetzt werden.

Jetzt könnten Sie all das in der Frequenzdomäne tun, das wäre einfach, aber aus Effizienzgründen möchten Sie das im Zeitbereich tun, um die Hin- und Her-FFT zu vermeiden. (In Ihrem Fall möchten Sie nur die Energie haben, die Sie auch in der Frequenzdomäne berechnen können, wie Sie es jetzt tun (Quadratsumme).)

Um Ihren Tiefpassfilter im Zeitbereich zu tun Anstelle von FT-Multiply-FT können Sie auch mit FT (Rechteckfunktion) falten. Die FT (Rechteckfunktion) ist das ideale Tiefpassfilter: Die sinc() - Funktion.

sinc(x) := sin(pi*x)/pi*x 

Dieses sinc (x) ist die Impulsantwort der Rechteckfunktion. Diese konkrete Impulsantwort ist unendlich, was unpraktisch ist. Dies würde bedeuten, dass Sie die Faltung Ihrer Eingabe mit einer unendlichen Anzahl von Werten berechnen müssten.

Was Sie wollen, ist ein Filter mit einer endlichen Impulsantwort: FIR. Dies führt zu Fehlern in Ihrem Filter, konkret, dass Sie nicht alle Frequenzen < 80Hz mit dem gleichen Gewicht sehen werden und dass Sie auch einige Frequenzen über 80Hz in Ihrer Energie sehen werden.

Dieser Kompromiss ist unvermeidlich. Wenn Sie den FFT-Ansatz verwenden, bei dem Sie Ihre perfekte Rechteckfunktion ohne Fehler anwenden können, leiden Sie indirekt auch an diesem Fehler, wenn Sie Ihr Eingangssignal vor dem Ausführen der FFT mit einem Fenster versehen. (Windowing bedeutet das Ausschneiden von Teilen (Fenstern) Ihrer Eingabe, um die FFT zu aktivieren.) Dies hat die gleichen negativen Auswirkungen auf Ihre Ausgabe und erfordert die gleichen Kompromisse wie Ihre Filterfunktion und Ihr Ergebnis.

Wahrscheinlich möchten Sie einen FIR-Filter als Tiefpassfilter. Und die seltsamen Zahlen, die Sie im Code von anderen sehen, sind höchstwahrscheinlich die Koeffizienten eines solchen FIR-Filters.

Das Problem ist, dass es keinen "optimalen" Kompromiss gibt, da der Kompromiss sehr davon abhängt, wie Sie "Fehler" im Filter definieren. Einige Leute müssen Frequenzanteile über 82 Hz (in Ihrem Beispiel) auf jeden Fall vermeiden und benötigen daher eine sehr steile Filterkante. Dies verursacht normalerweise große Artefakte nahe der Grenze von 80 Hz, die man dann akzeptieren muss. Anderen Leuten geht es gut mit etwas Energie, die von Frequenzen bis zu 120 Hz kommt und unter 10% über 120 Hz bleibt, um die Artefakte in der Nähe der Grenze von 80 Hz zu reduzieren (ein weicherer Tiefpassfilter).

Das ganze Thema ist hier sehr gut abgedeckt: https://ccrma.stanford.edu/~jos/sasp/FIR_Digital_Filter_Design.html

Oder wenn Sie ganz am Anfang beginnen sollen: https://ccrma.stanford.edu/~jos/sasp/sasp.html

auch einen Blick auf den Wikipedia-Seiten von FIR-Filter und sinc nehmen.

Das obige ist nicht ausreichend, um Ihren eigenen Filter zu entwerfen und zu implementieren, gebe ich zu. Aber es sollte Ihnen genügend Hintergrund und Hinweise geben, um loszulegen.

Und lassen Sie sich nicht durch die manchmal seltsame Mathematik abschrecken.

Idee: Eine Möglichkeit, wie Sie Ihren Filter einsetzen können, ist eine FFT nach dem Anwenden des Filters und des Spektrums. Es wäre sehr schwierig zu sagen, ob der Filter funktioniert, wenn man nur den RMS-Wert betrachtet. Ihr iPad hat mehr als genug Rechenleistung dafür.

(Ich habe gerade gesehen, dass es auch http://dsp.stackexchange.com zur Signalverarbeitung ist.)

+0

Woow! Vielen Dank! Das hilft mir große Zeit! Ich möchte dir meine 'Kopfgeld' 'belohnen', aber es sagte, dass ich das nur in 20 Stunden tun kann, also wirst du sehen, dass du bald kommen wirst ... .. Danke für all die Hilfe, so wie ich es könnte etwas zu schaffen :) –

+0

Beeindruckend, sicherlich eine Antwort wert die Prämie! –

+0

Ich würde dieser Antwort noch 50 hinzufügen, wenn ich könnte, das ist großartig! –