Polyphonie: Mehrere Tonspuren

Für eine einzelne Tonspur ist alles recht einfach. Kompliziert wird es allerdings, wenn mehrere Spuren verwendet werden sollen - was wünschenswert ist, da mit einer einzelnen Spur selten interessante Musik entsteht. Würden wir dem Prinzip der einzelnen Tonspur folgen, bedeutete das: Jede Spur benötigt ein eigenes PWM-Modul.

Stellenmarkt
  1. SAP HCM / Fiori / ABAP Entwickler (m/w/x)
    über duerenhoff GmbH, Raum Karlsruhe, deutschlandweit (Home-Office)
  2. IT Operations Engineer / Cloud Ops Engineer (w/m/d)
    ING Deutschland, Frankfurt am Main
Detailsuche

Die Module haben nämlich einen großen Nachteil: Zwar haben sie theoretisch zwei Kanäle mit jeweils eigenem Vergleichswert - prinzipiell wäre es also möglich, zwei Spuren mit einem PWM-Modul zu realisieren. Praktisch können die Vergleichswerte allerdings nicht unabhängig geschrieben werden. Sie liegen zusammen in einem 32-Bit-Register. Den DMA-Automaten die Vergleichswerte unabhängig schreiben zu lassen, funktioniert nicht - bei einer 16-Bit-Schreiboperation werden beide Vergleichswerte mit dem geschriebenen Wert gefüllt.

Schlimmer noch: Für jede Tonspur brauchen wir einen Timer, der die Datenrate des DMA-Kanals reguliert. Je nach Design sind mit vier Tonspuren - so viele nutzen Gameboy und NES - bereits alle PWM-Module belegt. Mit etwas komplexerer Software lassen sich aber theoretisch beliebig viele Spuren auf nur ein Modul abbilden.

Die Spuren kommen in den Mixer

Das Grundproblem bei mehreren Tonspuren ist: Sie müssen zu einem Signal zusammengemischt werden. Das funktioniert entweder, wie oben beschrieben, mit einer Hardware-Einheit pro Spur, die analogen Signale werden dann einfach durch die Addition der Einzelspannungen gemischt. Alternativ können die digitalen Signale vor der Analogwandlung addiert werden.

Golem Karrierewelt
  1. IT-Sicherheit für Webentwickler: virtueller Zwei-Tage-Workshop
    07./08.02.2023, Virtuell
  2. First Response auf Security Incidents: Ein-Tages-Workshop
    14.11.2022, Virtuell
Weitere IT-Trainings

Das bedeutet allerdings: Alle Signale müssen die gleiche Abtastrate haben. Da für jede Grundschwingung nur ein Sample vorliegt, ist eine Abtastratenkonvertierung (auf Englisch heißt das resampling). Das bedeutet einigen Rechenaufwand, aber angesichts der Leistung der zwei Cortex-M0+-Kerne im RP2040 ist das vertretbar. Wichtig ist dabei der Hardware-Multiplizierer - der kann in jedem Takt zwei 32-Bit-Werte multiplizieren. Mit ein wenig Geschick lässt sich der Software-Mischer recht effizient realisieren.

Die Funktion des Mixers ist relativ simpel: Er berechnet für jede Tonspur anhand einer vorgegebenen Frequenz zuerst den auszugebenden Abtastwert. Den leitet er aus einem Sample ab, das frequenzunabhängig verwendet wird. Das bedeutet, dass die einzelnen Abtastpunkte des Samples entweder gestreckt werden - wenn eine Schwingung mit der Zielfrequenz mehr Abtastpunkte hätte als das Sample - oder dass Abtastpunkte ausgelassen werden, wenn die gewünschte Schwingung mit der Abtastfrequenz des Mixers an weniger Punkten abgetastet würde als das Sample.

  • Größerer Ausschnitt aus dem erzeugten Signal: links ein reiner Sinus, rechts Überlagerung aus Sinus und Rechtecksignal. (Bild: Johannes Hiltscher, Golem.de)
  • Das Grundsignal, mit dem das PWM-Signal die Spannungspegel erzeugt. Hier erzeugt ohne Vorteilung des Systemtakts. (Bild: Johannes Hiltscher, Golem.de)
  • In den PWM-Modulen des RP2040 läuft ein Zähler zwischen 0 und einem Maximalwert. Bei jedem Zählschritt wird sein Wert mit einem Register (Counter Compare) verglichen; ist der Zähler kleiner oder gleich, wird eine 1 ausgegeben, sonst eine 0. (Bild: Johannes Hiltscher, Golem.de)
  • So funktioniert die Abtastratenkonvertierung: Anhand des Ausgangssamples werden neue Abtastpunkte mit der Frequenz des Mixers erzeugt. Bei niedrigen Frequenzen werden neue Punkte erzeugt, bei hohen nur einige ausgewählt. (Bild: Johannes Hiltscher, Golem.de)
  • Das Ausgangssignal ist nicht ganz sauber, aber als Sinus erkennbar. Die Frequenz stimmt auch, hier ein G4.  (Bild: Johannes Hiltscher, Golem.de)
So funktioniert die Abtastratenkonvertierung: Anhand des Ausgangssamples werden neue Abtastpunkte mit der Frequenz des Mixers erzeugt. Bei niedrigen Frequenzen werden neue Punkte erzeugt, bei hohen nur einige ausgewählt. (Bild: Johannes Hiltscher, Golem.de)

Dazu enthält die Datenstruktur jeder Tonspur eine Variable, mit der die Position im Sample berechnet wird. Um die Tonqualität etwas zu optimieren, bildet man den Mittelwert zweier benachbarter Abtastwert (Interpolation). Das ist sinnvoll, da bei den wenigsten Zielfrequenzen die einzelnen Abtastwerte exakt getroffen werden; zusätzlich verringert es Signalverzerrungen. Aber hier erst einmal der Code (aus der Funktion doMixing() in pwm_retrosound.c):

  1. interpolation[0] = (channels[c].sampleOffset & 0xffff) >> 12;
  2. interpolation[1] = (0x10000 - (channels[c].sampleOffset & 0xffff)) >> 12;
  3.  
  4. offset = channels[c].sampleOffset >> 16;
  5.  
  6. sValues[0] = (channels[c].wavetable[offset & 0xf] * channels[c].volume) >> 4;
  7. sValues[1] = (channels[c].wavetable[(offset + 1) & 0xf] * channels[c].volume) >> 4;
  8.  
  9. mixingBuffer += ((sValues[0] * interpolation[0]) >> 4) + ((sValues[1] * interpolation[1]) >> 4);

In den ersten beiden Zeilen wird für die zwei Werte, zwischen denen interpoliert wird, der Faktor berechnet, mit dem sie ins Ergebnis einfließen. Dazu dient die Variable sampleOffset als Festkommawert. Dabei wird ein fester Teil der Variable als Nachkommateil verwendet - hier die unteren 16 Bit. Damit lassen sich auch auf Systemen ohne Gleitkommaeinheit rationale Zahlen verwenden, und zwar mit sehr geringem Aufwand.

Komplexe Mischung mit wenig Aufwand dank festem Komma

Additionen und Subtraktionen bedeuten bei Festkomma-Arithmetik keinen zusätzlichen Aufwand, Multiplikationen sind allerdings etwas komplizierter. Da im Code oben der Wertebereich angepasst ist, wird nur eine zusätzliche Verschiebeoperation erforderlich. Sie entspricht einer Division durch eine Zweierpotenz. In den ersten beiden Zeilen wird der Nachkommateil der Variablen auf vier Bit reduziert, um das Ergebnis der Multiplikation in der letzten Zeile im Wertebereich einer 16-Bit-Variable zu halten. Damit sind 15 Interpolationsstufen zwischen den beiden Werten möglich.

Vor der Interpolation werden allerdings noch die Werte der beiden Samples, zwischen denen interpoliert wird, auf die (einstellbare) Lautstärke angepasst. Sie werden mit einem Wert zwischen 1 und 16 multipliziert und danach durch 16 geteilt. Dadurch lässt sich die Lautstärke in 16 Stufen anpassen. So kann eine einzelne Spur die maximal mögliche Lautstärke ausnutzen, bei mehreren aktiven Spuren kann deren Lautstärke jedoch verringert werden, um Übersteuern zu vermeiden.

Am Ende werden noch die Samples der einzelnen Spuren zusammengemischt. Alles landet in einem von zwei Puffern, die die DMA-Einheit abwechselnd zum PWM-Modul transportiert. Das sieht fast genau so aus wie im Testcode, allerdings löst der DMA-Kanal einen Interrupt aus, sobald er einen Puffer vollständig übertragen hat. Dadurch erfährt der Prozessor, dass der nächste Puffer geschickt werden muss, damit es munter weiter tönt.

Jetzt brauchen wir nur noch einen Weg, um mit möglichst wenig Aufwand Musik zu erzeugen.

Bitte aktivieren Sie Javascript.
Oder nutzen Sie das Golem-pur-Angebot
und lesen Golem.de
  • ohne Werbung
  • mit ausgeschaltetem Javascript
  • mit RSS-Volltext-Feed
 Samples abspielen mit PWMMusik erzeugen mit Tracker 
  1.  
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8.  


Aktuell auf der Startseite von Golem.de
Core-i-13000
Intel präsentiert Raptor Lake mit bis zu 5,8 GHz

Auf der Innovation hat Intel die 13. Core Generation vorgestellt. Kernzahl, Takt und Effizienz sollen deutlich steigen.

Core-i-13000: Intel präsentiert Raptor Lake mit bis zu 5,8 GHz
Artikel
  1. Ukrainekrieg: Meta stoppt ausgefeilte russische Desinformationskampagne
    Ukrainekrieg
    Meta stoppt ausgefeilte russische Desinformationskampagne

    Gefakte Webseiten deutscher Medien machen Stimmung gegen die Russland-Sanktionen. Die falschen Artikel wurden über soziale Medien verbreitet.

  2. Star Wars: Lego bringt großes Set der Razor Crest aus The Mandalorian
    Star Wars
    Lego bringt großes Set der Razor Crest aus The Mandalorian

    Aus fast 6.200 Teilen besteht das große Lego-Set der Razor Crest. Sie ist teuer, nicht aber für ein Star-Wars-Set.

  3. Creative Commons, Pixabay, Unsplash: Rechtliche Fallstricke bei Gratis-Stockfotos
    Creative Commons, Pixabay, Unsplash
    Rechtliche Fallstricke bei Gratis-Stockfotos

    Pixabay, Unsplash, CC ermöglichen eine gebührenfreie Nutzung kreativer Werke. Vorsicht ist dennoch geboten: vor Abmahnmaschen, falschen Quellenangaben, unklarer Rechtslage.
    Eine Analyse von Florian Zandt

Du willst dich mit Golem.de beruflich verändern oder weiterbilden?
Zum Stellenmarkt
Zur Akademie
Zum Coaching
  • Schnäppchen, Rabatte und Top-Angebote
    Die besten Deals des Tages
    Daily Deals • AMD Ryzen 7000 jetzt bestellbar • CyberWeek: PC-Tower, Cooling & Co. • Günstig wie nie: Asus RX 6700 XT 539€, Acer 31,5" 4K 144 Hz 899€, MSI RTX 3090 1.159€ • AMD Ryzen 7 5800X 287,99€ • Xbox Wireless Controller 49,99€ • MindStar (Gigabyte RTX 3060 Ti 522€) [Werbung]
    •  /