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.