Trackermodul-Engine (sehr einfach)

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

Trackermodul-Engine (sehr einfach)

Beitrag von zatzen »

Hallo!

Ich überlege schon seit längerem, eine möglichst einfach zu implementierende
und Speicherschonende "MOD"-Engine zu bauen.

Die Patterns sollen möglichst platzsparend abgelegt werden und nicht
wie beim 4CHN Amigaformat 4 Byte pro Note, pro Zeile also dann 16
und für ein ganzes Pattern 1 KB beanspruchen.

Ich kann beim Trackern auch mal auf alle Effekte verzichten,
nur Lautstärke wäre ganz gut, auch für Echo-Effekte.


Ein wichtiger Punkt dabei ist, da die Samples ja in verschiedenen
Tonhöhen gemixt werden, wie man diese Sache löst.
Normalerweise legt man sich da eine Period-Table an -
allerdings kann ich bei meinem Tracker eine feste
C-3 Frequenz frei angeben zwischen z.b. 3000 und 48000 Hz,
und auf diese Freiheit möchte ich ungern verzichten, das
ist auch essentiell um die Samples fine zu tunen.
- aber so müsste ich mir ja ein Arsenal an Tables anlegen - oder nicht?

Ich dachte daran, dass das ursprüngliche Format erstmal
per Converter-Tool in ein einfacheres gewandelt wird, und
dass dann im Pattern direkt entweder Festkomma-Werte
in 8 oder 10 Bit geschrieben stehen, die man dann
nur noch auslesen und die Samples dementsprechend
fortschreitend Mixen muss.


Soviel meine bisherigen Gedanken dazu, um mit möglichst
wenig Speicherbedarf und Rechenaufwand und überhaupt wenig Aufwand
Tracker-Musik in ein Spiel zu bringen.

Ich dachte da so an 8 Kanal, max. 128 Zeilen.
Die Patterns, dynamisch gehalten, je nachdem wieviel sich
gerade tut in der Musik, würde ich tendentiell seriell anlegen, mit Indizierung,
um wiederum alles sehr kompakt halten zu können und kein festes Array
anzulegen.
Ich bin noch am austüfteln wie man ein Pattern möglichst kompakt
seriell codiert, unter Berücksichtigung dass es auch einfach auszulesen ist.

Bisher dachte ich vielleicht so für jede Zeile ein Info-Byte, auf welchem
Kanal überhaupt eine Änderung stattfindet, und dann alle in diesem
Byte anzeigten Veränderungen. Aber das scheint mir irgendwie noch
etwas zu verschwenderisch.

konventioneller Speicher ist kostbar ;)



Der Tracker den ich benutze (X-Tracker) ist leider keiner der MOD bzw. XM kompatiblen.
Aber ich habe es an ihm gelernt und komme nicht von dieser tollen Software los.
Daher bleibt mir nichts anderes übrig als das Format zu konvertieren.
Man kann auch eine Originaldatei abspielen, sicherlich, aber dem wirklich
gerechtzuwerden ist ein derartiger Programmieraufwand - ich finde das steht
in keinem richtigen Verhältnis dazu, dass man es auch sehr viel einfacher haben
kann wenn einem der Lautstärkebefehl reicht. NoteSlides sind immerhin möglich,
wenn auch nur abrubt, wenn man einfach den Pitch ändert ohne neu zu triggern,
das geht problemlos.
mov ax, 13h
int 10h

while vorne_frei do vor;
freecrac
DOS-Guru
Beiträge: 861
Registriert: Mi 21. Apr 2010, 11:44
Wohnort: Hamburg Horn

Re: Trackermodul-Engine (sehr einfach)

Beitrag von freecrac »

Ich selber habe mit Sound-Programmierung keinerlei Erfahrung und kenne mich mit der gesamten Materie leider auch nicht aus. Ich verfolge aber deine Beiträge ganz bestimmt und andere Mitleser wahrscheinlich auch.
.... mit wenig Speicherbedarf und Rechenaufwand und überhaupt wenig Aufwand Tracker-Musik in ein Spiel zu bringen.
Das wäre genial.

Ab welcher CPU mit wieviel RAM soll es denn sein?

Dirk
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von zatzen »

Hui gut dass du mal was schreibst. Habe schon befürchtet die Sache wäre zu trivial, da
man sich ja Anleitungen zum Programmieren eines MOD Players runterladen kann.
Aber ein kompletter MOD Player wird in der Tat sehr umfangreich und kompliziert.
Daher macht eine Vereinfachung evtl. Sinn.
Ab welcher CPU mit wieviel RAM soll es denn sein?
CPU weiss ich nicht genau was da ausreicht.
RAM erstmal nur 640 KB, um im Real Mode zu bleiben,
und Samples aus dem XMS zu holen wäre zu langsam.
mov ax, 13h
int 10h

while vorne_frei do vor;
wobo
DOS-Guru
Beiträge: 613
Registriert: So 17. Okt 2010, 14:40

Re: Trackermodul-Engine (sehr einfach)

Beitrag von wobo »

zatzen hat geschrieben: Ich überlege schon seit längerem, eine möglichst einfach zu implementierende
und Speicherschonende "MOD"-Engine zu bauen.

Die Patterns sollen möglichst platzsparend abgelegt werden und nicht
wie beim 4CHN Amigaformat 4 Byte pro Note, pro Zeile also dann 16
und für ein ganzes Pattern 1 KB beanspruchen.
So richtig Ahnung habe ich von der Materie nicht. Ich bin da eher ordentlich gescheiert. Aber die 4 Byte umfassenden Noten des Original Amiga-Formats kann man IMHO verlustfrei in 3 Byte pressen, so dass die Zeile dann nur noch 12 Byte, das ganze Pattern nur noch 768 Byte beansprucht.

zatzen hat geschrieben: Ich kann beim Trackern auch mal auf alle Effekte verzichten,
nur Lautstärke wäre ganz gut, auch für Echo-Effekte.
Gut, wer trackern kann. Ich kann das leider nicht mal die Bohne. Was auch das Player schreiben erschwert.

Die Tonhöhen bezogenen Effekte finde ich am schwierigsten und habe sie auch bis heute nicht richtig umsetzen können. Die Lautstärke-Effekte sind IMHO dagegen recht einfach zu implementieren. Sich anfangs auf Lautstärke-Effekte zu beschränken finde ich daher aus eigener Erfahrung sehr vernünftig.

zatzen hat geschrieben: Ein wichtiger Punkt dabei ist, da die Samples ja in verschiedenen
Tonhöhen gemixt werden, wie man diese Sache löst.
Normalerweise legt man sich da eine Period-Table an -
allerdings kann ich bei meinem Tracker eine feste
C-3 Frequenz frei angeben zwischen z.b. 3000 und 48000 Hz,
und auf diese Freiheit möchte ich ungern verzichten, das
ist auch essentiell um die Samples fine zu tunen.
- aber so müsste ich mir ja ein Arsenal an Tables anlegen - oder nicht?
Ich habe mich bisher nur im 4CHN-Mods beschäftigt, was schwierig genug ist ... Wenn Dein Tracker aber variable Standardfrequenzen für C-3 kennt, dann würde Deine Period-Tabelle bei 5 Oktaven (4CHN hat im Original nur 3!) ja 45000*60 Einträge haben, was nicht in die 640k passen wird...

Aber irgendwo habe ich gelesen, dass deine Zielplattform der Pentium ist. Ich sehe dort kein Problem (schon ab P60, ggf. auch alle 486er) die Periods bzw. die sich hieraus ergebenden Faktoren pro angespielter Note - quasi in Echtzeit - zu errechnen. Auch bei 8 Kanälen hast Du ja pro Sekunde allenfalls Noten in zweistelliger Höhe. Für einen P60 kein Problem, auch wenn der Player im Hintergrund laufen soll. (IMHO)

zatzen hat geschrieben: Ich dachte daran, dass das ursprüngliche Format erstmal
per Converter-Tool in ein einfacheres gewandelt wird, und
dass dann im Pattern direkt entweder Festkomma-Werte
in 8 oder 10 Bit geschrieben stehen, die man dann
nur noch auslesen und die Samples dementsprechend
fortschreitend Mixen muss.
8 bzw. 10 bit dürften ein bisschen wenig sein, wenn Du jetzt nicht nur den Nachkomma-Anteil meinst.

zatzen hat geschrieben: Soviel meine bisherigen Gedanken dazu, um mit möglichst
wenig Speicherbedarf und Rechenaufwand und überhaupt wenig Aufwand
Tracker-Musik in ein Spiel zu bringen.

Ich dachte da so an 8 Kanal, max. 128 Zeilen.
Da ist schon doppelte Qualität dessen, an dem ich gescheitert bin ;-)))

zatzen hat geschrieben: Die Patterns, dynamisch gehalten, je nachdem wieviel sich
gerade tut in der Musik, würde ich tendentiell seriell anlegen, mit Indizierung,
um wiederum alles sehr kompakt halten zu können und kein festes Array
anzulegen.
Ich bin noch am austüfteln wie man ein Pattern möglichst kompakt
seriell codiert, unter Berücksichtigung dass es auch einfach auszulesen ist.

Bisher dachte ich vielleicht so für jede Zeile ein Info-Byte, auf welchem
Kanal überhaupt eine Änderung stattfindet, und dann alle in diesem
Byte anzeigten Veränderungen. Aber das scheint mir irgendwie noch
etwas zu verschwenderisch.


Ich denke mal, dass es am Speicher schonensten wäre, nicht patternweise die Musik zu speichern, sondern die einzelnen Tracks/Kanäle. IMHO habe ich manchmal den Eindruck, dass sich einzelne Tracks über mehrere Pattern wiederholen (z.B. Schlagzeug, Bass?), während nur die Melodiestimme variiert. Wenn man das Modul trackweise beschreiben würde, dann könnte man diese Wiederholungen, die eben nicht das ganze Pattern betreffen, speicherschonender berücksichtigen.


Außerdem könnte man wohl auch innerhalb eines Tracks besser komprimieren als innerhalb einer Zeile eines Patterns. Es ist IMHO wohl nicht so, dass stets pro neuer Zeile eines Patterns jedes Mal neue Noten angeschlagen werden. Jedenfalls, wenn das Song spezifisch also nicht der Fall ist, könnte man relativ viel Speicher mit einem simplen Run-Length-Encoding sparen, was auch das Abspielen nicht verlangsamen würde.

zatzen hat geschrieben: Der Tracker den ich benutze (X-Tracker) ist leider keiner der MOD bzw. XM kompatiblen.
Aber ich habe es an ihm gelernt und komme nicht von dieser tollen Software los.
Daher bleibt mir nichts anderes übrig als das Format zu konvertieren.
Man kann auch eine Originaldatei abspielen, sicherlich, aber dem wirklich
gerechtzuwerden ist ein derartiger Programmieraufwand - ich finde das steht
in keinem richtigen Verhältnis dazu, dass man es auch sehr viel einfacher haben
kann wenn einem der Lautstärkebefehl reicht. NoteSlides sind immerhin möglich,
wenn auch nur abrubt, wenn man einfach den Pitch ändert ohne neu zu triggern,
das geht problemlos.
Ich kenne den Tracker nicht. Aber ich beiße mir ja schon am 4CHN-Format die Zähne aus.

Hast Du auch die Format Doku für Deinen Tracker?

Was heißt "triggern"?
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von zatzen »

Also, angesichts das Tatsache dass Samples auch nicht gerade wenig Speicherplatz
benötigen könnte man sagen, es ist relativ egal wieviel Platz die Patterns belegen
werden.
Allerdings kann man sowas ja auch Chiptune mäßig aufziehen. Und das typische
für Amiga-Chiptunes ist, dass die Samples fast keinen Platz beanspruchen,
aber das Modul durch die Patterns total aufgebläht ist!

Hinzu kommt, dass ich vor habe, 8 Kanäle zu benutzen (guter Kompromiss
finde ich - die wird man wohl ausfüllen, gleichzeitig wirds aber auch nicht
zu eng), und es kommt dazu dass ich nicht wie bei MODs standardmäßig
64 Zeilen pro Pattern will sondern bis zu 128 (oder auch mehr), und dann
aber mit hoher (doppelter) Geschwindigkeit darüber rase, das gibt mehr
Möglichkeiten bzgl. Präzision und rhythmischer Rafinessen.

Würde ich das also nach dem Schema Standard MOD Pattern-Speicher machen
hätte ich auf einmal 4 KB pro Pattern... Das ist viel zu viel, denn 4 KB ist schon
eine recht stolze Sample-Größe...
Lauflängenkomprimierung ist keine schlechte Idee, wobei es noch überlegens-
wert wäre ob da 4 Bit reichen, denn es ist äußerst selten dass in einem Pattern
mehr als 16 Zeilen Zwischenraum vorkommen. Gerade dann, wenn die Samples
klein gehalten werden müssen und man sich keine langen Loops leisten kann.
Eine komplett leere Spalte liesse sich so immerhin mit 4 Byte definieren.
Erstmal grob umrissen. Eigentlich kann man ja mit 4 Bit nur sagen, 15 Leerräume.
Man könnte ein Byte definieren mit einem Counter (meinetwegen auch 5 Bit)
und die restlichen 3 Bit sind Flags, was man in der Spalte nach Ablauf des
Counters an Änderungen zu erwarten hat (Pitch, Volume, Samplenummer).
Allerdings wenn ich mir das so überlege, könnte ich sogar auf max. 32
Kanäle hochgehen! Ich müsse einfach nur vor jedes Pattern ein DWORD
hängen in dem geflagt ist auf welchen Kanälen etwas passiert.
Das ist dann schön flexibel,man muss sich nicht mehr verschwenderisch
vorkommen wenn man mal nur 3 Tracks benutzt, und auf der anderen
Seite hat man die Möglichkeit, wunderbar vielstimmige Streicher-
Orgien zu veranstalten ;-)

Da war aber noch ein kleiner Denkfehler: Ich möchte die Patterns ja
nicht in einem festen Array ablegen sondern alle seriell hintereinandergeklatscht
in einem einzigen Datensegment das nur so groß sein muss wie die ganzen
lauflängenkomprimierten Patters zusammen. Um trotz der Läuflängenkomprimierung
zeilenweise lesen zu können brauche ich Offsets. Und zwar müssen die
jeweils auf den Anfang der Spalten zeigen. Das ließe sich lösen
indem ich nach dem DWORD das verrät welche Kanäle Aktivität zeigen
Offsets zu den jeweiligen Anfängen einbringe.
Offset zum ersten kann ich mir dann sparen, wieder 2 Byte gespart 8-)
Das mit der Lauflängencodierung ist echt gut, denn mit nem Info-Byte
vor jeder Zeile hätte ich allein fürs Grundgerüst eines Patterns immer
so viel Byte wie Zeilen, z.B. 128. Und die Einschränkung auf 8 Tracks.
Mit Lauflängen dagegen, wenn nur ein Track aktiv und auf dem nur ne
Bassdrum sein sollte, habe ich dann meinetwegen nur ca. 20 Byte!

8 bzw. 10 bit dürften ein bisschen wenig sein, wenn Du jetzt nicht nur den Nachkomma-Anteil meinst.
Das ist die Frage. Ich dachte mir eigentlich, um Rechenzeit zu sparen und um auch noch sowas
wie Finetune Befehle aus dem Tracker zu übernehmen, dass ich eben die "Delta" Werte direkt
in die Patterns reinschreibe. Wenn der Nachkommateil mit 8 Bit ausreichend ist, müssten
für die Vorkommastelle eine handvoll Bits genügen, denn man macht ja keine Sprünge
von 100 Bytes wenn man ein Sample abspielt.
Wenn ich das Finetuning ausser acht lasse (ich würde es sowieso seltenst verwenden), dann
könnte ich wohl tatsächlich auch die Deltas in Echtzeit berechnen, zumal ich nur für jede
Zeile neu berechnen muss, da ich keine Slide, Vibrato oder Arpeggio Effekte realisieren werde.
Die Formel müsste in etwa so sein: C-3-Frequenz / Mixrate * Notenfaktor[Note],
wobei Notenfaktor eine Tabelle ist, die bei C-3 den Wert 1 hat.
Inwieweit man das mit Integern berechnen kann könnt ihr mir vielleicht sagen,
mit Fliesskomma möchte ich da lieber nicht ran.

Ich schätze mal: ( C-3-Frequenz * Notenfaktor ) DIV Mixrate

Wobei man Notenfaktor auch wiederum anders definieren müsste, vielleicht mit 1024 multiplizieren
und so zum Integer machen. Anmerkung: Notenfaktor ist bei C-2 0,5 und C-1 0,25 und dazwischen
auch jede Menge krumme Zahlen.
Tipps erwünscht!

Aber ich habs denk ich mal. Notenfaktor bestimmt gewissermaßen maßgeblich den Delta-Wert.
Den muss ich dann so einregeln, dass man daraus durch Division und Modulo mit X den tatsächlichen
Deltawert in Form von Vor- und Nachkommewert bekommt (fix). X müsste demnach der Wert sein, den
Notenfaktor bei C-3 hat. Kann jemand folgen?

Ich kenne den Tracker nicht. Aber ich beiße mir ja schon am 4CHN-Format die Zähne aus.

Hast Du auch die Format Doku für Deinen Tracker?

Was heißt "triggern"?
Der Tracker ist von seiner Leistung her Vergleichbar mit FT2, allerdings hat er
ein eigenes Format, das sich von den Amiga-Vorgaben gelöst hat. Alle Effekwerte
z.B. funktionieren über 8 Bit. Und er kann 3 verschiedene Effekte gleichzeitig.
32 Kanäle, bis 255 Samples.

Format Doku habe ich, ja. Ich habe mir 1997 auch einen Renderer programmiert,
sehr langsam (Fliesskomma u.a.), aber die Ergebnisse klingen sehr gut.

Triggern heisst, das Sample neu "anschlagen", also von vorne abspielen.
Passiert im allgemeinen wenn man im Pattern die Samplenummer
mit bei der Note stehen hat - lässt man sie weg dann läuft das
Sample weiter und ändert nur die Tonhöhe. Mag bei manchen Trackern
anders sein, aber bei meinem ist das so.


Dann danke ich erstmal für die Beteiligung hier!
Habe bisher gedacht es wäre "lame" ein vereinfachtes MOD Format zu erfinden.
Aber nuja, da ich selbst wenig mit Vibrato und sowas arbeite macht es für mich
wirklich kaum einen Unterschied ob ich diese Effekte benutzen kann oder nicht.
Diese ausser acht zu lassen hat den großen Vorteil dass man immer nur Veränderungen
zeilenweise checken muss, und nicht auch noch zigfach zwischen den Zeilen...
mov ax, 13h
int 10h

while vorne_frei do vor;
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von zatzen »

Zur Effektivität der Lauflängenkomprimierung:

Ich denke die ist enorm!

Ich hatte ja gesagt, man hat ein Byte, Counter + Flags.
Der Zähler bekommt 5 Bit, und er kann somit entweder sagen,
jetzt sofort gibts ne Änderung (0) oder erst in soundsoviel
Zeilen (bis 31). Er kann somit den Raum zwischen Noten,
die man jeweils mit nem Abstand von bis zu 32 Zeilen gesetzt
hat, überbrücken.

Die anderen 3 Bits funktionieren als Flags:
- Samplenummer
- Note
- Lautstärke

Man bräuchte vielleicht noch einen Speed-Befehl.
Das Notenbyte braucht nur 7 Bit und sein MSB ließe sich
als Flag benutzen, dass ein Geschwindigkeitsbyte folgt.

Samples müssten auch 127 reichen.
Hätte man noch ein Extra-Flag.
Die Lautstärke muss auch nicht mit 8 Bit aufgelöst sein.


Was aber speichermäßig interessant ist, ist die Flag-Kombination:
- Samplenummer (1)
- Note (0)
- Lautstärke (0)

Hier erzeugt das Info- bzw. Counter und Flag - Byte das Abspielen eines Samples, ohne
dass weitere Parameter nötig sind.
Ich kann mit meinem Tracker keine Samplenummer setzen ohne eine Note.
Daher wird hier die Kombi Samplenummer ohne Notenwert als erneutes Abspielen
des Samples, was zuletzt auf dem Kanal spielte, interpretiert, und das in der
gleichen Tonhöhe. Das passiert am häufigsten bei Schlagzeug, aber auch nicht
selten bei Melodieläufen, wo man auch mehrmals hintereinander die gleiche
Note anschlägt.
Für den Fall dass ein anderes Sample auf die Spur kommt, wird dieses
wieder mit Samplenummer + Note definiert.

Im Idealfall, beispielsweise ner Bassdrum, hat man nur so viele Bytes
in der Spalte, wie Bassdrums einprogrammiert sind.
Man könnte vielleicht noch weiterdenken und anfangen mit wiederholungs-Countern,
aber das wird dann wieder sehr schwer umzusetzen und rechtfertigt die paar Bytes
weniger dann wieder nicht.

Den Fall, dass die Samplenummer wechselt und aber die Note gleich bleibt
habe ich noch nicht überdacht. Vielleicht kann man da irgendwas mit den
möglichen Flags der Datenbytes umsetzen. Muss ich gleich mal drüber
sinnieren... bis nachher...
mov ax, 13h
int 10h

while vorne_frei do vor;
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von zatzen »

Okay, wie gut auch immer die Sache mit der Spalten-weisen Lauflängenkodierung ist -
das ist programmiertechnisch eher fummelig und es fragt sich ob sich der Aufwand lohnt.

Ich habe mir gerade mal etwas über das PSM Format durchgelesen, das hält die Patterns
auch schön klein, geht aber Zeilenweise vor. Das hat den Vorteil dass man nicht die
ganze Zeit in den Patterndaten rumspringen muss sondern sich einfach geradlinig
da durchlesen kann.

Ich finde mich mal einfach damit ab dass jedes Pattern ein Grundgerüst hat,
so viele Bytes wie Zeilen. Dafür spare ich mir die Counter-Bytes in einer Spalte,
die bei 8 Kanälen und durchschnittlicher Patternbelegung auch schnell über
200 oder mehr werden können.

Ich kehre aber zurück auf 8 Kanäle. Das genügt und so
hat man klare und bescheidene Grenzen für den Player.


Ich muss mir das aber erstmal gründlich überlegen, bevor ich hier
einfach drauf los schreibe und schriftlich rumgrüble...
mov ax, 13h
int 10h

while vorne_frei do vor;
wobo
DOS-Guru
Beiträge: 613
Registriert: So 17. Okt 2010, 14:40

Re: Trackermodul-Engine (sehr einfach)

Beitrag von wobo »

zatzen hat geschrieben:Also, angesichts das Tatsache dass Samples auch nicht gerade wenig Speicherplatz benötigen könnte man sagen, es ist relativ egal wieviel Platz die Patterns belegen
werden. ...
Dachte ich anfangs auch mal...
zatzen hat geschrieben: ... Allerdings kann man sowas ja auch Chiptune mäßig aufziehen. Und das typische für Amiga-Chiptunes ist, dass die Samples fast keinen Platz beanspruchen,
aber das Modul durch die Patterns total aufgebläht ist!
... bis ich mal ein paar Module zu Gesicht bekommen habe, die nur sehr kleine Samples (teilweise unter 100 byte) verwendet haben. Da bestand das gesamte Modul fast nur aus Patterns!

zatzen hat geschrieben:
8 bzw. 10 bit dürften ein bisschen wenig sein, wenn Du jetzt nicht nur den Nachkomma-Anteil meinst.
Das ist die Frage. Ich dachte mir eigentlich, um Rechenzeit zu sparen und um auch noch sowas
wie Finetune Befehle aus dem Tracker zu übernehmen, dass ich eben die "Delta" Werte direkt
in die Patterns reinschreibe. Wenn der Nachkommateil mit 8 Bit ausreichend ist, müssten
für die Vorkommastelle eine handvoll Bits genügen, denn man macht ja keine Sprünge
von 100 Bytes wenn man ein Sample abspielt.

Ob 8 oder 10 bit Nachkommanteil ausreichen, kann ich nicht sagen. In meinem 4CHN-Player verwende ich 8-bit Nachkomma, weil ich lediglich 16bit/286 instructions verwende und ich ohnehin den Sound mit max. 4-13khz über die Soundblaster ausgebe (mehr schafft mein 386sx bei meiner Programmierung nicht).

Ein guter Player wie z.B. der Inertia-Player, hat jedoch eine viel bessere Soundqualität, auch wenn ich die Ausgabefrequenz dort ebenfalls auf z.B. gleich niedrige 13 khz einstelle. Das kann natürlich viele Ursachen haben. Die bessere Soundqualität könnte aber auch, wenigstens zum Teil, daran liegen, dass (meiner Meinung nach) der Inertia Player einen Nachkommaanteil über 12 bit verwendet.

Ich hatte auch mal eine Grafikroutine, bei der ich anfangs mit 8-bit Nachkomma gerechnet habe. Das Ergebnis war sehr schlecht. Ich habe dann den Nachkommanteil auf 10 bit erhöht, was zu wesentlich besseren Ergebnissen geführt hat. Ich war sehr erstaunt, was zwei zusätzliche Bit ausmachen.

Ich denke daher mittlerweile, dass ein geringer Nachkommaanteil sich massiv quaitätsmindernd auswirkt. Durch die ständige Addition des (durch den geringen Nachkommaanteil bedingten) Rundungsfehlers in den Delta-Offsets summiert sich der Fehler während des Abspielens ja ebenfalls ständig.

Bei meinem Player kann ich leider nicht aussprobieren, ob sich die Qualität erhöht, wenn ich die Nachkommastellen erhöhe, weil alles fix auf 8bit-Nachkomma angelegt ist. Ich müßte ihn hierzu komplett neu designen und neu schreiben...

Ich würde mich daher beim Schreiben eines neuen Players hier nicht zu früh festlegen wollen und den Player vielleicht so designen, dass ich eine höhere Nachkommagenauigkeit ggf. noch nachbessern könnte. Würde ich neu anfangen, würde ich jetzt jedenfalls mit 4 bit Vorkomma und 12 bit Nachkomma anfangen.


Ob die Delta-Werte tatsächlich schon im Pattern stehen sollten? Dann benötigen sie natuerlich mehr Speicher im Pattern, als wenn Du nur den Notenindex aufnimmst und hieraus dann die Delta-Werte errechnest. Außerdem legst Du Dich ja dann schon von Anfang auf die Nachkommagenauigkeit fest (s.o.). Ich würde daher die Delta-Offset allenfalls beim Laden des Moduls in die pattern eintragen, nicht aber beim Speichern des moduls auf HD (d.h. auf Disc abgelegte Patterns und im Ram des Players befindliche Patterns wären dann unterschiedlich).

zatzen hat geschrieben: Wenn ich das Finetuning ausser acht lasse (ich würde es sowieso seltenst verwenden), dann
könnte ich wohl tatsächlich auch die Deltas in Echtzeit berechnen, zumal ich nur für jede
Zeile neu berechnen muss, da ich keine Slide, Vibrato oder Arpeggio Effekte realisieren werde.
Die Formel müsste in etwa so sein: C-3-Frequenz / Mixrate * Notenfaktor[Note],
wobei Notenfaktor eine Tabelle ist, die bei C-3 den Wert 1 hat.
Inwieweit man das mit Integern berechnen kann könnt ihr mir vielleicht sagen,
mit Fliesskomma möchte ich da lieber nicht ran.

Ich schätze mal: ( C-3-Frequenz * Notenfaktor ) DIV Mixrate
Ich gehe mal davon aus, mit Mixrate meinst Du die Ausgabefrequenz, mit der z.B. die Soundblaster letztlich den vermixten Sound ausgeben soll.

Wenn ich jetzt mal als Beispiel für die C-3-Frequenz 8000 Hz nehme, und für die Mixrate 16000Hz, dann ergibt Deine Formel als Ergebnis in diesem Beispiel 0,5.

Wenn ich allgemein ein 8000 Hz - Sample habe und es mit 16000 Hz abspielen will, ohne dass sich die Tonhöhe und Sampledauer ändern, dann muss ich doppelt so viele Sampledaten ausgeben wie bei der Ausgabe mit originalen 8000 Hz. Mein Sample vergrößert sich also um den Faktor 2,0. Um mein Sample mit Brachialgewalt auf 2,0 zu vergrößern, gebe ich in meinem Mod-Player im Sample jedes Samplebyte doppelt aus, d.h. ich gehe im Sample dann mit dem Tempo 0,5 (Einheit: Offsetschrittweite) weiter.

Wenn Du Deine Formel also als Formel für die Deltaoffset-Schrittweite interpretierst, mit der Du bei der zu übergebenden Note und der Mixrate im Sample weiterwandern willst, wäre sie IMHO richtig.


Zur Klarstellung: Mit dem Begriff Sample meine ich immer das Sample im weiteren Sinn (quasi das "Instrument"), mit Samplebyte/Sampledatum das Sample im engeren Sinn. In Zweifelsfällen denke ich immer an 8-bit-mono-Samples. Bei Soundausgabe denke ich immer an die Soundblaster/Kompatible. Andere Karten kenne ich nicht.

zatzen hat geschrieben: Wobei man Notenfaktor auch wiederum anders definieren müsste, vielleicht mit 1024 multiplizieren und so zum Integer machen. Anmerkung: Notenfaktor ist bei C-2 0,5 und C-1 0,25 und dazwischen auch jede Menge krumme Zahlen. Tipps erwünscht!
Ja, wenn Du die Fließkomma-Offsets in Fixkomma umwandeln willst, muesstest Du das Ergebnis noch mit der Fixkomma-Auflösung (z.B. 1024 bei 10bit Nachkomma) multiplizieren.

Bei C-2 müßte sich aber, wenn ich das richtig verstanden habe, ein Notenfaktor von 2,0 ergeben, wenn Deine obige Formel den Delta-(Additions-)Offset angeben soll. C-2 bedeutet ja, dass das Sample mit der halben Frequenz von C-3 abgespielt werden muss, Du also Dein Sample doppelt so schnell bei gleicher Tondauer ausgeben musst, und deswegen im Sample nur jedes zweite Samplebyte ausgibst. Der Delta-Offset wäre also 2,0.

Willst Du für die Notenfaktoren an der Frequenz-Relation festhalten, müßtest Du in Deiner Formel also den Kehrbruch verwenden, um die Delta-Offsets zu erhalten, um die die Sampleposition beim Abspielen weiterwandern muß. (IMHO)

zatzen hat geschrieben: Aber ich habs denk ich mal. Notenfaktor bestimmt gewissermaßen maßgeblich den Delta-Wert.
Den muss ich dann so einregeln, dass man daraus durch Division und Modulo mit X den tatsächlichen
Deltawert in Form von Vor- und Nachkommewert bekommt (fix). X müsste demnach der Wert sein, den
Notenfaktor bei C-3 hat. Kann jemand folgen?
Ich denke ja. Zumindest habe ich das so in meinem 4chn-player gemacht, d.h. für jeden Halbton (12. Wurzel von 2) den entsprechenden FixkommaWert durch Division und Modulo in Abhängigkeit der gewählten MixRate errechnet. (Und diesen Fixkomma-Wert dann in einer Tabelle abgelegt, was bei 4chn problemlos ist, weil dort alles m.W. auf C-2 @ 8363/8287Hz bezogen ist.)

zatzen hat geschrieben:
Ich kenne den Tracker nicht. Aber ich beiße mir ja schon am 4CHN-Format die Zähne aus.

Hast Du auch die Format Doku für Deinen Tracker?

Was heißt "triggern"?
Der Tracker ist von seiner Leistung her Vergleichbar mit FT2, allerdings hat er
ein eigenes Format, das sich von den Amiga-Vorgaben gelöst hat. Alle Effekwerte
z.B. funktionieren über 8 Bit. Und er kann 3 verschiedene Effekte gleichzeitig.
32 Kanäle, bis 255 Samples.

Format Doku habe ich, ja. Ich habe mir 1997 auch einen Renderer programmiert,
sehr langsam (Fliesskomma u.a.), aber die Ergebnisse klingen sehr gut.



Wow, den Renderer würde ich jedenfalls irgendwann mal gerne Probe hören, am besten im Vergleich zum Abspielen ohne Renderer. Würde mich sehr interessieren, ebenso, wenn Du Deinen Player fertig hast.


Vielen Dank auch für die Infos zum Triggern. Ein Problem meines Players ist z.B., dass ich nicht wußte, wie ich damit umzugehen habe, wenn im Pattern auf einmal nur eine Note ohne Samplenummer oder nur eine Samplenummer ohne Note (oder nur ein Effekt ohne Note?) eingetragen ist. Durch Deine Ausführungen zum triggern ist mir so einiges klar geworden.
Mal kucken, vielleicht bastel ich doch noch mal in meinen, jetzt schon älteren Sources rum...

Zum Abschluss noch kurz: Ich habe etwas in Deinem Youtube-Channel geschmökert. Auch wenn das einfach nicht "meine" Musik ist, so fand ich es sehr unterhaltsam, kurzweilig und humorvoll. ich werde bei Gelegenheit bestimmt noch einmal reinschauen. Auch kann ich mir sofort die Verbindung Deiner Musik mit z.B. einem nicht zu trockenen Jump ń Run vorstellen. Die Idee, dass Du mit DosFeratu an einem Game werkelst, hätte also meine moralische Unterstützung ;-). Ich denke wirklich, dass das harmonieren könnte.

Also @DosFeratu & @Zatzen: bitte gemeinsames Game ausprobieren! ;-)
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von zatzen »

Hallo!

Hab gerade nur kurz Zeit, muss gleich weg.

Nur ein paar Dinge:


Die Nachkommaauflösung wirkt sich ja nicht wirklich auf die Klangqualität
aus, sondern auf die Genauigkeit der Tonhöhe. D.h. bei zu wenig Auflösung
werden vor allem die tiefsten Töne schief klingen. Man könnte also einfach
mal ausprobieren bis zu wieviel Bit runter es noch tolerabel klingt.
Ein sich addierender Fehler dürfte nicht so schlimm sein, denn wenn
es nicht schief klingt wird dieser so gering sein, dass selbst Drumloops
noch rund laufen.

Zudem kann man so eine Frequenztabelle nicht einfach mathematisch
berechnen, da sich in unseren Breitengraden ja die temperierte Stimmung
eingebürgert hat. Einfach geradezahlige Verhältnisse der Notenfrequenzen
würde man also wiederum als schief empfinden.

In der Tat, wenn ich die Festkommawerte direkt in den Patterns speichern würde,
wäre ich auf eine Mixrate fixiert.

Was deinen Player angeht: Ich denke eher, je höher die Mixrate, desto weniger
Bits braucht man im Nachkomma.


Was meine VIdeos angeht: Du kannst mal auf http://www.youtube.com/user/videocuts2010/videos
gucken was ich noch so mit dem Tracker anstelle, habe mir da ein Tool programmiert
was sich zu den Samples, die ich aus Videos rausgeholt habe, die zugehörigen
Bilder merkt und sie hinterher dazufügt... Vielleicht ganz witzig ;-)


Den Renderer schick ich dir bei nächster Gelegenheit, auch mit Sourcecode,
der allerdings riesig ist... Natürlich auch mit nem Trackerfile, da kannst
du mal vergleichen zwischen gerendertem und Cubic Player.
Das Argument für den Player war nicht nur die Qualität sondern
auch dass kein Player die Effekte richtig interpretiert hatte.

Dein Player würde mich aber auch interessieren! Überhaupt auch deine Spiele...
Warum gibts hier nicht ne Ecke wo jeder seine bisherigen Projekte vorstellt?
mov ax, 13h
int 10h

while vorne_frei do vor;
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von zatzen »

So ich denke ich habe jetzt eine gute Variante, die Patterndaten möglichst kompakt zu strukturieren.

Für jede Zeile mach ich erstmal ein Info-Byte.
Jedes Bit daraus definiert ob auf einem der acht Kanäle Änderungen stattfinden oder nicht.

Wenn eine Änderung auf einem Track stattfindet dann koderiere ich die möglichen Daten so:

Die Daten sind immer 6 Bit Werte. Es genügen 64 Stufen für Samplenummer,
Note sowie Volume. Zusätzlich brauche ich noch einen Trigger und ein Stop Command.

Aber mal ans Eingemachte:

Anmerkung: Es gibt immer mindestens 1 Byte, wenn das Index Byte vor jeder Zeile
den betreffenden Track positiv geflagt hat. Und da packe ich schonmal immer fest den
Notenwert rein, weil der sich am häufigsten ändert und somit fast immer vertreten sein wird.

1. Byte: xxxxxxyz
x: Notenwert
(wenn Notenwert=63 dann Stop Sample, wenn 0 dann ignorieren bzw. kein Update
yz: Was zusätzlich?
0: Nichts mehr
1: Nur triggern
2: Samplenummer folgt
3: Volume folgt

(bei yz = 0 oder 1 wäre Ende, aaaber:)
für bspw. yz=2
2. Byte: xxxxxxyz
x: Samplenummer
yz: was zusätzlich? (wiederum)
0: Nichts mehr
1: Nur triggern
2: Samplenummer folgt
3: Volume folgt

hier auch wieder, Ende bei yz = 0 oder 1, aber
für yz=3 z.B.:
3. Byte: xxxxxxyz
x: Volume
yz: Was zusätzlich?
0: Kein Triggern
1: Triggern

Da ist noch eine gewisse Redundanz drin. z.B. könnte ja klar sein
dass wenn einmal schon Samplenummer drin ist dass die dann nicht
nochmal kommt oder wenn Volume drin ist dass die da nicht Nochmal
kommt. Aber so könnte ich es nach Lust und Laune auch mal so
und mal so mit Werten füllen...
Zudem sind die Fälle bzw. Bits yz beim 3. Byte nur halb belegt, da
danach keine 6 Bit Datenwerte mehr kommen die deklariert werden müssten.


Vielleicht sieht ja noch einer ne Möglichkeit zum Optimieren, wobei
ich schon ganz zufrieden bin mit der Sache!


Wenn ich nun nen Song habe wo auf einem Kanal ein Instrument dudelt,
dann komm ich da (bis auf die erste Zeile wo die Samplenummer definiert werden muss)
für jeden Ton mit lediglich einem Byte hin. Jenes Byte enthält dann den Notenwert
und in seinen zwei Infobits entweder die Info "Triggern" (um das Sample von vorn abzuspielen)
oder die Info "gar nichts", dann würde das Sample weiterspielen und währenddessen auf
ne andere Note "sliden" aber halt abrupt. Dashört sich aber wunderbar für Träller an,
besonders bei Flöten.

3 Bytes bräucht ich nur gesetzt den Fall, dass ich ständig die Samplenummer und Volume
ändere, wobei zumindest ersteres selten ist, ausser wenn man komplexes Schlagzeug
auf einen Kanal zusammenpfercht.


Mal ne Größe eines 8 x 128 Patterns überschlagen:
Angenommen:
Durchschnittliche Ereignisdichte auf nem Track: Alle vier Zeilen
und:
Durchschnittliche benötigte Dateninformationen (s.o.) ergeben jeweils 2 Byte

Dann hätte ich:
128 + 128/4*8*2 = 640 Byte für ein solches Pattern. (Amiga 8CHN wäre bei 128 Zeilen immerhin 4K)
Ich denke in der Praxis wird das aber noch deutlich kleiner.
Trotzdem, 100 Patterns gingen somit schonmal in ein 64K Segment, und 100
genügen dickstens.
Werde das Format nochmal gut überprüfen und dann mal nen Converter schreiben.
Bis dann...
mov ax, 13h
int 10h

while vorne_frei do vor;
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von zatzen »

Okay, also ich habe meine Formatüberlegungen für gut befunden und bin dabei,
den Converter zu schreiben. Vorerst eben nur einer für DMF, Module aus X-Tracker,
weil ich den eben benutze zum trackern.
Man kann zudem nicht einfach beliebige Module konvertieren, weil ja die ganzen
komplizierteren Effekte ignoriert werden.
Viel mehr muss man im Tracker darauf achten, dass alles auch ohne
Spezialeffekte so klingt wie es soll, und dann kann man das Modul in
mein Format konvertieren.
Vorerst wirds den Converter nur für DMF geben, aber falls Interesse besteht
mache ich auch gern noch andere Ausgangsformate dazu.

Wenn der Converter und somit auch das konkrete Format steht,
mach ich mich erstmal an einen Renderer bzw. "Disk Writer".
Das deshalb, weil Soundblaster Programmierung nochmal ne Sache
für sich ist, da will ich erstmal sichergehen ob das Format
und meine Mischroutinen funktionieren.


Man könnte sich fragen, wozu so ein Format... Wo es doch Units gibt die
z.B. XM's vollständig und mit allen Effekten abspielen können.
Nunja, ich denke ein "echter" Dos-Coder will bis ins kleinste Detail
verstehen was in seinen Programmen vor sich geht, und mit einem
vereinfachten Modulformat ist es wahrscheinlicher, dass man die Vorgänge
so gut versteht, dass man sich so eine Unit sogar selber schreiben
kann, ohne dabei Kopfschmerzen zu bekommen.

Irgendwie hatte ich das Bedürnis nach so einem Format schon
sehr lange, allein weil ich nicht einfach eine fremde, 40 K große TPU
benutzen wollte...



Okay dann noch was anderes:
wobo wollte mal meinen DMF (X-Tracker Modul) Renderer sehen.
Hier ist er:
http://www.zatzen.net/fdw2-dos.zip
Inklusive 2 DMF's, eines habe ich 1995 gemacht, das andere 2005.
Wenn ihr euch den Cubic Player (eine Version um 1996) besorgt
habt ihr einen Vergleich, der mich damals dazu bewogen hat diesen
Renderer zu schreiben.
Weil ich bis heute Huffman nicht kapiert habe bzw. rekursive
Programmierung irgendwie pervers finde, kann mein Renderer
nur DMFs mit ungepackten Samples... Zudem komme ich so
ohne erweiterten Speicher hin, weil ich die Samples direkt aus
der Datei lese. Natürlich nicht Byte für Byte, so bekloppt bin ich
auch nicht, aber mit nem Puffer eben. Mit Festplattencache ist
das aber kein Problem.
Wenn ihr weitere DMFs mit meinem Renderer zu WAVs machen
wollt, müsst ihr die also irgendwie entpacken, und das geht
eigentlich nur mit dem X-Tracker selbst, den es aber mittlerweile
glaube ich als Freeware gibt. Kaufen tut den jedenfalls keiner mehr ;-)
mov ax, 13h
int 10h

while vorne_frei do vor;
wobo
DOS-Guru
Beiträge: 613
Registriert: So 17. Okt 2010, 14:40

Re: Trackermodul-Engine (sehr einfach)

Beitrag von wobo »

Die Welt dreht sich schon wieder schneller, als ich ihr folgen kann! Deswegen noch kurz was zu den älteren Postings:

Ich habe mir am Sonntag Deine VideoCuts angeschaut. Gestartet habe ich mit Markus Lanz vs. Piratin und mich halb tot gelacht. Auch einige andere Clips fand ich sehr witzig. (Schön auch, dass Du im Video-Kommentar den Link zum Original-Video angegeben hast. Ich war dem gefolgt, und hatte dann noch ´ne halbe Stunde politische Bildung dran gehängt. War also ein ziemlich kompletter Abend für mich. Danke!)

Du hast Dir da ´ne Software geschrieben, die die Videostellen zu den passenden Soundschnipseln findet? Heftig. Ich bin hinsichtlich allem, was nicht den Low-End-Dos-Bereich (286) betrifft, leider reiner Konsument. Ich wüßte deswegen nicht einmal im Ansatz, wo ich da ansetzen müßte.


Zum Format:
Gefällt mir ziemlich gut. Mir gefällt auch die Idee, dass Du es grundsätzlich ziemlich schnell erweitern könntest. Z.B., wenn Du mehr Effekte als einen SetVolume-Befehl unterstützen wolltest. Bei yz=3 hättest Du halt einen Effekt, der in xxxxxx genauer beschrieben ist. Im nachfolgenden 4. Byte könntest Du dann den Effektoperand folgen lassen.

Mir gefällt Deine Vorgehensweise so gut, dass ich mit dem Gedanken spiele, eine Variation für meinen 4chn-PLayer zu schreiben. Wobei ich derzeit - spezifisch für 4chn - wohl fix 2 byte für Note/Sample/Effekt verwenden würde, und den Effektoperand bei Bedarf im dritten Byte nachliefern würde. 2 byte fix deswegen, weil ich aus dem Bauch heraus sagen würde, dass bei 4chn die Kombi Note+Sample doch recht häufig sein müßte, und ich andererseits vom Vorhandensein verschiedener Effekte zwingend ausgehen muss.

zatzen hat geschrieben: Da ist noch eine gewisse Redundanz drin. z.B. könnte ja klar sein
dass wenn einmal schon Samplenummer drin ist dass die dann nicht
nochmal kommt oder wenn Volume drin ist dass die da nicht Nochmal
kommt. Aber so könnte ich es nach Lust und Laune auch mal so
und mal so mit Werten füllen...
Diese Redundanz zu vermeiden ist für mich Formatdefinition und damit Aufgabe des Konverters, d.h. der Player dürfte imho ohne Sicherheitsprüfung davon ausgehen, dass auf die Angabe eines Samples für dieselbe Note nicht noch eine weitere Sampleangabe erfolgt. Denn es gibt ja eigentlich keine vernünftige Lösung, was es bedeuten soll, wenn innerhalb einer Note mehrere Sampleangaben stehen: gilt dann das erste oder das letztgenannte Sample?

PS: Vielen Dank für Dein "lautes Denken" und Deine sonstigen Ausführungen in diesem Thread. Es war für mich sehr horizonterweiternd.
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von zatzen »

Zu der Technik mit den Video-Cuts:
Das ist einfacher als man denkt, aber auf die Idee ist wohl noch keiner gekommen.
Also:
Ich habe eine Video.
Ich speichere den Ton aus diesem Video als WAV-Datei (44100, Stereo, 16 Bit).
Nun sehe ich erstmal zu dass ich das Ding mono mache (beide Kanäle gleich,
damit auf dem linken auch alles zu hören ist).
Als nächstes geht ein Programm von mir hin und schreibt auf dem rechten Kanal
der WAV Datei treppenstufenmäßig jeweils die Nummer des Bildes die zum Ton auf
der linken Spur gehört.
Angenommen ich habe eine Framerate von 25 fps.
Dann geht das Programm mit einer Schrittweite von 40 ms, also 1764 Samples vor.
Die ersten 1764 Words vom rechten Kanal bekommen den Wert 0, die nächsten
1764 den Wert 1, die nächsten den Wert 2 usw ...
Ich kann, aufgrund der 16 Bit, Videos mit bis zu 65536 Bildern verarbeiten,
bei 25 fps also gut 43 Minuten.
Also, wenn dieses erste Programm seine Arbeit getan hat, habe ich nun eine
WAV Datei vorliegen, in der links der Ton ist und im rechten Kanal ein Index,
welches Bild jeweils zu der entsprechenden Stelle gehört.
Interessant wird es nun wenn ich anfange zu schneiden.
Dann schneide ich mit dem Ton gleichzeitig auch die Indizes um und habe
somit immer noch die Info, welches Bild zum Ton gehört.
Wenn ich mit dem Schnitt fertig bin kann ich so weitermachen:
Ich hole mir aus dem Originalvideo in meinem Fall mittels Virtualdub alle Bilder einzeln als BMP raus.
Jetzt kommt mein nächstes Programm zum tragen.
Es arbeitet sich durch die geschnittene WAV Datei und erstellt neue BMP Bilder,
nummeriert sie von 0 aufsteigend, aber nimmt sich als Quelle die Bilder in der
Reihenfolge wie sie in der geschnittenen WAV stehen.
Dabei gibt es nicht immer nur eindeutige, sondern auch schonmal Mischbilder,
(hier hat sich Freepascal für Win übrigens als sehr praktisch erwiesen - man
kann Problemlos mehrere BMPs in HD Größe im Speicher halten und für diese
Anwendung reichen LAAAAME Hochsprachenschleifen um die Bilder byteweise
zu mischen) man schneidet ja nicht immer genau an einer Framegrenze. Und
genau das macht den entscheidenen Unterschied aus, mit einem Videoprogramm kann
man immer nur an Framegrenzen schneiden, aber ich habe hier eine Technik
mit der ich mich voll und ganz auf den Ton konzentrieren kann.
Ich muss dann nur noch mit Vdub die erzeugten BMPs reinladen,
den Ton aus der linken Spur drunterlegen, und fertig.

Wenn ich was mit dem Tracker "schneiden" will, dann hole ich mir die Samples
aus der WAV-Datei mit den Indizes.
Im Tracker selbst verwende ich nur die linke Spur, also den Ton.
Später tausche ich die Tonsamples durch Index-Samples aus und berechne dieses
reine Index-Modul mit dem abgewandelten Renderer, dem ich noch übergeben
muss welchen Kanal er als Indexwerte interpretieren soll.
Der macht eine 16 Bit Mono WAV, nur Indizes, und somit hab ich die
korrekte Bilderfolge zu der Trackermusik.

Videostellen zu den Soundschnipseln *finden* wäre aber auch kein Ding der Unmöglichkeit.
Nicht unmöglich aber ziemlich utopisch ;-)

Hier mal ein Screenshot wie das Video mit Markus Lanz im Editor aussieht,
habe den rechten Kanal vertikal etwas gezoomt:
Image1.png
Image1.png (7.95 KiB) 18383 mal betrachtet



Okay, zurück zu dem Easy-Tracker Format (wollte ich übrigens .ZEM nennen, "ZETM", Zatzen Easy Tracker Module):
Ich habe schon angefangen mit dem Converter.
Allerdings gefällt mir die Codierung der Datenbytes noch nicht ganz.
Das muss ich noch mit sehr viel Geduld vielleicht etwas besser austüfteln.
Ich habe praktisch 4 Parameter die voneinander unabhängig sind:
- Trigger
- Samplenummer
- Note
- Volume

Wobei Triggern keine Daten braucht, da nur ein "boolean".
Trigger und Note kommen zwar sehr häufig vor, aber auch wieder nur im "rohen" Pattern.
Selbst bei Melodien folgen oft mehrere gleiche Töne hintereinander, von Schlagzeug
ganz zu schweigen.
Und eigentlich möchte ich, wenn nur eines der Parameter sich ändert, auch nur ein Byte
ver(sch)wenden. Bisher wäre es aber so, dass ein alleiniger Volume-Befehl gleich zwei
Byte frisst. Das ist ungut, denn es kommt nicht selten vor, dass sich nur Volume allein ändert.
Und ich möchte beim Trackern nicht immer ein schlechtes Gewissen haben wenn ich
Volume Befehle setze. ;-)
"Ändert" ist das Stichwort: Da dieses Format fürs reine Abspielen optimiert sein
soll speichere ich grundsätzlich nur Daten, die sich geändert haben.


Du sagst, die Kombi Note+Samplenummer kommt sehr häufig vor.
Das stimmt für die Darstellung eines Patterns im Tracker.
Aber wenn man es mal bzgl. Veränderungen sieht, dann ändert sich
die Samplenummer auf einem Track innerhalb eines Patterns
oft überhaupt nicht. Samplenummer bedeutet fürs Abspielen
lediglich, dass das Sample neu getriggert wird. Die Samplenummer
selbst sollte man eher als Statusinformation verstehen, welches
Sample eben gerade "gesetzt" ist.
Triggern lässt sich aber über 1 Bit oder sonstige schlaue Datenorganisation
definieren, und das Datenbyte für die Samplenummer kann man sich sparen,
anstatt es z.b. 25 x pro Track zu speichern.
Für die erste Zeile in einem Pattern werde ich allerdings alle gegebenen
Werte speichern, denn man weiss ja nie, was im letzten Pattern
definiert war bzw. in welcher Reihenfolge die Patterns im Sequencer
stehen.


Wegen der Redundanz:
Ich meinte damit eher was die Flags angeht.
Während in meiner jetzigen Formatdefinition beim ersten Datenbyte alle
4 Flagvarianten sinnvoll sind und zum Tragen kommen können, sind beim
zweiten Datenbyte nur noch 3 Möglichkeiten sinnvoll... Und wenn ich
nicht irre beim dritten Datenbyte nur noch zwei.
Nuja ich muss das noch überdenken weil wie gesagt alle 4 Parameter
eigentlich unabhängig auftreten können, zumindest wenn es nur ums Abspielen geht.

Es ist auch mein Ziel, den Player wie eine CPU zu befüttern, so dass er möglichst
einfach gehalten werden kann und keine Sicherheitsabfragen braucht.
Zuletzt geändert von zatzen am Do 26. Apr 2012, 06:12, insgesamt 1-mal geändert.
mov ax, 13h
int 10h

while vorne_frei do vor;
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von zatzen »

So, ich habe mir Gedanken gemacht und möchte die Datenorganisation
ändern. Diese 6-Bit-mit-Flags-was-danach-passiert Methode ist etwas
fummelig, auch wenn man es nur abspielt.

Andere Methode:

Ich lasse das globale Infobyte weg. Das spart dann erstmal so viele Byte wie es Zeilen gibt.
Stattdessen bekommt jedes Event auf einem Kanal folgende Struktur:
- Infobyte:
unterste 3 Bit: Tracknummer
nächste 3 Bit: Flags, welche Daten folgen (Samplenummer, Note, Volume)
nächstes Bit: Triggern?
noch ein Bit: wenn gesetzt, dann Ende der Daten für diese Zeile

Das ganze ist viel aufgeräumter.
Und ich kann nun volle 8 Bit Werte für die Daten verwenden.
Die Wirksamkeit der Kompression ist vergleichbar mit meiner vorherigen Idee.

Bei einer kompletten Leerzeile werden alle 5 oberen Bits nicht gesetzt,
und die untersten 3 Bit werden als counter interpretiert, wieviele
Leerzeilen noch folgen.
Denn wenn weder Daten folgen noch getriggert wird entspricht dies
genau gar keiner Aktion. Ich könnte noch das oberste Bit setzen,
aber ich lasse das bleiben, so muss der Player einfach nur gucken
ob das Byte kleiner 8 ist und kann es dann direkt in eine Zählvariable
einlesen.

Vielleicht hat sich noch ein Denkfehler eingeschlichen...

Werde diese Ideen jetzt mal versuchen in den Converter einzubringen.

bis dann...
mov ax, 13h
int 10h

while vorne_frei do vor;
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von zatzen »

Der Converter funktioniert, und ich bin mit einem der Coder für openmpt (Tracker für Windows)
befreundet, der hat mir netterweise mal ne Version der Software mit nem Loader für mein
Format gebastelt. Daher weiss ich dass alles schonmal so funktioniert.

Hier mal meine ausführliche Formatbeschreibung:

----------------------------------------------------------------------------------------------------------------------------------------

Zatzen Easy Tracker Module - File Format:


[HEADER]

- 4 BYTE: ID ("ZETM")
- 1 BYTE: Version (1)
- 1 WORD: Sequencer Length
- 1 WORD: Sequencer Loop Start
- 1 WORD: Patterndata Length
- 1 BYTE: Number of Samples

Sequencer Loop Start ist ein Index
und fängt bei 0 an und bezeichnet dann
den ersten Eintrag.




[SEQUENCER]

- X WORDS: Sequencerdaten,
jeweils absolute Offsets zu den jeweiligen Patterns,
wie sie nach dem Laden in einem Speicherbereich
am Stück hintereinander vorliegen.
Erstes Pattern hat Offset 0.
Hat das erste Pattern bspw. die Bytelänge 341,
dann ist Offset zu Pattern 2 eben 341.
Es gibt so viele WORD-Einträge wie im Header
mit Sequencer Length definiert ist.

Anmerkung: Der Sequencer endet immer an
seinem Schleifenende, da fürs Abspielen
mehr Daten keinen Sinn machen, zumindest
für diese Version 1. Ende des Sequencers
ist also immer auch Schleifenende.



[PATTERNS]

- X Byte: Patterndaten, Länge definiert durch
Patterndata Length.
Daten:
Ersteinmal 3 Byte: BeatsPerMinute, Zeilen pro Beat,
und Zeilen - 1 (255 bedeutet 256 Zeilen)

Danach die konkreten Daten:
Diese beginnen jeweils mit einem Info-Byte.
Es gilt:
Info-Byte = 128: Ende des Patterns
Info-Byte < 8: Es liegt eine Leerzeile vor
und es folgen noch so viele wie Info-Byte groß ist.
Bsp.: Info-Byte = 3 -> vier Leerzeilen.

Andernfalls:
Info-Byte wird wie folgt (Bit-weise) interpretiert:
E-T-V-S-N-C-C-C

Die drei untersten Bits geben die Track-Nummer an,
möglich ist 0-7, d.h. 1-8

N gesetzt: Notenwert folgt.
S gesetzt: samplenummer folgt
V gesetzt: Volume folgt
T gesetzt: sample wird "getriggert" d.h. (von vorn) abgespielt

E gesetzt: Es folgen nach den mit N S und V geflagten Daten
keine Daten mehr für diese Zeile



[SAMPLE-INFO]

Number of Samples mal:
- 1 WORD: Sample Size (immer in Byte, da 8 Bit)
- 1 WORD: Sample Loop Start
- 1 WORD: Sample C3-Frequenz
- 1 BYTE: Sample Standard Volume (1-255)

Wichtig:
Wenn Sample Loop Start < Sample Size,
dann ist Schleife an, ansonsten nicht.

Wenn Sample nicht verwendet wird, dann sind
alle Infos 0, und das Sample ist natürlich auch
nicht in den Sampledaten zu finden.



[SAMPLEDATEN]

Alle Samples hintereinander, Format: 8 Bit signed


----------------------------------------------------------------------------------------------------------------------------------------


Vielleicht fällt jemandem von euch noch ein wie man die Patterns noch kompakter, trotzdem aber noch
einfach lesbar, codieren kann.
mov ax, 13h
int 10h

while vorne_frei do vor;
Antworten