Prehisto a écrit:
Un bit pour un octet ?
Pas tout à fait.
Déjà il faut voir comment la musique est produite par le player.
Ce dernier anime 4 compteurs 16 bits. Chaque compteur est comparé à une valeur de seuil. S'il est au dessus, le buzzer est à 1, sinon il est à 0. Le buzzer prend donc 4 valeurs différentes le long des 125µs que représentent un cycle de la boucle principale du player. Le buzzer garde sa valeur environ 125/4=31µs ce qui est très faible, tellement faible que le haut-parleur prend une position reflétant la moyenne des 4 valeurs que lui donnent chacun des compteurs. On retrouve ainsi les positions 0% (tout en bas), 25%, 50%, 100% (tout en haut) de la menbranne du haut-parleur. C'est cela qui permet d'avoir l'illusion d'avoir 4 voix indépendantes avec le buzzer, même sans utiliser le convertisseur numérique analogique de l'extension "musique et jeux". En principe plus la boucle principale tourne vite, meilleur est le moyennage. Au mieux j'ai obtenu 111µs, mais cette vitesse introduit un siflement désagréable à l'oreille sur émulateur lié à la fréquence d'échantillonnage de ce dernier. Une valeur qui convient bien est 125µs, cette valeur est en outre un diviseur exacte de la seconde ce qui simplifie les expressions et les calculs manuels.
Ok, donc le compteur compte, mais à quelle vitesse au juste? C'est une bonne question. Supposons que le seuil soit à $8000. Le compteur part de 0 et va jusqu'à $7FFF. Pendant ce temps le buzzer est à 0, puis il passe à $8000 et termine à $FFFF avec le buzzer à 1. Enfin il retombe à $0000 et le cycle reprend. Le buzzer fait donc une alternance régulère de 0 et de 1, à la même vitesse que le compteur en met pour aller de $0000 à $FFFF. Si l'incrément du compteur vallait $8000, il y aurait alternance de 0 et 1 à chaque nouveau tour de la boucle principale. On produit alors un son de période 2*125=250µs (4khz). Plus généralement si l'incrément du compteur est (delta), il faudra (2*$8000/delta) tours de la boucle principale pour faire un cycle audio. C'est à dire que l'on fait un son de période ($10000/delta)*125µs=(8192/delta) ms. Sous forme de fréquence on a donc la relation f = (delta/8.192) hz ou delta = (freq_note_hz * 8.192). Le plus petit delta vaut 1, ce qui correspond à un son de période 8.192s, ce qui est tellement bas que seuls les éléphants peuvent l'entendre (infrason). En pratique on ne joue pas des sons aussi bas. On utilise plutôt les 5 octaves de la gamme tempérée (
http://davbucci.chez-alice.fr/index.php ... /scala.inc) allant de 65.404hz (delta=536) à 1975.53hz (delta=16184). Le LA440 s'obtient pour delta = 8.192*440 = 3604.
Et le seuillage, on peut le changer? Oui! On a vu qu'un seuillage à $8000 faisait faire des créneaux au buzzer de telle sorte que la durée à 0 soit la même que celle à 1. Descendons le seuillage à $4000. Le compteur part de 0, et atteint $3FFF et pendant ce temps le buzzer est à 0, puis le compteur passe à $4000 et va jusqu'à $FFFF avec le buzzer à 1 tout ce temps. Le rapport des durées à 1 et à 0 a maintenant changé. Il passe 3x plus de temps à 1 qu'à 0. Si on passe le seuil à $2000, le buzzer sera 7x plus de temps à 1 qu'à 0. On fait donc varier le rapport cyclique de la note jouée rien qu'en altérant le seuillage. Il vaut 1 avec un seuil à $8000, il vaut 1/3 avec un seuil à $4000, puis 1/7 avec un seuil à $2000. Plus généralement parlant avec un seuil à (thr), le rapport cyclique vaut r=thr/($10000-thr). Donc pour avoir le rapport cyclique (r), il faut utiliser le seuil $10000*r/(r+1). En pratique on a pas besoin d'un seuillage sur 16bits. On peut se contenter de comparer l'octet de poids fort du compteur à une valeur 8 bits. C'est plus rapide et nécessite moins de mémoire.
Reste encore un dernier paramètre pour caractériser la boucle principale du player: sa durée. On sait que le player fait un tour en 125µs, donc s'il tourne (y) fois, il dure (y*125)µs. Un tempo standard est de 120bpm. Il y a donc 120 temps (i.e. 120 noires) dans une minute. Une noire dure donc 60/120s = 1/2 seconde, ce qui correspond à y = 500 000µs/125µs = 4000. Il faut donc itérer exactement 4000 fois la boucle principale pour faire une noire. Mais une blanche alors? Ben ca vaut 2 noirs, donc exactement 8000 tours de boucle. La croche vaut elle 1/2 noire, donc 2000 tour de boucle. Facile! On pourrait stocker ce nombre de tour sur 16bits, mais c'est un peu trop précis car la plus petite unité de temps étant disons la quintuple croche correspond à 125 tours de boucle (au delà il faudrait un nombre de tour non entier). On pourrait compter les durées en multiples de la quintuple croche (1/32ème de battement). Elle aurait la durée 1. La quadruple croche aurait la durée 2, la triple croche la durée 4, la double croche la durée 8, la croche 16, la noire 32, la blanche 64, et la ronde 128. Pas mal: toutes les durées de notes tiennent dans un octet. On peut même dépasser la durée d'une ronde tout en restant dans un octet: la ronde pointée vaut 128+64=192. Impec!
Donc, résumons. Notre player joue 4 note chacune ayant sa fréquence (2 octets) et son rapport cyclique (1 octet), pendant une certaine durée codée sur un octet. Il faut ajouter que le player est aussi capable de faire du bruit sur sa 4ème voix. Pour cela il faut un octet supplémentaire indiquant si l'on va jouer les 4 voix ou juste 3voix plus du bruit. Cela nous fait 3*4+1+1=14 octets pour configurer le player pour jouer de la musique pendant un certain temps. Ils sont organisés comme suit
Code:
<flag:1> <durée:1> (<seuil:1> <freq:2>) (<seuil:1> <freq:2>) (<seuil:1> <freq:2>) (<seuil:1> <freq:2>)
total: 14 octets
On appelle une telle ligne un "pattern". Un morceau de musique est constitué par un ensemble de lignes indiquant les notes à jouter. Exemple:
Code:
* Bach_Toccate_Fugue_BWV565.mid
zik
fcb $82,$20,$80,$16,$56,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$20,$80,$13,$e7,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$40,$80,$16,$56,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$20,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$10,$80,$13,$e7,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$10,$80,$11,$ba,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$10,$80,$10,$bc,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$10,$80,$0e,$e9,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$20,$80,$0e,$14,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$20,$80,$0e,$e9,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$c0,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$20,$80,$0b,$2b,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$20,$80,$09,$f3,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$40,$80,$0b,$2b,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$20,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$20,$80,$08,$5a,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$20,$80,$08,$dd,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$20,$80,$07,$0a,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$40,$80,$07,$74,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$e0,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$20,$80,$05,$91,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$20,$80,$04,$f5,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$40,$80,$05,$91,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$20,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$10,$80,$04,$f5,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$10,$80,$04,$6a,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$10,$80,$04,$28,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$10,$80,$03,$b6,$00,$00,$00,$00,$00,$00,$00,$00,$00
fcb $82,$20,$80,$03,$85,$00,$00,$00,$00,$00,$00,$00,$00,$00
...
Quelle place ca prend ? Le player est tout petit, il tient dans 256octets facilement, par contre les patterns sont volumineux. Un
player de MOD typique met à jour les registres musicaux toutes les VBL. Ca veut dire qu'on consomme 14 octets 50 fois par secondes, soit 700 octets/seconde. Une minute de musique consomme donc 42ko, et un morceau de 3 minutes 168ko. C'est énorme! Alors on peut essayer de ne pas mettre à jour à chaque VBL, mais disons une sur 5, ce qui fait 33.6ko, ce qui tient en RAM. Mais s'il faut utiliser la commutation de bank mémoire ce qui complexifie le player, c'est surtout que la plus petite note possible dure 100ms, environ 1/4 de noire: une double croche (quarter note chez les anglos-saxon). Les effets plus rapides que 100ms ne seront pas reproductibles. C'est pas terrible.
Il faut trouver une solution...