FAQ DelphiConsultez toutes les FAQ
Nombre d'auteurs : 124, nombre de questions : 934, dernière mise à jour : 23 octobre 2024 Ajouter une question
Cette FAQ a été réalisée à partir des questions fréquemment posées sur les forums Delphi et Delphi et bases de données de www.developpez.com et de l'expérience personnelle des auteurs.
Nous tenons à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose soient correctes. Les auteurs font le maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous souhaitez y apporter des corrections ou la compléter, contactez un responsable (lien au bas de cette page).
Nous espérons que cette FAQ saura répondre à vos attentes. Nous vous en souhaitons une bonne lecture.
L'équipe Delphi de Developpez.com.
Avec Windows NT, Windows 2000 et Windows XP :
Il suffit d'utiliser la fonction Windows.Beep (dwFreq : DWord, dwDuration : DWord) où dwFreq correspond à la fréquence du son voulue (en Hertz) et dwDuration est la durée du son voulue (en millisecondes).
Par exemple, pour jouer la note LA durant 1/10ème de seconde :
Code delphi : | Sélectionner tout |
Windows.Beep(440, 100)
Avec Windows 95, Windows 98 et Windows Me :
Avec ces versions de Windows, la fonction Beep effectue toujours le même son, quels que soient les paramètres. Le seul moyen d'émettre un son sur le haut-parleur est de le commander directement. L'assembleur en ligne est le moyen le plus simple depuis la disparition des tableaux prédéfinis Port et PortW.
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | { Fonction d'émission d'un son sur le haut-parleur interne. } { Hz est la fréquence du son } procedure Sound(Hz : Integer);Pascal; Asm CMP Hz,0 JZ @FIN MOV AL,182 OUT $43,AL IN AL,$61 OR AL,3 OUT $61,AL MOV EAX,1193180 XOR EDX,EDX DIV Hz OUT $42,AL XCHG AL,AH OUT $42,AL @FIN: End; { Fonction d'arrêt du son sur le haut-parleur interne. } procedure NoSound; Asm MOV AL,182 OUT $43,AL IN AL,$61 AND AL,3 OUT $61,AL End; |
Par exemple, pour jouer la note LA durant 1/10ème de seconde :
Code delphi : | Sélectionner tout |
1 2 3 | Sound(440); Sleep(100); NoSound; |
Pour jouer un son simplement dans un programme, on peut utiliser la fonction
Code delphi : | Sélectionner tout |
PlaySound(pszSound: PChar; hmod: HMODULE; fdwSound: DWORD): BOOL; stdcall;
Code delphi : | Sélectionner tout |
PlaySound('c:\windows\media\ding.wav',0,SND_FILENAME);
Code delphi : | Sélectionner tout |
PlaySound('NomRessource',GetModuleHandle(Nil),SND_RESOURCE);
Les fichiers .cda décrivent les pistes contenues dans un CD audio. Ces fichiers sont visibles dans l'explorateur de Windows lorsque vous ouvrez une fenêtre correspondant au CD.
Il n'existe pas de fonction de l'API permettant de consulter le contenu de ces fichiers mais vous pouvez utiliser ou vous inspirer des fonctions disponibles à l'adresse suivante :
Cette procédure permet de jouer une note de musique en fonction de sa fréquence et de sa durée, non pas sur le speaker interne comme la procédure Windows.Beep(), mais sur la carte son.
Après avoir donné les propriétés du wav (Dans WaveFormatEx : nombre de voies, fréquence d’échantillonnage, bits par échantillon etc.), la structure est écrite dans un MemoryStream qui est ensuite passé en paramètre à sndPlaysound en spécifiant la lecture d'un flux mémoire
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | uses MMSystem; type TVolumeLevel = 0..127; procedure MakeSound(Frequency{Hz}, Duration{mSec}: Integer; Volume: TVolumeLevel); var WaveFormatEx: TWaveFormatEx; MS: TMemoryStream; i, TempInt, DataCount, RiffCount: integer; SoundValue: byte; w: double; // omega=2*pi*fréquence const Mono: Word = $0001; //Son Mono SampleRate: Integer = 11025; // autres taux d'échantillonnage possibles 8000, 11025, 22050, or 44100 //Champs de l'en-tête d'un fichier .WAV RiffId: string = 'RIFF'; WaveId: string = 'WAVE'; FmtId: string = 'fmt '; DataId: string = 'data'; begin //si la fréquence de la note est trop élevée par rapport au taux d'échantillonnage if Frequency > (0.6 * SampleRate) then begin //... on considère que la note sera injouable. ShowMessage(Format('Un taux d''échantillonage de %d est trop bas pour jouer une tonalité de %dHz', [SampleRate, Frequency])); Exit; end; with WaveFormatEx do begin //Paramètres d'un en-tête de fichier WAV au format PCM wFormatTag := WAVE_FORMAT_PCM; nChannels := Mono; nSamplesPerSec := SampleRate; wBitsPerSample := $0008; nBlockAlign := (nChannels * wBitsPerSample) div 8; nAvgBytesPerSec := nSamplesPerSec * nBlockAlign; cbSize := 0; end; MS := TMemoryStream.Create; with MS do begin //Calcule la longueur des données du son à jouer et celle du fichier WAV qui en découle DataCount := (Duration * SampleRate) div 1000; // sound data RiffCount := Length(WaveId) + Length(FmtId) + SizeOf(DWORD) + SizeOf(TWaveFormatEx) + Length(DataId) + SizeOf(DWORD) + DataCount; // données du fichier //écriture de l'en-tête du fichier WAV dans le flux mémoire Write(RiffId[1], 4); // 'RIFF' Write(RiffCount, SizeOf(DWORD)); // taille du fichier Write(WaveId[1], Length(WaveId)); // 'WAVE' Write(FmtId[1], Length(FmtId)); // 'fmt ' TempInt := SizeOf(TWaveFormatEx); Write(TempInt, SizeOf(DWORD)); // taille de TWaveFormat Write(WaveFormatEx, SizeOf(TWaveFormatEx)); // taille d'un enregistrement WaveFormatEx Write(DataId[1], Length(DataId)); // 'data' Write(DataCount, SizeOf(DWORD)); // taille des données du son //calcule et écrit le signal sonore // calcul des valeurs qui composent le son, // c'est une courbe sinusoïdale dont les valeurs sont comprises entre 0 et 255, //donc l'axe médian de la sinusoïde est en y=127) w := 2 * Pi * Frequency; // omega for i := 0 to DataCount - 1 do begin SoundValue := 127 + trunc(Volume * sin(i * w / SampleRate)); // explication : wt = w * i / SampleRate //on écrit notre "point" de la courbe dans notre fichier WAV Write(SoundValue, SizeOf(Byte)); end; //Maintenant on joue le son en disant à Windows : //-SND_MEMORY : c'est un son écrit dans un flux mémoire //-SND_SYNC : de jouer le son de façon synchrone (tant que le son n'est pas terminé, le code ne se déroule plus. // Ainsi, un deuxième appel consécutif à notre procédure ne "coupera pas le sifflet" du premier appel. sndPlaySound(MS.Memory, SND_MEMORY or SND_SYNC); MS.Free; end; end; |
Code delphi : | Sélectionner tout |
1 2 3 4 | procedure TForm1.Button1Click(Sender: TObject); begin MakeSound(440, 1000, 60); end; |
Une note de musique est caractérisée par 3 paramètres : sa hauteur, son amplitude et son timbre.
- la hauteur, ou encore fréquence de la note : plus la fréquence est basse, plus la note sera grave. Musicalement, pour augmenter une note d'une octave, il faut multiplier sa fréquence par 2.
- l'amplitude : C'est la puissance sonore, ou encore plus communément appelé "Volume". Notre fichier WAV n'utilise pas la notion de décibels, mais une valeur comprise entre 0 (silence) et 127 (le plus fort possible).
Le résultat final en décibels, dépend de la puissance de vos enceintes et du réglage du bouton de volume de ces dernières. - Le timbre est le paramètre qui caractérise le son. C'est lui qui permet différencier 2 instruments de musiques différents jouant la même note (une flûte et un piano par exemple, ou plus subtil, un violon "lambda" et un "Stradivarius").
Il est lié à la forme de notre courbe périodique. Dans notre code, celà se caractérise par le rendu d'une courbe (onde) sinusoïdale. Nous aurions pu ,par exemple, calculer une courbe en triangles, en dents de scie, etc.
Quelques Fréquences (approximatives) de notes de musique :
Octave n°3 :
- Do : 264 Hz
- Ré : 297 Hz
- Mi : 330 Hz
- Fa : 352 Hz
- Sol : 396 Hz
- La : 440 Hz (Le LA du diapason)
- Si : 495 Hz
- Do4 : 528 Hz
Pour aller plus loin :
- Vous trouverez une description détaillée de la structure des fichiers wav sur le site de Wotsit's format
- Ensemble de tutoriels sur le format wav par Sub0 : http://sub0.developpez.com
- Deux sources Delphi par Bestiol (Olivier Lance) pour apprendre à manipuler les fichiers Wav :
Concaténation de fichiers WAV
Faites des morceaux de vos fichiers WAV ! - Et d'une manière générale, sur tout internet : http://www.google.fr/search?&q=Wave ...urceid=firefox
Sous Delphi 6 :
Code Delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | Unit Unit1; Interface Uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, mmSystem, StdCtrls; {mmSystem vous permet d'avoir accès aux fonctions de contrôle midi} {----------------------------------------------------------------} Type TForm1 = Class(TForm) Button1: TButton; Edit1: TEdit; Procedure FormCreate(Sender: TObject); Procedure FormDestroy(Sender: TObject); Procedure Button1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); Procedure Button1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); End; const Hpc=$100; Hpdm=$10000; Var Form1: TForm1; MidiOut: hMidiOut; Implementation {----------------------------------------------------------------} {$R *.dfm} {----------------------------------------------------------------} Procedure TForm1.FormCreate(Sender: TObject); Var Res: DWORD; msg: String; Begin Res := midiOutOpen(@MidiOut, MIDI_MAPPER, Handle, 0, CALLBACK_WINDOW); //La partie qui est çi-dessous peut être omise. Mais vous donneras des indications en cas d'erreur If Res <> 0 Then Begin Case Res Of MMSYSERR_BADDEVICEID: msg := 'Device invalide'; MMSYSERR_ALLOCATED: msg := 'Erreur d''allocation mémoire'; MMSYSERR_NOMEM: msg := 'Pas assez de mémoire'; MIDIERR_NOMAP: msg := 'Midi mapper non trouvé'; MIDIERR_NODEVICE: msg := 'Device non trouvé'; Else msg := 'Erreur inconnue'; End; MessageBox(Form1.Handle, pChar(msg), 'Error', MB_OK); Close; End; //------------------------------------------------------------------------------------------------- End; {La procédure çi dessous vous permet d'arrêter tout événement midi à la sortie du programme} {rien ne vous empêche de vous faire un petit boutton “Panic” dans le programme à partir de ça, au cas ou un noteOff n'aie pas été détécté} Procedure TForm1.FormDestroy(Sender: TObject); Begin midiOutShortMsg(MidiOut, $00007BB0); midiOutClose(MidiOut); End; {----------------------------------------------------------------} Procedure TForm1.Button1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); Begin midiOutShortMsg(MidiOut, ($7F*Hpdm)+($25*Hpc)+($99)); End; {----------------------------------------------------------------} Procedure TForm1.Button1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); Begin midiOutShortMsg(MidiOut, ($7F*Hpdm)+($25*Hpc)+($89)); end; {----------------------------------------------------------------} End. |
midiOutShortMsg(MidiOut, 007F2599) vous permet de jouer un click de métronome sur le canal 10 au volume 127 :
- le volume c'est 7F en hexadécimal ;
- le click c'est 25 ;
- 99 : le premier 9 veut dire jouer la note, le deuxième sur le canal 10 (car les canaux vont de 0 à 9).
midiOutShortMsg(MidiOut, 007F2589) : le 8 veut dire qu'on arrête la note sur le même canal.
Vous remarquerez que j'ai omis les premiers octets (00), qui sont de toutes façon inutilisés.
En ce qui concerne l'écriture
Code Delphi : | Sélectionner tout |
midiOutShortMsg(MidiOut, ($7F*Hpdm)+($25*Hpc)+($99));
Si j'utilise la variable 'Note', par exemple, pour pouvoir jouer une note sur le canal 1, j'écrirai
Code Delphi : | Sélectionner tout |
midiOutShortMsg(MidiOut, ($7F*Hpdm)+(Note*Hpc)+($80));
J'aurais pu écrire
Code Delphi : | Sélectionner tout |
midiOutShortMsg(MidiOut, ($7F*$10000)+(Note*$100)+($80));
Si vous voulez interagir sur cette commande, vous pourrez écrire par exemple :
Code Delphi : | Sélectionner tout |
midiOutShortMsg(MidiOut, (Volume*$10000)+(Note*$100)+(8*$10)+Canal));
Attention avec les procédures Button1MouseDown et up. Si vous faites un copier-coller des procédures et que vous rajoutez le bouton après, ça ne marche pas. Aucun son ne sort.
Proposer une nouvelle réponse sur la FAQ
Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour çaLes sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.