• 操作 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.
    
  • 相关阅读:
    如何让你的Sublime和Codeblocks支持C++11
    Python print不换行输出的替代方法
    阶梯博弈
    hdu4633_Polya定理
    Ural_1169_Pairs
    ACM竞赛中的魔方问题专题(不定时更新)
    LintCode 35. 翻转链表
    windows中mysql5.7中配置中文字符集和默认datadir
    CentOS7使用打开关闭防火墙与端口
    关于阿里巴巴开发手册"不得使用外键与级联,一切外键概念必须在应用层解决"的疑惑
  • 原文地址:https://www.cnblogs.com/del/p/1601006.html
Copyright © 2020-2023  润新知