Delphi/MCI话筒专用控制

Delphi/MCI话筒专用控制,delphi,windows-10,delphi-xe,mci,Delphi,Windows 10,Delphi Xe,Mci,所以我用Delphi用MCISendString录制音频。代码运行良好,但有一个例外。我让用户设置参数、频道、位、频率,在Windows7上这一切都很好。现在在Windows 10上,我得到了mcierr\u wave\u输入信号 如果我将参数减少到1个通道,8位,8khz,它记录良好。任何超过这一点的事情,MCI都拒绝。根据我的设备,它应该是1个通道,16位,48k 我猜麦克风是共享的。有人知道如何让Delphi程序获得独占控制权,以便它可以使用设备的全部功能吗 我做了大量的挖掘工作,没有发现

所以我用Delphi用MCISendString录制音频。代码运行良好,但有一个例外。我让用户设置参数、频道、位、频率,在Windows7上这一切都很好。现在在Windows 10上,我得到了mcierr\u wave\u输入信号

如果我将参数减少到1个通道,8位,8khz,它记录良好。任何超过这一点的事情,MCI都拒绝。根据我的设备,它应该是1个通道,16位,48k

我猜麦克风是共享的。有人知道如何让Delphi程序获得独占控制权,以便它可以使用设备的全部功能吗

我做了大量的挖掘工作,没有发现任何有用的东西

谢谢

这是我正在使用的代码

 MRet := mciSendString(PChar('RECORD mysound'), NIL, 0, Handle);
它返回了一个322结果码。我已经试过了,有没有转换成PChar


它似乎与科尔塔纳有关。但由于无法完全禁用Cortana,因此获得独占控制似乎是唯一可能的解决方案。

您可以在此处找到使用WasAPI的简单Delphi应用程序示例:

请注意,原来的网站早已关闭,但wayback仍然拥有所有代码

进行实际录制的代码如下所示:

// http://msdn.microsoft.com/en-us/library/ms678709(VS.85).aspx
procedure TInputRecordThread.Execute;
const
  REFTIMES_PER_SEC = 10000000;
  REFTIMES_PER_MILLISEC = 10000;
var
  MMDev: IMMDevice;
  MMDevEnum: IMMDeviceEnumerator;
  AudioClient: IAudioClient;
  CaptureClient: IAudioCaptureClient;
  PropVar: ^tag_inner_PROPVARIANT;
  hnsRequestedDuration, hnsActualDuration: Int64;
  pWfx, pCloseWfx: PWaveFormatEx;
  BufferFrameCount, NumFramesAvailable, Flags, StreamFlags, PacketLength, FrameSize: Cardinal;
  pData: PByte;
  uDummy: UInt64;
  Returned: HRESULT;
  Wave: TWaveImage;
  Empty: array of byte;
  pEx: PWaveFormatExtensible;
begin
  FreeOnTerminate := True;
  pCloseWfx := nil;
  uDummy := 0;
  PropVar := nil;

  CoInitializeEx(nil, COINIT_APARTMENTTHREADED);
  CoCreateInstance(CLASS_MMDeviceEnumerator,
    nil,
    CLSCTX_ALL,
    IID_IMMDeviceEnumerator,
    MMDevEnum);

  if FLoopback then
    Returned := MMDevEnum.GetDefaultAudioEndpoint(eRender, eConsole, MMDev)
  else
    Returned := MMDevEnum.GetDefaultAudioEndpoint(eCapture, eConsole, MMDev);

  if Returned <> S_OK then
  begin
    OleCheck(Returned);
    Exit;
  end;

  Returned := MMDev.Activate(IID_IAudioClient, CLSCTX_ALL, PropVar^, Pointer(AudioClient));
  if Returned <> S_OK then
  begin
    OleCheck(Returned);
    Exit;
  end;

  AudioClient.GetMixFormat(pWfx);

  // http://www.ambisonic.net/mulchaud.html
  case pWfx.wFormatTag of
    WAVE_FORMAT_IEEE_FLOAT:
      begin
        pWfx.wFormatTag := WAVE_FORMAT_PCM;
        pWfx.wBitsPerSample := 16;
        pWfx.nBlockAlign := pWfx.nChannels * pWfx.wBitsPerSample div 8;
        pWfx.nAvgBytesPerSec := pWfx.nBlockAlign * pWfx.nSamplesPerSec;
      end;
    WAVE_FORMAT_EXTENSIBLE:
      begin
        pEx := PWaveFormatExtensible(pWfx);
        if not IsEqualGUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, pEx.SubFormat) then
        begin
          Exit;
        end;

        pEx.SubFormat := KSDATAFORMAT_SUBTYPE_PCM;
        pEx.ValidBitsPerSample := 16;
        pWfx.wBitsPerSample := 16;
        pWfx.nBlockAlign := pWfx.nChannels * pWfx.wBitsPerSample div 8;
        pWfx.nAvgBytesPerSec := pWfx.nBlockAlign * pWfx.nSamplesPerSec;
      end;
    else Exit;
  end;

  if AudioClient.IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, pWfx, pCloseWfx) <> S_OK then
  begin
    Exit;
  end;

  // Äŕçěĺđ ôđýéěŕ.
  FrameSize := pWfx.wBitsPerSample * pWfx.nChannels div 8;

  hnsRequestedDuration := REFTIMES_PER_SEC;
  if FLoopback then
    StreamFlags := AUDCLNT_STREAMFLAGS_LOOPBACK
  else
    StreamFlags := 0;
  Returned := AudioClient.Initialize(AUDCLNT_SHAREMODE_SHARED,
    StreamFlags,
    hnsRequestedDuration,
    0,
    pWfx,
    nil);
  if Returned <> S_OK then
  begin
    Exit;
  end;

  AudioClient.GetBufferSize(BufferFrameCount);

  Returned := AudioClient.GetService(IID_IAudioCaptureClient, Pointer(CaptureClient));
  if Returned <> S_OK then
  begin
    Exit;
  end;

  // Calculate the actual duration of the allocated buffer.
  hnsActualDuration := REFTIMES_PER_SEC * BufferFrameCount div pWfx.nSamplesPerSec;

  // Start recording.
  AudioClient.Start();

  Wave := TWaveImage.Create(FData);
  try
    Wave.InitHeader(pWfx^);

    // Each loop fills about half of the shared buffer.
    while not Terminated do
    begin
      // Sleep for half the buffer duration.
      Sleep(hnsActualDuration div REFTIMES_PER_MILLISEC div 2);

      CaptureClient.GetNextPacketSize(PacketLength);

      while PacketLength <> 0 do
      begin
        // Get the available data in the shared buffer.
        pData := nil;
        Returned := CaptureClient.GetBuffer(pData,
          NumFramesAvailable,
          Flags,
          uDummy,
          uDummy);

        if Returned <> S_OK then
        begin
          Exit;
        end;

        if (Flags or Cardinal(AUDCLNT_BUFFERFLAGS_SILENT)) = Flags then
        begin
          pData := nil;  // Tell CopyData to write silence.
        end;

        if pData = nil then
        begin
          SetLength(Empty, NumFramesAvailable * FrameSize);
          FillChar(Empty[0], Length(Empty), 0);
          FData.Write(Empty[0], Length(Empty));
        end
        else
        begin
          // Ĺîőđŕí˙ĺě äŕííűĺ.
          FData.Write(pData^, NumFramesAvailable * FrameSize);
        end;

        CaptureClient.ReleaseBuffer(NumFramesAvailable);
        CaptureClient.GetNextPacketSize(PacketLength);
      end;
    end;

    // ĂŽĹ„Ĺŕíŕâëčâŕĺě çŕďčńü.
    AudioClient.Stop();

    // ĂŽĹęîđđĺĹčđóĺě çŕÄîëîâîę.
    Wave.CorretHeader;
    FData.Position := 0;
  finally
    Wave.Free;

    if pWfx <> nil then
      CoTaskMemFree(pWfx);
  end;
end;
//http://msdn.microsoft.com/en-us/library/ms678709(第85节)
程序TInputRecordThread.Execute;
常数
每秒参考次数=10000000;
每毫秒的参考次数=10000;
变量
MMDev:immdev设备;
MMDevEnum:IMMDeviceEnumerator;
音频客户端:IAudioClient;
CaptureClient:IAudioCaptureClient;
PropVar:^tag\u inner\u PropVa变体;
HNSRequestDuration,hnsActualDuration:Int64;
pWfx,pCloseWfx:PWaveFormatEx;
BufferFrameCount、NumFramesAvailable、Flags、StreamFlags、PacketLength、FrameSize:基数;
pData:PByte;
uDummy:UInt64;
返回:HRESULT;
波浪:TWaveImage;
空:字节数组;
pEx:pwavex;
开始
FreeOnTerminate:=真;
pCloseWfx:=零;
uDummy:=0;
PropVar:=零;
Conitializex(无,Conit_公寓);
CoCreateInstance(类设备枚举器,
无
CLSCTX_ALL,
IID_IMMDeviceEnumerator,
MMDevEnum);
如果是地板的话
返回:=MMDevEnum.GetDefaultAudioEndpoint(eRender、eConsole、MMDev)
其他的
返回:=MMDevEnum.GetDefaultAudioEndpoint(eCapture、eConsole、MMDev);
如果返回S_OK,则
开始
OleCheck(返回);
出口
结束;
返回:=MMDev.Activate(IID_IAudioClient,CLSCTX_ALL,PropVar^,指针(AudioClient));
如果返回S_OK,则
开始
OleCheck(返回);
出口
结束;
AudioClient.GetMixFormat(pWfx);
// http://www.ambisonic.net/mulchaud.html
案例pWfx.wFormatTag
波形格式IEEE浮点数:
开始
pWfx.wFormatTag:=波形\格式\ PCM;
pWfx.wBitsPerSample:=16;
pWfx.nblockallign:=pWfx.nChannels*pWfx.wBitsPerSample div 8;
pWfx.nAvgBytesPerSec:=pWfx.nblockallign*pWfx.nSamplesPerSec;
结束;
WAVE_格式_可扩展:
开始
pEx:=pWfx(pWfx);
如果不是IsEqualGUID(KSDATAFORMAT\u子类型\u IEEE\u FLOAT,pEx.SubFormat),则
开始
出口
结束;
pEx.SubFormat:=KSDATAFORMAT\u SUBTYPE\u PCM;
pEx.ValidBitsPerSample:=16;
pWfx.wBitsPerSample:=16;
pWfx.nblockallign:=pWfx.nChannels*pWfx.wBitsPerSample div 8;
pWfx.nAvgBytesPerSec:=pWfx.nblockallign*pWfx.nSamplesPerSec;
结束;
否则退出;
结束;
如果AudioClient.isFormat受支持(AUDCLNT\u SHAREMODE\u SHARED、pWfx、pCloseWfx),则可以
开始
出口
结束;
// Äŕçěĺđ ôđýéěŕ.
框架尺寸:=pWfx.wBitsPerSample*pWfx.nChannels div 8;
hnsRequestedDuration:=每秒钟的引用次数;
如果是地板的话
StreamFlags:=AUDCLNT\u StreamFlags\u环回
其他的
StreamFlags:=0;
返回:=AudioClient.Initialize(AUDCLNT\u SHAREMODE\u SHARED,
流旗,
HNSRequestDuration,
0,
pWfx,
零);
如果返回S_OK,则
开始
出口
结束;
GetBufferSize(BufferFrameCount);
返回:=AudioClient.GetService(IID_IAudioCaptureClient,指针(CaptureClient));
如果返回S_OK,则
开始
出口
结束;
//计算分配的缓冲区的实际持续时间。
hnsActualDuration:=REFTIMES_PER_SEC*BufferFrameCount div pWfx.nSamplesPerSec;
//开始录音。
AudioClient.Start();
Wave:=twavimage.Create(FData);
尝试
Wave.InitHeader(pWfx^);
//每个循环大约占共享缓冲区的一半。
虽然没有终止
开始
//睡眠时间为缓冲时间的一半。
睡眠(hnsActualDuration div ref times_/u毫秒div 2);
CaptureClient.GetNextPacketSize(PacketLength);
而PacketLength为0
开始
//获取共享缓冲区中的可用数据。
pData:=零;
返回:=CaptureClient.GetBuffer(pData,
NumFramesAvailable,
旗帜,
乌杜米,
乌杜米);
如果返回S_OK,则
开始
出口
结束;
如果(标志或基数(AUDCLNT\u BUFFERFLAGS\u SILENT))=标志,则
开始
pData:=nil;//告诉CopyData以静默方式写入。
结束;
如果pData=nil,则
开始
SetLength(空,NumFramesAvailable*FrameSize);
FillChar(空[0],长度(空),0);
写入(空[0],长度(空));
结束
其他的
开始
// Ĺîőđŕí˙ĺě äŕííűĺ.
写入(pData^,NumFramesAvailable*FrameSize);
结束;
CaptureClient.ReleaseBuffer(NumFramesAvailable);
CaptureClient.GetNextPacketSize(PacketLength);
结束;
结束;
// ĂŽĹ„Ĺŕíŕâëčâŕĺě çŕďčńü.
AudioClient.Stop();
// ĂŽĹęîđđĺĹčđóĺě çŕÄîëîâîę.
波.相关阅读器;
正数据