简体   繁体   中英

Delphi / MCI Exclusive Control of Microphone

So I'm recording audio with Delphi using MCISendString. The code works fine with one exception. I'm letting the user set the parameters, channels, bits, freq, and on Windows 7 this worked fine. Now on Windows 10 I'm getting mcierr_wave_inputsinuse.

If I reduce the parameters to 1 channel, 8 bits, 8khz, it records fine. Anything above that and MCI refuses it. According to my device it should go 1 channel, 16 bit, 48k.

I'm guessing that the mic is being shared. Does anyone know how to get a Delphi program to take exclusive control so that it can use the full abilities of the device?

I did a good bit of digging and came up with nothing useful.

Thanks

Here's the code I'm using.

 MRet := mciSendString(PChar('RECORD mysound'), NIL, 0, Handle);

It's returning a 322 result code. I've tried it with and without converting to a PChar.

It appears to be related to Cortana. But since there is no way to fully disable Cortana, gaining exclusive control appears to be the only possible solution.

You can find an example of a simple Delphi app using WasAPI here:

https://web.archive.org/web/20130403023149/http://4coder.org/delphi-source-code/547/

Note that the original website has long since gone down, but wayback still has all the code.

The code to do the actual recording is here:

// 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;

You might also want to check out: http://torry.net/pages.php?id=167&sort=ID

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM