Oui mais j'aime bien les vieux mods qui m'épataient dans le temps comme celui-ci (plein de 90's inside):
http://artscene.textfiles.com/music/mod ... apower.modEn revenant sur la version initiale, je me rends compte que question fréquence on dépasse assez peu le 256. Si bien qu'on pourrait dire qu'un instrument joue à sa fréquence max revient à avoir un compteur incrémenté de 256/256==1 octet à la fois. Les autres notes sont plus basses, et donc incrémentées de x/256 avec x<256. Par exemple avec x=128 on joue à l'octave immédiatement en dessous. Du coup j'ai eu l'idée de ne plus utiliser un compteur sur 16bits, mais uniquement sur 8 bits. On obtient le squelette de code suivant:
Code:
org $nn00
setdp $nn
TAB RMB 64 ; table pour valeurs E7C1
RMB 1
* toujours dans le même segment "DP"
loop pshs x,y,u,cc
sts <sav_S
orcc #$50
sta <loop-1 ; tourne D fois
tfr b,a
ldx #ptr
p_X set *-2
ldy #ptr
p_Y set *-2
lds #ptr
p_S set *-2
ldu #ptr
p_U set *-2
voix_Y LDB #0 ; 2
ADDB #ff ; 2
STB <xx ; 4
BCS ZZZ ; 3
LDB ,Y ; 4
BRA *+4 ; 3
ZZZ LDB ,Y+ ; 6
BPL XXX ; 3
CMPY #nnnn ; fin instrument?
BCS XXX ; non => suite
LDY #ssss ; rebouclage
XXX ANDB #bit_instru ; 2
STB <YYY+1 ; 4
YYY LDB <TAB ; 4
STB $E7C1 ; 5 => 35µs la plupart du temps
* idem voix_X ; 35µs
* idem voix_S ; 35µs
* idem voix_U ; 35µs
deca ; 2
bne voix_Y ; 5 boucle
dec <loop-1
bne voix_Y
* total voix + bouclage == ???
stx <p_X
sty <p_Y
stu <p_U
sts <p_S
lds #0
sav_S set *-2
puls x,y,u,cc,pc
Qu'est ce qui change ?
- Et bien déjà on ne passe pas son temps à écrire et lire en mémoire les pointeurs instrument. Ces pointeurs restent dans des registres tout le temps de la boucle.
- L'incrément sur le pointeur d'instrument n'est plus fait par un "ADCB #0;ABX" mais est directement réalisé dans le LDB qui va charger l'échantillon ( ). Comme on incrément au plus de 1 et uniquement de temps en temps, c'est pas mal. Les deux chemins sur cette partie ne se font pas en temps identiques. L'un des chemins (ldb ,reg + bra) prend 7 cycle, et l'autre (ldb ,reg+) en prends 6. C'est très voisin, et en moyenne on prend (6+7)/2=6.5 cycles ici
- Du coup le code est plus petit, tellement petit qu'on peut s'arranger pour qu'il cohabite avec la TAB qui donne la valeur de E7C1 à appliquer (buzzer à 0 partout sauf pour les valeurs 1<<i, i=0..6). On utilise donc l'accès direct la plupart du temps, et en particulier pour simuler l'ancien "ldb b,u" juste avant l'écriture en $E7C1.
- On garde le registre A intact tout du long, ce qui fait que le bouclage D fois peut être découpé en 2 boucles ipmbriquées, l'une où l'on itère "A" fois rapidement, et l'autre ou l'on itère "B" (stocké dans loop-1) fois, un peu plus lentement, mais c'est pas grave car ca n'arrive pas souvent.
Au final avec cette architecture du code, la boucle jouant les instruments se fait la plupart du temps en 35*4+2+3 = 145µs. C'est à dire qu'on passe d'un rendu à 5khz à carrément 6.9khz!!! La qualité devrait être meilleure.
Bon j'ai pas encore testé, car il faut que je pousse l'analyse un peu plus loin pour les instruments non bouclants. En effet, ceux là ralentissent l'execution. Je m'explique: arrivé en fin d'instrument le test "BPL XXX" est faux et on fait le CMPreg #fin qui suit. Ok. Comme on est à la fin del l'instru on execute alors le "LDreg #fin" aussi ce qui ne change pas la valeur du reg. Donc contrairement aux échantillons de milieu d'instruments, ici on se tape 5+4 cycles de plus que les 35. Une fois de temps en temps c'est pas gênant, mais comme c'est un instrument "sans bouclage" et que le registre ne change pas de valeur (on reste coincé sur le dernier échantillon), au tour suivant on se re-tape encore une fois ces 9 cycles. Donc pour ces instruments, la gestion de la voix passe de 35µs à 44µs (+26%). C'est signifcativement plus lent: ca va jouer super faux!
Pour s'en sortir, il faudrait ne pas rester stationner en fin d'instrument mais repartir au début tout en éteignant la voix. Eteindre la voix c'est facile, il suffit d'annuler la valeur du ANDB qui suit, comme ca on ne sortira plus que 0 sur cette voix. Cette modif donnerait quelque chose comme:
Code:
BPL XXX ; 3
CMPY #nnnn ; fin instrument?
BCS XXX ; non => suite
LDY #debut ; rebouclage
CLR <XXX+1 ; ou "nop;nop" si l'instrument est reobuclant
XXX ANDB #bit_instru ; 2
Ca rallonge un peu le code, mais ca devrait faire le truc: empêcher de rester coincer longtemps en fin d'instrumentsur les CMPreg/LDreg. Il faut que je vois si ca nous fait sortir de la zone DirectPage ou pas ou si la boucle dépasse 128 octets auquel cas on ne pourra pas faire des beq simples après le décompte "D", mais il faudra utiliser des long-branch, nettement plus longs.
... reste à mettre cette belle théorie en pratique. J'espère qu'un son à 7khz sera nettement mieux qu'à 5khz.