Wave 文件(11): 使用 waveIn...函数录制 wav 文件

使用窗口接受音频设备发出的消息:

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.

posted @ 2010-01-13 15:10  架构师聊技术  阅读(356)  评论(0编辑  收藏  举报