Musik erzeugen mit Tracker

Um mit dem Soundmodul Musik zu erzeugen, muss aktuell noch jede Note einzeln ausgegeben werden. Das wird bei vier Kanälen (so viele habe ich aktuell implementiert) schnell ganz schön aufwendig. Außerdem ist es ungenau, da ein Timer regelmäßig den entsprechenden Code ausführen muss, der noch einmal Zeit braucht.

Stellenmarkt
  1. Test Manager (m/f/d) for Hardware Security Modules
    Elektrobit Automotive GmbH, Germany - Erlangen
  2. SAP Consultant (m/w/d) FI/CO/PS
    Universitätsklinikum Regensburg, Regensburg
Detailsuche

Idealerweise hätte unser Orchester einen Dirigenten, der dafür sorgt, dass alle Spuren gleich schnell spielen und gleichzeitig zum nächsten Ton wechseln. Vor dem Problem steht jeder Synthesizer und daher wurde schnell eine Lösung entwickelt: der Tracker. Er ist nichts anderes als ein digitales Notenblatt und ist unterteilt in einzelne Noten, die nacheinander durch den Synthesizer wiedergegeben werden. Dazu müssen noch die Abspielgeschwindigkeit (Beats per Minute, BPM) und die Notenwerte (ganze, halbe, viertel und so weiter) eingestellt werden.

In meinem Code erledigt das die Funktion setBeat(). Sie berechnet, wie schnell die Mixerfunktion durch die Tracks - jede Spur hat ihren eigenen - gehen soll. Das Ergebnis ist wieder ein Festkommawert, um die vorgegebene Geschwindigkeit möglichst genau einzuhalten. Hier wird zwar nicht interpoliert (das wäre etwas schwierig), allerdings kann nach einer zu spät begonnenen Note die nächste etwas vorgezogen werden. Dadurch addieren Fehler sich nicht auf.

Das digitale Notenblatt

Der Tracker ist ebenfalls in der Funktion doMixing() implementiert, aus der wir bereits einen Ausschnitt gesehen haben. Jede Tonspur speichert einen eigenen Track, und der ist nichts weiter als ein Array aus 8-Bit-Werten. Dazu gibt es je eine Variable, die die aktuelle Position im Track und dessen Länge speichert.

Golem Karrierewelt
  1. Adobe Premiere Pro Grundkurs: virtueller Zwei-Tage-Workshop
    27./28.10.2022, Virtuell
  2. Einführung in Unity: virtueller Ein-Tages-Workshop
    13.10.2022, Virtuell
Weitere IT-Trainings

Aktuell ist der Tracker nur für die gleichstufige Stimmung mit Kammerton A = 440 Hz ausgelegt, also die Tonfrequenzen, auf die die meisten Instrumente gestimmt sind. Jedes Byte ist aufgeteilt in je vier Bit für Oktave und Ton, zusätzlich gibt es ein Pausensymbol, das aus einer ungültigen Kombination besteht. Der Tracker-Code ist etwa ebenso lang wie der des Mixers:

  1. if(samplesProduced > (trackPtrCounter >> 8)) {
  2. trackPtrCounter -= (samplesProduced << 8);
  3. trackPtrCounter += trackPtrUpdateDeltaSamples;
  4. samplesProduced = 0;
  5.  
  6. incrementTrackPtr = true;
  7. }
  8.  
  9. for(uint c = 0; c < N_SOUND_CHANNELS; ++c) {
  10. if((channels[c].cs == PLAYING) && (channels[c].trackLength > 0)) {
  11. if(incrementTrackPtr) {
  12. ++channels[c].trackPtr;
  13.  
  14. if(channels[c].trackPtr >= channels[c].trackLength)
  15. channels[c].trackPtr = 0;
  16. }
  17. }
  18.  
  19. note = channels[c].track[channels[c].trackPtr];
  20.  
  21. if(note != PAUSE) {
  22. // hier kommt der Mixer-Code
  23. }
  24. }

Am Anfang steht eine Abfrage, die prüft, ob der Tracker zur nächsten Note springen muss. Dazu wird berechnet, wie viele Samples zwischen zwei Noten vergehen (trackPtrUpdateDeltaSamples) - als Festkommawert mit acht Nachkommabits. Eine Variable zählt, wie viele Abtastwerte der Mixer seit dem letzten Notenwechsel erzeugt hat (samplesProduced) und eine weitere Festkommavariable (trackPrCounter) speichert, nach wie vielen Samples der nächste Notenwechsel erfolgen soll.

Wechselt die Note, wird das erst einmal nur in einer Variable festgehalten. Den eigentlichen Wechsel nimmt der Code für die einzelnen Kanäle in der for-Schleife vor. Er sorgt auch dafür, dass am Ende des Tracks an dessen Anfang zurückgesprungen wird - einmal gestartete Tracks laufen, bis sie gestoppt werden. Nachdem die aktuelle Note aus dem Track gelesen wurde, folgt der Mixer-Code - es sei denn, es wurde eine Pause eingefügt.

Damit ist der Code vollständig - auch wenn hier nur ein kleiner Ausschnitt gezeigt wurde. Zeit, ihn auszuprobieren.

Bitte aktivieren Sie Javascript.
Oder nutzen Sie das Golem-pur-Angebot
und lesen Golem.de
  • ohne Werbung
  • mit ausgeschaltetem Javascript
  • mit RSS-Volltext-Feed
 Polyphonie: Mehrere TonspurenTestprogramm und Schlussbemerkungen 
  1.  
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8.  


Aktuell auf der Startseite von Golem.de
Superbase V
Zendures Solarstation mit 6.400 Wh kommt mit hohem Rabatt

Vor dem Verkaufsstart über die eigene Webseite verkauft Zendure seine Superbase V über Kickstarter - mit teilweise fast 50 Prozent Rabatt.

Superbase V: Zendures Solarstation mit 6.400 Wh kommt mit hohem Rabatt
Artikel
  1. Tesla Optimus: Elon Musk zeigt Roboter-Prototyp
    Tesla Optimus
    Elon Musk zeigt Roboter-Prototyp

    Roboter könnten für Tesla aus Sicht von Elon Musk bedeutender werden als Elektroautos. Der Konzern zeigte seinen ersten Roboter-Prototypen.

  2. Microsofts E-Mail: Modern Auth in Exchange macht Admins Arbeit
    Microsofts E-Mail
    Modern Auth in Exchange macht Admins Arbeit

    Ab dem 1. Oktober 2022 müssen Exchange-Clients zwingend Microsofts moderne Authentifizierung nutzen. Das bedeutet Mehrarbeit.
    Eine Analyse von Oliver Nickel

  3. Google: Nutzer fordern Bluetooth-Freigabe für Stadia-Controller
    Google
    Nutzer fordern Bluetooth-Freigabe für Stadia-Controller

    Mit der Einstellung von Stadia können auch Tausende der speziellen Controller ohne ein Update nicht mehr drahtlos genutzt werden.

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 • MindStar (u. a. LC-Power LC-M27-QHD-240-C-K 389€) und Damn-Deals (u. a. Kingston A400 240/480 GB 17,50€/32€, NZXT Kraken X73 139€) • Alternate: Weekend Sale • Razer Strider XXL 33,90€ • JBL Live Pro+ 49€ • PCGH-Ratgeber-PC 3000 Radeon Edition 2.500€ • LG OLED65CS9LA 1.699€ [Werbung]
    •  /