zoukankan      html  css  js  c++  java
  • 操作 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.
    
  • 相关阅读:
    【Uvalive4960】 Sensor network (苗条树,进化版)
    【UVA 1151】 Buy or Build (有某些特别的东东的最小生成树)
    【UVA 1395】 Slim Span (苗条树)
    【UVA 10600】 ACM Contest and Blackout(最小生成树和次小生成树)
    【UVA 10369】 Arctic Network (最小生成树)
    【UVA 10816】 Travel in Desert (最小瓶颈树+最短路)
    【UVA 11183】 Teen Girl Squad (定根MDST)
    【UVA 11865】 Stream My Contest (二分+MDST最小树形图)
    【UVA 11354】 Bond (最小瓶颈生成树、树上倍增)
    【LA 5713 】 Qin Shi Huang's National Road System (MST)
  • 原文地址:https://www.cnblogs.com/del/p/1601006.html
Copyright © 2011-2022 走看看