Auch (hochtrabend) Spectrumanalyzer, Spektrumanalysator, audio frequency analyzer genannt.
Es geht um eine logarithmisch nach Frequenzen aufgeteilte, in logarithmischen Amplitudenschritten aufgeteilte Aussteuerungsanzeige. Für eine LED-Matrix in der Größe 8×8 (mono) oder zwei derartige Matrizen (stereo). Mit Mikrocontroller, der das Tonsignal am Analogeingang zur Digitalisierung angeboten bekommt. Hier: ATmega32U4 oder ATmega328 auf Arduino Leonardo oder Arduino Uno.
Sollte ja bereits irgendjemand open-source gelöst haben, sieht aber nach einiger Recherche 2018 nicht so aus.
Bei dem gewünschten logarithmischen Umfang sowie dem Einsatz als Konsumgut, nicht als Messmittel, erscheint der Einsatz einer Fouriertransformation (FFT) als Overkill. Auch ist es erlaubt, das Tonsignal stückweise zu verarbeiten und so „blinde Stellen“ zuzulassen. Als Abtastrate kommt etwa 16 MHz / 64 / 13 = 19,23 kSa/s infrage.
Alle anderen Frequenzen sind entsprechende Teilfrequenzen. Das Suchintervall liegt bei 1/75 Hz = 13 ms. Der RAM-Berarf sind 256 Samples; der Algorithmus kann aber auch „strömend“ in Echtzeit (= ohne RAM-Puffer) arbeiten; dann werden nur 24 Akkumulatoren für die Real-, Imaginär- und Betragssummen benötigt. Begnügt man sich mit lückenhafter Audio-Erfassung, darf die Rechenzeit länger ausfallen. (Lückenhaft ist die Abtastung ohnehin wegen der fälligen cos²-Fensterung.) Auch kann man dann abwechselnd zwischen linkem und rechtem Kanal umschalten.
Spalte | Frequenz in Hz | Abtastwerte pro Intervall | Intervalle | alternativ? | Frequenz in Hz | Abtastwerte pro Intervall | Intervalle |
---|---|---|---|---|---|---|---|
0 | 75 | 256 | 1 | 0 | 50 | 768 | 2 |
1 | 150 | 128 | 2 | 1 | 100 | 384 | 4 |
2 | 300 | 64 | 4 | 2 | 200 | 192 | 8 |
3 | 601 | 32 | 8 | 3 | 401 | 96 | 16 |
4 | 1202 | 16 | 16 | 4 | 801 | 48 | 32 |
5 | 2404 | 8 | 32 | 5 | 1603 | 24 | 64 |
6 | 4808 | 4 | 64 | 6 | 3205 | 12 | 128 |
7 | 9615 | 2 | 128 | 7 | 6410 | 6 | 256 |
8 | 12821 | 3 | 512 | ||||
Abtastrate | 19231 | 38461 | |||||
Samples | 256 (0x100) | 1536 (0x600) | |||||
Zeit | ≈13 ms | ≈40 ms |
Das Signal wird in jedem Intervall cos²-gefenstert (Hann-Fenster)
und mit einer Kosinusfunktion (= Realteil) bzw. Sinusfunktion (= Imaginärteil) multipliziert.
Deren Summen werden zu einem Betrag umgewandelt.
Nicht aufwändig nach Pythagoras, sondern vereinfacht
ohne Wurzelziehen.
Diese Summe wird für jedes Intervall ermittelt und akkumuliert.
Das (stets vorzeichenlose) Ergebnis wird logarithmiert
(nach Tabelle oder switch
-Anweissung) und zur Anzeige gebracht.
Fertig.
Die entsprechend größere Frequenzfensterbreite für die höheren Frequenzen ergibt sich durch die kleiner werdenden Intervalle. Insgesamt handelt es sich um eine abgewandelte DFT, nicht um eine FFT. Bei der Alternative mit um 3/2 größerer Intervalllänge verringert die Fensterbreite entsprechend für weniger Überlappung.
Da Geschwindigkeit eine wesentliche Rolle spielt,
erscheint es sinnvoll, sowohl die Abtastwerte als auch die Werte aus der Sinustabelle
als vorzeichenbehaftete 8-Bit-Werte
(int8_t
oder signed char
) zu führen,
da so der 2 Takte schnelle muls
-Befehl zum Einsatz kommen kann.
Gleichspannungen eliminieren sich automatisch.
Im Einsatzfall eine Anzeige mit 64 Stück WS2812, mäanderförmig angeordnet.
Das Audiosignal kommt an die Arduino-Anschlüsse A0 und A1, mit Widerständen auf halbe Referenzspannung gelegt. Da die Referenzspannung bei den Arduinos dummerweise nicht herausgeführt ist, müssen die Widerstände ungleichmäßig sein. Etwa 10 kΩ nach Masse und 82 kΩ nach 5 V für 0,55 V Gleichspannung. Das Audiosignal wird über einen Kondensator zugeführt. Die maximale Eingangsspannung ist so auf 1,1 V USS = 0,4 Veff (ATmega328) festgelegt. Will man beim ATmega32U4 die interne Referenspannungsquelle benutzen und nicht von außen 1,1 V anlegen, so sind hier die Werte 2,56 USS = 0,9 Veff erlaubt, was beim Betrieb an typischen Line-Signalen einem Empfindlichkeitsverlust gleichkommt. (Leider ist mir dazu keine ordentliche Spannungsangabe bekannt.)
Für die Widerstände kommen 10 kΩ oder (etwas) mehr infrage. Für die Koppelkondensatoren genügen XC = 1/2π·75Hz·C < 10 kΩ; C > 1/2π·75Hz·10kΩ = 220 nF. Typischwerweise nimmt man dafür Elkos mit 0,47..10 µF, Pluspol zum Spannungsteiler und Mikrocontroller.
Todo. So etwas löst man nicht in einer ISR, sondern in der Hauptschleife. Eine ISR würde zu viel Zeit mit Push und Pop verschwenden. Auch wenn man's in Assembler programmiert.