Czy poprawne jest zwiększenie amplitudy (i prawdopodobnie jakości FFT) poprzez proste skalowanie danych?

10

Używam wersji „KISS FFT” Marka Borgerdinga. Akceptuje tablicę 16-bitowych wartości wejściowych o stałym punkcie i tworzy 32-bitową tablicę wyników liczb zmiennoprzecinkowych.

Odkryłem, że jeśli amplitudy wejściowe są niskie, wiele wartości liczb zmiennoprzecinkowych wychodzi na zero, ale jeśli po prostu skaluję dane wejściowe (powiedzmy, współczynnik 16), wówczas mniej wartości wyjściowych wynosi zero, a zatem wydaje się, że dane wyjściowe zawierają więcej szczegółów. (Nie dlatego, że ma to duże znaczenie dla moich celów, ale dla spójności dzielę następnie uzyskane wartości zmiennoprzecinkowe przez ten sam współczynnik skalowania.)

W każdym razie wydaje się, że to działa, jeśli chodzi o uzyskanie wyniku, gdy wcześniej otrzymywałem bufor praktycznie wszystkich zer, ale zastanawiam się, czy istnieje jakiś powód, dla którego może to nie być prawidłowe podejście.

(Należy zauważyć, że takie podejście oznacza, że ​​w danych jest znacznie więcej „zgrubności” / ziarnistości, a w szczególności nie występuje szum niskiego poziomu, który normalnie występowałby. Prawie zastanawiam się, czy rozsądnie byłoby wstrzyknąć trochę hałasu niskiego poziomu, aby zastąpić zerowe wartości na wejściu.)

Daniel R. Hicks
źródło
„Prawie zastanawiam się, czy rozsądnie byłoby wprowadzić trochę szumu niskiego poziomu, aby zastąpić wartości zerowe na wejściu.” = en.wikipedia.org/wiki/Dither
endolith

Odpowiedzi:

7

To może być prawidłowe podejście. Obserwujesz bardzo praktyczny problem, który pojawia się często przy stosowaniu arytmetyki stałoprzecinkowej (tj. Całkowitej) (chociaż może się to zdarzyć również w zmiennoprzecinkowym). Gdy format numeryczny, którego używasz do wykonywania obliczeń, nie ma wystarczającej precyzji, aby wyrazić pełny zakres wartości, które mogą wynikać z twoich obliczeń, wymagana jest jakaś forma zaokrąglania (np. Obcinanie, zaokrąglanie do najbliższego itd.) na). Jest to często modelowane jako addytywny błąd kwantyzacji twojego sygnału.

Jednak w przypadku niektórych kombinacji algorytmu i schematu zaokrąglania, gdy wielkość sygnału wejściowego jest bardzo niska, możliwe jest uzyskanie tego, co zaobserwowałeś: dużej liczby wyjść zerowych. Zasadniczo, gdzieś w sekwencji operacji, wyniki pośrednie stają się wystarczająco małe, aby nie przekroczyć progu wymaganego do kwantyzacji do niezerowego poziomu. Wartość jest następnie zaokrąglana do zera, co często może być propagowane do wyjścia. Wynikiem jest, jak zauważyłeś, algorytm, który generuje wiele zer wyjściowych.

Czy możesz więc obejść ten problem, zwiększając dane? Czasami (jest bardzo mało technik, które działają cały czas!). Jeśli Twój sygnał wejściowy jest ograniczony wielkością do wartości poniżej pełnej skali formatu liczbowego (liczby całkowite ze znakiem 16-bitowym działają w zakresie od -32768 do +32767), możesz skalować sygnał wejściowy w celu pełniejszego wykorzystania zakresu dostępnego dla to. Może to pomóc złagodzić skutki błędu zaokrąglenia, ponieważ wielkość każdego błędu zaokrąglenia staje się mniejsza w porównaniu z sygnałem zainteresowania. Tak więc, w przypadku, gdy wszystkie dane wyjściowe są zaokrąglane wewnętrznie do zer do algorytmu, może to pomóc.

Kiedy taka technika może cię zranić? W zależności od struktury obliczeń algorytmu zwiększenie skali sygnału wejściowego może narazić Cię na przepełnienia numeryczne. Ponadto, jeśli sygnał zawiera szum tła lub interferencję, która jest większa niż błąd zaokrąglenia algorytmu, wówczas jakość tego, co otrzymujesz na wyjściu, będzie zazwyczaj ograniczona przez środowisko, a nie błąd wprowadzany do obliczeń.

Jason R.
źródło
Używam dynamicznej techniki skalowania, która wydaje się działać całkiem dobrze. I, na szczęście, ekstremalne transjenty i tak są traktowane jako szum i obcinane, więc od czasu do czasu przesterowanie nie powinno stanowić problemu. Czy uważasz, że poprawne jest „odkamienianie” wyniku przez podzielenie przez współczynnik skali wejścia?
Daniel R Hicks
1

Najłatwiejszym i najgłupszym sposobem radzenia sobie z tym jest konwersja danych na zmiennoprzecinkowe PRZED FFT i użycie zmiennoprzecinkowego FFT. Jedynym minusem tego podejścia byłoby to, że możesz zużywać więcej procesora i pamięci. Ponieważ twój wynik i tak jest zmiennoprzecinkowy, prawdopodobnie nie ma praktycznej różnicy.

Hilmar
źródło
Otrzymałem ten projekt z już istniejącym algorytmem FFT i nie chcę w tym momencie z niego korzystać. A wszystko to dzieje się na telefonie w czasie rzeczywistym, więc wydajność jest zdecydowanie problemem.
Daniel R Hicks
Zrozumiany. Czy wiesz, czy wewnętrzny FFT jest stały czy zmiennoprzecinkowy? Jeśli zostanie to naprawione, musisz się martwić o wycinanie, przepełnienie i niedopełnienie
Hilmar,
Dokumentacja i komentarz są wyjątkowe pod nieobecność, ale widzę wiele int w kodzie i cenne kilka liczb zmiennoprzecinkowych i podwójnych. Wygląda na to, że zawiera surową platformę #ifdef do przełączania z 16-bitowej na 32-bitową lub zmiennoprzecinkową, ale najwyraźniej została ona długo wyłączona.
Daniel R Hicks
IPhone (ARM + NEON CPU) może wykonać zmiennoprzecinkowe FFT szybciej (za pomocą frameworka Accelerate) niż całkowita liczba FFT w C.
hotpaw2