操作 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.


 
   

你可能感兴趣的:(文件)