j´ai déja eu l´occasion de jouer a des jeux qui faisaient de la musique avec le haut parleur interne de l´ordi. bien sur, c´etaient des jeux vachement simples, avec des gros pixels et tout.
existe t-il une commande de programmation pour faire un son avec le haut parleur interne, par exemple en assembleur? ![]()
le plus con, c´est
printf("\b");
(ou cout << "\b";)
qui fait un "bip".
Mais il doit y avoir moyen de gérer ça de manière plus poussé.
merci, je vais essayer tout de suite!
oui, on peut regler la fréquence joué par le HP.
Il y a un programme sous unix qui joue du MIDI sur le HP interne mais je ne me rappele plus du nom.
sur msx et sur amstrad, c´est facile de faire des notes avec le hp interne, mais pas sur les ordis récents, c´est pas logique ![]()
Oui et non !
Tout d´abord parce que de nos jours, le haut parleur interne du PC est très peu utilisé, voir quasiemment plus du tout.
Pour utiliser le hp interne du PC, il faut accéder directement au port 61h et à l´interruption 1Ch.
Or Windows n´aime pas beaucoup que l´on accède directement aux ressources de la machine, il aime bien jouer les intermédiaires afin de tout contrôler.
en assembleur, sous ms dos, ca ne fonctionnerait pas? 61h et 1Ch... ca me rappelle l´assembleur, mov et tout le reste
Tiens, 2 exemples tirés de "La Bible PC" de Micro Application :
Tout d´abord le programme en C pour appeler la fonction Sound suivi du code assembleur contenant la fonction Sound :
/*************************************************
/* S O U N D C */
/*------------------------------------------------
----------------------------*/
/* Fonction : Sortie de la gamme chromatique des octaves 3 à 5 à */
/* l´aide d´une fonction assembleur. */
/*------------------------------------------------
----------------------------*/
/* Auteur : MICHAEL TISHER */
/* développé le : 18/08/1987 */
/* dernière modif : 29/04/1989 */
/*------------------------------------------------
----------------------------*/
/* (MICROSOFT C) */
/* Création : CL /AS SOUNDC.C SOUNDA */
/* Appel : SOUNDc */
/*------------------------------------------------
----------------------------*/
/* (BORLAND TURBO C) */
/* Création : Avec fichier Project de la teneur suivante : */
/* soundc */
/* soundca.obj */
/*************************************************
/*__ Déclaration des fonctions du module assembleur __________________________*/
extern void Sound(); /* Pour intégrer la routine assembleur */
/*************************************************
/** P R O G R A M M E P R I N C I P A L **/
/*************************************************
void main()
{
int Son;
printf("\nSOUND(c) 1987 by Michael Tischer\n\n");
printf("Si le haut-parleur de votre PC fonctionne correctement, vous");
printf(" allez entendre\nmaintenant la gamme entre les octaves 3 et ");
printf("5, chaque note étant jouée\npendant une demie seconde.\n\n");
for (Son = 0; Son < 35; Sound(Son++, 9)) ; /* Jouer chaque note une */
/* demie seconde */
printf("Fin\n");
}
;*************************************************
;* S O U N D C A *;
;*------------------------------------------------
----------------------------*;
;* Fonction : Fournit une fonction à intégrer en C pour jouer les *;
;* notes des octaves 3, 4 et 5. *;
;*------------------------------------------------
----------------------------*;
;* Auteur : MICHAEL TISHER *;
;* développé le : 18/08/1987 *;
;* dernière modif : 16/02/1991 *;
;*------------------------------------------------
----------------------------*;
;* Assemblage : MASM -mx SOUNDCA; *;
;* ... puis lier à SOUNDC *;
;*************************************************
IGROUP group _text ;R egroupement des segments de programme
DGROUP group const, _bss, _data ;R egroupement des segments de données
assume CS:IGROUP, DS:DGROUP, ES:DGROUP, SS:DGROUP
public _Sound ;F onction rendue accessible aux autres programmes
CONST segment word public ´CONST´ ;C e segment reçoit toutes les constantes
CONST ends ;q ui peuvent seulement être lues
_BSS segment word public ´BSS´ ;C e segment reçoit toutes les variables
_BSS ends ;s tatiques non initialisées
_DATA segment word public ´DATA´ ;T outes les variables globales et statiques
;i nitialisées sont logées dans ce segment
time_anc dw (?),(?) ;A dresse ancienne interruption temporisateur
cptr_s db (?) ;D urée restante d´une note en 1/18èmes de seconde
fin_s db (?) ;I ndique si note a déjà été jouée
notes dw 9121,8609,8123,7670 ;V aleurs de notes pour l´octave 3
dw 7239,6833,6449,6087
dw 5746,5423,5119,4831
dw 4560,4304,4063,3834 ;V aleurs de notes pour l´octave 4
dw 3619,3416,3224,3043
dw 2873,2711,2559,2415
dw 2280,2152,2031,1917 ;V aleurs de notes pour l´octave 5
dw 1809,1715,1612,1521
dw 1436,1355,1292,1207
_DATA ends
;_ _ Programme
__________________________________________________
_______________;
_TEXT segment byte public ´CODE´ ;L e segment de programme
;- - SOUND : Jouer une note
--------------------------------------------------
--
;- - Appel en C : Sound((int) Note, (int) Durée);
;- - Sortie : Aucune
;- - Infos : La note est le numéro de la note par rapport au Do
;- - de la 3ème octave
;- - Durée est la durée de la note en 1/18èmes de seconde
_Sound proc near
push bp ;R anger BP sur la pile
mov bp,sp ;T ransférer SP dans BP
;- - détourner interruption temporisateur sur routine utilisateur ---------------
mov word ptr cs:setds+1,ds ;S auver DS pour interruption temporisateur
mov ax,351ch ;L ire adresse de l´interruption temporisateur
int 21h ;A ppeler interruption du DOS
mov time_anc,bx ;A dresse d´offset de l´ancienne interruption
mov time_anc+2,es ;e t ranger adresse de segment
mov word ptr cs:stjump+1,bx ;P our nouvelle interruption temporisateur
mov word ptr cs:stjump+3,es ;S auvegarder
mov bx,ds ;R anger DS dans BX
push cs ;A mener pile sur pile
pop ds ;e t retirer pour DS
mov dx,offset sound_ti ;A dresse offset nouvelle routine tempo.
mov ax,251ch ;F ixer nouvelle routine temporisateur
int 21h ;A ppeler interruption du DOS
mov ds,bx ;R estaurer DS
mov al,182 ;P réparer génération d´un son
out 43h,al ;E nvoyer valeur au Timer Command Register
mov bx,[bp+4] ;L ire note
xor bh,bh ;B H pour adressage table notes = 0
shl bx,1 ;D oubler n° note (car table de mots)
mov ax,[notes+bx] ;L ire valeur de note
out 42h,al ;O ctet faible dans Timer Counter Register
mov al,ah ;T ransférer octet fort dans AL
out 42h,al ;e t aussi dans Timer Counter Register
in al,61h ;L ire bit de contrôle du haut parleur
or al,11b ;D eux bits inférieurs activent haut-parleur
mov fin_s,1 ;N ote doit encore être jouée
mov dl,[bp+6] ;L ire durée de note
mov cptr_s,dl ;e t sauvegarder
out 61h,al ;A ctiver haut-parleur
play: cmp fin_s,0 ;N ote terminée ?
jne play ;N on --> attendre encore
in al,61h ;L ire bit de contrôle du haut parleur
and al,11111100b ;A nnuler 2 bits inférieurs
out 61h,al ;D ésactiver haut-parleur
;- - Activer à nouveau ancienne interruption temporisateur ----------------------
mov cx,ds ;R anger DS
mov ax,251ch ;n ° fonction pour fixer vecteur d´interruption
lds dx,dword ptr time_anc ;C harger encienne adresse dans DX:DX
int 21h ;A ppeler interruption du DOS
mov ds,cx ;R amener DS
mov sp,bp ;R estaurer pointeur de pile
pop bp ;r etirer BP de la pile
ret ;R etour au programme d´appel
_Sound endp
;- - Nouvelle interruption temporisateur ----------------------------------------
sound_ti proc far ;E st appelée 18 fois par seconde
push ax ;R anger AX et
push ds ;D S sur la pile
setds: mov ax,0000h ;C ´est ici que doit être inscrit le DS C
mov ds,ax
dec cptr_s ;D écrémenter compteur
jne fin_st ;S i pas encore 0, alors fin
mov fin_s,0 ;S ignaler durée de note écoulée
fin_st: pop ds ;F ixer à nouveau ancien DS
pop ax ;R etirer aussi AX de la pile
stjump: db 0EAh,0,0,0,0 ;F AR JUMP vers l´ancienne interruption temporisateur
sound_ti endp
;_ _ Fin
__________________________________________________
______________________
_TEXT ends ;F in du segment de programme
end ;F in du source assembleur
Le même programme uniquement en assembleur :
;*************************************************
;* S O U N D *;
;*------------------------------------------------
----------------------------*;
;* Fonction : Sort la gamme chromatique de l´octave 3 à l´octave 5 à *;
;* l´aide d´une routine universelle de générat° de sons. *;
;*------------------------------------------------
----------------------------*;
;* Auteur : MICHAEL TISHER *;
;* développé le : 06/08/1987 *;
;* dernière modif : 16/02/1992 *;
;*------------------------------------------------
----------------------------*;
;* Assemblage : MASM SOUNDA; *;
;* LINK SOUNDA; *;
;* EXE2BIN SOUNDA SOUNDA.COM ou *;
;* TASM SOUNDA *;
;* TLINK /TC SOUNDA *;
;*------------------------------------------------
----------------------------*;
;* Appel : SOUND *;
;*************************************************
code segment para ´CODE´ ;D éfinition du segment de code
org 100h ;I l commence à l´adresse 100(h)
;d irectement à la suite du PSP
assume cs:code, ds:code, es:code, ss:code
;_ _ Programme
__________________________________________________
_______________;
sound proc near
;- - sortir message
--------------------------------------------------
-----------
mov ah,9 ;N uméro de fonction pour sortir chaîne
mov dx,offset initm ;A dresse d´offset du message
int 21h ;A ppeler interruption du DOS
;- - Jouer gammes chromatiques
--------------------------------------------------
xor bl,bl ;C ommencer par le Do de la 3ème octave
mov dl,9 ;J ouer une demi seconde chaque fois
nextune: call play_tune ;J ouer note
inc bl ;N ote suivante
;- - Sortir message de fin
--------------------------------------------------
----
mov ah,9 ;N uméro de fonction pour sortir chaîne
mov dx,offset endmes ;A dresse d´offset du message
int 21h ;A ppeler interruption du DOS
mov ax,4C00h ;T erminer programme par appel d´une
int 21h ;f onction DOS en renvoyant le code d´erreur 0
sound endp
;_ _ Données du programme principal _____________________________________________
initm db 13,10,"SOUND (c) 1987 by Michael Tischer",13,10,13,10
db "Si le haut-parleur de votre PC fonctionne correctement, "
db "vous allez entendre",13,10,"maintenant la gamme chro"
db "matique des octaves 3à 5.",13,10,"$"
endmes db 13,10,"Fin",13,10,"$"
;- - PLAY_TUNE : Jouer une note
-------------------------------------------------
;- - Entrée : BL = n° de note par rapport au Do de la 3ème octave
;- - DL = Durée de note en 1/18èmes de seconde
;- - Sortie : Aucune
;- - Registres : AX,CX,ES et FLAGS sont modifiés
;- - Infos : Le contrôle n´est rendu à la routine d´appel qu´une
;- - fois la durée de note écoulée
play_tune proc near
push dx ;R anger DX et
push bx ;B X sur la pile
;- - Détourner interruption temporisateur sur routine utilisateur ---------------
push dx ;R anger DX et
push bx ;B X sur la pile
mov ax,351ch ;L ire adresse de l´interruption temporisateur
int 21h ;A ppeler interruption du DOS
mov time_anc,bx ;A dresse d´offset de l´ancienne interruption
mov time_anc+2,es ;e t ranger adresse de segment
mov dx,offset sound_ti ;A dresse offset nouvelle routine tempo.
mov ax,251ch ;F ixer nouvelle routine temporisateur
int 21h ;A ppeler interruption du DOS
pop bx ;R etirer BX et
pop dx ;D X de la pile
mov al,182 ;P réparer génération d´un son
out 43h,al ;E nvoyer valeur au Timer Command Register
xor bh,bh ;B H pour adressage table notes = 0
shl bx,1 ;D oubler n° note (car table de mots)
mov ax,[notes+bx] ;L ire valeur de note
out 42h,al ;O ctet faible dans Timer Counter Register
mov al,ah ;T ransférer octet fort dans AL
out 42h,al ;e t aussi dans Timer Counter Register
in al,61h ;L ire bit de contrôle du haut parleur
or al,11b ;D eux bits inférieurs activent haut-parleur
mov fin_s,1 ;N ote doit encore être jouée
mov cptr_s,dl ;e t sauvegarder
out 61h,al ;A ctiver haut-parleur
play: cmp fin_s,0 ;N ote terminée ?
jne play ;N on --> attendre encore
in al,61h ;L ire bit de contrôle du haut parleur
and al,11111100b ;A nnuler 2 bits inférieurs
out 61h,al ;D ésactiver haut-parleur
;- - Activer à nouveau ancienne interruption temporisateur ----------------------
mov cx,ds ;R anger DS
mov ax,251ch ;n ° fonction pour fixer vecteur d´interruption
lds dx,dword ptr time_anc ;C harger encienne adresse dans DX:DX
int 21h ;A ppeler interruption du DOS
mov ds,cx ;R amener DS
pop bx ;R etirer BX et
pop dx ;D X de la pile
ret
play_tune endp
;- - Nouvelle interruption temporisateur ----------------------------------------
sound_ti proc far ;E st appelée 18 fois par seconde
dec cs:cptr_s ;D écrémenter compteur
jne fin_st ;S i pas encore 0, alors fin
mov cs:fin_s,0 ;S ignaler durée de note écoulée
fin_st: jmp dword ptr cs:[time_anc] ;V ers ancienne interruption temporisateur
sound_ti endp
;_ _ Voici les variables dont ont besoin les 4 routines _________________________
time_anc dw (?),(?) ;A dresse ancienne interruption temporisateur
cptr_s db (?) ;D urée restante d´une note en 1/18èmes de seconde
fin_s db (?) ;I ndique si note a déjà été jouée
notes dw 9121,8609,8123,7670 ;V aleurs de notes pour l´octave 3
dw 7239,6833,6449,6087
dw 5746,5423,5119,4831
dw 4560,4304,4063,3834 ;V aleurs de notes pour l´octave 4
dw 3619,3416,3224,3043
dw 2873,2711,2559,2415
dw 2280,2152,2031,1917 ;V aleurs de notes pour l´octave 5
dw 1809,1715,1612,1521
dw 1436,1355,1292,1207
;_ _ Fin
__________________________________________________
______________________
code ends ;F in du segment de CODE
end sound ;F in du programme assembleur
J´oubliais de préciser les noms des fichiers qui sont respectivement :
- soundc.c
- soundca.asm
- sounda.asm
M´énerf´ ce forum avec l´affichage du code
Bon, pour faire plus simple, le code à télécharger :
http://cedric.moreau8.free.fr/sons/soundc.c
http://cedric.moreau8.free.fr/sons/soundca.asm
http://cedric.moreau8.free.fr/sons/sounda.asm
mince, c´est vachement compliqué!
mais ![]()
En fait, pas tellement si tu utilise le 1er exemple.
Tu n´as rien à changer au source ASM, seulement à adapter le source en C à tes besoins.
L´exemple n´utilise que les octaves 3, 4 et 5, mais si tu en as besoin, j´ai toutes les fréquences pour les octaves 0 à 7.
Pour info, le "LA" de référence utilisé en musique est la 10ème note de l´octave 4 ![]()
en fait, j´ai téléchargé le programme en assembleur, c´est plus simple parce que le C et tout ca
seulement, ils me disent que j´ai un "invalid opcode at" avec plein de nombres derrière ![]()
L´assembleur plus simple que le C
Personnellement je préfère la version C + Assembleur, parce que l´assembleur tu n´as plus à y toucher (sauf si tu veux rajouter les autres octaves, mais c´est hyper simple.
Je n´ai que de vague notions de C (ANSI) qui datent d´il y´a plus de 10 ans et j´ai à peu près compris le fonctionnement de ce code. Il est assez simple :
Tous le début entre /* et */ n´est que du commentaire.
Intégration de la routine assembleur.
Affichage de quelques lignes à l´écran.
Une boucle de 0 à 36 pur jouer les 12 notes des octaves 3 à 5.
Affichage du message "Fin" à l´écran.
Si ça t´intéresse, le Site du Zér0 fait de très bons tutoriaux pour apprendre le C/C++ (très simple à comprendre, expliqués de façon amusante) :
http://www.siteduzero.com/tuto-3-8-0-apprenez-a-programmer-en-c.html
Et puis les codes que je t´ai donnés sont bien commentés.
Pour ce qui est de l´erreur, les fichiers que je t´ai donnés sont tirés du CD fourni avec le bouquin, je ne les ai pas essayés, donc ne peut garantir leur fonctionnement.
Il n´est pas rare que les sources fournis avec un bouquin ne fonctionne pas. Ce sont en général des erreurs minimes, comme des fautes de frappe.
merci beaucoup les gars! en fait, vous avez raison, je vais essayer la version assembleur-c++! mais je viens a peine de commencer l´assembleur et j´arrive pas a faire le tri entre les notes et tout
vous ne sauriez pas comment faire juste une note de fréquence donnée pendant un temps donné en assembleur?
Dans le programme en assembleur, les notes n´ont pas été enregistrée en Hz, mais ont été converties de façon exploitable par l´assembleur.
Le temporisateur qui permet d´exploiter le HP interne utilise l´horloge interne du PC, qui qui produit 1 193 180 impulsions par secondes.
=> valeur_note = 1 193 180 / frequence_note
exemple : le La de référence a pour fréquence 440Hz
=> valeur_LA = 1 193 180 / 440 = 2711
Les notes des octaves 3 à 5 ont été ainsi convertie et stockées dans une table du code assembleur dans l´ordre suivant :
do, do#, ré, ré#, mi, fa, fa#, sol, sol#, la, la#, si, ... mêmem chose pour chaques octaves.
Pour jouer le La de référence, il faut jouer la 34ème valeur de la table (12 + 12 + 10), en commençant par 0, ce qui donne 33.
Dans le cas présent, la durée se mesure en 1/18èmes de secondes.
Pour une demie-seconde, il faut mettre la valeur 9, pour une seconde => 18, 2 sec => 36, ...
Donc pour jouer le La de référence pendant 3 secondes, dans le prog en C, tu mettras :
Sound(33, 54);