PROGRAMMATION D'UNE CARTE COMPATIBLE SOUND BLASTER
I.Généralités
Comment programmer la sound blaster ? Bonne question. Assez vaste, d'ailleurs. Ici, on ne va s'occuper que des sons digitaux, c'est-à-dire l'échantillonage, et pas la synthèse FM (comme les fichiers MIDI ou MOD &), ni l'utilisation du lecteur CD à travers la carte son. Toutes les commandes décrites sont tout à fait compatibles Sound Blaster. Je ne parlerais pas d'autres cartes ici, comme la Gravis Ultra Sound, qui se programme différemment. Il vaut donc mieux que vous lanciez le programme de test qui se trouve sur le site pour tester la compaptibilité de votre carte son si vous n'êtes pas sûr d'elle.
Autre chose : les cartes Sound Blaster n'en sont pas restées au même point depuis leur création, et à chaque version correspond un DSP différent. Il y a eu les Sound Blaster (DSP version 1.xx), les Sound Blaster 2 (DSP v. 2.xx), les Sound Blaster Pro (DSP v.3.xx) et les Sound Blaster 16 (DSP v.4.xx). Les Sound Blaster 32 et plus récentes changent surtout au niveau de la qualité, des fonctions Windows ou autres modes Dolby Digital, et se programme donc de la même façon qu'une Sound Blaster 16. Les DSP 1 et 2 n'ont pas beaucoup de différences, mais la version 3 inclut le mode High Speed, qui permet une fréquence d'échantillonage plus importante, et une table de mixage plus évoluée. Quand à la version 4, et inclut une table de mixage évoluée et la gestion de tous les modes (8/16 bits, 5000-48000 Hz, mono/stéréo), en seulement deux commandes, ce qui rend donc le mode High Speed obsolète, ce qui fait que ce mode n'est en fait présent que dans la version 3. Vous avez donc 2 solutions pour gérer la carte son : soit vous faire chier à supporter chaque version avec ses limites, soit ne supporter que la version 4, qui est après tout répandue partout et beaucoup plus simple. Vous devinerez évidemment quel parti j'ai pris. Néanmoins, pour les plus puristes (ou pour ceux qui n'ont qu'une vieille SB Pro, n'est-ce pas Kéké ?), je mettrais en annexe la liste de toutes les vieilles fonctions des précédentes versions.
Bon, revenons à nos moutons : comment programme-t-on cette putain de carte
son ?
Pour synthétiser des sons, la carte utilise un processeur, le DSP
(Digital Sound Processing), le gros boss de la carte son. C'est lui qui s'occupe
de tous les transfert et les conversions. Et c'est lui que l'on programme
pour enregistrer ou lire un son, via les ports. Globalement, c'est pas très
dur : on dispose de 2 commandes, une qui sort un échantillon 8 bits sur les
haut-parleurs, et l'autre qui en renvoie 1 à partir du micro. Donc pour lire
ou écrire un son, il suffit de répéter un certain nombre de fois ces fonctions.
Mais pour lire un son de 44KHz, il faudrait répéter la fonction de lecture
44000 fois par seconde, ce qui est impossible, même si votre processeur tourne
à 500MHz, puisque la vitesse du bus et de la carte son ne le permet pas. Et
en plus, il faudrait tout le temps faire une boucle pour jouer un son, ce
qui est un peu con dans un jeu.
On ne peut donc avec ces fonctions que lire ou écrire des échantillons de piètre définition. Pour opérer correctement, on est donc obligé de passer par le DMA (Direct Memory Access), qui s'occupera tout seul de la lecture (ou l'écriture) des échantillons dans la mémoire à la demande du DSP, ce qui permet d'atteindre une résolution de 48KHz stéréo 16 bits, et en plus de libérer le processeur pour faire d'autres choses, puisqu'il suffit de lancer le DMA et ensuite il se débrouille tout seul. Ce document est donc divisé en plusieurs parties :
Hein ? Pourquoi l'IRQ ? Hé ben tu verras bien, on n'est pas pressé !
II.Le DSP
Le DSP se contrôle via les ports. Communément, la carte se trouve sur le
port 220h. Mais son adresse peut varier entre 210h et 280h. Ici, nous prendrons
donc toujours comme addresse de base 2x0h, où x représente un chiffre variable,
et puis en plus tout le monde fait pareil.
Le DSP possède 5 registres :
Adresse |
Nom |
Lecture |
Ecriture |
Description |
2x4h |
Port d 'adresse de la table de mixage |
|
X |
Envoyer ici le numéro de port de la table de mixage à lire ou écrire |
2x5h |
Port de données de la table de mixage |
X |
X |
Ici on entre ou on lit les données du port |
2x6h |
Reset |
|
X |
Réinitialise le DSP |
2xAh |
Read Data |
X |
|
Pour lire les données envoyées par le DSP |
2xCh |
Write Command |
|
X |
Pour envoyer des commandes au DSP |
Write Data |
et lui transmettre des données |
|||
Etat du registre Write |
X |
|
Pour savoir si le DSP est au bout du fil |
|
2xEh |
Etat du registre Read |
X |
|
Pour savoir si le DSP a envoyé des données |
IRQ 8 bits |
ou pour lui dire que l'IRQ 8 bits est bien arrivé |
|||
2xFh |
IRQ 16 bits |
X |
|
Pour lui dire que l'IRQ 16 bits est bien arrivé |
Principe
du contrôle du DSP :
Envoi de données :
On envoie la commande (ou fonction) désirée au DSP via le port Write Command. Mais il faut d'abord savoir s'il est prêt à recevoir la commande en testant ce même port (puisque registre Write Status=registre Write Data) : tant que le bit 7 est à 1, le DSP est occupé, en train de traiter la commande précédente. Sinon, il est prêt à écouter ce que vous avez à lui dire. Sinon, hé ben on recommence à tester le port Write Command ! Si on doit aussi lui transmettre des données, on envoie d'abord le code sur le port Write Command, puis les données sur ce même port (puisque Write Data=Write Command), dans l'ordre définit par la fonction, en vérifiant toujours que le DSP est prêt à les recevoir. On résume :
Tant que bit 7 du Port[2xCh]=1 : Attendre
;
Dès que
bit 7 du Port[2xCh]=0 : Port[2xCh] = commande ;
Si données
à envoyer en plus, refaire la même chose depuis le début mais en remplaçant
la commande par les données à envoyer.
Lecture de données :
Le principe est exactement le même, sauf qu'on teste si le DSP a envoyé les données avec le port Read Data Status 2xEh et on les lit sur le port Read Data 2xAh. Attention : ici, c'est lorsque le bit 7 du port 2xEh est à 1 que les données ont été envoyées !
Les
fonctions du DSP :
Après avoir vu comment on envoyait des commandes au DSP, voyons quelles sont ces commandes :
Reset du DSP :
On doit toujours commencer par initialiser le DSP avant de la programmer. On procède de la manière suivante :
Port[2x6h] =1 ;
Attendre
env. 3 microsecondes ;
Port[2x6h]
=0 ;
Si Port[2xAh]==0AAh
(ne pas oublier d'attendre que le DSP ait envoyé les données, via le port
2xEh), le DSP est correctement initialisé.
Un truc : on peut comme ça tester le port de base de la Sound Blaster, mais y a un problème : si le canal est mauvais, on risque d'attendre plutôt longtemps que le registre Read Data Status dise que la réponse est disponible. Il faut donc faire une petite boucle limitée du genre (au hasard) LOOPNE et comme ça on sait tout de suite si le port choisi est bon.
Connaître le n° de version du DSP
:
C'est pratique de savoir si la version du DSP est bien conforme à celle qu'on est sensé utiliser. Pour le savoir, on exécute la commande E1h, qui renvoie sur le regsitre Read Data le numéro de version principal, puis le numéro secondaire
Fréquence d'échantillonnage :
Avant la version 4, il fallait faire un calcul savant pour savoir quoi dire au DSP, via la fonction 40h. Maintenant, on envoie directement la fréquence en Hz à la fonction 41h (sortie) ou 42h (entrée), en envoyant d'abord l'octet de poids fort puis l'octet de poids faible. Les valeurs sont comprises entre 5000 et 44100 Hz.
Activer / désactiver les haut-parleurs
:
Il vaut mieux vérifier que le lien entre la carte son et les haut-parleurs est présent avant de jouer un son sinon on risque fortement de s'arracher les cheveux en se demandant pourquoi ça marche pas. La fonction D1h active le lien Carte son-HP tandis que la D3h le désactive. Pour tester le lien, on peut utiliser la fonction D8h qui renvoie sur le Read Data un octet qui vaut 0FFh si le lien est présent, ou 00h s'il n'y en a pas.
Déclenchement du transfert :
Enfin, quand vous avez bien tout paramétré tout ça, préparé le DMA et détourné l'IRQ, vous pouvez lancer le transfert en envoyant au DSP la commande Byh ou Cyh. y varie suivant le mode d'échantillonnage (j'ai mis y au lieu de x pour pas qu'il y ait de confusion avec le port de base). Ces fonctions sont beaucoup plus pratiques que la vingtaine de fonctions différentes selon que l'on est en 16 ou bits, stéréo ou mono, entrée ou sortie & Ici, on utilise juste Bxh pour un transfert 16 bits, et Cxh pour 8 bits. La structure des deux commandes est la même et se présente comme ceci :
Structure du premier octet de commande |
||||||||||
Bits |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|
|
Valeurs |
|
|
|
|
|
|
|
0 |
||
|
|
|
|
|
|
|||||
|
1 = FIFO activé / 0 = FIFO désactivé |
|||||||||
|
1 = Auto-Init / 0 = pas d'Auto-Init |
|||||||||
|
1 = Entrée (enregistre) / 0 = sortie (joue) |
|||||||||
|
B = 16 bits / C = 8 bits |
|||||||||
Après la commande, le DSP réclame un deuxième octet, déterminant si le transfert est codé en nombres signés ou pas :
Structure du deuxième octet de commande |
||||||||||
Bits |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|
|
Valeurs |
0 |
0 |
|
|
0 |
0 |
0 |
0 |
||
|
|
|
|
|||||||
|
1 = signé |
|||||||||
|
1 = non signé |
|||||||||
On envoie enfin une troisième valeur qui détermine le nombre d'échantillons (16 bits pour Byh, 8 bits pour Cyh) à jouer au format word, en envoyant en premier l'octet de poids faible. Et voilà, normalement ça joue le son. N'oubliez pas de paramétrer d'abord le DMA et le gestionnaire d'interruption.
III.Le DMA
Sur les PC/AT (c 'est-à-dire les nôtres), il y a deux contrôleurs DMA : un maître et un esclave. Le maître contrôle les canaux 5 à 7 et l 'esclave les canaux 0 à 3. Le canal 4 est utilisé par le maître pour transmettre les commandes aux canaux inférieurs à 4 à l 'esclave par un procédé appelé "cascade". On contrôle l 'esclave via les ports 08h à 0Fh et le maître via les ports 0D0h à 0DEh.
Description des
canaux DMA :
Canal |
Contrôleur |
N°DMA |
Utilisation habituelle |
0 |
Esclave |
0 (00) |
RAM-Refresh |
1 |
Esclave |
1 (01) |
Lecteur disquettes |
2 |
Esclave |
2 (10) |
Libre, souvent SB |
3 |
Esclave |
3 (11) |
Lecteur disque dur |
4 |
Maître |
0 (00) |
Cascade Maître è Esclave |
5 |
Maître |
1 (01) |
Libre, souvent SB |
6 |
Maître |
2 (10) |
Libre |
7 |
Maître |
3 (11) |
Libre |
Les registres du
DMA sont les suivants :
Registre |
Port (maitre) |
Port(Esclave) |
Accès |
Status |
D0h |
08h |
Read |
Commande |
D0h |
08h |
Write |
Requête |
D2h |
09h |
Write |
Masque 1 |
D4h |
0Ah |
Write |
Mode |
D6h |
0Bh |
Write |
FlipFlop |
D8h |
0Ch |
Write |
Mem temp |
DAh |
0Dh |
Read |
Reset |
DAh |
0Dh |
Write |
Reset de masque |
DCh |
0Eh |
Write |
Masque 2 |
DEh |
0Fh |
Write |
Description des
registres :
Le registre Status permet
de savoir quels requêtes et quels TC (Terminal Count = fin de transfert) sont
activés. Il ne nous intéresse pas ici.
Le registre Commande permet
de paramétrer de quelle façon se font les requêtes. Toutes les valeurs doivent
être laissées par défaut, donc on n 'y touche pas. De plus, il a l 'inconvénient
de ne pas être lisible (si on le lit on récupère le status), donc on ne connaît
pas les paramètres effectifs.
Le registre Requête permet
de simuler une requête matérielle par logiciel. On ne s'en sert pas non plus.
Le registre Masque 1 nous
sert parce qu 'on doit inhiber le canal sur lequel on va travailler avant
d 'y toucher pour éviter de mettre les couilles dans l 'engrenage. Après toutes
les opérations, on devra ensuite bien sûr le démasquer, pour qu'il soit opérationnel.
Structure du registre Masque 1 |
||||||||||
Bits |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|
|
Valeurs |
0 |
0 |
0 |
0 |
0 |
|
|
|
||
|
|
|
||||||||
|
N° DMA |
|||||||||
|
1 = Masquer le canal / 0 = Démasquer |
Le registre Mode est aussi important
car il permet de déterminer le sens du transfert, l 'auto-init, le mode &
Structure du registre Mode |
|
||||||||||
Bits |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|
|
|
Valeurs |
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
||||||
|
N° DMA |
|
|||||||||
|
Type de transfert : |
|
|||||||||
|
1 = Auto-Init / 0 = pas Auto-Init |
|
|||||||||
|
Sens de lecture : 0 = Incrémeter l'adresse / 1 = Décr. |
|
|||||||||
|
Mode de transfert : |
Quelques précisions sur le mode Auto-init
:
Pout mettre au point clairement
les choses, on va prendre un petit exemple : imaginez que vous programmez
un jeu en utilisant la carte son, puisque vous venez de tout apprendre dans
ce merveilleux et complet document (restons modestes) : vous décidez donc
d'y incorporer des sons 16 bits stéréos à 44100 Hz, histoire de faire bien.
Ca fait donc 4 octet par bloc, à 44100 blocs par seconde, c'est-à-dire environ
172 Ko par seconde de son.
Outre que ça prend un peu de place, il y a un autre problème, plutôt gros
: le DMA étant une relique de l'antiquité, il ne travaille que sur des blocs
de 64Ko max, ce qui fait un peu juste pour y mettre 170Ko : même en serrant
très fort, ça va avoir du mal à rentrer. Alors, la solution ? Hé bien je suis
sûr que vous vous êtes dit, en programmeur averti : "pas compliqué :
je place les 64 premiers Ko dans un buffer, que je fait jouer par la carte,
et ensuite, dès qu'elle a finit, j'y met les 64 Ko suivants, je réinitialise
le DMA et je refais jouer le DSP, etc...".
C'est bien ! vous êtes très fort ! Mais seulement, il y a plus simple : il
suffit de programmer le DMA et le DSP en mode Auto-Init. Dans ce mode, le
DMA se réinitialise automatiquement dès qu'il arrive à la fin du bloc, tandis
que le DSP joue continuellement le son : en gros, le son est répété indéfiniment.
On peut donc utiliser ce système en raifraichissant le buffer à chaque fois
qu'il a été lu. La seule question est de savoir comment il a finit d'être
lu. Et la réponse se trouve au chapitre suivant, sur l'IRQ
Quelques précisions sur le mode de
transfert :
Le DMA transmet (ou écrit) les données dans la mémoire à la demande du périphérique qui lui est relié, via la ligne DREQ. Il y a donc plusieurs façon de lui envoyer ces données : soit elles sont envoyées tant que cette ligne est à 1 (mode "à la demande"), soit le DMA envoie un octet à chaque fois que cette ligne passe à 1, c'est-à-dire est activée sur front montant (mode "unique"), soit le DMA balance carrément tout le bloc lorsque DREQ passe à 1 (mode "en bloc"). Dans le cas de la carte son, c'est la carte qui demande au DMA un octet chaque fois qu'elle en a besoin : on utilise donc toujours le mode unique.
Nous allons voir l'utilité du
registre Flip-Flop un peu plus bas
Le registre Mem Temp ne
nous sert à rien, tout comme les registres Reset et Reset de Masque,
qui ne doivent pas être utilisés. Quant au registre Masque 2, il a
la même fonctionnalité que le registre Masque 1, mais est programmé
différemment. Comme on sait programmer le 1, on n'a pas besoin du 2.
Transmission de
la taille et de l'adresse du bloc au contrôleur DMA :
En effet, même s 'il sait par où et de quelle façon transférer les données, le DMA ne sait toujours pas leur taille et leur emplacement. Il faut donc le lui dire. Pour cela, on envoie ces informations aux ports suivant ce tableau :
Canal DMA |
Addresse de début |
Longueur du bloc |
Lower Page |
Upper Page |
0 |
00h |
01h |
87h |
487h |
1 |
02h |
03h |
83h |
483h |
2 |
04h |
05h |
81h |
481h |
3 |
06h |
07h |
82h |
482h |
4 |
C0h |
C2h |
8Fh |
??? |
5 |
C4h |
C6h |
8Bh |
48Bh |
6 |
C8h |
CAh |
89h |
489h |
7 |
CCh |
Ceh |
8Ah |
48Ah |
L 'adresse du bloc est un nombre de 28 bits qui permet
d 'adresser jusqu 'à 256Mo. Elle est divisée en deux parties : l 'offset
(16 bits inférieurs) et la page (12 bits supérieurs). Sa valeur est aisément
calculable par 16*seg(adresse) + ofs(adresse).
Mais un port ne peut recevoir qu 'une valeur 8 bits, et l 'adresse est une
valeur 28 bits ! Il faut donc encore passer par une astuce conne, à savoir
mettre à zéro le Filp-Flop, puis envoyer l 'octet de poids faible puis
l 'octet de poids fort de l 'offset dans le registre d 'adresse de début correct
(voir tableau ci-dessus). Quand à la page, il faut l 'envoyer dans d 'autres
ports : on envoie d 'abord au registre Lower Page les 8 bits inférieurs
de la page, puis au Upper Page les 4 derniers bits (ouf !).
Note : après expérimentation, il
s'avère que le registre Upper Page ne sert apparemment à rien, et il n'est
d'ailleurs pas mentionné dans toutes les docs. Le DMA ne va donc que jusqu'à
des adresses de 16 Mo max.
On a enfin donné l 'adresse au
DMA. Reste maintenant à lui donner la taille du bloc, qui n 'est codée
que sur 16 bits (ce qui limite malheureusement à 64Ko la taille du buffer).
Ici, il suffit de mettre à zéro le Flip-Flop, puis d 'envoyer l 'octet
de poids faible, puis l 'octet de poids fort au registre aquédat (voir plus
haut).
Petite précision sur l'utilité
du registre Flip-Flop :
Ce registre sert à initialiser une bascule interne pour séléctionner l'octet
de poid faible / octet de poid fort des registre 16 bits (adresse de début,longueur
...). En effet on ne peut pas lire ou ecrire directement des valeurs de 16
bits dans ces registres. Il faut écrire d'abord 0 dans le registre Flip-Flop
pour indiquer qu'on va écrire le poid faible du mot (16 bits) : on écrit ensuite
l'octet de poid faible (8 bits inferieurs) dans le registre. A ce moment le
registre Flip-Flop bascule automatiquement pour permettre d'écrire
le poid fort. On inscrit donc l'octet de poid fort dans ce registre. Remarque
: le Flip-Flop bascule sur le pois faible à nouveau, ce qui permet
d'écrire l'adresse puis la longueur (ou vice-versa) à la suite en ne l'utilisant
qu'une fois.
Attention
:
Certains contrôleurs DMA, ayant été fabriqués par des pines, ne peuvent pas
sauter les segments, c'est-à-dire que s'ils arrivent à 000C:FFFF, ils ne passeront
pas à 000D:0000, mais à 000C:0000. Chez moi, ça ne le fait pas, mais il parait
que c'est aussi influencé par la présence d'un driver EMS. Bref, l'info est
à vérifier. Soyez vigilant.
Voilà, vous savez tout comment faire. Rapellons qu' il faut :
Masquer le canal DMA - registre Masque
1 ;
Spécificer
le mode de transfert - registre Mode ;
Donner
l 'adresse du buffer (offset + page) - registre Flip-Flop ;
Donner
la taille du buffer - registre Flip-Flop ;
Libérer
le canal DMA - registre Masque 1.
Remarque : vous n'êtes pas du tout obligé de suivre cet ordre (mis à part le masquage, bien sûr). L'essentiel est d'avoir fourni toutes les infos au DMA.
Effectuer un transfert 16 bits
Pour les sons codés sur 16 bits, on procède exactement de la même manière que pour les sons 8 bits. Les canaux DMA 16 bits sont ceux du maitre (4 à 7), tandis que les canaux 8 bits sont les canaux 0 à 3. La carte son dispose d'un canal 16 bits et d'un canal 8 bits : il suffit donc de preogrammer le bon canal pour avoir une sortie 16 ou 8 bits. En fait, la grosse différence est que l'adresse et la taille des données sont codées en words pour le transfert 16 bits et en octet pour le transfert 8 bits. Pensez donc à diviser par 2 ces 2 valeurs avant de les envoyer au controleur DMA.
Remarque : sur certaines cartes, il faut initialiser les deux canaux pour avoir un transfert 16 bits.
IV.L'IRQ
L'IRQ : quoi qu'est-ce
?
Comme vous devez le savoir, les programmes sur PC sont composés d'instructions et d'interruptions. Les interruptions qui composent les programmes sont en fait les interruptions logicielles, car il existe aussi des interruptions matérielles, qui sont, comme leur nom l'indique, générées par le matériel. La plus connue est l'interruption clavier, qui informe le PC qu'une touche a été enfoncée, ce qui évite au processeur d'aller tout le temps voir ce qui s'y est passé (d'autant plus qu'il ne s'y passe presque jamais rien). Pour gérer ces interruptions, les PC sont équipés de 2 contrôleurs d'interruptions, ou PICs (Programmable Interrupt Controller), gérant chacun 8 interruptions. On ne peut donc avoir que 16 interruptions max. En général, le PIC sert à déclencher l'interruption logicielle associée à l'IRQ activée (IRQ = Interrupt Request = interruption matérielle).Bon d'accord, mais qu'est-ce que cette connerie d'IRQ vient foutre là ? Hé bien elle sert à nous simplifier la vie, puisque lorsque le DSP a terminé le bloc que vous lui avez soumis, elle vous le dit en activant l'IRQ déterminé par la config.
Voici les correspondances entre n°IRQ et interruption :
IRQ |
Interruption |
0 |
08h |
1 |
09h |
2 |
0Ah |
3 |
0Bh |
4 |
0Ch |
5 |
0Dh |
6 |
0Eh |
7 |
0Fh |
8 |
70h |
9 |
71h |
10 |
72h |
11 |
73h |
12 |
74h |
13 |
75h |
14 |
76h |
15 |
77h |
Si je vous dit ça, c 'est pas pour des prunes. En effet, si cette interruption est bien pratique pour le mode Auto-Init lorsqu 'on a plus de 64Ko à jouer, elle ne sert pas à grand chose en mode Single Cycle. Mais elle doit obligatoirement être gérée, même en mode Single Cycle. Pourquoi ? Hé bien tout simplement parce que lorsque le DSP a balancé l 'interruption, il attend un accusé de réception ' : il faut donc toujours lui envoyer son accusé de réception, même si on s 'en fout.
Nous devons donc détourner l 'interruption concernée, et inclure dans la nouvelle interruption l 'envoi de l 'accusé, avec en plus la gestion du mode auto-init si on veut gérer les sons de plus de 64Ko.
Bon, en clair, comment on l 'envoie ce putain d 'accusé ? Hé ben tout connement en effectuant une lecture du regsitre IRQ (voir tableau du DSP) 8 bits si c 'est la fin d 'un transfert 8 bits, et du registre IRQ 16 bits si c 'est la fin d 'un transfert 16 bits.
Note : IRQ 16 bits ne veut pas dire que ce registre est un registre de 16 bits, mais qu 'il sert à gérer l 'IRQ pour les transfert 16 bits.
Normalement, vous savez si vous avez déclenché un transfert 16 bits ou 8 bits, donc ça ne pose pas de problèmes. Mais si vous ne savez pas, il existe une technique pour connaître le mode de transfert : il faut lire le registre 82h de la table de mixage. Si le bit 0 de ce registre est posé, c 'est qu 'il s 'agit d 'un transfert 8 bits. Si c 'est le bit 1 qui est posé, alors c 'est un transfert 16 bits :
Bits |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|
1
= transfert 8 bits |
||||||
|
0 |
0 |
0 |
0 |
0 |
0 |
|
|
|
|||||||
|
|
|
|
|
|
|
|
|
|
|||||||
|
|
|
|
|
|
|
|
|
|
|||||||
|
|
|
|
|
|
|
|
|
|
|||||||
Bon, tant qu 'à faire, je vais aussi vous parler de comment gérer les sons > 64Ko. Il existe deux technique : la première, le double-buffering, consiste à séparer le buffer en 2 zones de 32Ko, et pendant que l 'une est lue par le DMA et la carte son, l 'autre est remplie par le programme. Elle a l 'avantage de ne provoquer aucune coupure, mais occupe un tout petit peu plus le processeur. La seconde méthode consiste tout simplement à placer la suite du son dans le buffer lorsque celui-ci a été lu. Elle ne provoque en fait pas de coupure même si l 'ordinateur est assez lent, du moment qu 'on s 'y prend bien. De toute façon, la différence au niveau programmation est minime et si on sait faire la deuxième méthode, passer au double-buffering est très facile.
Dans les deux cas, on initialise au début le DMA en mode auto-init, comme ça il reviendra automatiquement au début dès qu 'il arrivera à la fin. Et pour la dernière tranche de l 'échantillon, on le réinitialise en mode single cycle pour ce qui reste.
Un dernier point : à la fin du gestionnaire d 'interruption, il faut envoyer la commande EOI (End Of Interrupt) à l 'IRQ pour lui dire qu 'on a fini. Concrètement, il suffit d 'envoyer la commande 20h au port 20h. Si ce n'est pas fait, l'échantillonage s'arrêtera au prochain bloc.
V.La table de mixage
Elle permet de gérer la sortie
du son tout comme une table de mixage normale, ou comme la fenêtre 'contrôle
du volume' de Windows. On peut régler notemment la balance, le volume général,
le volume wave, midi, line-in, etc... Pour lire ou écrire dans un registre
de la table de mixage, on envoie son numéro dans le port d'adresse de la table
de mixage (2x4h - voir tableau DSP) et on lit (ou écrit) sa valeur dans le
port de données (2x5h).
Les registres présentés ici ne valent que pour des DSP de version 4.00 ou
plus. Tous les registres ci-dessous peuvent à la fois être lus et modifiés.
Voici donc les différents registres utiles de la table de mixage :
Nom |
Registre |
Infos |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Volume master - gauche |
30h |
Codé sur 5 bits (bits 3 à 7). Le volume varie de -62db à 0 db par pas de 2db. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Volume master - droit |
31h |
Codé sur 5 bits (bits 3 à 7). Le volume varie de -62db à 0 db par pas de 2db. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Volume voice - gauche |
32h |
Codé sur 5 bits (bits 3 à 7). Le volume varie de -62db à 0 db par pas de 2db. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Volume voice - droit |
33h |
Codé sur 5 bits (bits 3 à 7). Le volume varie de -62db à 0 db par pas de 2db. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Volume CD - gauche |
36h |
Codé sur 5 bits (bits 3 à 7). Le volume varie de -62db à 0 db par pas de 2db. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Volume CD - droit |
37h |
Codé sur 5 bits (bits 3 à 7). Le volume varie de -62db à 0 db par pas de 2db. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Volume line-in - gauche |
38h |
Codé sur 5 bits (bits 3 à 7). Le volume varie de -62db à 0 db par pas de 2db. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Volume line-in- droit |
39h |
Codé sur 5 bits (bits 3 à 7). Le volume varie de -62db à 0 db par pas de 2db. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Volume micro |
3Ah |
Codé sur 5 bits (bits 3 à 7). Le volume varie de -62db à 0 db par pas de 2db. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Volume line-in- droit |
3Bh |
Codé sur 2 bits (bits 6 à 7). |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sélection sorties |
3Ch |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sélection entrées |
3Dh |
|
VI.Remerciements
Document écrit
par Antoche – Antoche@altern.org - #ICQ : 38 08 99 43
Libre reproduction
et diffusion autorisée
Je remercie La Bible du programmeur, qui contient pas mal d'infos sur la SB, et Ethan Brodsky (si vous avez besoin d'une unité SoundBlaster performante en Pascal, il en a fait une vraiment excellente librement diffusée sur le net).