Sonntag, 12. Juli 2020

Üpdäätle -53-

Viel ist passiert. Ich habe im Juni mein Kompositionsstudium abgeschlossen, und eine Hormonersatztherapie begonnen (von der ich noch eher nichts merke). Das waren mal die Großnachrichten.

Die Kleinnachrichten:

AlgoLineB hat im Juni pausiert, ich habe aber in den letzten Wochen am GUI geschraubt, es gibt jetzt ein eigenes Menüfenster, mit einem Textfeld, in das direkt das Rezept geschrieben werden kann und auf Validität geprüft. Einziger Makel dabei: Sobald der Player gestartet wird, ist das Menü nicht mehr zugänglich, d.h. um etwas zu ändern, muss das Programm jedesmal neu gestartet werden.

Zwar wäre es problemlos möglich, das umzubauen - allerdings habe ich festgestellt, dass Java den Speicher des Players nicht freigibt, wenn ich nur das Player-Fenster schließe. D.h. wenn ich vom Menü aus oft den Player aufrufe, ohne das Programm neu zu starten, wird immer mehr Platz vom Arbeitsspeicher belegt. Das ist unschön und scheint mir etwas zu riskant, daher habe ich das deaktiviert.

Was ich - wie mir aufgefallen ist - einbauen kann, ist eine Funktion, in einem eigenen Fenster Rezept-Instruktionen und -Selektoren direkt im Programm zusammenzustellen (d.h. eine Erleichterung für Benutzer:innen, die sich nicht durchs ohnehin derzeit nur halb fertige Manual lesen müssen.) Aber das wäre eine Menge Arbeit, ich kann also nicht sagen, ob ich das angehe. Was das GUI angeht, ist es zwar funktionabel, aber noch nicht schön gestaltet, da ich mir noch nicht angeschaut habe, wie Layout funktioniert.

An den Algorithmen selbst habe ich nur wenig gemacht: ein SMOOTH-Keyword, das es ermöglicht, dass benachbarte Töne aufeinander abfärben, spricht wenn das Programm den Ton c' vermeiden will, dann vermeidet es auch die rundum - allerdings dafür c' weniger. Das funktioniert bislang ziemlich schlecht. Vielleicht habe ich noch nicht herausgefunden, mit welchen Instruktionen das gut zusammenarbeitet; der Effekt ist meist recht schal. Möglicherweise muss ich an der Funktionsweise dieses Keywords noch einmal schrauben. Praktisch ist jedoch, dass es auf alle Instruktionen anwendbar ist.

Eigentlich überlege ich schon, AlgoLine jetzt einmal längere Zeit ruhen zu lassen - zumindest wenn ich eine dafür geeignete Stelle erreicht habe - und ein neues Projekt anzufangen, ein Gehörbildungsprogramm, mit dem ich mich auf das Hören von Mikrointervallen schulen kann. Aber im Moment ist das noch ein vager Zukunftsplan.

Ansonsten stecke ich viel Energie darin, meine Gunnerkrigg Chords nach und nach aufzuschreiben, sowie an unfertigen Stücken weiterzuarbeiten. Das Aufschreiben ging zunächst recht zügig voran, mittlerweile bin ich nicht mehr so motiviert, also werde ich vermutlich dann allmählich ein neues Hauptprojekt suchen.

Anyway: Eigentlich ist jedes der erwähnten Projekte auch davon abhängig, wo es Interesse gibt. Für AlgoLine suche ich irgendwann Tester:innen (und wenn es welche gibt, bin ich auch motiviert, das Programm präsentierbar zu machen), und bei den Gunnerkrigg Chords komme ich eher voran, wenn es Leute gibt, die an den Noten Interesse haben.

Jundurg Delphimė


Freitag, 1. Mai 2020

AlgoLine B (work-in-progress)

Vorgestern hatte ich einen Tag von akuter Programmiersucht - denn ich hatte mir vorgenommen, endlich etwas zu vereinheitlichen, und alle Instruktionen auf eine gemeinsame Basis zu stellen, sodass bestimmte Keywords für alle verwendbar werden.

Dadurch gibt es jetzt u.a. die Keywords 'start' und 'end', um eine Instruktion nur in einem bestimmten Teil des Stücks aktiv sein zu lassen. Gleich verwendet habe ich das gerade eben mit der ebenfalls neuen Deterministic-Random-Instruktion. Zufallsfaktor will ich eigentlich minimieren, damit würde ich es mir zu leicht machen. Aber hin und wieder ist so ein bisschen Zufall recht praktikabel. Besonders am Start. Die ersten 5 Schläge zufällig zu bestimmen, und dann den Rest des Stückes Regeln folgen zu lassen (die die Vorgabe der ersten 5 Schläge verwenden) hat aber was.

Die Zufallsfunktion ist bewusst "trashy" programmiert, da sind zwei kleine Potenzen drin, und ein Sinus, und das irgendwie hochmultipliziert. Ich wollte da nicht lange darüber nachdenken - es reicht, wenn es irgendwas tut. Und vor allem: Es muss immer das gleiche tun, solange die Parameter unverändert sind. Denn dann kann ich am Stück feilen, ohne ständig eine neue Vorgabe zu haben, mit der die Instruktionen vielleicht vollkommen unterschiedliche Ergebnisse haben.

Allen Instruktionen gemeinsam sind also jetzt die Keywords 'start', 'end', 'fade_in', 'fade_out', 'max' und 'min'. Die Fade-Keywords habe ich noch nicht implementiert, die sollen später dann mit start/end zusammenwirken.

'MAX' ist relativ einfach zu erklären: Es setzt der Gesamtwirkung einer Instruktion einen fixen Deckel - sobald es darüber hinausgeht, wird alles herabskaliert, sodass es in den Rahmen zwischen 0 und diesen Deckel passt.

'MIN' ist etwas schwieriger zu erklären. Es legt nämlich nicht die geringstmögliche Wirkung fest (denn häufig wird ja ein Pitch mit 0 bewertet, und das lässt sich durch multiplizieren schon mal nicht hochskalieren) sondern es setzt ein Minimum fürs Maximum fest. Klingt verdreht?
Ist gar nicht so verdreht. Die Instruktion soll mindestens die festgelegte Auswirkung auf das Stück haben. Mehr ist möglich, dann wird nicht herabskaliert. Wohl aber wird hochskaliert, bis der höchste Wert zumindest mal MIN erreicht hat.

MIN x MAX x lässt es nun in Kombination zu, den höchsten Wert immer fix auf x zu belassen. Vorausgesetzt, es gibt überhaupt eine Wirkung. (Jetzt gerade fällt mir auf, dass eine Instruktion die nur Nullen liefert eventuell Probleme macht. Das muss ich wohl erst abfangen...)

Fehler gibt's viele. Teilweise mache ich durch das Fixen von Bugs alte Stücke, deren Rezept ich noch gespeichert hatte, kaputt. Damit muss ich wohl leben; Rückwärtskompatibilität kann ich einfach nicht gewährleisten, solange ich immer mal wieder an den Grundlagen schraube. Aber insgesamt wird es momentan in sich konsistenter.

Ich lad auch bald wieder neue Stücke hoch. Anhören tut sie quasi niemand.^^ Ein Stück hat zwei Dislikes und sonst nix, das finde ich ziemlich amüsant. Ich selbst hab viel Spaß daran. Zum Erhalt meiner psychischen Gesundheit muss ich nämlich jeden Tag spazieren gehen, und dabei hör ich mir dann die Stücke an. In Zukunft werd ich dann wohl an die erste Pandemiewelle, die Dürre und an die (fast) immer-gleiche Spazierstrecke denken, wenn ich die wieder höre.^^


Was ich bald implementieren will:

- die eine oder andere Funktion, die auf der Zeitachse läuft. Zum Beispiel sowas wie eine Sinuskurve über die Tonhöhen. Vermutlich eher albern, aber was solls, wär recht einfach zu implementieren, und ist noch mal was anderes.

- die Selektoren benötigen ebenfalls eine Generalüberholung (bei denen wär's dann schon die zweite). Ich will ein Feature, das es erlaubt, bevorzugt bei einer bestimmten Tonhöhe zu selektieren (im Moment gibt es da nur: höchster Ton, niedrigster Ton, und mittlerster Ton. Das ist ausbaubar.)

- und einen Selektor will ich einbauen, mit dem vor 4 Jahren mal die erste Version von AlgoLine begonnen hat: Wähle nur einen Ton aus, wenn es nur genau eine bestbewertete Tonhöhe gibt - sonst Stille. Das führte damals zu Stücken die relativ bald in sich selbst zusammenfielen und einfach aus waren. Aber mit der Menge an Instruktionsoptionen, die ich mittlerweile habe, dürfte das anders sein. Bzw. ich kann diesen Selektor ja zu anderen dazuschmeißen.^^

Sonntag, 26. April 2020

AlgoLine B (work in progress)

Die letzten Tage wurde wieder etwas am Programm geschraubt. Ich habe neu eine sustain Instruktion eingebaut, die das Halten von Tönen für bestimmte Längen veranlasst, und dazu auch gleich ein modulo Keyword. Ein Halten von Tönen für Längen kongruent mit 0 modulo 8 erzeugt, wenn es stark genug gewichtet ist, für einen regelmäßigen langsameren Puls, der sich durch das Stück zieht.

(Es ist oft so, dass sich das Gewichtsverhältnis von Instruktionen im Verlauf ändert - im Test hatte ich auch ein Stück, das am Anfang einem klaren Puls folgt, der aber nach einer Weile zusammenbricht und ab dann überhaupt nicht mehr erkennbar aufscheint.)

Modulo ist ein wichtiges Keyword; ich will das bei einigen anderen Instruktionen einbauen. Schon gesehen ist dies bei same_intervals, wo es eine besonders große Rolle spielt - es ist also jetzt möglich, dass diese Instruktion z.B. ein Intervall aufwärts zu einem C und zwei Oktaven abwärts zu einem C als das gleiche ansieht. Auch möglich ist es, Intervalle als gespiegelt zu betrachten, sodass 5 Schritte aufwärts und 5 Schritte abwärts gemeinsam gezählt wird. (same_intervals zählt von Anfang an mit, welche Intervalle schon im Stück sind, und vermeidet oder bevorzugt je nach Häufigkeit)

Leider führt das im Moment zu einer deutlich höheren Rechenzeit - zwar speichere ich die verwendeten Intervalle während dem Generieren mit, aber das tue ich nur für die tatsächlichen, nicht für Modulo. Und da die "Notenzeile" selbst nicht wissen kann, welche Modulo später über sie angewendet werden, kann ich das auch nicht so ohne weiteres mitspeichern. Daher müssen für jeden Schritt alle Intervalle von Anfang an wieder durchlaufen werden, was ein enormer Aufwand ist. Mal sehen, ob ich das geschickter hinkriege - eigentlich müssten ja eher die Instruktionen mitspeichern. Im Moment führt das dazu, dass das Generieren geschätzt zehnmal langsamer abläuft. (Vermutlich noch durch andere Faktoren beeinflusst - allmählich summiert sich schlechte Implementierung auf.)

~

Ein grundsätzliches Problem ist, dass alle Instruktionen aufsummiert werden, aber das Auswählen der Töne auf Basis von den Besten funktioniert. D.h. wenn eine Funktion bewirkt, dass Töne a, b, c, d, e, ... um +1000 bevorzugt werden, aber eine andere bewirkt, dass Ton b um +1 bevorzugt wird - dann ist b alleine der beste Ton und alle fast gleichen anderen werden ignoriert.

Damit das nicht so ist, gibt es jetzt das Selector-Keyword threshold. Damit ist z.B. eine Auswahl aus der Menge aller Töne mit einer Bewertung von den mit 98% bis 100% des jeweiligen Maximalwertes möglich.

Exzessiv angewandt habe ich dieses Keyword in Fumbling Important Extremely Talon. Dort gibt es an Instruktionen überhaupt nur das allereinfachste avoid same_pitches, und die eigentliche Arbeit machen die Selektoren - die entweder die tiefsten oder die höchsten Werte auswählen, allerdings aus vielen verschiedenen Prozentbereichen. Darunter auch so niedrige wie 15% - 25%. Das heißt, dass schlecht bewertete Töne nach einer Weile auch ausgewählt werden, was dazu führt, dass unter einer Aufwärtsbewegung allmählich weitere entstehen. Die durcheinanderlaufenden Geraden mit unterschiedlicher Steigung sind auch optisch schön, ich habe aber leider kein Bild davon erstellt.

~

Im Moment ist der Code an vielen Stellen chaotisch und es gibt Inkonsistenzen gegenüber der Eingabe und der Ausgabe, was natürlich absolut nicht ideal ist, da ich ja die Rezepte aus dem Programm wieder als Text speichern können möchte, und zwar exakt der Eingabe entsprechend.

Je mehr Keywords ich hinzufüge, desto größer wird das Chaos, da es dieses und jenes Keyword bei der einen Instruktion gibt und bei der anderen nicht, und sie überall mehrfach implementiert sind. (Bis zu einem gewissen Grad notwendig, da sie verschiedene Dinge tun.) Für die wichtigsten Keywords möchte ich das aber ändern, sie sollen gemeinsam erfasst werden, und nur bei den Instruktionen einen Effekt haben, bei denen es eine Implementierung dafür gibt.

Etwas, was ich außerdem gerne einführen möchte, ist ein Keyword start, das bewirkt, dass eine Instruktion erst ab einer gewissen Stelle hinzugeschaltet wird. Eigentlich wollte ich das ursprünglich gar nicht, da ich es interessanter fand, wenn Veränderungen allein aus den immer-geltenden Instruktionen, die gegeneinander greifen, entstehen... aber mal sehen. Interessanter ist vielleicht das Keyword end. Denn oft ist es ja so, dass eine Instruktion unbedingt notwendig ist, damit am Anfang ein bisschen "Chaos" erzeugt wird, und z.B. vermieden wird, dass nur Tonleitern übrigbleiben. Sobald das aber einmal geschehen ist, läuft es eigentlich auch ohne dieser interessant weiter.

~

Zum Abschluss: Cute demon faces! <3


Ich habe den Graphikbereich um einiges verbreitert - weil ich zwischendurch mal Achtzehnteltöne implementiert habe, für die schlicht nicht mehr genug Pixel da waren - und so sieht es jetzt aus. Am GUI arbeite ich selten. Es gibt eine Reihe von praktischen Tastenkürzeln, d.h. die Buttons auf der rechten Seite sind nur ein paar der Befehle, die es gibt.

Ein Uploads stehen an, für die muss ich jetzt aber erst noch Bilder machen. Theoretisch wäre es wohl interessant, eine Aufnahme vom Programm in Bewegung zu sehen, wie ich das beim alten AlgoLine gemacht habe - aber in der Praxis läuft mein Rechner bereits heiß und der surrende Lüfter packt es fast nicht mehr. Es macht mir aber auch Spaß, passende Bilder zu finden/erstellen, und es verkürzt die Video-Erstellungszeit um ... eigentlich quasi alles, also Faktor 1000 oder sowas.^^






Freitag, 27. März 2020

AlgoLine B: "Voice Shadow Glitter Eventuality" und mehr...

Heute hab ich am Programm selbst keine Veränderungen gemacht, sondern Parameter geschraubt und Stücke generiert. Ich mag das Ergebnis:

1. Untrue Island Mess Linguist
2. Voice Shadow Glitter Eventuality
3. Well Nothing Thought Splash

In allen drei Fällen habe ich nachträglich einen Low-Pass-Filter darübergelegt - hohe Töne sind einfach generell lauter bei MIDI, und dem muss ich entgegen wirken. Well Nothing hat außerdem noch deutlich mehr Nachhall verpasst gekriegt.

Das Muster ist jeweils ähnlich. Der zentrale Bestandteil:

avoid 1 same_interval except 0 .. ..
avoid 1 same

Es werden also sowohl Tonwiederholungen als auch Intervallwiederholungen vermieden, mit Ausnahme vom 0-Intervall (also ein liegender Ton). Das führt prinzipiell mal zu einem Muster von anfänglichen Chaos, das sich allmählich sortiert zu immer längeren Liegetönen oder Akkorden.

Zweitens gibt es eine Auswahl von Präferenzen für verschiedene Modi - bzw. eigentlich den selben Modus in unterschiedlichen Transpositionen. Indem es der selbe ist, ist es nämlich leichter, Überlappungen zu verhinden, die einzelne Töne herausstechen ließen. Für die ersten beiden Stücke ist es jeweils ein Quarten-Turm-Modus, leicht mikrotonal verschoben.

Und schließlich Rampen, die dafür sorgen, dass bestimmte Register gegenüber anderen bevorzugt oder benachteiligt werden - was eine temporäre Sache ist, da "avoid same" alle Unterschiede im Laufe der Zeit ausgleicht.

Für die ersten beiden Stücke habe ich das Rezept leider nicht zwischengespeichert, das dritte hab ich hingegen und kann es hier vollständig präsentieren:

~ ~ ~

Well Nothing Thought Splash

Twelfthtone

avoid 12 same_intervals except 0 114 -114 144 -144
avoid 12 same

avoid 1 ramp_region 100 0
avoid 1 ramp_region 240 0
avoid 1 ramp_region 500 200
avoid 1 ramp_region 400 500

prefer 512 set modus 12 12 10 8 12 18
prefer 256 set modus 12 12 10 8 12 18 offset 7
prefer 128 set modus 12 12 10 8 12 18 offset 5
prefer 64 set modus 12 12 10 8 12 18 offset 8
prefer 32 set modus 12 12 10 8 12 18 offset 4
prefer 16 set modus 12 12 10 8 12 18 offset 9
prefer 8 set modus 12 12 10 8 12 18 offset 3
prefer 4 set modus 12 12 10 8 12 18 offset 10
prefer 2 set modus 12 12 10 8 12 18 offset 2
prefer 1 set modus 12 12 10 8 12 18 offset 11
prefer 1 set modus 12 12 10 8 12 18 offset 1

prefer 16 set modus 72
prefer 16 set modus 72 offset 7
prefer 16 set modus 72 offset 5
prefer 16 set modus 72 offset 8
prefer 16 set modus 72 offset 4
prefer 16 set modus 72 offset 9
prefer 16 set modus 72 offset 10
prefer 16 set modus 72 offset 2
prefer 16 set modus 72 offset 11
prefer 16 set modus 72 offset 1

select lowest 3 apathetic
select lowest 3
select middleregister 1
select middleregister 3 apathetic

dimension 500
lowest_pitch 20

~ ~ ~

(In der Aufnahme wird dieses Rezept rückwärts abgespielt - deswegen die glockenhafte Zunahme des Chaos ganz am Ende.)

Ich habe bereits angefangen, ein Usermanual zu schreiben - dann kann ich das Programm auch mal anderen Menschen in die Hände geben. :)

Freitag, 20. März 2020

AlgoLine B (Work-in-Progress)

In den letzten Tagen hat sich die Motivation, an AlgoLine zu arbeiten, etwas verflüchtigt. Aber ein bisschen etwas geht doch immer weiter.

So sieht der Player derzeit aus:



Die wesentliche Änderung - neben dem, dass es jetzt auch wieder möglich ist, während dem Abspielen Tempo und Instrument zu ändern - ist, dass ich das Design der Selectors doch nochmal überdacht habe.

Deren Interface lässt jetzt auch Parameter zu, anstatt bloß aus "nimm diesen Selector" zu bestehen.

"select lowest 5" bedeutet naheliegenderweise, unter den gerade bevorzugten Tönen die fünf untersten auszuwählen, etwas verwirrender ist das Schlüsselwort "apathetic" - es wählt genau diejenigen Töne aus, deren Bewertung in der Mitte zwischen "am meisten bevorzugt" und "am dringendsten vermieden" liegen.

In einem Stück sowohl höchstbewertete als auch mittelbewertete Töne auszuwählen, führt zu einer interessanten Mehrstimmigkeit, da sich die beiden doch etwas anderes verhalten.

Das nächste Vorhaben ist die Implementierung von ein paar intervallbezogenen Instruktionen.

Dabei bin ich gespannt auf eine Interaktion zwischen:
prefer interval 3
prefer interval -3

Das müsste nämlich - so meine naive Annahme - dazu führen, dass Töne liegenbleiben, wenn sie im Abstand von 3 liegen. Vielleicht lassen sich damit Präferenzen für bestimmte Akkorde einbauen. Aber wahrscheinlich kommt es wieder komplett anders als ich mir das jetzt vorstelle.^^

Dienstag, 17. März 2020

AlgoLine B (Work-in-Progress)

#bingecreating heißt es in diesen Quarantänezeiten. Es hat sich also gut getroffen, dass ich ohnehin gerade diesen Monat ein Projekt, das ich lange liegen habe lassen, wieder frisch angehen wollte: AlgoLine.

(Lange liegen lassen aus gutem Grund: Ich hatte mir vor 2 Jahren gesagt, dass ich erst dann wieder daran weitermache, wenn mein Orchesterstück und meine Diplomarbeit fertig sind.)

Der Code von 2016, das stellte sich nach kurzer Begutachtung heraus, war absolut grauenhaft; wüstes Durcheinander von Referenzen, unklar benannten Variablen, einem Mischmasch aus Deutsch und Englisch... daran weiterzumachen, hatte ich echt keine Lust. Also nochmal komplett neu anfangen.

Im Gegensatz zu AlgoLine A (wie ich die alte Version jetzt mal nenne), wo es keinerlei Interface gab, um die Generation des Stücks zu beeinflussen (alle Befehle dafür standen direkt im Code) wollte ich es diesmal so anlegen, dass auch andere Personen theoretisch etwas damit anfangen können. Daher gibt es zu jedem Algorithmus, der im Programm zur Verfügung steht, eine äquivalente Textzeile - damit ist sowohl laden als auch speichern möglich, und vor allem, die Anweisungen können vorher in ein txt-File geschrieben werden.

Ich überlege im Moment noch, was ich noch alles in diese "Rezepte" hineinnehme. Derzeit besteht noch jedes Rezept aus drei Teilen:

1) Auswahl der StepWidth, standardmäßig 12 Töne pro Oktav, möglich sind aber auch 24, 36, 48, 60 und 72. Intern gelöst ist das, indem ich z.B. für Vierteltöne einen zweiten Midi-Channel zuziehe, dem zur Initialisierung einmal ein PitchBend-Befehl zugewiesen wird, alles um einen Viertelton höher abzuspielen. Für die 72-stufige Oktav sind es dann schon 6 Kanäle. Noch kleinere Abstände wären also theoretisch noch möglich, aber praktisch ist es schon bei Zwölfteltonschritten schwer, einen Unterschied zu hören.

2) Die Instructions, jeweils eine Zeile pro Instruktion. Diese dienen alle dazu, zu entscheiden, welche Tonhöhen für einen neuen Schlag ausgewählt werden, basierend auf den bisherigen oder ohne Kontext. Jede Instruktion liefert einen positiven oder negativen Wert für jede einzelne auswählbare Tonhöhe. Die Werte aller Instruktionen werden dann addiert, und das Gesamtergebnis an die Selectors weitergegeben.

3) Die Selectors, deren Aufgabe es ist, basierend auf den Bewertungen eine Auswahl zu treffen. Mit "die am höchsten bewertete Tonhöhe" allein ist es nämlich noch nicht getan, denn da gibt es häufig Gleichstände. Ein AllSelector wählt in diesem Fall einfach alle aus, während ein LowNoteSelector sich jeweils nur die tiefste herauspickt. (Meistens mit der Konsequenz, dass die übrigen der Reihe nach von unten nach oben abgearbeitet werden) Es gibt auch noch die Möglichkeit, einen LowNoteReverseSelector zu verwenden, der wählt dann nicht aus den höchstbewerteten, sondern aus den niedrigstbewerteten Tonhöhen jeweils den tiefsten Ton aus.

Das Eingeben/Speichern/Laden von Rezepten passiert in der Konsole, erst nach dem Generieren eines Stückes startet der Player - dessen GUI ich zumindest mal angefangen habe:

Die roten Punkte in der Mitte sind die aktuell klingenden Tonhöhen. Alles darüber ist vergangen, das darunterliegende kommt noch. Je heller der Grauton, desto höher die Bewertung für die einzelne Tonhöhe.

Rechts wird es eine Buttonspalte geben. Da ist vorläufig nur mal ein paar bunte Quadrate anzuklicken; später soll da noch draufstehen, was der Button tut, und welches Tastaturkürzel stattdessen auch verwendet werden könnte.

Unten gäbe es eine Anzeige für die Tonhöhen, aber bei den Zwölfteltonschritten sind es einfach zu viele, als dass es sich gut darstellen ließe. Da muss ich noch etwas überlegen, wahrscheinlich werden dann nur bestimmte Tonspalten beschriftet, anstelle von allen.

~

Vorhin hab ich mal das erste neue Stück auf Youtube hochgeladen:

Sweet Soil Exhort Navel

 Davon kann ich hier das gesamte Rezept vorstellen:

// Sweet Soil Exhort Navel 2020-02-17

TWELFTHTONE

prefer 4000 set modus 28 5 14 28 5 14 14 5 offset 3
prefer 1600 set modus 14 14 14 5 14 14 5 offset 7
prefer 400 set modus 14 14 14 5 14 14 5 offset 10
prefer 100 set modus 14 14 14 5 14 14 5 offset 11
prefer 25 set modus 14 14 14 5 14 14 5 offset 2
prefer 5 set modus 14 14 14 5 14 14 5 offset 8
prefer 1 set modus 14 14 14 5 14 14 5 offset 9

avoid 100 sameas -300 to -200 ramp
avoid 200 sameas -2000 to -1000 ramp
avoid 1 sameas -900 to -1 ramp

avoid 10 same

AllSelector

~

Jede Instruktionszeile beginnt entweder mit "avoid" oder "prefer", was im Prinzip ein Vorzeichen darstellt. Die Zahl danach ist ein Verstärker, der die Zeile im Verhältnis zu den anderen gewichtet. (Was nicht immer ganz so gut funktioniert, da manche Instruktionen einfach um ein Vielfaches stärker sind als andere.) "Modus" ist eine von mehreren Möglichkeiten, eine Menge an Tonhöhen herauszupicken, die vorzuziehen sind. Die Zahlen geben die jeweiligen Intervalle an - in semitonaler Musik (^^) würde 2 2 1 2 2 2 1 eine Durtonleiter vom untersten Ton an beschreiben. Mit Offset-Wert versetze ich die Skala dann noch ein Stück.

"sameas" lässt einen Bereich in der Vergangenheit definieren, und Noten von dort vermeiden oder bevorzugen. "avoid sameas -4 -2" würde sagen, dass die Noten vom vorletzten bis vorvorvorletzten Schlag (?) zu vermeiden sind. "ramp" ist ein mächtiger kleiner Zusatz: Da wird fließt nämlich ein Ton umso mehr in die Wertung ein, je näher er am Jetztzeitpunkt ist. Und da ich das nicht gut skaliert habe, heißt das, dass eine 100-Töne lange Rampe de facto den letzten Schlag 100mal gewichtet.^^

"Avoid same" ist die simpelste Instruktion, die aber fast immer gut ist, dabeizuhaben... das Stück zählt mit, wieviele Noten es von einer Tonhöhe schon gab, und wertet sie niedriger, je mehr es sind. Führt dann also dazu, dass Tonhöhen, die lange Zeit nicht vorkamen, irgendwann doch durchbrechen.

~

TODO:

- das GUI ist ja erst halbfertig. Da kommt noch eine Möglichkeit, Spieltempo und Instrument zu verstellen, neben anderem wichtigen Kram.

- neue Algorithmen! Die Schwierigkeit ist hier, etwas zu finden, das nicht enorme Rechenzeit oder Speicherplatz braucht. "avoid same" funktioniert nur, weil ich die Töne beim Generieren schon mitzähle.

Ich möchte aber gerne ein "avoid same-intervals", und da muss ich gerade noch überlegen, wie ich das genau definiere. Damit das geht, würde ich für jeden Schlag speichern, welche Intervalle er gegenüber zum vorigen beinhaltet. Bei einzelnen Noten geht das ja, aber bei Akkord zu Akkord? Da steigt die Anzahl der möglichen Intervalle ja schnell an. Dreiklang zu Dreiklang beinhaltet 9 Intervalle: Von jedem Ton des ersten Klangs zu jedem Ton des zweiten...

Wenn ich die bloß als Menge (Set) speichere, verliere ich noch die Information, wie oft ein Intervall auftaucht. Hmm...

- mal ein paar Standardrezepte als kommentierte txt-Files erstellen, damit es für andere verständlicher wird.

- mich entscheiden, ob die "dimension" - Anzahl der verschiedenen Tonhöhen eines Stücks - und der Offset von den tiefsten Midipitches auch Teil des Rezepts werden sollen. Da hab ich nämlich beim Rezept oben vergessen, zu erwähnen, dass es auf eine Dimension von 400 angewendet wurde, um das Stück zu erzeugen.

- danach suchen, ob AllSelector nicht doch noch irgendwo einen Bug hat, der dazu führt, dass aufwärtslaufende Girlanden entstehen, wo es ja eigentlich keine Bevorzugung der Tonhöhe geben sollte. o_0

Samstag, 14. März 2020

Üpdäätle -52-

Viel ist passiert in den letzten Monaten...

Zunächst - meine Diplomarbeit wurde im Januar fertig und ist abgegeben. Ich kann also demnächst meinen Abschluss machen... vorausgesetzt, es finden überhaupt noch Prüfungen statt.^^

Ich bin am Ende sogar recht zufrieden gewesen mit meiner Arbeit - einige Ideen zum Einvierteltakt bei Ustwolskaja, über die ich gerne schreiben wollte, habe ich letztlich untergebracht. Der ganze Prozess, bist das Ding gedruckt und schließlich bewertet war, hat nochmal ein Monat gedauert.

~

Im Februar habe ich mir wieder eine große Playlist mit Neuer Musik zusammengestellt. Eventuell werde ich darüber noch etwas schreiben - aber im Moment bin ich anderweitig beschäftigt:

Ich arbeite nämlich gerade an einer neuen Version von AlgoLine, meinem Programm für algorithmische Musik... der Code der alten Version, von 2016, erwies sich als absolut unbrauchbar: schlecht strukturiert und wenig ausbaufähig. Also hab ich komplett von vorne begonnen.

Mein Ziel ist:

Ein Programm, das in der Konsole oder aus einem Txt-File einige Instruktionen einliest, und daraus dann automatisch ein Stück generiert, das dann im Player (mit Midi) abgespielt werden kann.

Außerdem soll das ganze noch Vierteltöne unterstützen, dachte ich mir ... und wo ich schon dabei war, hab ich das gleich noch zu Sechsteltönen erweitert und ... bis zu Zwölfteltönen. Darauf freue ich mich schon sehr, zu hören, wie das so klingen wird.

Bis jetzt habe ich:

- Eingabe und Ausgabe von Instruktionen (jedenfalls dem dutzend Standardalgorithmen, mit denen ich anfange, das ist aber relativ leicht später erweiterbar)

- Den Teil, der tatsächlich ein Stück generiert... der ist noch nicht fertig, aber es ist alles dafür nötige da, und muss nur noch zusammengebaut werden

- Die allererste Planung für die visuelle Gestaltung des Players. Das ist der schwierigste Teil. (Mit GUI kenn ich mich einfach zuwenig aus, und es ist frustrierend, zu wissen, dass ich da eher pfusche ... aber funktionieren wirds, immerhin tat das die Version von 2016 auch.)

Noch zu tun ist also, das GUI fertig zu stellen, und dann alles nochmal miteinander zu verbinden - und dann steht nichts mehr im Wege, nach Anweisungen im txt.-Format Zwölfteltonkompositionen zu generieren. :)

Derweil höre ich neben dem Programmieren die kompletten Streichquartette von Alois Hába - schonmal Vierteltöne schnuppern. Bei meinen eigenen Midi-Stücken im Dezember habe ich festgestellt, dass für mich kleinere Unterteilungen tatsächlich besser funktionieren - etwas wie Sechsteltöne, oder Achteltöne, scheint mir im Hören intuitiver. Seltsam.