Spektrum-VU-Anzeige

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.

Funktionsprinzip

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.

Frequenzaufteilung. Jede Frequenzverdopplung entspricht einer Oktave
SpalteFrequenz in HzAbtastwerte pro IntervallIntervallealternativ?Frequenz in HzAbtastwerte pro IntervallIntervalle
0752561 0507682
11501282 11003844
2300644 22001928
3601328 34019616
412021616 48014832
52404832 516032464
64808464 6320512128
796152128 764106256
8128213512
Abtastrate1923138461
Samples256 (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.

Hardware

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.

Firmware

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.