PortAudio/portaudio

Win32/WASAPI loopback: can not open stream at mono mode, paInvalidChannelCount

RightFS opened this issue · 19 comments

Describe the bug
Pa_OpenStream() return paInvalidChannelCount when open stream at mono mode on a loopback device, but Pa_IsFormatSupported() report paFormatIsSupported
To Reproduce
Steps to reproduce the behavior. Include code if applicable.

// Open loopback device
    int loopback = portaudio::getDefalutLoopback();
    if (loopback < 0)
    {
        std::cout << "Error: No loopback device found" << std::endl;
        return false;
    }
    int sampleRates[] = {8000, 16000, 32000, 44100, 48000};
    PaStreamParameters loopbackParameters{};
    loopbackParameters.channelCount = 1;
    loopbackParameters.device = loopback;
    loopbackParameters.sampleFormat = paInt16;
    loopbackParameters.suggestedLatency = Pa_GetDeviceInfo(loopbackParameters.device)->defaultLowInputLatency;
    loopbackParameters.hostApiSpecificStreamInfo = NULL;
    for (int i = 0; i < 5; i++)
    {
        // Check if the format is supported
        PaError err = Pa_IsFormatSupported(&loopbackParameters, NULL, sampleRates[i]);
        if (err == paFormatIsSupported)
        {
            m_nloopbackSampleRate = sampleRates[i];
        }
    }
    err = Pa_OpenStream(&loopbackStream, &loopbackParameters, NULL, m_nloopbackSampleRate, m_frame_size * 2, paClipOff, NULL, NULL);
    if (err != paNoError)
    {
        qDebug() << "Error: sampleRate " << Pa_GetErrorText(err) << m_nloopbackSampleRate;
        return false;
    }

Desktop (please complete the following information):

  • OS: windows 10 22h2
  • PortAudio version: stable, nightly snapshot (which?), current (please give date and/or Git hash): current master branch
  • If Windows or Linux, which Host API (e.g. WASAPI): WASAPI

@RightFS thank you for reporting the problem. It seems issue may be caused by some undefined behavior of WASAPI. The only place which can potentially return paInvalidChannelCount in Pa_OpenStream() is here (line 3342):

pSub->monoMixer = GetMonoToStereoMixer(&pSub->wavexu.ext, (output ? MIX_DIR__1TO2 : MIX_DIR__2TO1_L));
if (pSub->monoMixer == NULL)
{
(*pa_error) = paInvalidChannelCount;
LogHostError(hr = AUDCLNT_E_UNSUPPORTED_FORMAT);
goto done; // fail, no mixer for format
}

This behavior is not reproducible on my machine, so your debugging help is needed to find the cause. Would you please put breakpoint on line 3339 and get value of pSub->wavexu.ext for me.

@RightFS would you please have a look into the issue. It is not reproducible on my side, therefore your participation is needed as long as you can reproduce it on your side and help with debugging.

@dmitrykos do you have a Windows 10 22h2 instance for testing? If not I have it here.

I have Windows 10 Pro 22H2. The problem is not reproducible and probably could be caused by some process memory corruption on user side, so I think if reporter does not reply or assist with debugging this ticket needs to be closed as non reproducible/not confirmed.

Here is fully working example based on reporter's code which anyone can try:

#include <stdio.h>
#include <stdlib.h>
#include "portaudio.h"

#define FRAMES_PER_BUFFER (512)

int main(void)
{
    PaError err = paNoError;
    PaStream* loopbackStream;
    int loopbackSampleRate = 0;
    int loopbackDeviceIndex = -1;
    PaDeviceInfo *loopbackDevice = NULL;
    int sampleRates[] = {8000, 16000, 32000, 44100, 48000};
    PaStreamParameters loopbackParameters = {0};
    int i;

    err = Pa_Initialize();
    if (err != paNoError)
        goto done;

    for (i = Pa_GetDeviceCount() - 1; i >= 0; i--)
    {
        if ((loopbackDevice = Pa_GetDeviceInfo(i)) != NULL)
        {
            if (strstr(loopbackDevice->name, "[Loopback]") != NULL)
            {
                loopbackDeviceIndex = i;
                break;
            }
        }
    }

    if ((loopbackDevice = Pa_GetDeviceInfo(loopbackDeviceIndex)) == NULL)
    {
        fprintf(stderr,"Error: Loopback device not found.\n");
        goto done;
    }

    loopbackParameters.channelCount = 1;
    loopbackParameters.device = loopbackDeviceIndex;
    loopbackParameters.sampleFormat = paInt16;
    loopbackParameters.suggestedLatency = Pa_GetDeviceInfo(loopbackParameters.device)->defaultLowInputLatency;
    loopbackParameters.hostApiSpecificStreamInfo = NULL;

    for (i = 0; i < 5; i++)
    {
        // Check if the format is supported
        err = Pa_IsFormatSupported(&loopbackParameters, NULL, sampleRates[i]);
        if (err == paFormatIsSupported)
        {
            loopbackSampleRate = sampleRates[i];
        }
    }

    err = Pa_OpenStream(&loopbackStream, &loopbackParameters, NULL, loopbackSampleRate, FRAMES_PER_BUFFER, paClipOff, NULL, NULL);
    if (err != paNoError)
    {
        fprintf(stderr,"Error: Failed opening a stream.\n");
        goto done;
    }

done:
    Pa_Terminate();
    return err;
}

I can reproduce this with PortAudio 18a606e on Windows 10 Home 22H2 19045.4529. Changed the above program slightly to add some diagnostic: https://gist.github.com/arkadijs/7027bf8aad399f3420406600c73df9e4
Specifying .channelCount = 2 allow Pa_OpenStream() to succeed.

arkad@Lenovo3050 UCRT64 /c/Users/arkad/Documents/portaudio
$ ./loopback.exe
Device: Windows WDM-KS > Speakers (Nahimic mirroring Wave Speaker) rate:44100
Device: Windows WDM-KS > Headphones (Realtek HD Audio 2nd output) rate:44100
Device: Windows WDM-KS > Zestaw mikrofonów (Realtek HD Audio Mic Array input) rate:44100
Device: Windows WDM-KS > Miks stereo (Realtek HD Audio Stereo input) rate:48000
Device: Windows WDM-KS > Mikrofon (Realtek HD Audio Mic input) rate:44100
Device: Windows WDM-KS > Głośnik PC (Realtek HD Audio output with HAP) rate:44100
Device: Windows WDM-KS > Speakers 2 (Realtek HD Audio output with HAP) rate:44100
Device: Windows WDM-KS > Speakers 1 (Realtek HD Audio output with HAP) rate:48000
Device: Windows WASAPI > Głośniki (Realtek(R) Audio) [Loopback] rate:48000 <=======
Device: Windows WASAPI > Zestaw mikrofonów (Realtek(R) Audio) rate:48000
Device: Windows WASAPI > Głośniki (Realtek(R) Audio) rate:48000
Device: MME > Głośniki (Realtek(R) Audio) rate:44100
Device: MME > Microsoft Sound Mapper - Output rate:44100
Device: MME > Zestaw mikrofonów (Realtek(R) A rate:44100
Device: MME > Microsoft Sound Mapper - Input rate:44100
Error: Failed opening a stream: Invalid device

It's a Ryzen Lenovo laptop.
PortAudio built without DirectSound.
MSYS2 ucrt64 GCC 14.1.

@arkadijs tried your updated code but all is ok for me:

Device: Windows WASAPI > Speakers (Realtek(R) Audio) [Loopback] rate:48000 <=======
Device: Windows WASAPI > Microphone (Realtek(R) Audio) rate:44100
Device: Windows WASAPI > Speakers (Realtek(R) Audio) rate:48000

(process 1480) exited with code 0.

Could you please compile PA with PA_ENABLE_DEBUG_OUTPUT defined, to see the place of the failure inside PA WASAPI. If you could debug execution by putting breakpoints to all places inside PA WASAPI code where paInvalidDevice is thrown, it would be even better.

Here is a GDB session, full output https://0x0.st/XmYQ.txt

after paHostApiInitializers[2].
Device: Windows WDM-KS > Speakers (Nahimic mirroring Wave Speaker) rate:44100
Device: Windows WDM-KS > Headphones (Realtek HD Audio 2nd output) rate:44100
Device: Windows WDM-KS > Zestaw mikrofon├│w (Realtek HD Audio Mic Array input) rate:44100
Device: Windows WDM-KS > Miks stereo (Realtek HD Audio Stereo input) rate:48000
Device: Windows WDM-KS > Mikrofon (Realtek HD Audio Mic input) rate:44100
Device: Windows WDM-KS > G┼éo┼Ťnik PC (Realtek HD Audio output with HAP) rate:44100
Device: Windows WDM-KS > Speakers 2 (Realtek HD Audio output with HAP) rate:44100
Device: Windows WDM-KS > Speakers 1 (Realtek HD Audio output with HAP) rate:48000
Device: Windows WASAPI > G┼éo┼Ťniki (Realtek(R) Audio) [Loopback] rate:48000 <=======
Device: Windows WASAPI > Zestaw mikrofon├│w (Realtek(R) Audio) rate:48000
Device: Windows WASAPI > G┼éo┼Ťniki (Realtek(R) Audio) rate:48000
Device: MME > G┼éo┼Ťniki (Realtek(R) Audio) rate:44100
Device: MME > Microsoft Sound Mapper - Output rate:44100
Device: MME > Zestaw mikrofon├│w (Realtek(R) A rate:44100
Device: MME > Microsoft Sound Mapper - Input rate:44100
WASAPI: IAudioClient2 set properties: IsOffload = 0, Category = 0, Options = 0

Thread 1 hit Breakpoint 2, CreateAudioClient (pStream=0x8095e0, pSub=0x809750, output=0, pa_error=0x5ffbe4)
    at C:/Users/arkad/Documents/portaudio/portaudio-master/src/hostapi/wasapi/pa_win_wasapi.c:3336
3336        if ((params->channelCount == 1) && (pSub->wavexu.ext.Format.nChannels == 2))
(gdb) n
3349        if ((pSub->shareMode != AUDCLNT_SHAREMODE_EXCLUSIVE) &&
(gdb) p params->channelCount
$3 = 1
(gdb) p pSub->wavexu.ext
$4 = {Format = {wFormatTag = 1, nChannels = 1, nSamplesPerSec = 48000, nAvgBytesPerSec = 96000, nBlockAlign = 2, wBitsPerSample = 16, cbSize = 0}, Samples = {wValidBitsPerSample = 0,
    wSamplesPerBlock = 0, wReserved = 0}, dwChannelMask = 0, SubFormat = {Data1 = 0, Data2 = 0, Data3 = 0, Data4 = "\000\000\000\000\000\000\000"}}
(gdb) n
[New Thread 10552.0x2760]
3350            (!pSub->streamFlags || ((pSub->streamFlags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) == 0)))
(gdb)
3349        if ((pSub->shareMode != AUDCLNT_SHAREMODE_EXCLUSIVE) &&
(gdb)
3350            (!pSub->streamFlags || ((pSub->streamFlags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) == 0)))
(gdb)
3353                pSub->wavexu.ext.Format.nSamplesPerSec);
(gdb)
3352            framesPerLatency = _CalculateFramesPerHostBuffer(userFramesPerBuffer, params->suggestedLatency,
(gdb)
3381        if (output && fullDuplex)
(gdb)
3385        if (framesPerLatency == 0)
(gdb)
3390        if (!output && (pSub->shareMode == AUDCLNT_SHAREMODE_EXCLUSIVE))
(gdb)
3398        _CalculateAlignedPeriod(pSub, &framesPerLatency, ALIGN_BWD);
(gdb)
3403        if (pSub->shareMode == AUDCLNT_SHAREMODE_SHARED)
(gdb)
[New Thread 10552.0xd9c]
3405            if (pSub->period < pInfo->DefaultDevicePeriod)
(gdb)
3436            if (pSub->shareMode == AUDCLNT_SHAREMODE_EXCLUSIVE)
(gdb)
3469        _CalculatePeriodicity(pSub, output, &eventPeriodicity);
(gdb)
3472        hr = IAudioClient_Initialize(audioClient,
(gdb) s
[New Thread 10552.0x364]
warning: avcore\audiocore\client\audioclient\audioclientcore.cpp(1501)\AUDIOSES.DLL!00007FF94CC27915: (caller: 00007FF94CC04FA5) ReturnHr(1) tid(2c88) 887C0030
3483        if (output && SUCCEEDED(hr) && (pSub->shareMode == AUDCLNT_SHAREMODE_EXCLUSIVE))
(gdb) p hr
$5 = -2004287480
(gdb) p audioClient
$6 = (IAudioClient *) 0x806f10
(gdb) p *audioClient
$7 = {lpVtbl = 0x7ff94ccf0fb8}
(gdb) p *pSub
$8 = {clientParent = 0x0, clientStream = 0x0, clientProc = 0x0, wavexu = {ext = {Format = {wFormatTag = 1, nChannels = 1, nSamplesPerSec = 48000, nAvgBytesPerSec = 96000,
        nBlockAlign = 2, wBitsPerSample = 16, cbSize = 0}, Samples = {wValidBitsPerSample = 0, wSamplesPerBlock = 0, wReserved = 0}, dwChannelMask = 0, SubFormat = {Data1 = 0, Data2 = 0,
        Data3 = 0, Data4 = "\000\000\000\000\000\000\000"}}, iec61937 = {FormatExt = {Format = {wFormatTag = 1, nChannels = 1, nSamplesPerSec = 48000, nAvgBytesPerSec = 96000,
          nBlockAlign = 2, wBitsPerSample = 16, cbSize = 0}, Samples = {wValidBitsPerSample = 0, wSamplesPerBlock = 0, wReserved = 0}, dwChannelMask = 0, SubFormat = {Data1 = 0,
          Data2 = 0, Data3 = 0, Data4 = "\000\000\000\000\000\000\000"}}, dwEncodedSamplesPerSec = 0, dwEncodedChannelCount = 0, dwAverageBytesPerSec = 0}}, bufferSize = 0,
  deviceLatency = 0, period = 213333, latencySeconds = 0, framesPerHostCallback = 0, shareMode = AUDCLNT_SHAREMODE_SHARED, streamFlags = 131072, flags = 0, params = {
    device_info = 0x803840, stream_params = {device = 2, channelCount = 1, sampleFormat = 8, suggestedLatency = 0.0030000000000000001, hostApiSpecificStreamInfo = 0x0}, wasapi_params = {
      size = 0, hostApiType = paInDevelopment, version = 0, flags = 0, channelMask = 0, hostProcessorOutput = 0x0, hostProcessorInput = 0x0, threadPriority = eThreadPriorityNone,
      streamCategory = eAudioCategoryOther, streamOption = eStreamOptionNone, passthrough = {formatId = ePassthroughFormatPcmIec60958, encodedSamplesPerSec = 0, encodedChannelCount = 0,
        averageBytesPerSec = 0}}, frames_per_buffer = 512, sample_rate = 48000, blocking = 1, full_duplex = 0, wow64_workaround = 0}, buffers = 0, framesPerBuffer = 0,
  userBufferAndHostMatch = 0, monoBuffer = 0x0, monoBufferSize = 0, monoMixer = 0x0, tailBuffer = 0x0, tailBufferMemory = 0x0}
(gdb) p eventPeriodicity
$9 = 0
(gdb) n
3540        while ((hr == E_OUTOFMEMORY) && (pSub->period > (100 * 10000)))
(gdb)
3577        if ((hr == AUDCLNT_E_BUFFER_SIZE_ERROR) || (hr == AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED))
(gdb)
3609        if (FAILED(hr))
(gdb)
3611            (*pa_error) = paInvalidDevice;
(gdb)

Thread 1 hit Breakpoint 1, CreateAudioClient (pStream=0x8095e0, pSub=0x809750, output=0, pa_error=0x5ffbe4)
    at C:/Users/arkad/Documents/portaudio/portaudio-master/src/hostapi/wasapi/pa_win_wasapi.c:3612
3612            LogHostError(hr);
(gdb) n
WASAPI ERROR HRESULT: 0x88890008 : AUDCLNT_E_UNSUPPORTED_FORMAT
 [FUNCTION: CreateAudioClient FILE: C:/Users/arkad/Documents/portaudio/portaudio-master/src/hostapi/wasapi/pa_win_wasapi.c {LINE: 3612}]
3613            goto done;

Thank you for the log.

It seems WASAPI driver of your system is malfunctioning (has bug, surprisingly you also have Realtek(R) Audio):

  • it accepts Mono format by IAudioClient_IsFormatSupported in GetClosestFormat
  • but later it fails in CreateAudioClient with IAudioClient_Initialize

Basically it is not PA's issue because IAudioClient_IsFormatSupported must return closest supported format which guarantees that IAudioClient_Initialize does not fail. Most probably there is buggy rare version of Realtek driver which is causing it because in most cases it is not a problem.

Could you please show the value of sharedClosestMatch by setting breakpoint after line 2965 IAudioClient_IsFormatSupported:

hr = IAudioClient_IsFormatSupported(client, shareMode, &outWavex->Format, (shareMode == AUDCLNT_SHAREMODE_SHARED ? &sharedClosestMatch : NULL));
// Exclusive mode can require packed format for some devices
if ((hr != S_OK) && (shareMode == AUDCLNT_SHAREMODE_EXCLUSIVE))

Thank you for the support. Looks like driver issue indeed. I was able to find a workaround though.

For the invalid device run:
4 times the pointer is set

Thread 1 hit Breakpoint 1, GetClosestFormat (client=0x765050, sampleRate=8000, _params=0x5ffce0, shareMode=AUDCLNT_SHAREMODE_SHARED, outWavexU=0x5ffbe0, output=0)
    at C:/Users/arkad/Documents/portaudio/portaudio-master/src/hostapi/wasapi/pa_win_wasapi.c:2965
2965        hr = IAudioClient_IsFormatSupported(client, shareMode, &outWavex->Format, (shareMode == AUDCLNT_SHAREMODE_SHARED ? &sharedClosestMatch : NULL));
(gdb) p sharedClosestMatch
$1 = (WAVEFORMATEX *) 0x0
(gdb) n
2968        if ((hr != S_OK) && (shareMode == AUDCLNT_SHAREMODE_EXCLUSIVE))
(gdb) p sharedClosestMatch
$2 = (WAVEFORMATEX *) 0x763940
(gdb) p *sharedClosestMatch
$3 = {wFormatTag = 65534, nChannels = 2, nSamplesPerSec = 48000, nAvgBytesPerSec = 384000, nBlockAlign = 8, wBitsPerSample = 32, cbSize = 22}
(gdb)

then 2 times sharedClosestMatch is NULL

Thread 1 hit Breakpoint 1, GetClosestFormat (client=0x76adf0, sampleRate=48000, _params=0x76aaf0, shareMode=AUDCLNT_SHAREMODE_SHARED, outWavexU=0x76aa88, output=0)
    at C:/Users/arkad/Documents/portaudio/portaudio-master/src/hostapi/wasapi/pa_win_wasapi.c:2965
2965        hr = IAudioClient_IsFormatSupported(client, shareMode, &outWavex->Format, (shareMode == AUDCLNT_SHAREMODE_SHARED ? &sharedClosestMatch : NULL));
(gdb) n
2968        if ((hr != S_OK) && (shareMode == AUDCLNT_SHAREMODE_EXCLUSIVE))
(gdb) p *sharedClosestMatch
Cannot access memory at address 0x0
(gdb) n
2975        if (hr == S_OK)
(gdb) c
Continuing.
warning: avcore\audiocore\client\audioclient\audioclientcore.cpp(1501)\AUDIOSES.DLL!00007FF94CC27915: (caller: 00007FF94CC04FA5) ReturnHr(1) tid(32d4) 887C0030
WASAPI ERROR HRESULT: 0x88890008 : AUDCLNT_E_UNSUPPORTED_FORMAT
 [FUNCTION: CreateAudioClient FILE: C:/Users/arkad/Documents/portaudio/portaudio-master/src/hostapi/wasapi/pa_win_wasapi.c {LINE: 3612}]
WASAPI ERROR PAERROR: -9996 : Invalid device
 [FUNCTION: ActivateAudioClient FILE: C:/Users/arkad/Documents/portaudio/portaudio-master/src/hostapi/wasapi/pa_win_wasapi.c {LINE: 3646}]
WASAPI ERROR PAERROR: -9996 : Invalid device
 [FUNCTION: OpenStream FILE: C:/Users/arkad/Documents/portaudio/portaudio-master/src/hostapi/wasapi/pa_win_wasapi.c {LINE: 3850}]
G┼éo┼Ťniki (Realtek(R) Audio) [Loopback]: Invalid device

For the good run, sharedClosestMatch is always set:

Thread 1 hit Breakpoint 1, GetClosestFormat (client=0x7a9450, sampleRate=48000, _params=0x7a9dd0, shareMode=AUDCLNT_SHAREMODE_SHARED, outWavexU=0x7a9d68, output=0)
    at C:/Users/arkad/Documents/portaudio/portaudio-master/src/hostapi/wasapi/pa_win_wasapi.c:2965
2965        hr = IAudioClient_IsFormatSupported(client, shareMode, &outWavex->Format, (shareMode == AUDCLNT_SHAREMODE_SHARED ? &sharedClosestMatch : NULL));
(gdb) n
2968        if ((hr != S_OK) && (shareMode == AUDCLNT_SHAREMODE_EXCLUSIVE))
(gdb) p *sharedClosestMatch
$6 = {wFormatTag = 65534, nChannels = 2, nSamplesPerSec = 48000, nAvgBytesPerSec = 384000, nBlockAlign = 8, wBitsPerSample = 32, cbSize = 22}
(gdb) c
Continuing.
wFormatTag     =WAVE_FORMAT_EXTENSIBLE
SubFormat      =KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
Samples.wValidBitsPerSample =32
dwChannelMask  =0x3
nChannels      =2
nSamplesPerSec =48000
nAvgBytesPerSec=384000
nBlockAlign    =8
wBitsPerSample =32
cbSize         =22
WASAPI::OpenStream(input): framesPerUser[ 512 ] framesPerHost[ 1126 ] latency[ 23.46ms ] exclusive[ NO ] wow64_fix[ NO ] mode[ POLL ]
G┼éo┼Ťniki (Realtek(R) Audio) [Loopback]: success

Workaround

Open sound device properties and disable audio enhancements.
Speaker Properties / Additional device properties (to open classic UI) => Advanced => Signal Enhancements => Enable audio enhancements => uncheck.
This must be done per output, even if headphones are attached to the same chip.

FTR, Realtek driver 3/16/2021 6.0.9132.1; PCI id 10EC:0257.

Test program updated to try open all loopback devices.

Great catch!

My Realtek driver version: 19/10/2023, 10.0.19041.3636. Your is older, so probably Realtek fixed it and thus I do not observe similar behavior. In my case Disable all enhancements is unchecked but no effect was checked either. I tried activating effects (Bass Boost, Virtual Surround, Loudness Equalization) but it did not change anything - test code worked without an issue.

Microsoft docs specify the following:
For shared mode, if the audio engine supports the caller-specified format, IsFormatSupported sets *ppClosestMatch to NULL and returns S_OK. If the audio engine does not support the caller-specified format but does support a similar format, the method retrieves the similar format through the ppClosestMatch parameter and returns S_FALSE.

So, if hr is S_OK and sharedClosestMatch is NULL then we can't do anything with that. There is another possibility for workaround though:
In shared mode, the audio engine always supports the mix format, which the client can obtain by calling the IAudioClient::GetMixFormat method.

Therefore, workaround could be as follows:

  • If params.channelCount == 1 and sharedClosestMatch == NULL and hr == S_OK then get channel count obtained by IAudioClient::GetMixFormat and if it is >1 set outWavex->Format.nChannels to 2

Shall I open PR for that and you would be able to test the proposed workaround?

I'll be able to test, thanks!

I'm going to send test survey to a few friends, some had this issue.
None of non-Realtek-sound Windows PCs I tried at home have this problem.

@arkadijs the PR #934 is created, would you please test how it works for you and comment.

Tested the PR, works on my machine (regardless of audio enhancements options enabled or not). Thanks!

This Realtek driver is very odd. Capturing loopback of Speakers works any time. But capturing loopback of Headphones works only if some audio is played - callback not called otherwise, blocking API also doesn't work, changing default sound device makes no difference:

arkad@Lenovo3050 UCRT64 /c/Users/arkad/Documents/portaudio
$ ./loopback.exe
Device: MME > Microsoft Sound Mapper - Input rate:44100
Device: MME > Mikrofon (Realtek(R) Audio) rate:44100
Device: MME > Zestaw mikrofonów (Realtek(R) A rate:44100
Device: MME > Microsoft Sound Mapper - Output rate:44100
Device: MME > Słuchawki (Realtek(R) Audio) rate:44100
Device: MME > Głośniki (Realtek(R) Audio) rate:44100
Device: Windows WASAPI > Głośniki (Realtek(R) Audio) rate:48000
Device: Windows WASAPI > Słuchawki (Realtek(R) Audio) rate:48000
Device: Windows WASAPI > Mikrofon (Realtek(R) Audio) rate:48000
Device: Windows WASAPI > Zestaw mikrofonów (Realtek(R) Audio) rate:48000
Device: Windows WASAPI > Głośniki (Realtek(R) Audio) [Loopback] rate:48000 <=======
Device: Windows WASAPI > Słuchawki (Realtek(R) Audio) [Loopback] rate:48000 <=======
Device: Windows WDM-KS > Speakers 1 (Realtek HD Audio output with HAP) rate:48000
Device: Windows WDM-KS > Speakers 2 (Realtek HD Audio output with HAP) rate:44100
Device: Windows WDM-KS > Głośnik PC (Realtek HD Audio output with HAP) rate:44100
Device: Windows WDM-KS > Mikrofon (Realtek HD Audio Mic input) rate:44100
Device: Windows WDM-KS > Miks stereo (Realtek HD Audio Stereo input) rate:48000
Device: Windows WDM-KS > Zestaw mikrofonów (Realtek HD Audio Mic Array input) rate:44100
Device: Windows WDM-KS > Headphones (Realtek HD Audio 2nd output) rate:44100
Device: Windows WDM-KS > Output (AMD HD Audio HDMI out #0) rate:44100
Device: Windows WDM-KS > Speakers (Nahimic mirroring Wave Speaker) rate:44100
Głośniki (Realtek(R) Audio) [Loopback]: trying callback API...
Głośniki (Realtek(R) Audio) [Loopback]: pushed 512 frames
Głośniki (Realtek(R) Audio) [Loopback]: pushed 512 frames
Głośniki (Realtek(R) Audio) [Loopback]: pushed 512 frames
Głośniki (Realtek(R) Audio) [Loopback]: pushed 512 frames
Głośniki (Realtek(R) Audio) [Loopback]: pushed 512 frames
Głośniki (Realtek(R) Audio) [Loopback]: success
Głośniki (Realtek(R) Audio) [Loopback]: trying blocking API...
Głośniki (Realtek(R) Audio) [Loopback]: read 512 frames
Głośniki (Realtek(R) Audio) [Loopback]: read 512 frames
Głośniki (Realtek(R) Audio) [Loopback]: read 512 frames
Głośniki (Realtek(R) Audio) [Loopback]: read 512 frames
Głośniki (Realtek(R) Audio) [Loopback]: read 512 frames
Głośniki (Realtek(R) Audio) [Loopback]: success
Słuchawki (Realtek(R) Audio) [Loopback]: trying callback API...
Słuchawki (Realtek(R) Audio) [Loopback]: no frames pushed
Słuchawki (Realtek(R) Audio) [Loopback]: trying blocking API...
Słuchawki (Realtek(R) Audio) [Loopback]: read 512 frames <=== unpaused player here
Słuchawki (Realtek(R) Audio) [Loopback]: read 512 frames
Słuchawki (Realtek(R) Audio) [Loopback]: read 512 frames
Słuchawki (Realtek(R) Audio) [Loopback]: read 512 frames
Słuchawki (Realtek(R) Audio) [Loopback]: read 512 frames
Słuchawki (Realtek(R) Audio) [Loopback]: success

Updated sample program here.
Realter driver updated to 7/28/2022 6.0.9389.1 which is latest from Lenovo for this machine.

This Realtek driver is very odd.

What strikes me as especially odd is that WASAPI Loopback is an internal feature of the Windows Audio Engine itself that should have nothing to do with the driver - AFAIK the loopback occurs in audiosrv/audiodg, before the driver even gets involved. I find it surprising that the driver would be a factor in any of this.

This Realtek driver is very odd. Capturing loopback of Speakers works any time. But capturing loopback of Headphones works only if some audio is played - callback not called otherwise, blocking API also doesn't work, changing default sound device makes no difference.

I have also encountered this problem when I use PortAudio capturing loopback for echo cancellation. I have to fill some muted data manually to my buffer by timeline for the alignment between playback out and micphone in. It's too weird...It was supposed to provide a continuous audio stream.

But I've left that job, so I didn't have my test environment ...

Tested the PR, works on my machine (regardless of audio enhancements options enabled or not). Thanks!

@arkadijs Thank you very much for testing and confirming!

I propose to create new issue for capturing loopback of Headphones to avoid mixing 2 issues in this issue as this one will be closed after PR #934 is approved. Would you please create new issue and re-post there your test code and log, so we could continue there.

Created new issue #935.

@arkadijs thank you very much.