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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
| unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons;
type
TForm1 = class(TForm)
StringGrid1: TStringGrid;
BitBtn1: TBitBtn;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Déclarations privées }
public
{ Déclarations publiques }
end;
var
Form1: TForm1;
implementation
uses MMSystem;
{$R *.dfm}
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;
procedure BipCourt;
begin
MakeSound(880, 50, 60);
sleep(100);
end;
procedure BipLong;
begin
MakeSound(880, 150, 60);
sleep(100);
end;
procedure Silence;
begin
sleep(200);
end;
procedure JouerCodeMorse(CodeMorse:string);
Var i:integer;
begin
for i:=1 to length(CodeMorse) do
case CodeMorse[i] of
'.':BipCourt;
'-':BipLong;
' ':Silence;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
JouerCodeMorse('... --- ... ');
end;
end. |
Partager