Delphi中的实时麦克风?

3

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

我正在寻找一个无需缓冲即可提供结果的组件。


1
“没有缓冲区”是什么意思?音频数据总是需要稍微缓冲一下。只需经常读取缓冲区内容即可快速获取音频。你实际上想要解决什么问题? - CodesInChaos
我想制作一个实时示波器,记录来自麦克风的样本,然后快速绘制(或处理)它。例如,我需要看到是否收到脉冲信号,然后立即执行某些操作,而不需要进行超时等待。 - user558126
2
音频路径已经存在显著的延迟。只需创建一个计时器,例如10毫秒的超时,在其中读取缓冲区并绘制接收到的新样本即可。如果您想在几毫秒内对信号做出反应,则常见的音频API可能不是您想要的,而Windows甚至可能不是您想要的操作系统。 - CodesInChaos
你看过这个吗?http://www.oscilloscope-lib.com/ - Warren P
3个回答

9
您需要一张带有ASIO驱动程序的音频卡,例如高端的Sound Blaster音频卡。ASIO具有非常低的延迟,因为它在软件和硬件之间提供了最小的层。然后您可以使用以下内容: Delphi ASIO & VST项目 其他选择包括使用FFMPEG Delphi端口和当然Jedi的Direct X。

1
ASIO是所有音乐软件都使用的,对吧?我相信FruityLoops最初是用Delphi编写的,并且它使用了ASIO。 - Warren P
@Warren P,如果你在谈论与键盘/鼓垫等乐器的同步,那就是MIDI和VST。 - Marcus Adams
1
FruityLoops既是虚拟乐器(VST)插件驱动的合成器,又是带有实时效果的MIDI输入/输出序列器。总而言之,它包含了上述所有功能。 - Warren P

5

有来自Mitov软件的AudioLab,它声称可以完成您所描述的事情。我没有尝试过。


4

实时获取麦克风数据并存储在一个数组中:

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;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接