Forum: Offtopic Kurzer Denkanstoss (Mathe-Nachhilfe) benötigt (FFT)


von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Ich will ein Tool programmieren, was per DMX MovingHeads in Abhängigkeit 
vom aktuellen Umgebungs-Sound steuert - so eine Art moderne Lichtorgel. 
Was ich bereits habe und was funktioniert sind Programm-Fragmente für:

- Soundgrabbing (liefert eine festgelegte Anzahl von Samples in einem 
Array)
- DMX-Ausgabe

Zur Trennung der Spektralanteile (und deren Verteilung auf die 
DMX-Kanäle) möchte ich FFT verwenden, dazu habe ich ein Beispielprogramm 
mit einer entsprechenden Funktion. Leider blicke ich bei deren Nutzung 
nicht ganz durch, zumal der Beispielcode nur mit einer Listenausgabe 
daher kommt.

Als Übergabeparameter bekommt diese Funktion ein Array mit komplexen 
Zahlen, die vorher aus meinem Array mit den Sampling-Daten erzeugt 
werden (z.B. 1024 Werte). Zurück bekomme ich ein gleich großes Array 
voller komplexer Zahlen ... und nun? Wie bekomme ich daraus die 
spektralen Anteile? Ist so verdammt lang her ...
1
  dim N,k as integer //Anzahl der Eingangs-Werte
2
  dim x() as Double //Array für Eingangswerte real 
3
  dim c() as Complex //Array für Eingangswerte komplex
4
  
5
  N=1023
6
  
7
  for k = 0 to N
8
    x.Append sin(k/10) + 0.5 * sin(k/3) 'Erzeugen von Beispiel-Eingangswerten mit zwei Sinus-Funktionen
9
  next
10
  
11
  for k = 0 to N
12
    c.append new Complex(x(k),0) // Complex with real part = x(k) and imaginary part = 0
13
  next
14
  
15
  // Calculate FFT
16
  dim C_() as Complex = fft(c)
17
  
18
  // Extract magnitudes
19
  dim m() as double
20
  
21
  for k = 0 to N
22
    m.Append C_(k).Abs
23
  next
24
  
25
  for k=0 to N //Ausgabe der Ergebnisse in eine Tabelle
26
    list.addrow str(k) //Zeilennummer
27
    list.cell(k,1)=str(sin(k/10) + 0.5 * sin(k/3)) //EIngangswerte
28
    list.cell(k,2)=str(c_(k)) //Resultat komplex
29
    list.cell(k,3)=str(m(k)) //Resultat real
30
  next
 (ist RealBasic/Xojo)

von Joe F. (easylife)


Lesenswert?

Na, steht doch im Code.
"Magnitude" = Amplitude des jeweiligen Frequenzanteils.
Der Imaginärteil beinhaltet die Phasenlage (für deinen Anwendungsfall 
uninteressant).

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Joe F. schrieb:
> Na, steht doch im Code.
> "Magnitude" = Amplitude des jeweiligen Frequenzanteils.
> Der Imaginärteil beinhaltet die Phasenlage (für deinen Anwendungsfall
> uninteressant).

Ja, das habe ich auch schon vermutet.

Finde es nur seltsam, dass es genau so viele Frequenzanteile gibt, wie 
Eingangswerte ... oder ist das dem vereinfachten bzw. digital 
optimierten Algorithmus geschuldet?

von Joe F. (easylife)


Lesenswert?

Frank E. schrieb:
> oder ist das dem vereinfachten bzw. digital
> optimierten Algorithmus geschuldet?

Das ist das Prinzip von FFT.
Wenn du übrigens nur ein paar wenige Frequenzbänder beobachten willst, 
könnte der Goertzel-Algorithmus deutliche Geschwindigkeitsvorteile 
gegenüber einer FFT bringen.

von Georg A. (georga)


Lesenswert?

Frank E. schrieb:
> Finde es nur seltsam, dass es genau so viele Frequenzanteile gibt, wie
> Eingangswerte ... oder ist das dem vereinfachten bzw. digital
> optimierten Algorithmus geschuldet?

Eigentlich gibt es sogar doppelt so viele, das Ergebnis ist ja komplex. 
Liegt aber daran, dass die FFT an sich auch komplexe Eingangsdaten hat, 
die bei der real->complex-FFT aber mit 0 belegt werden.

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Danke für den Hinweis auf Goertzel, habe diesen Code hier gefunden und 
werde mal versuchen, ihn umzusetzen.

https://netwerkt.wordpress.com/2011/08/25/goertzel-filter/

Eine Frage hätte ich noch: An welchem Parameter müsste ich "drehen", um 
die Bandbreite zu beeinflussen? Denn eigentlich will ich ja nicht eine 
ganz konkrete Frequenz, sondern so Bereiche bzw. Bänder?

Hilft es da, mit der Anzahl der Samples zu spielen?

: Bearbeitet durch User
von Joe F. (easylife)


Lesenswert?

Frank E. schrieb:
> Hilft es da, mit der Anzahl der Samples zu spielen?

Genau. Je weniger Samples, desto weniger Bänder und desto breiter die 
Bänder.
Das hat natürlich Grenzen, da man tiefe Frequenzen nur mit genügend 
Samples analysieren kann.
Dem kann man dann aber z.B. mit Downsampling begegnen.

Eine andere Möglichkeit wäre noch BiQuads zu benutzen.
Da kannst du Q recht frei wählen.
Dabei fällt natürlich nicht direkt die Amplitude raus, du müsstest für 
die Bänder eine Spitzenwerterkennung mit drop-down implementieren 
(ähnlich einem Level Meter eines Mischpultes).

: Bearbeitet durch User
von Pandur S. (jetztnicht)


Lesenswert?

>Frank
>Finde es nur seltsam, dass es genau so viele Frequenzanteile gibt, wie
Eingangswerte ... oder ist das dem vereinfachten bzw. digital
optimierten Algorithmus geschuldet?

Es geht sogar noch etwas weiter. Die Fouriertransformation ist 
bidirektional. Zeitraum <-> Frequenzraum, oder auch Ortsraum <-> 
Impulsraum

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.