Ist es gültig, die Amplitude (und vermutlich die FFT-Qualität) durch einfaches Skalieren der Daten zu erhöhen?


10

Ich benutze eine Version von "KISS FFT" von Mark Borgerding. Es akzeptiert ein Array von 16-Bit-Festkomma-Eingabewerten und erzeugt ein 32-Bit-Float-Ergebnisarray.

Ich habe festgestellt, dass bei niedrigen Eingangsamplituden viele der Float-Ergebniswerte Null sind. Wenn ich jedoch die Eingänge einfach skaliere (z. B. um den Faktor 16), sind weniger Ausgangswerte Null und daher scheint der Ausgang zu enthalten Mehr Details. (Nicht, dass es für meine Zwecke wichtig ist, aber aus Gründen der Konsistenz dividiere ich dann die resultierenden Float-Werte durch denselben Skalierungsfaktor.)

Wie auch immer, dies scheint zu funktionieren, um ein Ergebnis zu erzielen, wenn ich zuvor nur einen Puffer mit praktisch allen Nullen erhalten hätte, aber ich frage mich, ob es einen Grund gibt, warum dies möglicherweise kein gültiger Ansatz ist.

(Beachten Sie, dass dieser Ansatz bedeutet, dass die Daten viel "gröber" / granularer sind, und insbesondere das normalerweise vorhandene geringe Rauschen ist nicht vorhanden. Ich frage mich fast, ob es sinnvoll wäre, zu injizieren etwas leises Rauschen, um die Nullwerte im Eingang zu ersetzen.)


"Ich frage mich fast, ob es sinnvoll wäre, ein leises Rauschen einzufügen, um die Nullwerte im Eingang zu ersetzen." = en.wikipedia.org/wiki/Dither
Endolith

Antworten:


7

Dies kann ein gültiger Ansatz sein. Sie beobachten ein sehr praktisches Problem, das häufig bei der Verwendung von Festkomma-Arithmetik (dh Ganzzahl-Arithmetik) auftritt (obwohl dies auch im Gleitkomma auftreten kann). Wenn das numerische Format, das Sie zum Ausführen von Berechnungen verwenden, nicht genau genug ist, um den gesamten Wertebereich auszudrücken, der sich aus Ihren Berechnungen ergeben kann, ist eine Form der Rundung erforderlich (z. B. Abschneiden, Runden auf die nächste usw.) auf). Dies wird häufig als additiver Quantisierungsfehler zu Ihrem Signal modelliert .

Bei einigen Kombinationen von Algorithmus und Rundungsschema ist es jedoch möglich, bei einer sehr geringen Größe des Eingangssignals das zu erhalten, was Sie beobachtet haben: eine große Anzahl von Null-Ausgängen. Grundsätzlich werden die Zwischenergebnisse irgendwo in der Abfolge der Operationen klein genug, um den Schwellenwert, der zum Quantisieren auf ein Niveau ungleich Null erforderlich ist, nicht zu überschreiten. Der Wert wird dann auf Null gerundet, was sich häufig vorwärts zum Ausgang ausbreiten kann. Das Ergebnis ist, wie Sie bemerkt haben, ein Algorithmus, der viele Ausgangsnullen erzeugt.

Können Sie dies umgehen, indem Sie die Daten vergrößern? Manchmal (es gibt nur sehr wenige Techniken, die ständig funktionieren!). Wenn Ihr Eingangssignal in seiner Größe auf einen Wert unter dem Skalenendwert des numerischen Formats begrenzt ist (16-Bit-Ganzzahlen mit Vorzeichen reichen von -32768 bis +32767), können Sie das Eingangssignal skalieren, um den verfügbaren Bereich besser zu nutzen es. Dies kann dazu beitragen, die Auswirkungen eines Rundungsfehlers abzuschwächen, da die Größe eines Rundungsfehlers im Vergleich zum interessierenden Signal kleiner wird. In dem Fall, in dem alle Ihre Ausgaben intern im Algorithmus auf Nullen gerundet werden, kann dies hilfreich sein.

Wann kann dich eine solche Technik verletzen? Abhängig von der Struktur der Berechnungen des Algorithmus können Sie durch Skalieren des Eingangssignals numerischen Überläufen ausgesetzt werden. Wenn das Signal Hintergrundrauschen oder Interferenzen enthält, deren Größe größer ist als der Rundungsfehler des Algorithmus, wird die Qualität dessen, was Sie am Ausgang erhalten, normalerweise durch die Umgebung begrenzt, nicht durch Fehler, die bei der Berechnung auftreten.


Ich verwende eine dynamische Technik zur Skalierung, die ziemlich gut zu funktionieren scheint. Und wie es das Glück wollte, werden extreme Transienten sowieso als Rauschen behandelt und abgeschnitten, sodass gelegentliches Abschneiden kein Problem darstellen sollte. Denken Sie, dass es gültig ist, die Ausgabe durch Teilen durch den Skalierungsfaktor der Eingabe zu "entkalken"?
Daniel R Hicks

1

Der einfachste und narrensicherste Weg, damit umzugehen, besteht darin, die Daten VOR der FFT in Gleitkomma umzuwandeln und eine Gleitkomma-FFT zu verwenden. Der einzige Nachteil dieses Ansatzes wäre, dass Sie möglicherweise mehr Prozessor und Speicher verbrauchen. Da Ihre Ausgabe ohnehin Gleitkomma ist, gibt es wahrscheinlich kaum einen praktischen Unterschied.


Mir wurde dieses Projekt mit dem bereits vorhandenen aktuellen FFT-Algorithmus übergeben, und ich bin an dieser Stelle nicht bereit, mich damit zu beschäftigen. Und das alles läuft auf einem Telefon in Echtzeit, sodass die Leistung definitiv ein Problem darstellt.
Daniel R Hicks

Verstanden. Wissen Sie, ob die interne FFT fest oder Gleitkomma ist? Wenn es behoben ist, müssen Sie sich um Clipping, Überlauf und Unterlauf sorgen
Hilmar

Die Dokumentation und der Kommentar sind in ihrer Abwesenheit außergewöhnlich, aber ich sehe viele Ints im Code und nur wenige Floats und Doubles. Es scheint das grobe # ifdef-Framework für den Wechsel von 16-Bit zu 32-Bit oder Float zu enthalten, aber das Framework ist anscheinend schon lange deaktiviert.
Daniel R Hicks

Ein iPhone (ARM + NEON-CPU) kann eine Float-FFT schneller (über das Accelerate-Framework)
ausführen
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.