FAQ DelphiConsultez toutes les FAQ

Nombre d'auteurs : 123, nombre de questions : 920, dernière mise à jour : 8 novembre 2019  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.

Commentez


SommaireSystèmeSon (5)
précédent sommaire suivant
 

Avec Windows NT, Windows 2000 et Windows XP :

Il suffit d'utiliser la fonction Windows.Beep (dwFreq : DWord, dwDuration : DWord)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;

Mis à jour le 14 janvier 2014 Al-Yazdi

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;
Cette fonction peut lire un fichier :
Code delphi : Sélectionner tout
PlaySound('c:\windows\media\ding.wav',0,SND_FILENAME);
Ou directement une ressource :
Code delphi : Sélectionner tout
PlaySound('NomRessource',GetModuleHandle(Nil),SND_RESOURCE);
Une autre solution est d'ouvrir le fichier .WAV comme un document avec ShellExecute.

Mis à jour le 14 janvier 2014 Nono40

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 :

Mis à jour le 17 janvier 2014 Pierre Castelain

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;
Exemple, un La3 (La 440) qui dure une seconde :
Code delphi : Sélectionner tout
1
2
3
4
procedure TForm1.Button1Click(Sender: TObject); 
begin 
  MakeSound(440, 1000, 60); 
end;
Petits rappels pratiques :
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 :

Mis à jour le 14 janvier 2014 LadyWasky phuphus

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.
Petite explication :

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));
Je vous explique : cela permet de modifier les valeurs à l'intérieur de la phrase.
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));
où 'Hpdm' et 'Hpc' sont des constantes.

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));
où Volume, Note et Canal sont des variables évidemment.

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.

Mis à jour le 10 avril 2014 ornitho

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 ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les 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 © 2019 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.