【问题标题】:Real time microphone in Delphi?Delphi中的实时麦克风?
【发布时间】:2011-11-01 19:27:39
【问题描述】:

是否有实时麦克风 Delphi 组件?

我正在寻找一种无需缓冲即可提供结果的产品。

【问题讨论】:

  • “没有缓冲区”是什么意思。音频数据总是需要稍微缓冲一下。只需经常阅读缓冲区内容即可快速获取音频。你真正想解决什么问题?
  • 我想制作一个现场示波器来记录来自麦克风的样本,然后快速绘制(或处理它)。例如,我需要查看我是否收到脉冲,然后非常快地做某事,而不需要超时。
  • 音频路径已经有明显的延迟。只需创建一个超时时间为 10 毫秒的计时器,您可以在其中读取缓冲区并绘制收到的新样本。如果您想在几毫秒内对信号做出反应,那么常见的音频 API 不是您想要的,Windows 甚至可能不是您想要的操作系统。
  • 你见过这个吗? oscilloscope-lib.com

标签: delphi audio-recording microphone


【解决方案1】:

您需要具有 ASIO 驱动程序的声卡,例如更高端的 Sound Blaster 卡。 ASIO 的延迟非常低,因为它在软件和硬件之间提供了一个最小层。然后你可以使用这个:

Delphi ASIO & VST Project

其他替代方案包括使用 FFMPEG Delphi 端口,当然还有 Jedi 的 Direct X。

【讨论】:

  • ASIO 是所有音乐软件使用的,对吧?我相信 FruityLoops 最初是用 Delphi 编写的,并且使用了 ASIO。
  • @Warren P,如果您说的是与键盘/鼓垫等乐器同步,那就是 MIDI 和 VST。
  • FruityLoops 既是一个虚拟乐器 (VST) 插件驱动的合成器,也是一个具有实时效果的 MIDI 输入/输出音序器。综上所述。
【解决方案2】:

有来自 Mitov Software 的 AudioLab,它声称可以做你描述的事情。我没试过。

【讨论】:

    【解决方案3】:

    实时获取一个数组中的麦克风数据:

    unit WaveSound;
    
    interface
    
    uses
      SysUtils, MMSystem;
    
    const
      NUMSAMPLES = 1024;    // Number of Samples
    
    type
      TIndata      = array[0 .. NUMSAMPLES - 1] of Integer;
      PIndata      = ^TIndata;
    
      TFrec= record
        Fx, dx  :Integer;
      end;
    
      function SNDInitWaveIn: Cardinal;
      procedure SNDProcWaveIn(var Indata : TIndata);
      procedure SNDStopWave;
    
    implementation
    
    var
      DevHandle   : Integer;
      WAVEFORMAT1 : TWAVEFORMATEX;
      Wave        : WAVEHDR;
    
    function SNDInitWaveIn: Cardinal;
    begin
        with WAVEFORMAT1 do begin
            wFormatTag := WAVE_FORMAT_PCM;
            nChannels := 1;
            nSamplesPerSec := 44100;// 11025; //11khz
            wBitsPerSample := 16;
            nBlockAlign := (nChannels * wBitsPerSample) div 8;
            nAvgBytesPerSec := nBlockAlign * nSamplesPerSec;
            cbSize := 0;
        end;
        Result:= waveInOpen(@DevHandle, cardinal(-1),@WAVEFORMAT1, cardinal(0), cardinal(0), cardinal(0));
        If not(DevHandle = 0) Then waveInStart(DevHandle);
    end;
    
    procedure SNDProcWaveIn(var Indata : TIndata);
    begin
      //lpdata requires the address of an array to fill up data with
          Wave.lpData := @Indata;
      //the buffer length
          Wave.dwBufferLength := NUMSAMPLES;
          Wave.dwFlags := 0;
       //prepare device for input
          waveInPrepareHeader(DevHandle, @Wave, sizeof(Wave));
          waveInAddBuffer(DevHandle, @Wave, sizeof(Wave));
          // if the following statement is removed, the vis. will be a lot faster (avs style)
          // but uses up 100% of cpu!
          // this is why i hate avs
          Sleep(10); // give device a breather
          // the following loop is quite useless, but anyway...
          repeat
              //Just wait for the blocks to be done or the device to close
          until (((Wave.dwFlags and WHDR_DONE)= WHDR_DONE) or (DevHandle = 0));
          If (DevHandle = 0) Then Exit;  //Cut out if the device is closed
          waveInUnprepareHeader(DevHandle, @Wave, sizeof(Wave));
    end;
    
    procedure SNDStopWave;
    begin
        waveInReset(DevHandle);
        waveInClose(DevHandle);
        DevHandle := 0;
    end;
    /////////// [sample of use : ] /////////////////
    var
      ind :TIndata;    
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      SNDInitWaveIn;
      Timer1.Enabled:= true;
    end;
    
    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
        SNDProcWaveIn(ind);
        //code for proc data in "ind" buffer
    end;
    
    procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
        SNDStopWave;
    end;
    

    【讨论】:

      猜你喜欢
      • 2023-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-16
      • 1970-01-01
      • 2022-01-14
      • 2019-02-02
      • 2010-09-20
      相关资源
      最近更新 更多