Neue Trackermodul-Engine (vollst. MOD-Standard und evtl. mehr)

Diskussion zum Thema Programmierung unter DOS (Intel x86)
Antworten
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Neue Trackermodul-Engine (vollst. MOD-Standard und evtl. mehr)

Beitrag von zatzen »

Wie im Thread "Trackermodul-Enginge (sehr einfach)" abgehandelt, hatte ich mir mein eigenes Modulformat ausgedacht. Damit es für den Anfang leicht für mich umzusetzen war, habe ich dabei auf alle Effekte verzichtet, bis auf Lautstärkeänderungen. Besondere Features waren eine sehr kompakte Speicherung der Patterndaten sowie letztlich das Konvertieren der Samples nach 4 Bit nichtlinear Delta, und das Entpacken in Echtzeit. Außerdem wurden die Module dahingehend gescannt, wie lang jedes einzelne Sample tatsächlich gespielt wurde, und wenn möglich wurden diese gekürzt. Dadurch war bzw. ist ein ZSM (so taufte ich die Module) garantiert immer nur < 50 % so groß wie das original MOD, und entsprechend viel Speicher spart man im RAM.

Mittlerweile hat sich bei mir die Begeisterung für dieses Konzept ein wenig erschöpft. Die Speicherersparnis ist zwar nach wie vor irgendwie faszinierend, aber durch das Fehlen von Effekten besteht doch auf der anderen Seite eine große Beschränkung. Das Hauptkriterium bei der Auswahl von MODs die ich nach ZSM konvertieren konnte war, dass diese keine Effekte nutzen durften. Es gibt da eine Stange guter Musikstücke bei denen das so ist, aber die meisten guten Musikstücke benutzen Effekte, und das oft nicht zu knapp. Auch meine eigenen alten MODs die ich um 1994 machte nutzen Effekte.

Meine Entscheidung, in ZSM keine Effekte zu unterstützen legitimierte ich auch damit, dass ich bei aktuelleren Musikstücken, die ich im X-Tracker gemacht hatte, ebenfalls kaum Effekte nutzte. Das ergab sich aber daher, dass ich diese Musikstücke abschliessend noch einmal abmischte bzw. große Samples verwendete, die soetwas wie Hüllkurve und ein gewisses Leben schon mitbrachten. Wenn man aber für Spiele trackert, kann es sehr sinnvoll sein, kurze Samples oder gar eintönige Mini-Schleifen-Samples durch Effekte organischer klingen zu lassen.

Als ich die Portierung vom Beni-Tracker (AdLib) von QuickBASIC nach Pascal/Assembler vornahm, wurde mir klar, wie einfach Effekte prinzipiell realisiert werden:
Alles wird in 50 Hz gerastert, und die Effekte werden in diesem Raster abgearbeitet. Nun stellte sich für mich aber weiterhin eine Frage: Wenn alles in 50 Hz gerastert ist, kann man nur Geschwindigkeiten wie 125 oder 150 BPM usw... haben. Das ergibt sich aus dem Speed-Faktor, für 125 BPM ist dieser 6, für 150 BPM ist er 5, oder z.B. für 75 BPM 10 - alles bezogen darauf wenn eine Viertelnote vier Zeilen entspricht. Der Speed-Faktor gibt an, wieviele Ticks (die standardmäßig mit 50 Hz getaktet sind, also 20 ms dauern) eine Notenzeile dauert.
Eine Sache die mit dazu beigetragen hat, dass ich das mit den Effekten (und mit der Aufteilung in Ticks) nicht umsetzen wollte war, dass ich beliebige BPM Geschwindigkeiten unterstützen wollte. Nun, es ist letztlich kein Problem: Ich habe nun herausgefunden dass man einfach die Länge der Ticks anpasst: Für 125 BPM gelten 50 Hz bzw. 20 ms. Für 250 BPM entsprechend 100 Hz oder 10 ms. Bei 100 BPM wären es 40 Hz / 25 ms, usw...

Wozu nun einen MOD-Player programmieren, wo es doch sicherlich schon genug davon gibt, wahrscheinlich auch als Pascal-Unit?
Zum einen erfülle ich mir damit noch einmal einen kleinen Traum, ich wollte schon vor über 25 Jahren soetwas können, konnte es aber nicht. Mit ZSM konnte ich Erfahrungen auf dem Gebiet sammeln, und möglicherweise wird es auch nochmal irgendwo verwendet.
Zum anderen wird es aber wieder ein eigenes Format sein:
- Samples wahlweise 4 Bit Delta oder 8 bit unkomprimiert (wenn es auf Geschwindigkeit oder aber auch Soundqualität ankommt kann man unkomprimiert wählen, und ein Modul kann beide Arten auch gemischt enthalten)
- Patterndaten komprimiert: Bisher haben meine Überlegungen/Tests eine Redundanzkürzung auf zwei Ebenen als effektiv befunden:
1. Tabelle mit allen vorkommenden Zeilenereignissen jeweils nur einmal gelistet, jeder Eintrag braucht 4 Bytes.
2. Patterns werden in einspurige 8-Zeilen-Blöcke zerlegt und davon nur nicht-redundante gespeichert. In diesen Blöcken sind die Nummern der einzufügenden Zeilenereignisse hinterlegt, mit nur so viel Bit wie nötig (bis 64 gesamte unterschiedliche Zeilenereignisse: 6 Bit, bis 128: 7 Bit usw.)
3. Die Blöcke selber werden wiederum in Patterns angeordnet, auch nur mit wirklich benötigter Bitbreite. Für ein 4-Kanal 64-Zeilen Pattern bräuchte man also 4*64 / 8 = 32 Referenzen. Das mit den variablen Bitbreiten ist sinnvoll, u.a. weil es oft effektive nötige Bitbreiten von 9 Bit gibt, die sonst direkt mit 16 Bit abgedeckt werden müssten.
Ich habe schon etwas verglichen, und diese Patternkompression ist teilweise vergleichbar mit der von ZSM, liegt teilweise sogar drunter, im Schnitt aber bei etwa 20%. Dabei muss man bedenken, dass ZSMs kein Effektdaten beherbergen. Wäre das so, würde die Kompressionsrate dort deutlich schlechter ausfallen, je nach Effektaufkommen. Letztlich ist oben beschriebene Kompressionsmethode aber auch weniger fummelig und erlaubt bei entsprechender Programmierung Random-Access, während ZSM-Patterns strikt seriell gelesen werden müssen.
Warum die ganze Kompression der Patterns? Ein MOD-Pattern ist bei 64 Zeilen und 4 Kanälen genau 1 KB groß. Ein Song hat gut und gerne mal 32 Patterns. Das sind schon 32 KB, und wenn man das ganze dann auf 8 Kanäle erweitert hat man schon 64 KB voll. Da nutze ich lieber eine solche Kompression, die einem zudem das gute Gefühl gibt, dass nahezu jegliche Redundanz aus den Daten entfernt wird - es wird also nur wirkliche Information gespeichert, wenigstens im Raster von 8 Zeilen.

Kurzgesagt also zum neuen Format: Es soll die Vorzüge von ZSM mit dem vollwertigen MOD-Format verbinden.


In diesem Thema soll gerne rund um das Thema MOD/Tracker/Trackerdateien diskutiert werden. Vielleicht hat auch noch jemand eine bessere Idee für die Patternkomprimierung unter Beibehaltung von Random Access.

Vorab ist mir gerade die Implementierung der Lautstärke schonmal unklar: Der spontane Gedanke, das über eine Tabelle zu lösen, würde zu einer Tabelle der Größe 64*256=16834 Bytes führen, und wenn ich intern mit 16 Bit Präzision mischen will (wie bei ZSM) hätte ich direkt 32 KB an der Backe. Das würde einem den Spaß an Chiptunes verderben.
mov ax, 13h
int 10h

while vorne_frei do vor;
Antworten