vendredi 5 avril 2013

[Instant Prog] Long Line Theory


Salut à tous! J'aime bien l'ésotérisme, l'art de faire/programmer différemment. Par exemple les langages ésotériques de programmation sont nombreux, comme le fameux Brainf*ck et l'obscur INTERCAL. Il y a quelques temps, en cherchant du contenu sur la génération procédurale, la génération par algos et formules ( la génération des maps dans Minecraft est un exemple de génération procédurale ), je suis tombé sur ceci:



L'idée est de générer une valeur en fonction de la variable t sans cesse croissante. C'est l'équivalent d'un graphe d'une fonction, dont le résultat a été redirigé vers la sortie audio ( prog >> /dev/audio pour nos amis de Linux).
Certains patterns sont étrangement musicaux, par le miracle de la théorie des sons...
Mais une formule est plus intéressante en particulier que les autres...

- La théorie des sons, ou pourquoi les oreilles saignent -

Le son n'est que vibration. Touchez votre gorge et sortez une note grave (pas un rot gras, bande de cochons). Vous sentez vos cordes vocales trembler? Maintenant, élevez la note vers les aigus.  Vos cordes vocales tremblent tout autant, mais plus vite ! Vous venez de toucher votre gorge, mais aussi le principe fondamental du son: un son ne se produit qu'avec une vibration (compression/dilatation) du milieu auquel l'onde sonore se propage.


Je ne vais pas m'attarder longtemps sur ce sujet, mais sachez une chose principale pour ce qui suit : on peut combiner deux ondes sonores rien qu'en les additionnant. D'où les accords de guitare/piano/[INSERT YOUR INSTRUMENT HERE]…

- La vidéo, ou comment qu'yzontfait -

Info pré-blablative: les formules sont de la forme C-Like (C++, JS, Java, PHP, etc...), les priorités sont conservées. Le résultat est l'équivalent d'un unsigned char ( entier positif de 0 à 255 inclus ).
Revenons à notre vidéo, et observons. Vous entendez ce que la formule produit. Si vous regardez bien, on peut voir quelques patterns revenir, comme celui-ci:

t*b&t>>a, où a et b sont des entiers positifs.
On obtient un équivalent algorithmique du Triangle de Sierpinski. [Insérer ici image du triangle]. C'est cette forme qui donne cette tonalité. Vu la forme fractale du triangle, et vu sa composition en gruyère géométrique, on peut voir que par moments, plusieurs notes sont en simultanées, additionnés. Je vous renvoie au paragraphe sur la théorie du son! :p

- Long Line Theory -

Dans la vidéo, en 5:12, il y a un truc qui ressemble à de la vraie musique! Oo' Par quel maléfice? Par quelle magie mathématique? En trois lettres : WTF?!

Pour résumer, la musique est une "adaptation" de la bande sonore du demo Chaos Theory, que voici (à voir en HD):

C'est avant tout un bon gros exemple de ce que je pourrais appeler des modules musicaux : des portions de la formule sont utilisés, et assemblés juste en les ajoutant. C'est tout! C'est tout, mais c'est gros et indigeste... Voici la formule :

w=t>>9,k=32,m=2048,a=1-t/m%1,d=(14*t*t^t)%m*a,y=[3,3,4.7,2][p=w/k&3]*t/4,h="IQNNNN!!]]!Q!IW]WQNN??!!W]WQNNN?".charCodeAt(w/2&15|p/3<<4)/33*t-t,s=y*.98%80+y%80+(w>>7&&a*((5*t%m*a&128)*(0x53232323>>w/4&1)+(d&127)*(0xa444c444>>w/4&1)*1.5+(d*w&1)+(h%k+h*1.99%k+h*.49%k+h*.97%k-64)*(4-a-a))),s*s>>14?127:s

Un petit lien pour écouter le rendu : Long Line Theory

Ah ah... Un bon gros truc bien indigeste, ou pas. Faut se la jouer enzyme glouton et décomposer la formule en modules. Je vais vite vous résumer quelques opérateurs dispos particuliers
  • | = or binaire (or bit à bit)
  • & = and binaire (and bit à bit)
  • && = and (si les deux valeurs sont non nulles)
  • % = modulo (reste de la division euclidienne)
  • >> décalage a droite ( division par puissances de 2)
  • << décalage à gauche ( multiplication par puissances de 2 )
Ca devrait aller. Maintenant, voici je que j'ai tiré de la formule!

---- Stabilisateur ----

--Formule extraite :
s*s>>14?127:s
--Permet d'avoir un son correct et sans altérations... BIzarrement, LLT a un rendu carrément moche sans.

---- Delayeur ----

--Formule extraite :
w>>7 //&& après, pour que cela serve de condition
--Ca permet juste à la musique de commencer plus tard que le début. C'est totalement facultatif.

---- Base ----

--Formule extraite :
y*.98%80+y%80
--C'est les trois notes en boucle que l'on entend dès le début.
--Dépendances :
w=t>>9,k=32,
a=1-t/m%1,
y=[3,3,4.7,2][p=w/k&3]*t/4,h="IQNNNN!!]]!Q!IW]WQNN??!!W]WQNNN?".charCodeAt(w/2&15|p/3<<4)/33*t-t,
--Formule complète avec dépandances:
w=t>>9,k=32,m=2048,
a=1-t/m%1,
y=[3,3,4.7,2][p=w/k&3]*t/4,h="IQNNNN!!]]!Q!IW]WQNN??!!W]WQNNN?".charCodeAt(w/2&15|p/3<<4)/33*t-t,
s=y*.98%80+y%80
,s*s>>14?127:s
-- URL pour le rendu : Rendu

---- Drum ----

--Formule extraite :
a*((5*t%m*a&128)*(0x53232323>>w/4&1))
--J'aime bien ce drum. Je le trouve bien fichu. je m'en servirais bien comme ssample dans Famitracker, tiens!
--Dépendances :
w=t>>9,m=2048,
a=1-t/m%1,
--Formule complète avec dépandances:
w=t>>9,m=2048,
a=1-t/m%1,
s=a*((5*t%m*a&128)*(0x53232323>>w/4&1))
,s*s>>14?127:s
-- URL pour le rendu : Rendu

---- Noise ----

--Formule extraite :
a*((d&127)*(0xa444c444>>w/4&1)*1.5)
--Le noise, qui pourrait remplacer une cymbale ici va de pair avec le drum de plus haut...
--Dépendances :
w=t>>9,m=2048,
a=1-t/m%1,
d=(14*t*t^t)%m*a,
w=t>>9,m=2048,
--Formule complète avec dépandances:
w=t>>9,m=2048,
a=1-t/m%1,
d=(14*t*t^t)%m*a,
s=(d&127)*(0xa444c444>>w/4&1)*1.5
,s*s>>14?127:s
-- URL pour le rendu : Rendu

---- ??? ----

--Formule extraite :
(d*w&1)
--??? Ce truc ne sert absolument à rien! J'ai comparé LLt avec et LLt sans sur chaque oreille, et aucune différence. Et seul... Pas un bruit...
--Dépendances :
w=t>>9,m=2048,
a=1-t/m%1,
d=(14*t*t^t)%m*a,
--Formule complète avec dépandances:
w=t>>9,m=2048,
a=1-t/m%1,
d=(14*t*t^t)%m*a,
s=(d*w&1)
,s*s>>14?127:s

---- Mélodie ----

--Formule extraite :
a*((h%k+h*1.99%k+h*.49%k+h*.97%k-64)*(4-a-a))
--Voilà la mélodie qu'on entend, et celle qui fait que la musique est complète!
--Dépendances :
w=t>>9,k=32,m=2048,
a=1-t/m%1,
y=[3,3,4.7,2][p=w/k&3]*t/4,h="IQNNNN!!]]!Q!IW]WQNN??!!W]WQNNN?".charCodeAt(w/2&15|p/3<<4)/33*t-t,
--Formule complète avec dépandances:
w=t>>9,k=32,m=2048,
a=1-t/m%1,
y=[3,3,4.7,2][p=w/k&3]*t/4,h="IQNNNN!!]]!Q!IW]WQNN??!!W]WQNNN?".charCodeAt(w/2&15|p/3<<4)/33*t-t,
s=a*(h%k+h*1.99%k+h*.49%k+h*.97%k-64)*(4-a-a)
,s*s>>14?127:s

--URL pour le rendu : Rendu

Voilà... Ca fait un GROS pavé. Pour résumer, j'ai séparé chaque module, j'ai mis à coté les modules dont il dépend, et j'ai mis à chaque fois une formule qui marche... Ca n'aide que peu pour comprendre LLT, mais je peux désormais résumer la formule ainsi:

---- Long Line Thoery Explained ----
---- By Eiyeron, based on a work by ryg, p01 et al. ----
---- 2013 http://retro-actif.blogspot.com ----
w=t>>9,k=32,m=2048,
a=1-t/m%1,
d=(14*t*t^t)%m*a,
y=[3,3,4.7,2][p=w/k&3]*t/4,h="IQNNNN!!]]!Q!IW]WQNN??!!W]WQNNN?".charCodeAt(w/2&15|p/3<<4)/33*t-t,
delai=w>>7,
base=y*.98%80+y%80,
drum=a*((5*t%m*a&128)*(0x53232323>>w/4&1)),
noise=a*(d&127)*(0xa444c444>>w/4&1)*1.5,
melo=a*(h%k+h*1.99%k+h*.49%k+h*.97%k-64)*(4-a-a),
s=base + (delai&&(drum + noise + melo))
,s*s>>14?127:s

Voilà à quoi ressemble Long Line Theory quand on la décortique et qu'on donne des noms aux parties! Admettez que c'est plus compréhensible à présent! Vous pouvez même vous amuser à customiser la formule maintenant que tout a été réduit!
Et voici le lien pour l'écouter!
Et un autre lien pour comparer les deux formules, chacune sur une oreille : 
Ah oui,  par info, le machin coloré que vous voyez représente les visualisations des deux oreilles : rouge et vert pour chacune en indépendant, et jaune quand les valeurs sont égales des deux cotés. Ici, vous voyez que c'est jaune partout, c'est donc identique!

Voilà voilà. Un si gros pavé pour quelques secondes sonores... Bah, question progo, ça vaut le coup de jeter un coup d'oeil, surtout quand après, on peut s'amuser à customiser le résultat! ( Un exemple ici: LLT Delayed)
Bon, j'ai bien tapé pour aujourd'hui, je vous laisse vaquer à vous occupations, bye!

1 commentaire:

  1. Très beau billet, tu t'es beaucoup amélioré par rapport à tes débuts ;)

    RépondreSupprimer