Trackermodul-Engine (sehr einfach)
Re: Trackermodul-Engine (sehr einfach)
Ich lese schon mit... aber ich glaube du wirst bei der Implementierung immer wieder neue Ideen haben und alte Ideen über den Haufen werden. Also einfach anfangen und dann schauen, was draus wird. Viel Erfolg auf jeden Fall!
Re: Trackermodul-Engine (sehr einfach)
Nein, ich muss schon erstmal ein Konzept stehen haben, bevor ich auch nur eine Zeile Code schreibe.
Sonst müsste ich ja bei jeder Änderung Converter und Pattern-Decoder umschreiben.
Es eilt ja nicht, und ich werde ersteinmal eine Weile theoretisch weitertüfteln.
Sonst müsste ich ja bei jeder Änderung Converter und Pattern-Decoder umschreiben.
Es eilt ja nicht, und ich werde ersteinmal eine Weile theoretisch weitertüfteln.
mov ax, 13h
int 10h
while vorne_frei do vor;
int 10h
while vorne_frei do vor;
Re: Trackermodul-Engine (sehr einfach)
In Ruhe nochmals nachgedacht...
Und die Vorgehensweise nochmals vereinfacht, gleichzeitig wahrscheinlich verbessert.
Jedes Sample des Moduls erhält eine kleine (je nachdem) Tabelle, die nur die Notenwerte
enthält, auf denen es tatsächlich insgesamt auch abgespielt wird. Habe ich also z.B.
einen Bass der vielleicht insgesamt auf 7 Noten gespielt wird, so brauche ich nur 3 Bit,
um ihn zu referenzieren. Die Tabelle enthält dann z.B. C-2, D#-2, E-2, G-2, A-2, C-3 ...
Habe ich eine Snare, die immer nur auf einer Note gespielt wird, enthält die Tabelle
nur einen Wert, z.B. ein C-3. Bei der Referenzierung werden nun gar keine Bits gebraucht,
weil es ja nur einen Notenwert gibt.
Somit habe ich die volle Bandbreite an Noten (255) zur Verfügung, brauche sie aber nicht
als volle 8 Bit in den Patterns zu speichern.
Für den Lautstärke-Befehl, der bei mir nur Werte von 0-7 erhält (ich möchte in der Mix-
Routine mit dem Assembler-Befehl SAR arbeiten, nicht mit MUL oder einer großen Tabelle),
würde für jedes Pattern für jeden Track eine kleine Tabelle machen, welche Lautstärkebefehle
im Track vorkommen, so dass für zwei Unterschiedliche Lautstärken schon 1 Bit genügt um es zu definieren.
Weiterhin enthält jeder Track eine Liste der verwendeten Samplenummern, so dass
auch hier wieder viele Bits gespart werden können oder wenn kein Wechsel der Samplenummer
im Track vorliegt gar keine Bits gebraucht werden.
Die Patterns selbst mit ihren Trackereignissen werden relativ gespeichert, d.h. nur die
Veränderungen, und das auch aufgeteilt in Samplenummer, Note, Lautstärke und, das
muss ich kurz erklären, "Trigger": Es bedeutet dass das Sample neu "angeschlagen", d.h.
von vorn abgespielt wird. Dafür wird nur ein Bit benötigt, und es kann z.B. bei einer
Spur auf der nur eine Bassdrum gespielt wird sehr sparsam sein, weil im Prinzip nur
diese Information "nochmal so abspielen wie davor" gespeichert wird.
Wie ich das flagging genau mache und ob z.B. eine Samplenummer, die nur am Anfang des
Tracks kommt und danach nicht wieder, überhaupt in die Tabelle soll oder nur so als Start-
vorgabe definiert wird, das ist noch ein klein bisschen Denkarbeit.
Auch brauche ich nach wie vor für jede Zeile ein Info-Byte mit 8 Flags für die jeweiligen Kanäle,
ob auf denen Veränderungen stattfinden oder nicht, sowie einen Zähler für Leerzeilen.
Und die Vorgehensweise nochmals vereinfacht, gleichzeitig wahrscheinlich verbessert.
Jedes Sample des Moduls erhält eine kleine (je nachdem) Tabelle, die nur die Notenwerte
enthält, auf denen es tatsächlich insgesamt auch abgespielt wird. Habe ich also z.B.
einen Bass der vielleicht insgesamt auf 7 Noten gespielt wird, so brauche ich nur 3 Bit,
um ihn zu referenzieren. Die Tabelle enthält dann z.B. C-2, D#-2, E-2, G-2, A-2, C-3 ...
Habe ich eine Snare, die immer nur auf einer Note gespielt wird, enthält die Tabelle
nur einen Wert, z.B. ein C-3. Bei der Referenzierung werden nun gar keine Bits gebraucht,
weil es ja nur einen Notenwert gibt.
Somit habe ich die volle Bandbreite an Noten (255) zur Verfügung, brauche sie aber nicht
als volle 8 Bit in den Patterns zu speichern.
Für den Lautstärke-Befehl, der bei mir nur Werte von 0-7 erhält (ich möchte in der Mix-
Routine mit dem Assembler-Befehl SAR arbeiten, nicht mit MUL oder einer großen Tabelle),
würde für jedes Pattern für jeden Track eine kleine Tabelle machen, welche Lautstärkebefehle
im Track vorkommen, so dass für zwei Unterschiedliche Lautstärken schon 1 Bit genügt um es zu definieren.
Weiterhin enthält jeder Track eine Liste der verwendeten Samplenummern, so dass
auch hier wieder viele Bits gespart werden können oder wenn kein Wechsel der Samplenummer
im Track vorliegt gar keine Bits gebraucht werden.
Die Patterns selbst mit ihren Trackereignissen werden relativ gespeichert, d.h. nur die
Veränderungen, und das auch aufgeteilt in Samplenummer, Note, Lautstärke und, das
muss ich kurz erklären, "Trigger": Es bedeutet dass das Sample neu "angeschlagen", d.h.
von vorn abgespielt wird. Dafür wird nur ein Bit benötigt, und es kann z.B. bei einer
Spur auf der nur eine Bassdrum gespielt wird sehr sparsam sein, weil im Prinzip nur
diese Information "nochmal so abspielen wie davor" gespeichert wird.
Wie ich das flagging genau mache und ob z.B. eine Samplenummer, die nur am Anfang des
Tracks kommt und danach nicht wieder, überhaupt in die Tabelle soll oder nur so als Start-
vorgabe definiert wird, das ist noch ein klein bisschen Denkarbeit.
Auch brauche ich nach wie vor für jede Zeile ein Info-Byte mit 8 Flags für die jeweiligen Kanäle,
ob auf denen Veränderungen stattfinden oder nicht, sowie einen Zähler für Leerzeilen.
mov ax, 13h
int 10h
while vorne_frei do vor;
int 10h
while vorne_frei do vor;
Re: Trackermodul-Engine (sehr einfach)
Die 8-Bit-Info für alle 8 Kanäle könnte ich kleiner halten, indem ich zu jedem Pattern eine Information
speichere, welche Tracks überhaupt belegt sind. Wären es Beispielsweise nur vier nach einem Muster
von "11010010", dann speichere ich eben pro Zeile nur für diese 4 aktiven Kanäle die Info, ob dort etwas passiert.
Leerzeilen werde ich wohl einfach mit einem Bit einläuten, ob welche vorliegen, und dann mit 3 oder 4 Bit
die Anzahl angeben.
"Trigger" würde ich ersetzen durch "Repeat" - also wiederholen des zuletzt aufgetretenen Events.
Das dürfte bei Schlagzeug, sofern man nicht alles auf eine Spur packt sondern z.B. eine Hihat
Spur separat hat, sehr effizient sein, aber auch bei manchen Melodien, wo sich Töne wiederholen.
Die Flags für ein Kanal-Event wären folgende:
Repeat/SampleNr/Note/Volume (4 Bit)
Zuerst wird Repeat gelesen, und nur wenn dort eine 0 vorzufinden ist werden die weiteren Flags auch
gelesen, sonst einfach das letzte Event wiederholt.
Bei Tabellen < 3 Elemente fungieren die restlichen drei Flags selbst als Indizes. Das ist eine sehr kompakte Sache.
Gibt es längere Tabellen, dann haben die Flags entweder eine 0 oder eine 1 ob ein Wert vorliegt (wo sich etwas
geändert hat), und dann folgen der Tabellenlänge entsprechend viele Bits.
speichere, welche Tracks überhaupt belegt sind. Wären es Beispielsweise nur vier nach einem Muster
von "11010010", dann speichere ich eben pro Zeile nur für diese 4 aktiven Kanäle die Info, ob dort etwas passiert.
Leerzeilen werde ich wohl einfach mit einem Bit einläuten, ob welche vorliegen, und dann mit 3 oder 4 Bit
die Anzahl angeben.
"Trigger" würde ich ersetzen durch "Repeat" - also wiederholen des zuletzt aufgetretenen Events.
Das dürfte bei Schlagzeug, sofern man nicht alles auf eine Spur packt sondern z.B. eine Hihat
Spur separat hat, sehr effizient sein, aber auch bei manchen Melodien, wo sich Töne wiederholen.
Die Flags für ein Kanal-Event wären folgende:
Repeat/SampleNr/Note/Volume (4 Bit)
Zuerst wird Repeat gelesen, und nur wenn dort eine 0 vorzufinden ist werden die weiteren Flags auch
gelesen, sonst einfach das letzte Event wiederholt.
Bei Tabellen < 3 Elemente fungieren die restlichen drei Flags selbst als Indizes. Das ist eine sehr kompakte Sache.
Gibt es längere Tabellen, dann haben die Flags entweder eine 0 oder eine 1 ob ein Wert vorliegt (wo sich etwas
geändert hat), und dann folgen der Tabellenlänge entsprechend viele Bits.
mov ax, 13h
int 10h
while vorne_frei do vor;
int 10h
while vorne_frei do vor;
Re: Trackermodul-Engine (sehr einfach)
Update...
Die Flags Repeat/Samplenr/Note/Volume fungieren nicht nur direkt als Index wenn eine Tabelle weniger als 3
Elemente enthält, sondern werden als Flags auch obsolet wenn die Tabellen nur einen Eintrag haben.
Bei nur einem Eintrag wird das entsprechende Flag also erst gar nicht gelesen geschweige denn gespeichert.
Zudem kann man beim Parameter "Note" davon ausgehen, dass zu jedem Track-Event in fast allen Fällen
auch eine Notenänderung erfolgt, somit kann man bei einer Tabelle > 2 direkt, ohne vorherigem Flag,
mit 2 Bit oder mehr indizieren. Gibt es nur eine Note für das Sample (z.B. eine Hihat), dann braucht
es gar keine Indizierung.
Gleiches gilt für die Samplenummer, davon wird es auf einem Track in der Praxis im Schnitt nur zwei
geben, auch hier wäre es ökonomisch, direkt von der Tabellenlänge auf die zu lesenden Bits zu schliessen.
Ebenso bei Volume.
Damit wäre die ganze Sache schonmal deutlich statischer und besser zu handlen.
Der Vollständigkeit halber nochmals:
Samplenummer-Tabellen werden pro Track und Pattern erstellt. Volume-Tabellen ebenfalls.
Beide Arten von Tabellen werden im Schnitt vielleicht 2 Einträge haben.
Die Noten-Tabellen werde ich nicht pro Track erstellen sondern insgesamt pro Sample.
Für jeden Track definiert würde es nicht viel bringen, da bei Melodien die keine übermäßig
hohe Redundanz aufweisen die Tabelle mehr Speicher verschlingen würde als die Indizierung
auf die etwas größeren, aber nur einmal und nicht für jeden Track jedes Patterns vorkommenden
Tabellen pro Sample.
Aber was mache ich mit "Repeat"... Ich lasse es erstmal drin, wahrscheinlich lohnt es sich, auch wenn
es ein ganzes Bit verbraucht... Immerhin sorgt es dafür, dass wenn doch zwei gleiche Noten aufeinander
folgen, dass diese Redundanz optimal herausgekürzt wird, was aber nur funktioniert wenn die Events
wirklich gleich sind - gesellt sich ein Lautstärkebefehl dazu, der beim zweiten Event anders ist, dann
funktioniert es nicht. Zu überdenken wäre, ob man die Lautstärke hier rausnimmt d.h. hinter "Repeat"
doch nochmal abfragt. Was speichersparend funktionieren kann, da eine konstante Lautstärke, was
nicht selten der Fall in einem Track ist, ja gar kein einziges Bit benötigt.
Die Flags Repeat/Samplenr/Note/Volume fungieren nicht nur direkt als Index wenn eine Tabelle weniger als 3
Elemente enthält, sondern werden als Flags auch obsolet wenn die Tabellen nur einen Eintrag haben.
Bei nur einem Eintrag wird das entsprechende Flag also erst gar nicht gelesen geschweige denn gespeichert.
Zudem kann man beim Parameter "Note" davon ausgehen, dass zu jedem Track-Event in fast allen Fällen
auch eine Notenänderung erfolgt, somit kann man bei einer Tabelle > 2 direkt, ohne vorherigem Flag,
mit 2 Bit oder mehr indizieren. Gibt es nur eine Note für das Sample (z.B. eine Hihat), dann braucht
es gar keine Indizierung.
Gleiches gilt für die Samplenummer, davon wird es auf einem Track in der Praxis im Schnitt nur zwei
geben, auch hier wäre es ökonomisch, direkt von der Tabellenlänge auf die zu lesenden Bits zu schliessen.
Ebenso bei Volume.
Damit wäre die ganze Sache schonmal deutlich statischer und besser zu handlen.
Der Vollständigkeit halber nochmals:
Samplenummer-Tabellen werden pro Track und Pattern erstellt. Volume-Tabellen ebenfalls.
Beide Arten von Tabellen werden im Schnitt vielleicht 2 Einträge haben.
Die Noten-Tabellen werde ich nicht pro Track erstellen sondern insgesamt pro Sample.
Für jeden Track definiert würde es nicht viel bringen, da bei Melodien die keine übermäßig
hohe Redundanz aufweisen die Tabelle mehr Speicher verschlingen würde als die Indizierung
auf die etwas größeren, aber nur einmal und nicht für jeden Track jedes Patterns vorkommenden
Tabellen pro Sample.
Aber was mache ich mit "Repeat"... Ich lasse es erstmal drin, wahrscheinlich lohnt es sich, auch wenn
es ein ganzes Bit verbraucht... Immerhin sorgt es dafür, dass wenn doch zwei gleiche Noten aufeinander
folgen, dass diese Redundanz optimal herausgekürzt wird, was aber nur funktioniert wenn die Events
wirklich gleich sind - gesellt sich ein Lautstärkebefehl dazu, der beim zweiten Event anders ist, dann
funktioniert es nicht. Zu überdenken wäre, ob man die Lautstärke hier rausnimmt d.h. hinter "Repeat"
doch nochmal abfragt. Was speichersparend funktionieren kann, da eine konstante Lautstärke, was
nicht selten der Fall in einem Track ist, ja gar kein einziges Bit benötigt.
mov ax, 13h
int 10h
while vorne_frei do vor;
int 10h
while vorne_frei do vor;
Re: Trackermodul-Engine (sehr einfach)
@zatzen:
Hm. An sich klingt das alles sehr ambitioniert und auch irgendwie "speichersparend".
Ich habe damals[tm] mal ein sequentielles Übertragungsformat für parallete Datenströme mit etlichen Features und bitbasierten Parametern gemacht (um Bandbreite zu sparen, das Ganze ging über seriellen Port).
Das Ergebnis war dann leider, daß sich das ganze Ding irgendwie "totgefrickelt" hatte. Außerdem war der Code, um diese komplizieren Daten auseinanderzubauen/lesen/zusammenzubauen so groß geworden, daß von Speicherersparnis kaum noch eine Rede sein konnte.
Was will ich damit sagen? Wenn man das Ganze ZU kompliziert macht, nur um ein paar Bits Speicher zu sparen, muß man dafür an anderer Stelle wieder sehr viel mehr Speicher verschwenden - für den Programmcode, der das alles ausführt.
Außerdem neige ich in letzter Zeit immer mehr dazu, ein kleines bißchen "Luft zu lassen", damit, falls ich mal später etwas erweitern will (neue Features, neue Parameter, usw) noch etwas Platz habe, um das Ganze zu implementieren OHNE dafür das vorige Format (und Player) wieder komplett auseinanderreißen zu müssen.
Natürlich erstmal Lob von mir dafür, die Sounddaten platzsparender zu speichern als diese "alles, wo nichts passiert, füllen wir mit Nullen aus" Geschichte (wie in MOD-Files), wo dann 90% der Daten nur aus "nichtstuenden Nullen" bestehen.
Andererseits - und das wurde ja auch an anderer Stelle von jemand anderem schon sinngemäß so erwähnt (gerade keine Lust, die ganzen Threads durchzusuchen wo und wer das gesagt hat).... und zwar, daß die Benutzung von Samples das ganze Sounddatengepacke so ein wenig "ad absurdum" führt. Wenn im File (und im ständig Speicher) Samples, mit vielleicht zusammengenommen 300 kB Größe liegen (und vielleicht zusätzlich im XMS zum "Austauschen" noch welche mit insgesamt 2 MB oder so), macht das Sparen an den Soundbefehldaten, bei dem man aus vielleicht 20 kB Sounddaten am Ende 2 kB macht, nicht wirklich den großen Unterschied aus - zumal, wie bereits oben erwähnt - kompliziert gepackte/kompensierte Daten natürlich aufwendigeren Programmcode brauchen, um diese zu lesen/abzuspielen.
Ich wollte das nur kurz anmerken, bevor Du Dich eventuell in so ein "Sounddaten zu GIF" (bewußt übertrieben) Projekt verrennst und bei all der Mühe kaum relevanten Speichergewinn erzielst, weil der durch den Code wieder aufgefressen wird.
Ich wollte das nur kurz loswerden.
Kleines zusätzliches Halb-OffTopic:
Ich muß dabei natürlich zugeben, daß mein Format dafür an Übersichtlichkeit (gegenüber normalen Trackern) etwas einbüßt, weil es "Unterprogramme" und "Schleifen" erlaubt. Ich denke immer mal wieder zwischendurch darüber nach, die AUSGABE des "Pseudo-Trackers", den ich da gebaut habe, um eine Tracker-artige Ansicht zu erweitern - d.h. die internen Daten werden weiterhin wie immer gespeichert, aber der "Tracker" gibt es wie Tracks und Patterns aus.
Das, was mich hauptsächlich davon abhält, ist, daß man im Tracker-Mode auf viele der Features von ISM verzichten müßte, da sie einfach für die Ansicht ungeeignet sind. Somit könnte die ISM-Ansicht (Normal) dann sowohl "normale" als auch im Tracker-Mode erzeugte Musikdaten in beiden darstellen/editieren. Aber es ginge nicht andersherum: D.h. sobald im "normalen" (ISM) Modus erstellte Daten irgendwelche der speziellen Features benutzen, wäre es im Tracker-Mode nicht mehr darstellbar, weil ein Tracker die entsprechenden Sachen so nicht vorsieht.
Ein anderer Grund wäre der, daß ich dann wohl aus Platzgründen den ISM-"Tracker" immer eher 2x kompilieren würde, jeweils entweder die eine oder die andere Anzeige durch Compilerschalter (DEFINEs) an/ausgeschaltet, so daß am Ende 2 EXEn entstehen würden, die jede nur eine der beiden Anzeigen supporten würde. Der Grund ist einfach der, daß, wenn beide Anzeigen im gleichen Programm gleichzeitig verfügbar (und damit immer vorhanden) wären, würden sie beide zusammen wieder mehr Codespeicher belegen - der dann wieder für Samples u.ä. fehlen würde (und der Entwickler/Komponist würde sowieso je nach Geschmack immer nur einen der beiden Modes benutzen).
Hm. An sich klingt das alles sehr ambitioniert und auch irgendwie "speichersparend".
Ich habe damals[tm] mal ein sequentielles Übertragungsformat für parallete Datenströme mit etlichen Features und bitbasierten Parametern gemacht (um Bandbreite zu sparen, das Ganze ging über seriellen Port).
Das Ergebnis war dann leider, daß sich das ganze Ding irgendwie "totgefrickelt" hatte. Außerdem war der Code, um diese komplizieren Daten auseinanderzubauen/lesen/zusammenzubauen so groß geworden, daß von Speicherersparnis kaum noch eine Rede sein konnte.
Was will ich damit sagen? Wenn man das Ganze ZU kompliziert macht, nur um ein paar Bits Speicher zu sparen, muß man dafür an anderer Stelle wieder sehr viel mehr Speicher verschwenden - für den Programmcode, der das alles ausführt.
Außerdem neige ich in letzter Zeit immer mehr dazu, ein kleines bißchen "Luft zu lassen", damit, falls ich mal später etwas erweitern will (neue Features, neue Parameter, usw) noch etwas Platz habe, um das Ganze zu implementieren OHNE dafür das vorige Format (und Player) wieder komplett auseinanderreißen zu müssen.
Natürlich erstmal Lob von mir dafür, die Sounddaten platzsparender zu speichern als diese "alles, wo nichts passiert, füllen wir mit Nullen aus" Geschichte (wie in MOD-Files), wo dann 90% der Daten nur aus "nichtstuenden Nullen" bestehen.
Andererseits - und das wurde ja auch an anderer Stelle von jemand anderem schon sinngemäß so erwähnt (gerade keine Lust, die ganzen Threads durchzusuchen wo und wer das gesagt hat).... und zwar, daß die Benutzung von Samples das ganze Sounddatengepacke so ein wenig "ad absurdum" führt. Wenn im File (und im ständig Speicher) Samples, mit vielleicht zusammengenommen 300 kB Größe liegen (und vielleicht zusätzlich im XMS zum "Austauschen" noch welche mit insgesamt 2 MB oder so), macht das Sparen an den Soundbefehldaten, bei dem man aus vielleicht 20 kB Sounddaten am Ende 2 kB macht, nicht wirklich den großen Unterschied aus - zumal, wie bereits oben erwähnt - kompliziert gepackte/kompensierte Daten natürlich aufwendigeren Programmcode brauchen, um diese zu lesen/abzuspielen.
Ich wollte das nur kurz anmerken, bevor Du Dich eventuell in so ein "Sounddaten zu GIF" (bewußt übertrieben) Projekt verrennst und bei all der Mühe kaum relevanten Speichergewinn erzielst, weil der durch den Code wieder aufgefressen wird.
Ich wollte das nur kurz loswerden.
Kleines zusätzliches Halb-OffTopic:
Ich muß dabei natürlich zugeben, daß mein Format dafür an Übersichtlichkeit (gegenüber normalen Trackern) etwas einbüßt, weil es "Unterprogramme" und "Schleifen" erlaubt. Ich denke immer mal wieder zwischendurch darüber nach, die AUSGABE des "Pseudo-Trackers", den ich da gebaut habe, um eine Tracker-artige Ansicht zu erweitern - d.h. die internen Daten werden weiterhin wie immer gespeichert, aber der "Tracker" gibt es wie Tracks und Patterns aus.
Das, was mich hauptsächlich davon abhält, ist, daß man im Tracker-Mode auf viele der Features von ISM verzichten müßte, da sie einfach für die Ansicht ungeeignet sind. Somit könnte die ISM-Ansicht (Normal) dann sowohl "normale" als auch im Tracker-Mode erzeugte Musikdaten in beiden darstellen/editieren. Aber es ginge nicht andersherum: D.h. sobald im "normalen" (ISM) Modus erstellte Daten irgendwelche der speziellen Features benutzen, wäre es im Tracker-Mode nicht mehr darstellbar, weil ein Tracker die entsprechenden Sachen so nicht vorsieht.
Ein anderer Grund wäre der, daß ich dann wohl aus Platzgründen den ISM-"Tracker" immer eher 2x kompilieren würde, jeweils entweder die eine oder die andere Anzeige durch Compilerschalter (DEFINEs) an/ausgeschaltet, so daß am Ende 2 EXEn entstehen würden, die jede nur eine der beiden Anzeigen supporten würde. Der Grund ist einfach der, daß, wenn beide Anzeigen im gleichen Programm gleichzeitig verfügbar (und damit immer vorhanden) wären, würden sie beide zusammen wieder mehr Codespeicher belegen - der dann wieder für Samples u.ä. fehlen würde (und der Entwickler/Komponist würde sowieso je nach Geschmack immer nur einen der beiden Modes benutzen).
Re: Trackermodul-Engine (sehr einfach)
Mal ausrechnen, was die Patterndaten unkomprimiert ehrlich dargestellt an Speicher belegen würden:
Wir haben pro Pattern
- 8 Kanäle
- 128 Zeilen
Ein Track-Event besteht aus:
Samplenummer, Note, Volume (Effekte in dem Sinn habe ich nicht, lediglich werde ich Notenwerte > 128
vom Player als die gleichen -128 abspielen lassen, aber ohne Neuanschlagen des Samples, also in den
neuen Notenwert hineingleitend - man könnte es auch Portamento nennen, aber es geschieht abrupt.)
Volume habe ich nur mit 3 Bit angesetzt, ungepackt und ohne Bitgefrickel könnte man also ein Track-
Event in einem WORD verpacken, und davon haben wir 8*128, also 2048 Byte.
Damit wären wir schon mit 10 Patterns bei besagten 20 KB, und mehr als 31 Patterns wären nicht
möglich, weil ich keine Lust darauf habe, jedes Pattern einzeln per Pointer zu addressieren.
Was aber gerade für Spiele schön wäre, wenn da Musik drin wäre die sich nicht jede Minute
wiederholt sondern etwas länger läuft. Und was die Samples angeht, man kann auch mit z.B. 64K
schon viel anstellen, ich hab da 22 Jahre Erfahrung, das geht schon, gerade wenn es bei Spielen
nicht so super High-Endig klingen muss. Wenn ich Schleifen hinkriege im Player, dann kann
ich sogar einfach nur simple Wellenformen benutzen so dass wirklich fast nur die Patterndaten
etwas ausmachen.
Klar kann man jetzt sagen, dann pack die Patterns doch einfach ein wenig simpler...
Aber ich finde, wenn ichs mache, und wenn es mich fasziniert, dann mach ich es direkt ausführlich.
So viel Programm-Overhead sind die paar Tabellchen und die Bitlese-Routine nicht.
Vielleicht nehm ich dieses "Repeat" noch raus, da muss ich abwägen wie viel es einspart und
auf der anderen Seite aber auch nur aufbläht für alle Events die sich nicht wiederholen.
Ja, ich hatte das auch schonmal gesagt: Ich brauche einen Tracker so redundant wie er ist, weil ich
mir beim Trackern in dem Moment wo ichs reinprogrammiere etwas ausdenke und es im wirklichen
Rhythmus reinprogrammiere, indem ich entsprechende Tasten auf dem Keyboard (Tastatur) drücke.
Den Umweg über die ganze Sache erstmal in Noten aufschreiben und diese dann ins Programm
eingeben mache ich nicht, und wenn das so sein müsste hätte ich kaum Musik gemacht in den
letzten 22 Jahren.
Es gibt ein Format TFMX, das arbeitet auch mit Makros.
Und es wird mir gerade hier bei dem Versuch, Patterns zu komprimieren, klar, dass man für
eine optimale Speichernutzung eigentlich auch nur in einer Art Programmiersprache vorgehen
kann. Aber für den Workflow, das spontane Eingeben von Melodien und Rhythmen die einem
gerade so einfallen, sind Patterns mit tausend Nullen einfach praktischer.
Umsomehr habe ich, wie man ja merkt, das Bedürfnis, aus diesem "Schwamm" die meiste
Luft rauszulassen. Und das ist mir ein paar Tabellen und bitweises Lesen wert.
Ich hatte vor ein paar Jahren, ja so lang ists schon her, bereits einen Encoder und Decoder
fertig, der sehr ähnlich war. Aber was mir jetzt eingefallen ist dürfte deutlich effektiver sein.
Und klar, warum soll man nicht zwei Programme haben, wenn die Interfaces sich letztlich sowieso
nicht in beide Richtungen austauschen könnten.
PS: Ich empfinde es schon als starke Vereinfachung welche Methode mit jetzt eingefallen ist.
Hast du das gelesen was ich vor ein paar Monaten schrieb? Mit Tabellen, die sich zur Laufzeit
erst bilden usw? DAS wäre übertrieben gewesen...
Wir haben pro Pattern
- 8 Kanäle
- 128 Zeilen
Ein Track-Event besteht aus:
Samplenummer, Note, Volume (Effekte in dem Sinn habe ich nicht, lediglich werde ich Notenwerte > 128
vom Player als die gleichen -128 abspielen lassen, aber ohne Neuanschlagen des Samples, also in den
neuen Notenwert hineingleitend - man könnte es auch Portamento nennen, aber es geschieht abrupt.)
Volume habe ich nur mit 3 Bit angesetzt, ungepackt und ohne Bitgefrickel könnte man also ein Track-
Event in einem WORD verpacken, und davon haben wir 8*128, also 2048 Byte.
Damit wären wir schon mit 10 Patterns bei besagten 20 KB, und mehr als 31 Patterns wären nicht
möglich, weil ich keine Lust darauf habe, jedes Pattern einzeln per Pointer zu addressieren.
Was aber gerade für Spiele schön wäre, wenn da Musik drin wäre die sich nicht jede Minute
wiederholt sondern etwas länger läuft. Und was die Samples angeht, man kann auch mit z.B. 64K
schon viel anstellen, ich hab da 22 Jahre Erfahrung, das geht schon, gerade wenn es bei Spielen
nicht so super High-Endig klingen muss. Wenn ich Schleifen hinkriege im Player, dann kann
ich sogar einfach nur simple Wellenformen benutzen so dass wirklich fast nur die Patterndaten
etwas ausmachen.
Klar kann man jetzt sagen, dann pack die Patterns doch einfach ein wenig simpler...
Aber ich finde, wenn ichs mache, und wenn es mich fasziniert, dann mach ich es direkt ausführlich.
So viel Programm-Overhead sind die paar Tabellchen und die Bitlese-Routine nicht.
Vielleicht nehm ich dieses "Repeat" noch raus, da muss ich abwägen wie viel es einspart und
auf der anderen Seite aber auch nur aufbläht für alle Events die sich nicht wiederholen.
Ja, ich hatte das auch schonmal gesagt: Ich brauche einen Tracker so redundant wie er ist, weil ich
mir beim Trackern in dem Moment wo ichs reinprogrammiere etwas ausdenke und es im wirklichen
Rhythmus reinprogrammiere, indem ich entsprechende Tasten auf dem Keyboard (Tastatur) drücke.
Den Umweg über die ganze Sache erstmal in Noten aufschreiben und diese dann ins Programm
eingeben mache ich nicht, und wenn das so sein müsste hätte ich kaum Musik gemacht in den
letzten 22 Jahren.
Es gibt ein Format TFMX, das arbeitet auch mit Makros.
Und es wird mir gerade hier bei dem Versuch, Patterns zu komprimieren, klar, dass man für
eine optimale Speichernutzung eigentlich auch nur in einer Art Programmiersprache vorgehen
kann. Aber für den Workflow, das spontane Eingeben von Melodien und Rhythmen die einem
gerade so einfallen, sind Patterns mit tausend Nullen einfach praktischer.
Umsomehr habe ich, wie man ja merkt, das Bedürfnis, aus diesem "Schwamm" die meiste
Luft rauszulassen. Und das ist mir ein paar Tabellen und bitweises Lesen wert.
Ich hatte vor ein paar Jahren, ja so lang ists schon her, bereits einen Encoder und Decoder
fertig, der sehr ähnlich war. Aber was mir jetzt eingefallen ist dürfte deutlich effektiver sein.
Und klar, warum soll man nicht zwei Programme haben, wenn die Interfaces sich letztlich sowieso
nicht in beide Richtungen austauschen könnten.
PS: Ich empfinde es schon als starke Vereinfachung welche Methode mit jetzt eingefallen ist.
Hast du das gelesen was ich vor ein paar Monaten schrieb? Mit Tabellen, die sich zur Laufzeit
erst bilden usw? DAS wäre übertrieben gewesen...
Zuletzt geändert von zatzen am Mi 2. Mär 2016, 23:45, insgesamt 1-mal geändert.
mov ax, 13h
int 10h
while vorne_frei do vor;
int 10h
while vorne_frei do vor;
Re: Trackermodul-Engine (sehr einfach)
Update:
"Repeat" kommt raus.
Angenommen man hätte eine Bassdrum und die spielt auf einem Kanal alleine und wird insgesamt
nur auf einer Note gespielt und auf einer Lautstärke. Die würde dann genau 0 Bit brauchen. Mit
Repeat davor aber 1 Bit, mit gleichem Effekt. Zudem verbraucht "Repeat" ohne Wirkung Speicher
bei allem was sich nicht wiederholt.
Und die Leseroutine wie auch der Encoder gestalten sich eine Kleinigkeit einfacher ohne dieses Feature.
"Repeat" kommt raus.
Angenommen man hätte eine Bassdrum und die spielt auf einem Kanal alleine und wird insgesamt
nur auf einer Note gespielt und auf einer Lautstärke. Die würde dann genau 0 Bit brauchen. Mit
Repeat davor aber 1 Bit, mit gleichem Effekt. Zudem verbraucht "Repeat" ohne Wirkung Speicher
bei allem was sich nicht wiederholt.
Und die Leseroutine wie auch der Encoder gestalten sich eine Kleinigkeit einfacher ohne dieses Feature.
mov ax, 13h
int 10h
while vorne_frei do vor;
int 10h
while vorne_frei do vor;
Re: Trackermodul-Engine (sehr einfach)
Naja, in MOD haben Patterns ja nicht immer 128 Zeilen, sondern sind da variabel, je nachdem, wie lang die kürzestmögliche Note sein soll (bzw wie lang eine Punktierung wäre, bei 3/4 oder 6/8 Takt oder so).
Es gibt nur sehr wenige Musikstücke, die 1/128 Noten haben (weil sie auf realen Instrumenten quasi unspielbar sind).
Das Feature vorzusehen ist gut, es zum generellen Standard machen... - KANN man, MUß man aber nicht.
Aber zwischen Deiner Trackermodulengine (hat die schon einen Namen?) und meinem ISM bestehen sowieso gewaltige Unterschiede, das kann man überhaupt nicht vergleichen, weil bei beiden schon der ganze Ansatz komplett unterschiedlich ist.
Im Unterschied zu Dir fällt mir das mit den Notenwerten und Längen leichter - ich kann kein Instrument spielen und ich hätte auch ziemliche Schwierigkeiten, so wie Du auf der PC Tastatur (quasi als "Klavier-Ersatz") ein Musikstück einzuspielen.
Das liegt bei mir aber wohl daran, daß ich nicht musikalisch bin und quasi ALLES, was ich mache, irgendwie von der mathematischen Seite her betrachte: Grafik, Musik, Klangeffekte, interne Steuerung, Speicherung, Ein-/Ausgabe usw. Für die programmiererischen Anteile an so Projekten ist das sicher ein Vorteil, bei der "künstlerischen" Seite (z.B. Grafik, Musik) versuche ich nur, gewisse Gesetzmäßigkeiten einzuhalten, damit es nicht dämlich aussieht oder blöd klingt.
Ein wahrer Künstler würde von meinem Zeug wohl sagen: Nichts von dem hat irgendwie "Seele". Vielleicht sollte ich eigentlich mal ein Roboter werden oder sowas.
Es gibt nur sehr wenige Musikstücke, die 1/128 Noten haben (weil sie auf realen Instrumenten quasi unspielbar sind).
Das Feature vorzusehen ist gut, es zum generellen Standard machen... - KANN man, MUß man aber nicht.
Aber zwischen Deiner Trackermodulengine (hat die schon einen Namen?) und meinem ISM bestehen sowieso gewaltige Unterschiede, das kann man überhaupt nicht vergleichen, weil bei beiden schon der ganze Ansatz komplett unterschiedlich ist.
Im Unterschied zu Dir fällt mir das mit den Notenwerten und Längen leichter - ich kann kein Instrument spielen und ich hätte auch ziemliche Schwierigkeiten, so wie Du auf der PC Tastatur (quasi als "Klavier-Ersatz") ein Musikstück einzuspielen.
Das liegt bei mir aber wohl daran, daß ich nicht musikalisch bin und quasi ALLES, was ich mache, irgendwie von der mathematischen Seite her betrachte: Grafik, Musik, Klangeffekte, interne Steuerung, Speicherung, Ein-/Ausgabe usw. Für die programmiererischen Anteile an so Projekten ist das sicher ein Vorteil, bei der "künstlerischen" Seite (z.B. Grafik, Musik) versuche ich nur, gewisse Gesetzmäßigkeiten einzuhalten, damit es nicht dämlich aussieht oder blöd klingt.
Ein wahrer Künstler würde von meinem Zeug wohl sagen: Nichts von dem hat irgendwie "Seele". Vielleicht sollte ich eigentlich mal ein Roboter werden oder sowas.
Re: Trackermodul-Engine (sehr einfach)
DIe klassischen MOD-Patterns haben immer genau 64 Zeilen, länger gibts nicht, und für kürzere muss man den
Befehl "Pattern Break" setzen, dann wird das Pattern dort abgebrochen, aber dennoch alle 1024 Byte gespeichert.
Nebenbei, ganz interessant, ist mir gestern ein .AMF untergekommen mit sagenhaften 122 Patterns (Level-
Musik vom Spiel "Aladdin"), und obwohl AMF scheinbar die gleiche Effektpalette wie MOD hat, braucht dort
ein Pattern offenbar nur 512 Byte.
Ich kann bei meinen Patterns natürlich auch nur 64 Zeilen oder beliebige andere Längen wählen.
Für 3/4tel Takt dann nämlich z.B. 96 oder 48 Zeilen.
Die meisten MODs haben ein Tickspeed von 6, das ergibt 125 BPM, eine Viertelnote entspricht dann 4 Zeilen.
Damit kann man dann als kleinstes 16tel-Noten umsetzen. Es gibt dann noch den Befehl "Retrigger", mit dem
man ein Sample auf einer Zeile mehrfach anschlagen kann, womit man auch bei einem Tickspeed von 6 dann
32tel-Noten oder 64tel usw. realisieren kann, aber nur auf der gleichen Tonhöhe, also vornehmlich für
Schlagzeug geeignet.
Ich habe mich einfach über die Jahre daran gewöhnt, Patterns "doppelte" Geschwindigkeit zu geben, also
8 Zeilen pro Viertelnote, so dass ich 32tel-Noten ohne Effekt umsetzen kann. 64tel Noten habe ich bisher
nie gebraucht.
Weil ich bisher selten für Spiele Musik gemacht habe, sondern einfach nur zum Anhören, habe ich mich nicht
sonderlich um die effiziente Speichernutzung in den Patterns gekümmert. Wenn ich aber jetzt für mein
eigenes Format Musik programmiere, gehe ich vielleicht wieder auf 64 Zeilen und "halbe" Geschwindigkeit
zurück, wenn ich keine 32tel brauche. Wobei Leerzeilen in meinem Format auch nicht so viel kosten werden.
Das Format soll "Zatzen Simple Tracker Modul", kurz "ZSTM" bzw. die Erweiterung ".ZSM" heissen.
Simple nicht unbedingt wegen der Weise die Patterns zu speichern, sondern vielmehr wegen
der minimalistischen Codierung der Notenbefehle (Effekte: Nur Volume und Notenwechsel ohne
Neustart), und wegen der geringen Anforderungen für den Player, keine Lautstärketabelle und,
nicht wie bei richtigen MODs, keine 50Hz Rasterung von Pitch und allem, sondern immer nur
Änderungen je Zeile. Und nur feste Notenwerte, kein Finetune. Die Samples müssen so vorbereitet
werden, dass sie von der Stimmung her passen. Zudem eine Festlegung auf 16000 Hz Mixfrequenz.
Das mag jetzt einen Aufschrei geben, aber das erleichtert die Programmierung des Players, und
16kHz ist qualitativ in Ordnung, Menschen über 50 Jahre bekommen schon Schwierigkeiten, überhaupt
mehr Höhen (> 8 kHz) zu hören.
Ich kann auch nicht richtig ein Instrument spielen.
Wenn ich einen Track in den Tracker eingebe und es sei mal eine Melodie dann mach ich das so...
Die Taste "entf(ernen") dient mir als 16tel Pause, Tasten wie Y X C V B N M als Tasten der Tonleiter.
Auf diese weise gebe ich eine Melodie ein, wobei das ganze monophon ist und ich die Geschwindigkeit
völlig selbst bestimmen kann. Je nach eingestelltem Quantize habe ich 16tel Noten/Pausen oder 8tel,
Viertel usw... Oft verspiele ich mich, dann wird einfach mit den Pfeiltasten zurückgegangen.
Wie auch immer, bei meinem eigenen Format hätte ich schon einfach Spass daran mir einen Log
anzusehen, wo drin steht wie groß bzw. klein jedes einzelne Pattern geworden ist.
Und ich habe mich hiermit entschieden, etwas zu machen wo ich den XMS nicht nutze.
Zugunsten der Geschwindigkeit lege ich die Samples nicht im XMS ab. Würde ich das tun, hätte ich
dann etwas anderes vor, nämlich sehr lange Samples, die in sich schon Teile eines kompletten
Musikstücks sind und einfach nur ohne Pitching zusammenaddiert werden.
Befehl "Pattern Break" setzen, dann wird das Pattern dort abgebrochen, aber dennoch alle 1024 Byte gespeichert.
Nebenbei, ganz interessant, ist mir gestern ein .AMF untergekommen mit sagenhaften 122 Patterns (Level-
Musik vom Spiel "Aladdin"), und obwohl AMF scheinbar die gleiche Effektpalette wie MOD hat, braucht dort
ein Pattern offenbar nur 512 Byte.
Ich kann bei meinen Patterns natürlich auch nur 64 Zeilen oder beliebige andere Längen wählen.
Für 3/4tel Takt dann nämlich z.B. 96 oder 48 Zeilen.
Die meisten MODs haben ein Tickspeed von 6, das ergibt 125 BPM, eine Viertelnote entspricht dann 4 Zeilen.
Damit kann man dann als kleinstes 16tel-Noten umsetzen. Es gibt dann noch den Befehl "Retrigger", mit dem
man ein Sample auf einer Zeile mehrfach anschlagen kann, womit man auch bei einem Tickspeed von 6 dann
32tel-Noten oder 64tel usw. realisieren kann, aber nur auf der gleichen Tonhöhe, also vornehmlich für
Schlagzeug geeignet.
Ich habe mich einfach über die Jahre daran gewöhnt, Patterns "doppelte" Geschwindigkeit zu geben, also
8 Zeilen pro Viertelnote, so dass ich 32tel-Noten ohne Effekt umsetzen kann. 64tel Noten habe ich bisher
nie gebraucht.
Weil ich bisher selten für Spiele Musik gemacht habe, sondern einfach nur zum Anhören, habe ich mich nicht
sonderlich um die effiziente Speichernutzung in den Patterns gekümmert. Wenn ich aber jetzt für mein
eigenes Format Musik programmiere, gehe ich vielleicht wieder auf 64 Zeilen und "halbe" Geschwindigkeit
zurück, wenn ich keine 32tel brauche. Wobei Leerzeilen in meinem Format auch nicht so viel kosten werden.
Das Format soll "Zatzen Simple Tracker Modul", kurz "ZSTM" bzw. die Erweiterung ".ZSM" heissen.
Simple nicht unbedingt wegen der Weise die Patterns zu speichern, sondern vielmehr wegen
der minimalistischen Codierung der Notenbefehle (Effekte: Nur Volume und Notenwechsel ohne
Neustart), und wegen der geringen Anforderungen für den Player, keine Lautstärketabelle und,
nicht wie bei richtigen MODs, keine 50Hz Rasterung von Pitch und allem, sondern immer nur
Änderungen je Zeile. Und nur feste Notenwerte, kein Finetune. Die Samples müssen so vorbereitet
werden, dass sie von der Stimmung her passen. Zudem eine Festlegung auf 16000 Hz Mixfrequenz.
Das mag jetzt einen Aufschrei geben, aber das erleichtert die Programmierung des Players, und
16kHz ist qualitativ in Ordnung, Menschen über 50 Jahre bekommen schon Schwierigkeiten, überhaupt
mehr Höhen (> 8 kHz) zu hören.
Ich kann auch nicht richtig ein Instrument spielen.
Wenn ich einen Track in den Tracker eingebe und es sei mal eine Melodie dann mach ich das so...
Die Taste "entf(ernen") dient mir als 16tel Pause, Tasten wie Y X C V B N M als Tasten der Tonleiter.
Auf diese weise gebe ich eine Melodie ein, wobei das ganze monophon ist und ich die Geschwindigkeit
völlig selbst bestimmen kann. Je nach eingestelltem Quantize habe ich 16tel Noten/Pausen oder 8tel,
Viertel usw... Oft verspiele ich mich, dann wird einfach mit den Pfeiltasten zurückgegangen.
Wie auch immer, bei meinem eigenen Format hätte ich schon einfach Spass daran mir einen Log
anzusehen, wo drin steht wie groß bzw. klein jedes einzelne Pattern geworden ist.
Und ich habe mich hiermit entschieden, etwas zu machen wo ich den XMS nicht nutze.
Zugunsten der Geschwindigkeit lege ich die Samples nicht im XMS ab. Würde ich das tun, hätte ich
dann etwas anderes vor, nämlich sehr lange Samples, die in sich schon Teile eines kompletten
Musikstücks sind und einfach nur ohne Pitching zusammenaddiert werden.
mov ax, 13h
int 10h
while vorne_frei do vor;
int 10h
while vorne_frei do vor;
Re: Trackermodul-Engine (sehr einfach)
Übrigens, nochmal zur Klarstellung... Ich schreibe, zumindest vorerst, keinen speziellen Tracker für dieses Format.
Ich nutze fürs Erstellen der Musik meinen bisherigen Tracker. Der kann natürlich viel mehr Effekte usw., aber da
muss ich eben sehen dass ich innerhalb dieser Einschränkungen bleibe.
Der Converter müsste nur zum Zwecke einer automatischen Sample-Ende-Beschneidung das ganze Stück einmal
durchsimulieren. Der Sinn dahinter ist der, dass sichergestellt ist, dass von jedem Sample auch nur so viel
gespeichert wird, wie tatsächlich abgespielt wird.
Ich nutze fürs Erstellen der Musik meinen bisherigen Tracker. Der kann natürlich viel mehr Effekte usw., aber da
muss ich eben sehen dass ich innerhalb dieser Einschränkungen bleibe.
Der Converter müsste nur zum Zwecke einer automatischen Sample-Ende-Beschneidung das ganze Stück einmal
durchsimulieren. Der Sinn dahinter ist der, dass sichergestellt ist, dass von jedem Sample auch nur so viel
gespeichert wird, wie tatsächlich abgespielt wird.
mov ax, 13h
int 10h
while vorne_frei do vor;
int 10h
while vorne_frei do vor;
Re: Trackermodul-Engine (sehr einfach)
Ja, ich hab davon gelesen. Also die Speicherung von MODs fand ich immer schon etwas abenteuerlich, mit den vielen Leerräumen und so. Wer kommt bloß auf sowas? Sowas wäre mir nie eingefallen. Das Gen für sinnlose Speicherverschwendung scheint bei mir irgendwie zu fehlen...zatzen hat geschrieben:DIe klassischen MOD-Patterns haben immer genau 64 Zeilen, länger gibts nicht, und für kürzere muss man den Befehl "Pattern Break" setzen, dann wird das Pattern dort abgebrochen, aber dennoch alle 1024 Byte gespeichert.
Ich kenne die Specs der Formate nicht, nehme aber an, daß er vielleicht weniger "breite" Parameter (also weniger Bits) genutzt hat oder vielleicht wird mit Verweisen gearbeitet - ODER ein Pattern hat vielleicht nur je 32 Zeilen...zatzen hat geschrieben:Nebenbei, ganz interessant, ist mir gestern ein .AMF untergekommen mit sagenhaften 122 Patterns (Level-
Musik vom Spiel "Aladdin"), und obwohl AMF scheinbar die gleiche Effektpalette wie MOD hat, braucht dort
ein Pattern offenbar nur 512 Byte.
Naja, da es bei mir keine Patterns gibt, ist bei mir die Länge beliebig. Ich habe es so eingestellt, daß man pro Fenster 512 "Befehle" gleichzeitig sehen kann - aber da, wie bereits erklärt, das Ganze nur ein "Ausschnitt" aus dem gesamten mögichen "Musikdatenblock" ist, ist man nicht an diese Größe gebunden. Es dient eher dazu, die Stimmen "nebeneinanderlegen" zu können, um zu sehen, was da passiert.zatzen hat geschrieben:Ich kann bei meinen Patterns natürlich auch nur 64 Zeilen oder beliebige andere Längen wählen.
Für 3/4tel Takt dann nämlich z.B. 96 oder 48 Zeilen.
Ja, ich weiß, die arbeiten da mit auswählbaren festen Werten - das liegt daran, daß das Ganze mal für Amiga entwickelt und an dessen Soundchip angepaßt wurde.zatzen hat geschrieben:Die meisten MODs haben ein Tickspeed von 6, das ergibt 125 BPM, eine Viertelnote entspricht dann 4 Zeilen.
Damit kann man dann als kleinstes 16tel-Noten umsetzen. Es gibt dann noch den Befehl "Retrigger", mit dem
man ein Sample auf einer Zeile mehrfach anschlagen kann, womit man auch bei einem Tickspeed von 6 dann
32tel-Noten oder 64tel usw. realisieren kann, aber nur auf der gleichen Tonhöhe, also vornehmlich für
Schlagzeug geeignet.
Bei mir ist die kleinstmögliche Note 1/128. Aber ich kann auch dasselbe Stück Musik in unterschiedlichen Geschwindigkeiten abspielen, weil ich zusätzlich zu den Tönen, die Längenwerte von 0-511 haben können, auch noch einen Speedwert von 1-255 angeben kann. Bei Speed 1 sind also Notenlängen von 1/128 Sekunde bis knapp 4 Sekunden möglich. Bei Speed 255 sind es dann 1018 Sekunden (knapp 17 Minuten). Man könnte also ein knapp 17 Minuten langes WAV-Sample nehmen, eine Note mit Speed 255 und Länge 511 und dann abspielen. (Nur reicht der Platz nicht für 17minütige Samples.)zatzen hat geschrieben:Ich habe mich einfach über die Jahre daran gewöhnt, Patterns "doppelte" Geschwindigkeit zu geben, also
8 Zeilen pro Viertelnote, so dass ich 32tel-Noten ohne Effekt umsetzen kann. 64tel Noten habe ich bisher
nie gebraucht.
Und selbst wenn die Länge nicht reicht - es gibt ja den "HOLD" Befehl - der spielt die letzte Note/Sample da weiter, wo es aufgehört hat. Eigentlich dient er dazu, den Ton mittendrin zu verändern, d.h.: anspielen, Änderung, mit Hold weiterspielen. So können alle Effekte, die ISM nicht nativ eingebaut hat, quasi manuell nachgebaut werden.
Ja, durch Deine Art zu Packen, die etwas Ähnlichkeit mit dem DDMF und auch mit dem Van-Jacobsen-TCP/IP-Header-Compression (Packverfahren für Internetpakete über serielle Schnittstelle) hat, wird ja der "Nullenwahnsinn" von MODs recht eingeschränkt.zatzen hat geschrieben:Weil ich bisher selten für Spiele Musik gemacht habe, sondern einfach nur zum Anhören, habe ich mich nicht sonderlich um die effiziente Speichernutzung in den Patterns gekümmert. Wenn ich aber jetzt für mein
eigenes Format Musik programmiere, gehe ich vielleicht wieder auf 64 Zeilen und "halbe" Geschwindigkeit
zurück, wenn ich keine 32tel brauche. Wobei Leerzeilen in meinem Format auch nicht so viel kosten werden.
Finetune nutze ich gar nicht, ich auch überhaupt nicht vorgesehen bei mir. Aber ich habe ja ein Zusatztool gebaut, um Samples (WAVs) nicht nur in mein Sampleformat zu bringen, sondern auch, um ihm die richtige "Grundfrequenz" zuzuweisen (also die Frequenz, die man hört, wenn man das Sample abspielt). Diese kann ein Wert zwischen 16,0 Hz bis 4111,9375 Hz sein, mit Schrittweite 0,0625 Hz. Ich denke, das ist genau genug. Und Samples mit über 4 kHz sind aua...zatzen hat geschrieben:Das Format soll "Zatzen Simple Tracker Modul", kurz "ZSTM" bzw. die Erweiterung ".ZSM" heissen.
Simple nicht unbedingt wegen der Weise die Patterns zu speichern, sondern vielmehr wegen
der minimalistischen Codierung der Notenbefehle (Effekte: Nur Volume und Notenwechsel ohne
Neustart), und wegen der geringen Anforderungen für den Player, keine Lautstärketabelle und,
nicht wie bei richtigen MODs, keine 50Hz Rasterung von Pitch und allem, sondern immer nur
Änderungen je Zeile. Und nur feste Notenwerte, kein Finetune.
Die Mixfrequenz ist bei mir beliebig. Ich habe noch nicht ausprobiert, was das Ding maximal abkann, bevor es irgendwelche internen Überläufe kriegt. Die Frequenzen sind aber in Schrittweiten von 128. D.h. 14000 Hz werden als 13952 Hz generiert. (Das dient dazu, daß keine Abspiellängen mit Nachkommastellen auftreten und die Stimmensynchronität dadurch eventuell "aus dem Takt" kommt. Dieses Problem hatte ich anfangs. Fiel auf, wenn das Stück mehrmals in Schleife abgespielt wurde, daß die Stimmen anfingen, etwas unsynchron zueinander zu werden. Mit dem Frequenzfix habe ich das gefixt.)zatzen hat geschrieben: Die Samples müssen so vorbereitet werden, dass sie von der Stimmung her passen.
Zudem eine Festlegung auf 16000 Hz Mixfrequenz.
Wo denn? Ich hör nix...zatzen hat geschrieben:Das mag jetzt einen Aufschrei geben,
Mir reichen sogar auch 14 oder 12 Khz...
Ja, und wenn mein oder Dein Spiel mal irgendwann fertig wird, gibt es sowieso keine Menschen UNTER 50 Jahre mehr, die sich noch für DOS-Spiele interessieren...zatzen hat geschrieben:aber das erleichtert die Programmierung des Players, und
16kHz ist qualitativ in Ordnung, Menschen über 50 Jahre bekommen schon Schwierigkeiten, überhaupt
mehr Höhen (> 8 kHz) zu hören.
Ja, und dann noch die "schwarzen Tasten" schräg drüber. Hattest das ja mal erwähnt. Ich kann sowas einfach nicht.zatzen hat geschrieben:Ich kann auch nicht richtig ein Instrument spielen.
Wenn ich einen Track in den Tracker eingebe und es sei mal eine Melodie dann mach ich das so...
Die Taste "entf(ernen") dient mir als 16tel Pause, Tasten wie Y X C V B N M als Tasten der Tonleiter.
Ich hatte schonmal 'ne Idee, die ich vielleicht sogar mal umsetze:zatzen hat geschrieben:Auf diese weise gebe ich eine Melodie ein, wobei das ganze monophon ist und ich die Geschwindigkeit
völlig selbst bestimmen kann. Je nach eingestelltem Quantize habe ich 16tel Noten/Pausen oder 8tel,
Viertel usw... Oft verspiele ich mich, dann wird einfach mit den Pfeiltasten zurückgegangen.
Und zwar, daß man die Melodie dem Ding vorpfeifen kann. Und dann nur noch nacheditieren. So hat man schon die Längen und die Tonhöhen. (Man kann da ja so einen "Fixer" einstellen, der die Längen auf 8tel oder 16tel Noten fixt und die Frequenzen nur auf solche, die in der Notenleiter vorkommen - also entsprechend rundet.)
Ich habe sowas damals aufm C64 gemacht und erstaunlich gute Ergebnisse erzielt, dafür, daß der nur 1 MHz hat und die Samplefrequenz (Aufnahme) nur so ca 3kHz war oder so.
Erklärbar ist das glaube ich dadurch, daß Pfeifen fast reine Sinuswellen erzeugt, so daß man da relativ gut "die Wellen zählen" kann.
Ja, es ist immer schön, am Ende auch mal den Erfolg der ganzen Mühe zu sehen - vor allem, wenn die Programmierarbeit ein totaler Sumpf von Packen/Entpacken/Bitschieberei war, der erst getestet werden kann, wenn er fertig programmiert ist.zatzen hat geschrieben:Wie auch immer, bei meinem eigenen Format hätte ich schon einfach Spass daran mir einen Log
anzusehen, wo drin steht wie groß bzw. klein jedes einzelne Pattern geworden ist.
Naja, Gerade im Entwicklungsprozeß passiert es oft, daß man viele Dinge immer mal wieder umentscheidet...zatzen hat geschrieben:Und ich habe mich hiermit entschieden, etwas zu machen wo ich den XMS nicht nutze.
[/quote]zatzen hat geschrieben:Zugunsten der Geschwindigkeit lege ich die Samples nicht im XMS ab. Würde ich das tun, hätte ich
dann etwas anderes vor, nämlich sehr lange Samples, die in sich schon Teile eines kompletten
Musikstücks sind und einfach nur ohne Pitching zusammenaddiert werden.
Naja, zugunsten der Geschwindigkeit ist es vielleicht gut - aber wenn es ein Spiel werden soll, muß man immer noch beachten, daß auch Grafikdaten ein wahrer Speicherfresser sind... Die wollen auch alle in Speicherbereiche, auf die die CPU (und Grafikkarte) direkten Zugriff hat...
Das heißt, daß Du eher planst, einen Konverter/Packer für Dein Format zu schreiber, der die Ausgaben des Trackers in Dein Format wandelt. Aber Du brauchst natürlich immer noch einen Player für Dein Format.zatzen hat geschrieben:Übrigens, nochmal zur Klarstellung... Ich schreibe, zumindest vorerst, keinen speziellen Tracker für dieses Format.
Ich nutze fürs Erstellen der Musik meinen bisherigen Tracker. Der kann natürlich viel mehr Effekte usw., aber da
muss ich eben sehen dass ich innerhalb dieser Einschränkungen bleibe.
Der Converter müsste nur zum Zwecke einer automatischen Sample-Ende-Beschneidung das ganze Stück einmal
durchsimulieren. Der Sinn dahinter ist der, dass sichergestellt ist, dass von jedem Sample auch nur so viel
gespeichert wird, wie tatsächlich abgespielt wird.
OK, erstmal genug dazu.
Re: Trackermodul-Engine (sehr einfach)
MOD kommt ja vom Amiga, vielleicht liegts daran dass man lieber einfach mal so "flapps" ein Pattern
unkomprimiert in den Speicher lädt. Die machen ja, wenn man recht großzügige Samples nimmt, doch
eher den kleineren Teil aus. Aber auch Terminator II vom Amiga hat zwischendrin kurze Videosequenzen
die unkomprimiert sind. Da braucht dann eine Sekunde direkt 500KB oder so, obwohl die Auflösung da
nur ca. 160x100 war.
Ich habe jenes AMF im OpenMPT (Tracker) reingeladen, sind 64 Zeilen Patterns...
Eine Formatbeschreibung wäre mal interessant, habe ich aber auf die Schnelle nicht im Netz gefunden.
Am Amiga waren die MODs mit 50 Hz, also der PAL Bildfrequenz getaktet, manche Player
haben aber auch einen Schalter auf NTSC mit seinen 60 Hz.
Das Tickspeed gibt an, wieviele Bilder vergehen, bis die nächste Zeile kommt.
Auf dem Amiga waren also Bild und Ton untrennbar miteinander verheiratet, und die Nichtvariablität
war ja auch kein Problem weil alle Amigas das gleiche leisteten.
Oh, DDMF, das ist ja das Format des X-Trackers, der Tracker den ich heute noch benutze und von
dem ich konvertieren möchte. Daher kenne ich das Format sehr gut und die Patterns sind gespeichert
mit Lauflängen per Track, um die Nullen zu beseitigen, und mit Flaggen der Effekte.
Das komprimiert schonmal ganz nett, aber mein Vorgehen wird schon alleine wegen dem Lesen
in beliebiger und angepasster Bitbreite effizienter sein.
Erstaunliche Sache, mit dem Vorpfeifen. Es ist nur so, dass ich auch Samples verwende, die direkt
einen ganzen Akkord enthalten oder generell etwas das man nicht einfach einer Note zuordnen kann.
XMS: Da käme ja wieder das Argument rein, dass Patterns UND Samples klein sein sollen, meinetwegen
80KB für ein ganzes Spiel, für die Intro Musik, Level Musik etc. Klar könnte man auch einen Synthesizer
nehmen, im einfachsten Fall OPL3 also AdLib, aber irgendwie haben für mich Samples mehr Reiz, sie
klingen zwar wenn man Speicher spart etwas schäbig und sind vielleicht sehr kurz, aber man hat immer
noch einen ganz individuellen Sound, während AdLib Musik irgendwie die meisten Spiele erscheinen
lässt, als wären sie vom gleichen Entwickler.
Aber sehen wir es doch mal so: Wenn ich jetzt einen Adlib Tracker hätte und mir ein Pattern-Speicherformat
ausdenken würde... Dann hätte man gar keine Sampledaten. Wäre es dann nicht frevelhaft, nicht zu
versuchen, die Musik-Instruktionen so klein wie möglich zu halten?
Genau, das ganze wird nur ein Converter. Ein Tracker wäre zwar schön, aber ist im diesen Fall nicht erforderlich
und würde nur unnötig Aufwand kosten. Ausser mir wird wohl kaum jemand dieses Format nutzen, und wenn,
dann kann ich für's MOD oder IT oder XM Format einen Converter machen.
Der Player wird wohl in provisorischer Instanz erstmal nur die Patterns decodiert als Textdatei ausgeben.
unkomprimiert in den Speicher lädt. Die machen ja, wenn man recht großzügige Samples nimmt, doch
eher den kleineren Teil aus. Aber auch Terminator II vom Amiga hat zwischendrin kurze Videosequenzen
die unkomprimiert sind. Da braucht dann eine Sekunde direkt 500KB oder so, obwohl die Auflösung da
nur ca. 160x100 war.
Ich habe jenes AMF im OpenMPT (Tracker) reingeladen, sind 64 Zeilen Patterns...
Eine Formatbeschreibung wäre mal interessant, habe ich aber auf die Schnelle nicht im Netz gefunden.
Am Amiga waren die MODs mit 50 Hz, also der PAL Bildfrequenz getaktet, manche Player
haben aber auch einen Schalter auf NTSC mit seinen 60 Hz.
Das Tickspeed gibt an, wieviele Bilder vergehen, bis die nächste Zeile kommt.
Auf dem Amiga waren also Bild und Ton untrennbar miteinander verheiratet, und die Nichtvariablität
war ja auch kein Problem weil alle Amigas das gleiche leisteten.
Oh, DDMF, das ist ja das Format des X-Trackers, der Tracker den ich heute noch benutze und von
dem ich konvertieren möchte. Daher kenne ich das Format sehr gut und die Patterns sind gespeichert
mit Lauflängen per Track, um die Nullen zu beseitigen, und mit Flaggen der Effekte.
Das komprimiert schonmal ganz nett, aber mein Vorgehen wird schon alleine wegen dem Lesen
in beliebiger und angepasster Bitbreite effizienter sein.
Erstaunliche Sache, mit dem Vorpfeifen. Es ist nur so, dass ich auch Samples verwende, die direkt
einen ganzen Akkord enthalten oder generell etwas das man nicht einfach einer Note zuordnen kann.
XMS: Da käme ja wieder das Argument rein, dass Patterns UND Samples klein sein sollen, meinetwegen
80KB für ein ganzes Spiel, für die Intro Musik, Level Musik etc. Klar könnte man auch einen Synthesizer
nehmen, im einfachsten Fall OPL3 also AdLib, aber irgendwie haben für mich Samples mehr Reiz, sie
klingen zwar wenn man Speicher spart etwas schäbig und sind vielleicht sehr kurz, aber man hat immer
noch einen ganz individuellen Sound, während AdLib Musik irgendwie die meisten Spiele erscheinen
lässt, als wären sie vom gleichen Entwickler.
Aber sehen wir es doch mal so: Wenn ich jetzt einen Adlib Tracker hätte und mir ein Pattern-Speicherformat
ausdenken würde... Dann hätte man gar keine Sampledaten. Wäre es dann nicht frevelhaft, nicht zu
versuchen, die Musik-Instruktionen so klein wie möglich zu halten?
Genau, das ganze wird nur ein Converter. Ein Tracker wäre zwar schön, aber ist im diesen Fall nicht erforderlich
und würde nur unnötig Aufwand kosten. Ausser mir wird wohl kaum jemand dieses Format nutzen, und wenn,
dann kann ich für's MOD oder IT oder XM Format einen Converter machen.
Der Player wird wohl in provisorischer Instanz erstmal nur die Patterns decodiert als Textdatei ausgeben.
mov ax, 13h
int 10h
while vorne_frei do vor;
int 10h
while vorne_frei do vor;
Re: Trackermodul-Engine (sehr einfach)
Update:
Ich setze die Samples doch mit variabler Grundfrequenz um. Stimmbarkeit ist doch eine wertvolle Sache.
Da ich ja zu jedem Sample eine Tabelle speichern möchte, in der steht auf welchen Tönen es ingesamt
gespielt wird, mache ich nun statt Notenwerten direkt die "Periods" dort hinein, wahrscheinlich mit
16 Bit Auflösung. Und diese sind nun pro Sample individuell. So spare ich mir auch eine allgemeine
Period-Tabelle für das ganze Spektrum an Noten, wenn die Notentabellen für ein Sample nicht auf
eine allgemeine Tabelle verweisen sondern selbst direkt die Werte enthalten.
Übrigens auch ein Grund, warum ich das ganze so klein halten möchte ist, dass wenn ich schon für
DOS programmiere, ich mir auch die Möglichkeit offen halten möchte, etwas vom Datenumfang her
insgesamt sehr kleines zu schaffen.
Man denke nur an die alten Zeiten wo man mehrere Spiele auf einer Diskette hatte und diese auch
von dort startete.
Mit solch klotzigen MODs wäre das schwierig, wenn allein die Patterns pro Minute etwa schon 10 KB
oder je nach Geschwindigkeit sogar 20 KB verschlingen.
MODs unter 10 KB sind sehr rar.
Aber man kann wirklich auch mit sehr kleinen Samples Musik erzeugen.
Bloß die Motivation dazu war bisher nicht gegeben mit so großen Patterndaten, und das will ich ändern.
Dann gibt es da aber noch etwas, das mir nicht gefällt. Ein Melodie-Sample kann z.B. 10 Notenwerte
haben, auf denen es insgesamt gespielt wird. Das bedeutet, es würde überall in den Patterns durch
4 Bit repräsentiert. Aber es kann durchaus sein, dass mal ein Pattern vorliegt, in dem dieses Sample
nur auf zwei verschiedenen Noten gespielt wird, und man bräuchte dann nur 1 Bit.
Wie ich schon sagte kann ich nicht für jedes Pattern und für jeden Track für alle vorkommenden Samples
die jeweiligen Notentabellen anlegen, das würde mehr aufblähen als komprimieren.
Aber ich könnte entweder durch nur 10 Bit in diesem Fall flaggen, welche Noten im Track für
dieses Instrument kommen werden, oder aber vielleicht durch eine Startposition und Endposition
in der Tabelle eingrenzen. Ersteres wäre aber effektiver.
Ich habe das mal mehr als Brainstorming aufgeschrieben, da es doch fast etwas verrückt wirkt.
Eine Frage aber mal:
Wie setze ich in einem Player Schleifen um?
Die einfachste Möglichkeit wäre, wenn man die Position im Sample als Variable nimmt, die dann beim
Mixen in ein Register wandert, welches man bei jedem Sampleschritt entsprechend der Periods hochzählt
und mit einem anderen Register, welches das Schleifenende beinhaltet, vergleicht.
Eine andere, schnellere Möglichkeit soll sein, vorher auszurechnen wieviel von der Schleife in den Puffer
passt und wenn die Schleife kürzer ist als der Puffer, dann erstmal nur nen Mix-Loop für diese Schleifen-
länge machen, dann weiter bis der Puffer voll ist usw... Stelle ich mir etwas kompliziert vor.
Ich setze die Samples doch mit variabler Grundfrequenz um. Stimmbarkeit ist doch eine wertvolle Sache.
Da ich ja zu jedem Sample eine Tabelle speichern möchte, in der steht auf welchen Tönen es ingesamt
gespielt wird, mache ich nun statt Notenwerten direkt die "Periods" dort hinein, wahrscheinlich mit
16 Bit Auflösung. Und diese sind nun pro Sample individuell. So spare ich mir auch eine allgemeine
Period-Tabelle für das ganze Spektrum an Noten, wenn die Notentabellen für ein Sample nicht auf
eine allgemeine Tabelle verweisen sondern selbst direkt die Werte enthalten.
Übrigens auch ein Grund, warum ich das ganze so klein halten möchte ist, dass wenn ich schon für
DOS programmiere, ich mir auch die Möglichkeit offen halten möchte, etwas vom Datenumfang her
insgesamt sehr kleines zu schaffen.
Man denke nur an die alten Zeiten wo man mehrere Spiele auf einer Diskette hatte und diese auch
von dort startete.
Mit solch klotzigen MODs wäre das schwierig, wenn allein die Patterns pro Minute etwa schon 10 KB
oder je nach Geschwindigkeit sogar 20 KB verschlingen.
MODs unter 10 KB sind sehr rar.
Aber man kann wirklich auch mit sehr kleinen Samples Musik erzeugen.
Bloß die Motivation dazu war bisher nicht gegeben mit so großen Patterndaten, und das will ich ändern.
Dann gibt es da aber noch etwas, das mir nicht gefällt. Ein Melodie-Sample kann z.B. 10 Notenwerte
haben, auf denen es insgesamt gespielt wird. Das bedeutet, es würde überall in den Patterns durch
4 Bit repräsentiert. Aber es kann durchaus sein, dass mal ein Pattern vorliegt, in dem dieses Sample
nur auf zwei verschiedenen Noten gespielt wird, und man bräuchte dann nur 1 Bit.
Wie ich schon sagte kann ich nicht für jedes Pattern und für jeden Track für alle vorkommenden Samples
die jeweiligen Notentabellen anlegen, das würde mehr aufblähen als komprimieren.
Aber ich könnte entweder durch nur 10 Bit in diesem Fall flaggen, welche Noten im Track für
dieses Instrument kommen werden, oder aber vielleicht durch eine Startposition und Endposition
in der Tabelle eingrenzen. Ersteres wäre aber effektiver.
Ich habe das mal mehr als Brainstorming aufgeschrieben, da es doch fast etwas verrückt wirkt.
Eine Frage aber mal:
Wie setze ich in einem Player Schleifen um?
Die einfachste Möglichkeit wäre, wenn man die Position im Sample als Variable nimmt, die dann beim
Mixen in ein Register wandert, welches man bei jedem Sampleschritt entsprechend der Periods hochzählt
und mit einem anderen Register, welches das Schleifenende beinhaltet, vergleicht.
Eine andere, schnellere Möglichkeit soll sein, vorher auszurechnen wieviel von der Schleife in den Puffer
passt und wenn die Schleife kürzer ist als der Puffer, dann erstmal nur nen Mix-Loop für diese Schleifen-
länge machen, dann weiter bis der Puffer voll ist usw... Stelle ich mir etwas kompliziert vor.
mov ax, 13h
int 10h
while vorne_frei do vor;
int 10h
while vorne_frei do vor;
Re: Trackermodul-Engine (sehr einfach)
Naja, von allem (Grafik, Musik, Film, Text, Datenbank, Tabellen, etc...) gibt es Formate über Formate. Die Anzahl verschiedener Formate, die es für den gleichen Zweck gibt, gehen in die Tausende. Ich persönlich halte es für eine Mammutaufgabe, alle möglichen Formate zu supporten/umzusetzen. Wenn ich was brauche, gibt es schon passende Konverter. Ich selbst benutze nur wenige gängige Formate (die ich dann z.B. in eigene konvertiere).zatzen hat geschrieben:Ich habe jenes AMF im OpenMPT (Tracker) reingeladen, sind 64 Zeilen Patterns...
Eine Formatbeschreibung wäre mal interessant, habe ich aber auf die Schnelle nicht im Netz gefunden.
Für Grafik z.B. nur PCX und (MS-)BMP - habe aber auch schonmal einen GIF-Anzeiger gebaut. Für Sound nur ungepackte WAVs (Mono/Stereo, 8bit/16bit). Bei Text ist mir immer noch normaler Text am liebsten - ich kann auch UTF-8 lesen/schreiben, aber ein Textformat, bei dem die Zeichen unterschiedlich viel Speicher brauchen (Doppel- und Mehrfachbytes für Zeichen ab 128) läßt sich wesentlich schlechter verarbeiten und handlen. Das sind nur so Beispiele.
Ja, das ist der Vorteil monolithischer Systeme. Man kann das Ganze so hardwarenah/hardwarebezogen machen wie man will, ohne daß es seltsame Probleme gibt.zatzen hat geschrieben:Am Amiga waren die MODs mit 50 Hz, also der PAL Bildfrequenz getaktet, manche Player
haben aber auch einen Schalter auf NTSC mit seinen 60 Hz.
Das Tickspeed gibt an, wieviele Bilder vergehen, bis die nächste Zeile kommt.
Auf dem Amiga waren also Bild und Ton untrennbar miteinander verheiratet, und die Nichtvariablität
war ja auch kein Problem weil alle Amigas das gleiche leisteten.
Der PC ist eher ein Flickwerk aus allem Möglichen - aber zumindest zu einer bestimmten Zeit konnte man sich einigermaßen drauf verlassen, daß im PC eine VGA-kompatible (wenn auch nicht immer 100% registerkompatible) Grafikkarte drin war, dann irgendwas Soundblaster-mäßiges, was entweder ein selber ein SB war, oder zumindest SB 1, 1.5 oder 2.0 hinlänglich brauchbar supportete und auch sonstige Hardware/Speicher, die gewissen allgemein anerkannten Größen/Normen entsprachen. Da konnte man selbst auf dem PC ein Spiel bauen, das auf fast allen anderen PCs auch lief.
Dann kam Microsoft irgendwann mit seiner Softwaretreiber-Idee um die Ecke - schon brauchten Hardwarehersteller sich an überhaupt keinen Standard mehr zu halten und man war immer gezwungen, das gerade aktuellste OS zu nutzen, damit überhaupt IRGENDETWAS funktionierte. Aber bis WinXP (32bit), (von WinME und solchem Blödsinn mal abgesehen) konnte man sich sogar einigermaßen sicher sein, daß auch die meisten 16bit-DOS-Programme noch immer liefen.
Inzwischen sind moderne PCs nichts mehr, bei dem ich mir vorstellen könnte, daß mir programmieren darauf Spaß machen könnte. Aber ich bin ja auch nicht das "Maß der Dinge" - und solange es immer noch die alten Kisten gibt und die funktionieren, kann ich weiter meinem Hobby frönen. Ich bin in der glücklichen Lage, daß ich nie, nicht mal zu Zeiten, als das noch möglich gewesen wäre, Interesse daran hatte, an meiner Software Geld zu verdienen. Somit kann ich quasi "machen, was ich will"...
Ja, Du hattest mir ja mal die Specs geschickt und ich habe ich auch vor ein paar Monaten schonmal durchgelesen und fand die Art, wie die Speicher sparen und trotzdem alles ermöglichen, schon recht gut. Wie gesagt: Bitmaske mit benutzten Werden (0=Wert bleibt wie vorher und muß nicht neu gespeichert werden) wird auch von der Van-Jacobsen-TCP/IP-Header-Compression so benutzt, daran hat mich das gleich erinnert. Ist meiner Meinung nach eine recht effiziente Art der Speicherung.zatzen hat geschrieben:Oh, DDMF, das ist ja das Format des X-Trackers, der Tracker den ich heute noch benutze und von
dem ich konvertieren möchte. Daher kenne ich das Format sehr gut und die Patterns sind gespeichert
mit Lauflängen per Track, um die Nullen zu beseitigen, und mit Flaggen der Effekte.
Sobald Dein Format steht, würden mich da auch die Specs interessieren. Schaue mir immer gern an, was andere Coder, die ich kenne, so machen.zatzen hat geschrieben:Das komprimiert schonmal ganz nett, aber mein Vorgehen wird schon alleine wegen dem Lesen
in beliebiger und angepasster Bitbreite effizienter sein.
Ja, aber für diese wäre das ja sowieso nicht nötig. Es geht ja eher darum, wenn man eine Melodie haben will, die in "Noten" (also Computernoten, D#4 und so) abgebildet werden soll. Ich hab manchmal genau im Kopf, wie es klingen soll, aber ich "treffe" bei den Noten manchmal knapp daneben - muß dann immer anhören, wo es schräg klingt und die falsche Note eliminieren... Und das Gleiche mit den Längen. DAFÜR wäre das eigentlich gedacht. Wenn man ein komplettes Sample an eine Stelle setzen will, das aus mehreren verschieden hohen Tönen besteht, ist das etwas anderes. Das muß man ja "nehmen, wie es ist" und entsprechend pitchen.zatzen hat geschrieben:Erstaunliche Sache, mit dem Vorpfeifen. Es ist nur so, dass ich auch Samples verwende, die direkt
einen ganzen Akkord enthalten oder generell etwas das man nicht einfach einer Note zuordnen kann.
Naja, ich nehme ja keinen OPL3 - das Synthesizing passiert bei mir ebenfalls softwareseitig aus (kombinierbaren) Wellenformen und einstellbaren Hüllkurven. Das wird alles berechnet.zatzen hat geschrieben:XMS: Da käme ja wieder das Argument rein, dass Patterns UND Samples klein sein sollen, meinetwegen
80KB für ein ganzes Spiel, für die Intro Musik, Level Musik etc. Klar könnte man auch einen Synthesizer
nehmen, im einfachsten Fall OPL3 also AdLib, aber irgendwie haben für mich Samples mehr Reiz, sie
klingen zwar wenn man Speicher spart etwas schäbig und sind vielleicht sehr kurz, aber man hat immer
noch einen ganz individuellen Sound, während AdLib Musik irgendwie die meisten Spiele erscheinen
lässt, als wären sie vom gleichen Entwickler.
Aber natürlich. Ich sage ja auch nicht, daß es nicht so sein soll.zatzen hat geschrieben:Aber sehen wir es doch mal so: Wenn ich jetzt einen Adlib Tracker hätte und mir ein Pattern-Speicherformat ausdenken würde... Dann hätte man gar keine Sampledaten. Wäre es dann nicht frevelhaft, nicht zu
versuchen, die Musik-Instruktionen so klein wie möglich zu halten?
Ich komme nur mit meiner ganzen Computer-Musik-Selbermachen-Geschichte aus einer ganz anderen Ecke und habe z.B. Patterns nie für nötig erachtet. Für mich ist das nur ein weiteres sogenanntes Abstraktionslevel. D.h. es gibt einen Sequenzer, der dann angibt, welche Patterns gespielt werden sollen und dann gibts die Patterns.
ABER: Bedingt dadurch, daß mein ISM auch "Unterprogramme" unterstützt, wäre es kein Problem, das Ganze dementsprechend aufzuteilen/anzuzeigen. Nur ist es eben keine Pflicht - also kann man beliebige und beliebig lange Stücke und Teilstücke der Musik in jeder Stimme mit jedem Instrument an jeder Stelle in jeder Geschwindigkeit abspielen, braucht also quasi an keiner einzigen Stelle irgend etwas doppelt zu speichern. Wer allerdings MOD-artige Tracker gewöhnt ist, für den ist diese Art, Musik auf dem Computer zu "programmieren"/darzustellen, sicher extrem gewöhnungsbedürftig - das weiß ich auch.
zatzen hat geschrieben:Genau, das ganze wird nur ein Converter. Ein Tracker wäre zwar schön, aber ist im diesen Fall nicht erforderlich und würde nur unnötig Aufwand kosten. Ausser mir wird wohl kaum jemand dieses Format nutzen, und wenn,
dann kann ich für's MOD oder IT oder XM Format einen Converter machen.
Schon klar - damit man erstmal sieht, ob das Packen/Entpacken auch richtig arbeitet.zatzen hat geschrieben:Der Player wird wohl in provisorischer Instanz erstmal nur die Patterns decodiert als Textdatei ausgeben.
Ich gehe hier ganz anders vor. Ich habe eine Frequenztabelle für alle 96 Noten (8 Oktaven), die ich unterstütze (eigentlich unterstütze ich - mit Transponieren - etwas über 10 Oktaven...zatzen hat geschrieben:Update:
Ich setze die Samples doch mit variabler Grundfrequenz um. Stimmbarkeit ist doch eine wertvolle Sache.
Da ich ja zu jedem Sample eine Tabelle speichern möchte, in der steht auf welchen Tönen es ingesamt
gespielt wird, mache ich nun statt Notenwerten direkt die "Periods" dort hinein, wahrscheinlich mit
16 Bit Auflösung. Und diese sind nun pro Sample individuell. So spare ich mir auch eine allgemeine
Period-Tabelle für das ganze Spektrum an Noten, wenn die Notentabellen für ein Sample nicht auf
eine allgemeine Tabelle verweisen sondern selbst direkt die Werte enthalten.
Die Samples selbst erhalten bei mir keine solche Tabelle, sondern nur die Grundfrequenz. Dieser Wert wird vom Samplemaker eingestellt und gibt an, welchem Notenton das Sample entspricht, wenn man es 1:1 (also mit Originalgeschwindigkeit) auf 16384 Hz abspielen würde. Wird nun das Sample mit einem bestimmten Ton angeschlagen, berechnet eine Subroutine einen "Speed-Adder" für das Sample, abhängig von der "Abspielfrequenz" des Players, dem obengenannten definierten Samplegrundfrequenzwert und dem abzuspielenden Notenwert. Dann wird das Sample abgespielt. Dieser Adder ist 32-Bit Festkomma (16bit Vorkomma, 16bit Nachkomma) - damit ist eine hinreichende Genauigkeit gegeben.
Ich habe in meinem ganzen Leben noch nie RICHTIG gepitcht - ich wüßte nichtmal, wie das gehen soll. Wahrscheinlich mit Fourier-Frequenz-Analyse und so Zeug, aber wenn ich im Netz sowas suche und dazu die Formeln lese, bluten mir die Augen. Sowas könnt ich nicht mal in Hochsprache umsetzen, geschweige denn in Assembler.
Oder, um es anders auszudrücken: Ein mit höherem Ton gespieltes Sample wird schneller, eins mit niedrigerem Ton langsamer abgespielt. Meist sind Samples aber sowieso nur für die Spannweite von 1 oder 1,5 Oktaven geeignet, darunter und darüber klingen sie nicht mehr so dolle. Und weil die Änderung der Tonhöhe bei einem mit anderer Frequenz abgespielten Klangsample wesentlich eher auffällt als die andere Geschwindigkeit, sehe ich das nicht als das gravierendste Problem an.
Wenn allerdings jemand eine EINFACHE Methode kennt, um zu pitchen ohne Änderung der Abspiellänge, laßt es mich wissen...
Das ist sehr löblich. Genauso geht es mir auch - bei fast allem. Deshalb sind auch Sprites bei mir gepackt usw.zatzen hat geschrieben:Übrigens auch ein Grund, warum ich das ganze so klein halten möchte ist, dass wenn ich schon für
DOS programmiere, ich mir auch die Möglichkeit offen halten möchte, etwas vom Datenumfang her
insgesamt sehr kleines zu schaffen.
Klar. Auf dem C64 war das normal. DIe "großen" Spiele, die eine ganze oder beide Diskettenseiten brauchten, kamen erst später und selbst zuletzt (und jetzt) gibt es immer noch Singlefile-Spiele auf C64.zatzen hat geschrieben:Man denke nur an die alten Zeiten wo man mehrere Spiele auf einer Diskette hatte und diese auch
von dort startete.
Natürlich muß man bei jeder Verkleinerung immer mit Qualitätseinbußen leben. Vom Spielprinzip her würde etwas wie das neue TombRaider sicher auch vielleicht auf 20 Disks passen - nur dann eben mit einfarbigen groben Polygonen und ohne Effekte. Will man mehr Grafik, mehr Sound, usw. erreicht man irgendwann eine Grenze, wo mehr Packen einfach nicht mehr geht.
Ja natürlich. Ich für meinen Teil versuche immer, einen Trade-Off zwischen Speicherverbrauch, CPU-Leistungsverbrauch udn Qualität zu finden. Für mich ist da der "Mittelweg" das richtige Maß. Minimierung von Speicherverbrauch erfordert mehr Berechnung, Minimierung der Berechnungen erfordert mehr Speicher (weil schon vorberechnet oder ungepackt), Minimierung von beidem stößt irgendwann an die Untergrenze erträglicher Qualität.zatzen hat geschrieben:Mit solch klotzigen MODs wäre das schwierig, wenn allein die Patterns pro Minute etwa schon 10 KB
oder je nach Geschwindigkeit sogar 20 KB verschlingen.
MODs unter 10 KB sind sehr rar.
So ist es.zatzen hat geschrieben:Aber man kann wirklich auch mit sehr kleinen Samples Musik erzeugen.
Gut so.zatzen hat geschrieben:Bloß die Motivation dazu war bisher nicht gegeben mit so großen Patterndaten, und das will ich ändern.
Naja, wie gesagt: Ich gehe da von der anderen Seite aus dran, daher ergibt sich ein derartiges Problem für mich nicht.zatzen hat geschrieben:Dann gibt es da aber noch etwas, das mir nicht gefällt. Ein Melodie-Sample kann z.B. 10 Notenwerte
haben, auf denen es insgesamt gespielt wird. Das bedeutet, es würde überall in den Patterns durch
4 Bit repräsentiert. Aber es kann durchaus sein, dass mal ein Pattern vorliegt, in dem dieses Sample
nur auf zwei verschiedenen Noten gespielt wird, und man bräuchte dann nur 1 Bit.
Wie ich schon sagte kann ich nicht für jedes Pattern und für jeden Track für alle vorkommenden Samples
die jeweiligen Notentabellen anlegen, das würde mehr aufblähen als komprimieren.
Ja, wie gesagt, daß ich da ganz anders vorgehe, kann ich das Ganze nicht so nachvollziehen.zatzen hat geschrieben:Aber ich könnte entweder durch nur 10 Bit in diesem Fall flaggen, welche Noten im Track für
dieses Instrument kommen werden, oder aber vielleicht durch eine Startposition und Endposition
in der Tabelle eingrenzen. Ersteres wäre aber effektiver.
Ich habe das mal mehr als Brainstorming aufgeschrieben, da es doch fast etwas verrückt wirkt.
An der Stelle dachte ich, Du willst eine bestimmten Teil aus der Musik mehrmals spielen...zatzen hat geschrieben: Eine Frage aber mal:
Wie setze ich in einem Player Schleifen um?
... aber hier hat es sich geklärt: Du meinst den Sample-Repeat.zatzen hat geschrieben: Die einfachste Möglichkeit wäre, wenn man die Position im Sample als Variable nimmt, die dann beim
Mixen in ein Register wandert, welches man bei jedem Sampleschritt entsprechend der Periods hochzählt
und mit einem anderen Register, welches das Schleifenende beinhaltet, vergleicht.
Eine andere, schnellere Möglichkeit soll sein, vorher auszurechnen wieviel von der Schleife in den Puffer
passt und wenn die Schleife kürzer ist als der Puffer, dann erstmal nur nen Mix-Loop für diese Schleifen-
länge machen, dann weiter bis der Puffer voll ist usw... Stelle ich mir etwas kompliziert vor.
Naja, ein Sample, das gerade in Benutzung ist, liegt bei mir immer vollständig im Sample-Speicher.
Die Repeat-Position steht bei meinen Samples ebenfalls im Sample-Header. Man kann aber mit Spezialbefehlen
auch an jede beliebige Sample-Stellle springen. Das Puffer-Problem ist bei mir nicht existent.