使用窗口接受音频设备发出的消息:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
protected
procedure WndProc(var m: TMessage); override;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses MMSystem;
var
whIn1,whIn2, whOut: TWaveHdr;
hWaveIn,hWaveOut: HWAVE;
fmt: TWaveFormatEx;
buf1,buf2,SaveBuf: TBytes;
procedure TForm1.FormCreate(Sender: TObject);
begin
Button1.Caption := '开始录音';
Button2.Caption := '停止录音';
Button3.Caption := '播放录音';
end;
//开始录音
procedure TForm1.Button1Click(Sender: TObject);
begin
{指定要录制的格式}
fmt.wFormatTag := WAVE_FORMAT_PCM;
fmt.nChannels := 2;
fmt.nSamplesPerSec := 22050;
fmt.nAvgBytesPerSec := 88200;
fmt.nBlockAlign := 4;
fmt.wBitsPerSample := 16;
fmt.cbSize := 0;
SaveBuf := nil; {清除已录制的内容}
if waveInOpen(@hWaveIn, WAVE_MAPPER, @fmt, Handle, 0, CALLBACK_WINDOW) = 0 then
begin
SetLength(buf1, 1024*8);
SetLength(buf2, 1024*8);
whIn1.lpData := PAnsiChar(buf1);
whIn1.dwBufferLength := Length(buf1);
whIn1.dwBytesRecorded := 0;
whIn1.dwUser := 0;
whIn1.dwFlags := 0;
whIn1.dwLoops := 0;
whIn1.lpNext := nil;
whIn1.reserved := 0;
whIn2.lpData := PAnsiChar(buf2);
whIn2.dwBufferLength := Length(buf2);
whIn2.dwBytesRecorded := 0;
whIn2.dwUser := 0;
whIn2.dwFlags := 0;
whIn2.dwLoops := 0;
whIn2.lpNext := nil;
whIn2.reserved := 0;
waveInPrepareHeader(hWaveIn, @whIn1, SizeOf(TWaveHdr));
waveInPrepareHeader(hWaveIn, @whIn2, SizeOf(TWaveHdr));
waveInAddBuffer(hWaveIn, @whIn1, SizeOf(TWaveHdr));
waveInAddBuffer(hWaveIn, @whIn2, SizeOf(TWaveHdr));
waveInStart(hWaveIn);
end;
end;
//停止录音
procedure TForm1.Button2Click(Sender: TObject);
begin
waveInStop(hWaveIn);
waveInUnprepareHeader(hWaveIn, @whIn1, SizeOf(TWaveHdr));
waveInUnprepareHeader(hWaveIn, @whIn2, SizeOf(TWaveHdr));
waveInClose(hWaveIn);
end;
//播放录音
procedure TForm1.Button3Click(Sender: TObject);
begin
whOut.lpData := PAnsiChar(SaveBuf);
whOut.dwBufferLength := Length(SaveBuf);
whOut.dwBytesRecorded := 0;
whOut.dwUser := 0;
whOut.dwFlags := 0;
whOut.dwLoops := 1;
whOut.lpNext := nil;
whOut.reserved := 0;
waveOutOpen(@hWaveOut, WAVE_MAPPER, @fmt, Handle, 0, CALLBACK_WINDOW);
waveOutPrepareHeader(hWaveOut, @whOut, SizeOf(TWaveHdr));
waveOutWrite(hWaveOut, @whOut, SizeOf(TWaveHdr));
end;
procedure TForm1.WndProc(var m: TMessage);
var
ordLen: Integer;
begin
inherited;
case m.Msg of
{处理录音消息}
MM_WIM_OPEN: ; {此消息只携带了设备句柄}
MM_WIM_CLOSE: ; {此消息只携带了设备句柄}
MM_WIM_DATA: begin {此消息携带了设备句柄和 WaveHdr 指针(LParam)}
{保存录制的数据}
ordLen := Length(SaveBuf);
SetLength(SaveBuf, ordLen + PWaveHdr(m.LParam).dwBytesRecorded);
CopyMemory(Ptr(DWORD(SaveBuf)+ordLen), PWaveHdr(m.LParam).lpData, PWaveHdr(m.LParam).dwBytesRecorded);
{继续录制}
waveInAddBuffer(hWaveIn, PWaveHdr(m.LParam), SizeOf(TWaveHdr));
end;
{处理播放消息}
MM_WOM_OPEN: ; {此消息只携带了设备句柄}
MM_WOM_CLOSE: ; {此消息只携带了设备句柄}
MM_WOM_DONE: begin {此消息携带了设备句柄和 WaveHdr 指针(LParam)}
waveOutUnprepareHeader(hWaveOut, PWaveHdr(m.LParam), SizeOf(TWaveHdr));
waveOutClose(hWaveOut);
end;
end;
end;
end.
使用回调函数处理音频设备发出的消息:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses MMSystem;
var
whIn1,whIn2, whOut: TWaveHdr;
hWaveIn,hWaveOut: HWAVE;
fmt: TWaveFormatEx;
buf1,buf2,SaveBuf: TBytes;
//回调函数; 容易出错的是: 系统回调函数中不能使用本地变量
procedure WaveProc(hWave: HWAVE; uMsg, dwInstance, dwParam1, dwParam2: DWORD); stdcall;
var
ordLen: Integer;
begin
case uMsg of
{处理录音消息}
MM_WIM_OPEN: ; {此消息只携带了设备句柄}
MM_WIM_CLOSE: ; {此消息只携带了设备句柄}
MM_WIM_DATA: begin {此消息携带了设备句柄和 WaveHdr 指针(dwParam1)}
{保存录制的数据}
ordLen := Length(SaveBuf);
SetLength(SaveBuf, ordLen + PWaveHdr(dwParam1).dwBytesRecorded);
CopyMemory(Ptr(DWORD(SaveBuf)+ordLen), PWaveHdr(dwParam1).lpData, PWaveHdr(dwParam1).dwBytesRecorded);
{继续录制}
waveInAddBuffer(hWave, PWaveHdr(dwParam1), SizeOf(TWaveHdr));
end;
{处理播放消息}
MM_WOM_OPEN: ; {此消息只携带了设备句柄}
MM_WOM_CLOSE: ; {此消息只携带了设备句柄}
MM_WOM_DONE: begin {此消息携带了设备句柄和 WaveHdr 指针(dwParam1)}
waveOutUnprepareHeader(hWave, PWaveHdr(dwParam1), SizeOf(TWaveHdr));
waveOutClose(hWave);
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Button1.Caption := '开始录音';
Button2.Caption := '停止录音';
Button3.Caption := '播放录音';
end;
//开始录音
procedure TForm1.Button1Click(Sender: TObject);
begin
{指定要录制的格式}
fmt.wFormatTag := WAVE_FORMAT_PCM;
fmt.nChannels := 2;
fmt.nSamplesPerSec := 22050;
fmt.nAvgBytesPerSec := 88200;
fmt.nBlockAlign := 4;
fmt.wBitsPerSample := 16;
fmt.cbSize := 0;
SaveBuf := nil; {清除已录制的内容}
if waveInOpen(@hWaveIn, WAVE_MAPPER, @fmt, DWORD(@WaveProc), 0, CALLBACK_FUNCTION) = 0 then
begin
SetLength(buf1, 1024*8);
SetLength(buf2, 1024*8);
whIn1.lpData := PAnsiChar(buf1);
whIn1.dwBufferLength := Length(buf1);
whIn1.dwBytesRecorded := 0;
whIn1.dwUser := 0;
whIn1.dwFlags := 0;
whIn1.dwLoops := 0;
whIn1.lpNext := nil;
whIn1.reserved := 0;
whIn2.lpData := PAnsiChar(buf2);
whIn2.dwBufferLength := Length(buf2);
whIn2.dwBytesRecorded := 0;
whIn2.dwUser := 0;
whIn2.dwFlags := 0;
whIn2.dwLoops := 0;
whIn2.lpNext := nil;
whIn2.reserved := 0;
waveInPrepareHeader(hWaveIn, @whIn1, SizeOf(TWaveHdr));
waveInPrepareHeader(hWaveIn, @whIn2, SizeOf(TWaveHdr));
waveInAddBuffer(hWaveIn, @whIn1, SizeOf(TWaveHdr));
waveInAddBuffer(hWaveIn, @whIn2, SizeOf(TWaveHdr));
waveInStart(hWaveIn);
end;
end;
//停止录音
procedure TForm1.Button2Click(Sender: TObject);
begin
waveInStop(hWaveIn);
waveInUnprepareHeader(hWaveIn, @whIn1, SizeOf(TWaveHdr));
waveInUnprepareHeader(hWaveIn, @whIn2, SizeOf(TWaveHdr));
waveInClose(hWaveIn);
end;
//播放录音
procedure TForm1.Button3Click(Sender: TObject);
begin
whOut.lpData := PAnsiChar(SaveBuf);
whOut.dwBufferLength := Length(SaveBuf);
whOut.dwBytesRecorded := 0;
whOut.dwUser := 0;
whOut.dwFlags := 0;
whOut.dwLoops := 1;
whOut.lpNext := nil;
whOut.reserved := 0;
waveOutOpen(@hWaveOut, WAVE_MAPPER, @fmt, DWORD(@WaveProc), 0, CALLBACK_FUNCTION);
waveOutPrepareHeader(hWaveOut, @whOut, SizeOf(TWaveHdr));
waveOutWrite(hWaveOut, @whOut, SizeOf(TWaveHdr));
end;
end.