thestk / rtaudio

A set of C++ classes that provide a common API for realtime audio input/output across Linux (native ALSA, JACK, PulseAudio and OSS), Macintosh OS X (CoreAudio and JACK), and Windows (DirectSound, ASIO, and WASAPI) operating systems.
Other
1.51k stars 322 forks source link

Failure with PlaySaw on WASAPI #281

Closed sjk7 closed 3 years ago

sjk7 commented 3 years ago

Hello, I am using the playsaw file with the following important parts: typedef float MY_TYPE;

define FORMAT RTAUDIO_FLOAT32

define SCALE 1.0

define USE_INTERLEAVED

And I always get an error opening the following device: (it's at index 1 in WASAPI) Using device, with name: Speakers (Xonar SoundCard)

Unhandled exception at 0x00007FFBE15BD759 in playsaw.exe: Microsoft C++ exception: RtAudioError at memory location 0x0000004313DFF3E0. The errorText from the thrown exception in the callback is: "RtApiWasapi::wasapiThread: Unable to retrieve render buffer size."

Tried all manner of channels, samplerates, exclusivity and so on but always the same error. Note: works fine in PortAudio. Any help, please?

MarcusTomlinson commented 3 years ago

We actually have an existing issue related to Xonar here: https://github.com/thestk/rtaudio/issues/254

@jaw, I believe you've since found a solution to your issue. Would you mind sharing it with us?

jaw commented 3 years ago

Absolutely!

The error message isn't the exact same I dealt with, but I'm not surprised there are more quirks in these drivers.

I spent many many hours debugging RtAudio together with SDL2 on my Xonar card, peeling off layer by layer to get to the root of the problem.

In the end I found out that just one call in to windows API creating a GDI device (or similar, it was one of the calls needed to bring up a window anyway) would wreck the internal state of the audio driver.

It is also the case that the Asus drivers only supports this:

HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);

whereas the joystick initialization code in SDL2 needs a different parameter and will thus turn run the same call which overturns the state of driver just as well.

Also, CoInitialize thread mode is per process.

So in the end the grand solution is running the audio stack in its own process (not thread!). I glanced at OBS a bit, and they run it in a DLL, IIRC a DLL is in fact its own process, so that might be why it works with OBS. I'm not 100% sure there.

I've gone a step further and run the audio stack in an entirely different EXE file which I interface to using UDP packages. I did rewrite the whole WASAPI backend for myself to get more thorough error messages than both the RtAudio implementation and OBS but that took a weekend or so for the recording part so it's not a big deal.

One can still try to find a contact at Asus, I tried to but their web site is a wall of FAQ's and RMA stuff aimed at consumers with no section for developer support (or even professional support).

Side note: I just tried a tweet at them, we'll see how that goes.

So even though the workaround works I'm still interested in getting this fixed.

MarcusTomlinson commented 3 years ago

Thanks for taking the time to share such a detailed update @jaw!

jaw commented 3 years ago

I've now actually logged a ticket with Asus from their web site. Had to dig up the serial number (it was on the xonar card box thankfully) and fill out a massive customer support form.

sjk7 commented 3 years ago

You guys may find this useful. You can get the format of the (non-shared) device without guessing by using the following: HRESULT GetStreamFormat(IMMDevice device, WAVEFORMATEX &wfx) { IPropertyStore store = nullptr;

HRESULT hr = device->OpenPropertyStore(STGM_READ, &store);

if (FAILED(hr))
{
    return hr;
}

PROPVARIANT prop;

hr = store->GetValue(PKEY_AudioEngine_DeviceFormat, &prop);
auto pwfx = (PWAVEFORMATEX)prop.blob.pBlobData;
wfx = *pwfx;
store->Release();
return S_OK;

}

jaw commented 3 years ago

@MarcusTomlinson I actually can confirm that the bug I had seems to be fixed. It wasn't back in October, but when trying my previously broke code, it now works great. Asus did reply and we closed the issue.

MarcusTomlinson commented 3 years ago

Oh nice. Thanks for the update @jaw.

MarcusTomlinson commented 3 years ago

@sjk7 can we close this? Doesn’t sound like something we can fix in RtAudio.

sjk7 commented 3 years ago

Yeh, u can if you want though, as stated it works fine in PortAudio -- so you guys have some catching up to do. The WASAPI code is pretty yucky and mostly looks like the (terrible) MS sample code. Goto's all over the place (double yuk)