Das folgende Beispiel demonstriert, wie man anhand des Soundoutputs einen Wave Sound generieren kann. Es wird keine Datei abgespielt, sondern ein Wave Sound anhand des Soundchips generiert und als Grafik visualisiert.
Es werden benötigt : 2xButton, 2xTrackBar, 1xPaintBox
uses MMSystem, StdCtrls, ExtCtrls, ComCtrls
procedure changeToneClick(Sender: TObject);
private
{ Private declarations }
procedure mm_wom_Open (var Msg: TMessage); message mm_wom_open;
procedure mm_wom_Done (var Msg: TMessage); message mm_wom_done;
procedure mm_wom_Close (var Msg: TMessage); message mm_wom_close;
procedure PlayBuffer(bb: array of byte);
procedure startGenerate;
procedure stopGenerate;
procedure DrawSgnl(graphBuf: array of integer);
var
Form1: TForm1;
waveOut: hWaveOut;
outHdr: array [0..1] of TWaveHdr;
header: TWaveFormatEx;
pKey: boolean;
pBuf: array [0..1] of tHandle;
pBuffer: array [0..1] of pointer;
fPlay: boolean;
Opened: boolean;
//
procedure TForm1.changeToneClick(Sender: TObject);
begin
if pkey = false then pkey:=true;
startGenerate;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if pKey = false then begin
startGenerate;
pKey:=true;
end else begin
stopGenerate;
pKey:=false;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
if pKey = true then begin
stopGenerate;
pKey:=false;
end;
end;
procedure TForm1.PlayBuffer(bb: array of byte);
var
i, err: integer;
begin
with header do begin
wFormatTag := WAVE_FORMAT_PCM;
nChannels := 1;
nSamplesPerSec := 44100;
wBitsPerSample := 8;
nBlockAlign := nChannels * (wBitsPerSample div 8);
nAvgBytesPerSec := nSamplesPerSec * nBlockAlign;
cbSize := 0;
end;
err:=WaveOutOpen(addr(waveOut), 0, @header,
Handle, 0, CALLBACK_WINDOW);
if Err <> 0 then Exit;
for i:=0 to 1 do begin
pBuf[i] := GlobalAlloc(GMEM_MOVEABLE and GMEM_SHARE, length(bb));
pBuffer[i]:=GlobalLock(pBuf[i]);
with outHdr[i] do begin
lpData := pbuffer[i];
dwBufferLength := length(bb);
dwUser := 0;
dwFlags := 0;
dwLoops := 0;
end;
err:=WaveOutPrepareHeader(waveOut, @outHdr[i], sizeof(outHdr));
if Err <> 0 then Exit;
copyMemory(pBuffer[i], @bb, length(bb));
err:=WaveOutWrite(waveOut, @outHdr[i], sizeof(outHdr));
if Err <> 0 then Exit;
end;
end;
procedure TForm1.mm_wom_open (var Msg: tMessage);
begin
Opened:=True;
end;
procedure TForm1.mm_wom_done (var Msg: tMessage);
begin
if fPlay = false then begin
waveOutWrite(waveOut, @outHdr[0], sizeof(outHdr));
fPlay:=true;
end else begin
waveOutWrite(waveOut, @outHdr[1], sizeof(outHdr));
fPlay:=false;
end;
end;
procedure Tform1.mm_wom_close (var Msg: tMessage);
begin
Opened:=False;
end;
procedure tform1.startGenerate;
var
i: integer;
buffer: array [0..44099] of byte;
tmpBuf: array of integer;
mult: double;
mag: double;
begin
Label1.caption:='Volume: '+inttostr(trackbar1.position)+'%';
Label2.caption:='Frequency: '+inttostr(trackbar2.position*200)+' hz';
for i:=0 to length(buffer) - 1 do begin
mult := i / length(buffer);
mag := (127 * trackbar1.position * 0.01) * Sin(2 * Pi * mult * trackbar2.position * 200);
mag := mag + 127;
buffer[i] := round(mag);
end;
setLength(tmpbuf, 128);
for i:=0 to 127 do begin
tmpBuf[i]:=round((buffer[i]-127)*256);
end;
DrawSgnl(tmpBuf);
if Opened = false then begin
playBuffer(buffer);
end else begin
for i:=0 to 1do
copyMemory(pBuffer[i], @buffer, length(buffer));
end;
end;
procedure tform1.stopGenerate;
var
i: integer;
begin
WaveOutReset(WaveOut);
WaveOutClose(WaveOut);
for i:=0 to 1 do begin
GlobalUnlock(pBuf[i]);
GlobalFree(pBuf[i]);
end;
fPlay:=false;
end;
procedure TForm1.DrawSgnl(graphBuf: array of integer);
var
i, tmpX, tmpY: integer;
begin
PaintBox1.Refresh;
with PaintBox1.Canvas do begin
pen.style := psSolid;
pen.Color := clRed;
brush.style := bsSolid;
brush.color:=clBlue;
Rectangle(0,0,PaintBox1.Width,PaintBox1.Height);
end;
PaintBox1.Canvas.MoveTo(0, PaintBox1.Height div 2);
for i:=0 to length(graphbuf) - 1 do
begin
tmpX := Round(i*PaintBox1.Width/length(graphBuf));
tmpY := PaintBox1.Height div 2 - Round(graphBuf[i]*PaintBox1.Height/2/32767);
PaintBox1.Canvas.LineTo(tmpX, tmpY);
end;
end;
Keine Kommentare:
Kommentar veröffentlichen