Col-Tracker, part VIII

La première partie de cette série est disponible ici.

Le silence c’est compliqué

L’éditeur d’instruments avec stages séparés fonctionne, et on peut maintenant jouer une pattern sur 2 canaux (le 1 et le 2).

Pour le 3ème canal, il reste un problème à cause des silences…

J’ai écrit un algorithme pour générer des silences entre les notes de la façon la plus optimale (c’est à dire qui prend le moins d’octets sur la cartouche de la Colecovision) et ça m’a appris beaucoup sur la façon dont le BIOS décode les notes.

Il y a une commande « rest » qui sert à faire des pauses. Celle-ci utilise 5 bits pour la durée de la pause (en nombre de frames, c’est à dire en 1/50 secondes pour une console PAL et en 1/60 secondes pour NTSC). Je pensais que lorsque ces 5 bits étaient à zéro la pause serait de 32 frames (25=32), mais en fait cela fait une pause de 256 frames ce qui est à la fois surprenant et totalement non-documenté(*).

Petit détail amusant, j’avais constaté ce comportement en regardant les sources de l’applet Flash de Daniel Bienvenu, et je pensais qu’il avait fait une erreur (désolé Daniel :o) ). Heureusement c’était un bug facile à corriger, donc maintenant tout devrait fonctionner, non ?

Non… Ca fonctionne bien sur les canaux 1 et 2, mais pas sur le canal 3.

Le problème vient également de la commande « rest« .
Le format de celle-ci est :  » <nº de canal sur 2 bits> 1 <durée sur 5 bits> « .

Lorsqu’on veut faire une pause de 31 frames sur le canal 3, ça donne « 11111111« , ou 0xFF en hexadécimal. Hors, 0xFF est aussi utiliser pour indiquer qu’un canal n’a aucune note.

J’ai supposé en lisant la documentation technique que ça ne fonctionnait que lorsque 0xFF était au début des données du canal, mais en fait dès qu’un 0xFF est présent dans un canal (à la place d’une note) celui-ci s’arrête.

J’ai d’abord pensé à faire un algorithme différent et un peu moins optimisé pour le canal 3 afin de ne jamais avoir de 0xFF mais j’ai réalisé qu’il me faudrait aussi un algorithme différent pour la canal 0 (celui des bruits blancs)(**).

A la place, j’ai essayé une solution un peu plus exotique : Puisque chaque canal « logique » a une priorité, et peut jouer des notes sur plusieurs canaux « hardware« , je vais générer toutes les pauses sur le canal « hardware » 1.

Si je donne au canal « logique » 1 la priorité la plus grande, quand un des autres canaux va essayer de jouer un « rest« , ils vont être suspendus jusqu’à ce que ce canal « hardware » 1 soit disponible. Ca devrait fonctionner cette fois, non ?

Après un test rapide ça a l’air de fonctionner mais il faut que j’implémente cette solution pour pouvoir tester tous les cas. Ca ne fonctionne pas du tout dans l’applet Flash par contre, mais je peux toujours générer des données différentes pour celle-ci (par exemple en remplaçant « 0xFF » par « 0xF 0xE1 » (pause de 30 frames, puis pause de 1 frame)).

Essayons ! :o)

La neuvième partie de cette série est ici.

(*) En fait, je pense que c’est un effet de bord de la manière dont le code à été écris : La valeur sur 5 bits est copiée dans un registre 8 bits (les 3 bits supérieurs sont mis à zéro), puis une pause d’une frame est effectuée et le registre est décrémenté ; la commande se termine quand le registre contient zéro, mais si on part de zéro, celui-ci sera décrémenté avant le premier test, et contiendra alors 255, ce qui entraîne une durée de 256 frames.

(**) En effet ce canal ne supporte pas les « Frequence sweep » que j’utilise beaucoup dans les silences car ça permet d’avoir une pause de 4096 frames pour seulement 6 octets.

2 commentaires sur “Col-Tracker, part VIII

Laisser un commentaire