Reputation: 31
I'm attempting to use AudioClient interface for the first time, without luck. So far I managed to get the default AudioClient interface using the successfully MMDeviceEnumerator and MMDevice interfaces:
CoCreateInstance(
CLSID_MMDeviceEnumerator, nil,
CLSCTX_ALL, IID_IMMDeviceEnumerator,
MMEnumerator);
MMEnumerator.GetDefaultAudioEndpoint(eRender,eConsole,MMDevice);
MMDevice.Activate(IID_IAudioClient, CLSCTX_ALL, nil, AudioClient);
(Result checking code not included here). This 3 call all returned no errors, and I've got a non-nil interface ptr in AudioClient variable. My problem is when I try to get the mixing waveformat:
AudioClient.GetMixFormat(pwfx)
This returns the code 0x88890001 which is AUDCLNT_E_NOT_INITIALIZED. -> Of course not initialized as I only wanted to get what waveformat it likes first.
Looking up msdn tells that the AudioClient.GetMixFormat can be called before AudioClient.Initialization. Also the AUDCLNT_E_NOT_INITIALIZED is not on the list of possible return values. So I'm confused about what did I do wrong. GetMixFormat() doc -> http://msdn.microsoft.com/en-us/library/windows/desktop/dd370872(v=vs.85).aspx
Another weird thing is that when I call AudioClient.GetStreamLatency() it returns with S_OK and with a quasi-random value around 1000ms. But the documentation states that "This method requires prior initialization of the IAudioClient interface. All calls to this method will fail with the error AUDCLNT_E_NOT_INITIALIZED until the client initializes the audio stream by successfully calling the". Therefore I think I have a working AudioClient interface, I just can't understand why it doesn't work as the way documentation says.
(I'm using win7 64bit, Sound Blaster Live 5.1 with kx-project driver (DSound and classic windows MM sound works ok, but with a 100ms terrible long latency, that's the only reason why I'm going to use WASAPI on the win7)
Thank you in advance.
Upvotes: 3
Views: 2996
Reputation: 325
I actually found the bug. The definition of IAudioClient
in MFPack is incorrect, the interface functions are in the wrong order. (I'd like to push this in some way some day, if I find the time for it, move to git etc.)
This is the correct ordering of methods in IAudioClient:
IAudioClient = interface(IUnknown)
['{1CB9AD4C-DBFA-4c32-B178-C2F568A703B2}']
function Initialize(ShareMode: AUDCLNT_SHAREMODE; StreamFlags: Dword; hnsBufferDuration: REFERENCE_TIME; hnsPeriodicity: REFERENCE_TIME; pFormat: PWaveFormatEx; AudioSessionGuid: LPCGUID): HResult; stdcall;
function GetBufferSize(out pNumBufferFrames: UINT32): HResult; stdcall;
function GetStreamLatency(out phnsLatency: REFERENCE_TIME): HResult; stdcall;
function GetCurrentPadding(out pNumPaddingFrames: UINT32): HResult; stdcall;
function IsFormatSupported(ShareMode: AUDCLNT_SHAREMODE; pFormat: PWaveFormatEx; out ppClosestMatch: PWaveFormatEx): HResult; stdcall;
function GetMixFormat(out ppDeviceFormat: PWaveFormatEx): HResult; stdcall;
function GetDevicePeriod(out phnsDefaultDevicePeriod: REFERENCE_TIME; phnsMinimumDevicePeriod: REFERENCE_TIME): HResult; stdcall;
function Start(): HResult; stdcall;
function Stop(): HResult; stdcall;
function Reset(): HResult; stdcall;
function SetEventHandle(const eventHandle: HANDLE): HResult; stdcall;
function GetService(const riid: TGUID; out ppv: Pointer): HResult; stdcall;
//The GetService method supports the following service interfaces: IAudioCaptureClient, IAudioClock, IAudioRenderClient,
//IAudioSessionControl, IAudioStreamVolume, IChannelAudioVolume, IMFTrustedOutput, ISimpleAudioVolume.
//Since Windows 7 the new interface indentifier IID_IMFTrustedOutput has been added, but is not implemented here.
end;
The function ReleaseBuffer is also wrong, this is the correct parameters:
IAudioRenderClient = interface(IUnknown)
['{F294ACFC-3146-4483-A7BF-ADDCA7C260E2}']
function GetBuffer(const NumFramesRequested: UINT; out ppData: PByte): HResult; stdcall;
function ReleaseBuffer(const NumFramesWritten: UINT32; const dwFlags: DWord): HResult; stdcall;
end;
Upvotes: 3