Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible issue with FlexASIO #26

Closed
AGENTE44 opened this issue May 17, 2024 · 40 comments
Closed

Possible issue with FlexASIO #26

AGENTE44 opened this issue May 17, 2024 · 40 comments

Comments

@AGENTE44
Copy link

AGENTE44 commented May 17, 2024

Hi I'm working with your nice library on my project (dll)
I'm testing different ASIO drivers but I'm getting a crash with FlexASIO (v1.9)
This is the simple sequence of code (C code):

error = XtServiceOpenDevice(service, id, &device); // no error detected here, device not NULL
error = XtDeviceGetBufferSize(device, format, &bufferInfo); // no error detected here
// Set the XtDeviceStreamParams here
error = XtDeviceOpenStream(device, &deviceParams, userpointer, &stream); // it crash!!!

I can read some info from FlexASIO, but I haven't had a chance to detect the error with device before opening a stream with this driver, so my program inevitably crashes
its possible that bad device params may collapse the library? (I'm not using any exotic parameter)
since I installed the FlexASIO 1.9, the Xt.Gui.exe is also crashing before initializing!!!
thanks in advance

@ofsjoerdk
Copy link

Just tried with flexasio 1.9, I can render audio without problems.
Could you post a fully runnable example program ?

Also just out of curiosity what's your use case for flexasio? That driver is internally backed by portaudio with it's most likely output being wasapi. So your full stack now looks like xtaudio->flexasio->portaudio->wasapi. Why not just go for xtaudio->wasapi or portaudio->wasapi? Just curious, obviously the thing shouldn't crash in any case.

@AGENTE44
Copy link
Author

Just tried with flexasio 1.9, I can render audio without problems. Could you post a fully runnable example program ?

Also just out of curiosity what's your use case for flexasio? That driver is internally backed by portaudio with it's most likely output being wasapi. So your full stack now looks like xtaudio->flexasio->portaudio->wasapi. Why not just go for xtaudio->wasapi or portaudio->wasapi? Just curious, obviously the thing shouldn't crash in any case.

Hi
No particular preference over FlexASIO, I'm just checking the stability of the library on different scenarios
I'm working with GCC x86 and xt-audio.dll (2.0.1), I'm running the "Detailed list" example (translated to C code)
this is the report I got

xt1

Everything looks normal compared to the ASIO4ALL v2 report
with ASIO4ALL v2, I can select one of the valid formats, open a stream, and run a dummy Callback without any issue
but that is not happening with FlexASIO, which is crashing inside of XtDeviceOpenStream()
below it's showing the Realtek ASIO status, and there's no valid format found
but I understand that there is a problem with Realtek's driver here (at least, I can detect the error before calling XtDeviceOpenStream())

xt2

I downloaded an ASIO driver tester from this link, and I'm getting this message (in both 32 and 64bit version of the app):

xt3

Since Xt.Gui.exe is also crashing, it confirms my suspicions about the XtDeviceOpenStream() function
I run the Xt.Gui app in a different machine (WIN11) with the same tragic result (I'm coding on WIN10 machine)
after uninstalling the FlexASIO, the Xt.Gui backs to life
Greetings

@sjoerdvankreel
Copy link
Owner

Ok, so I can confirm the crash now. Just tested with XtGui and it's busted immediately.
I did manage to write a sample that successfully calls XtDeviceOpenStream on FlexASIO though, see below.

Can you test it and see if it at least works for you ?
One thing that strikes me as odd is that FlexASIO operates in 32-bit floating point mode.
I've never seen an asio driver do that, it's always 32 bit integer. But, it's allowed by the asio spec, so it should work.
Did you confirm XtDeviceSupportsFormat() before opening the stream ?

The GUI thing i still have to work out yet. To be continued.

#include <xt/XtAudio.h>
#include <iostream>
#include <cassert>
#include <Windows.h>

static uint32_t XT_CALLBACK 
onBuffer(XtStream const* stream, XtBuffer const* buffer, void* user)
{
  return 0;
}

int main()
{
  int devcount;
  XtDeviceList* list = NULL;
  char idbuf[201] = { 0 };
  char namebuf[201] = { 0 };

  // just checking if maybe flexasio doesnt like message windows, but it seems ok
  void* windowHandle = nullptr;
  windowHandle = CreateWindowA("STATIC", 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, 0);

  XtPlatform* platform = XtAudioInit("DEMO", windowHandle);
  assert(platform != nullptr);
  XtService const* service = XtPlatformGetService(platform, XtSystemASIO);
  XtError error = XtServiceOpenDeviceList(service, XtEnumFlagsAll, &list);
  assert(error == 0);
  error = XtDeviceListGetCount(list, &devcount);
  assert(error == 0);
  for (int d = 0; d < devcount; d++)
  {
    if (d != 2) continue; // flexasio is 2 for me

    int size = 200;
    XtDevice* device = 0;
    XtStream* stream = 0;
    XtFormat format = { 0 };
    XtBool supports = false;
    XtDeviceStreamParams params = { 0 };

    error = XtDeviceListGetId(list, d, idbuf, &size);
    assert(error == 0);
    error = XtDeviceListGetName(list, idbuf, namebuf, &size);
    assert(error == 0);
    std::cout << d << " " << namebuf << "\n";
    
    error = XtServiceOpenDevice(service, idbuf, &device);
    assert(error == 0);
    params.stream.onXRun = 0;
    params.stream.onRunning = 0;
    params.stream.onBuffer = onBuffer;
    params.stream.interleaved = false;

    format.channels.outputs = 2;
    format.channels.outMask = 3;
    format.mix.rate = 44100;
    format.mix.sample = XtSampleFloat32;     
    error = XtDeviceSupportsFormat(device, &format, &supports);
    assert(error == 0);
    if(supports) std::cout << "format supported\n";
    else std::cout << "format not supported\n";
    if(!supports) continue; // just leak it, i sure miss my raii

    params.bufferSize = 10;
    params.format = format;

    error = XtDeviceOpenStream(device, &params, 0, &stream);
    std::cout << error << "\n"; // skip over format not supported etc
    if(error == 0) std::cout << "yay, managed to open a stream!" << "\n";
    XtStreamDestroy(stream);
    XtDeviceDestroy(device);
  }
  XtDeviceListDestroy(list);
  XtPlatformDestroy(platform);
  return 0;
}

@sjoerdvankreel
Copy link
Owner

Request for clarification over at FlexASIO dechamps/FlexASIO#230. Hoping they can help out.

@sjoerdvankreel
Copy link
Owner

Seems like a hard crash is caused by opening FlexASIO twice (i.e. XtServiceOpenDevice). Any chance that's the problem ?

@AGENTE44
Copy link
Author

Hi
your code is not returning correctly (didn't touch anything):

xt4

I can open and destroy the FlexASIO device multiple times without any issue

@sjoerdvankreel
Copy link
Owner

<< I can open and destroy the FlexASIO device multiple times without any issue

The gui crash is caused by opening multiple FlexASIO devices at the same time, i.e. opening FlexASIO twice in a row without destroying it. Although that's not officially supported by the ASIO sdk, most asio drivers allow it. It's probably not what's causing you problems, though.

<< your code is not returning correctly (didn't touch anything):

I assume its still crashing in XtDeviceOpenStream? Any chance you can produce a stacktrace?
Also i've been trying to build FlexASIO from source, but no luck yet.

@sjoerdvankreel
Copy link
Owner

sjoerdvankreel commented May 20, 2024

Btw, it seems like your taking a stack overflow.
https://stackoverflow.com/questions/23409809/how-do-you-diagnose-the-exception-code-0xc0000409-on-windows.
This stuff just keeps getting more interesting :)

[EDIT] actually i misread. Thats not a stack overflow, it's STATUS_STACK_BUFFER_OVERRUN. I.e., either xt-audio or flexasio is corrupting memory somewhere.

@dechamps
Copy link

dechamps commented May 20, 2024

STATUS_STACK_BUFFER_OVERRUN makes me think of dechamps/FlexASIO#209. I would somewhat surprised if that was really the root cause as AFAIK it seems to happen rarely in practice. However, if FlexASIO is being uninitialized and re-initialized repeatedly, then that would increase the chances of that bug being triggered quite significantly.

@dechamps
Copy link

…although now that I think about it, this bug can only be triggered after CreateBuffers() has been called, so if the crash happens before that, that can't be it.

@AGENTE44
Copy link
Author

ok I did a multiple open device (without destroying the device) on the following drivers I have:

ASIO link pro -> doesn't allow multiple opens (the second try of XtServiceOpenDevice() returns error )
ASIO4ALL v2 -> I opened 3 devices under the same service, without warnings/errors
FlexASIO -> it crash at the second try of XtServiceOpenDevice() !!!
Realtek ASIO -> despite I have problems to make this driver work (Realtek's fault I think), I can open 3 devices without errors on XtServiceOpenDevice()

I'm unable to do a stacktrace (I'm a novice programer)

@sjoerdvankreel
Copy link
Owner

In order to grab a stacktrace you have to run a debug build of your program linked to a debug build of xt-audio. The .zip download provides both debug binaries and pdb files (necessary for stacktrace) in /core/xt/x64/Debug. If you run that under the debugger (for example visual studio), it should report you a stacktrace of the crash.

But still, XtServiceOpenDevice() is probably not the problem. Your crash is not on XtServiceOpenDevice() but rather on XtDeviceOpenStream(). I hope, a stracktrace gives some insight. Let me know if you need more help with it.

@sjoerdvankreel
Copy link
Owner

@dechamps

<< this bug can only be triggered after CreateBuffers()

actually yes, XtServiceOpenDevice corresponds to CoCreateInstance<IASIO> as well as IASIO->init().

AsioService::OpenDevice(char const* id, XtDevice** device) const

Then XtDeviceOpenStream corresponds to IASIO->createBuffers().

AsioDevice::OpenStreamCore(XtDeviceStreamParams const* params, XtStream** stream)

Although, @AGENTE44 gets the crash on the above demo code, which opens the device only once.
Maybe my fancy runtime codegen is to blame here, but i've never experienced any issue with it since the project's inception 8 years ago. But, who knows.

@AGENTE44

I tried with both x64 and x86 versions, no problems. Of course this is sort of a "works on my machine" scenario, but it's really difficult for me to operate without a clue. I have attached a visual studio solution of the above sample code including all xt-audio debug binaries and pdb files (64-bit only). I'm assuming you can run visual studio, there's a fully-functional free community edition also. See here: ConsoleApplication4.zip

Can you maybe give that a try? If it crashes, you can grab the stacktrace from the debug callstack window, see screenshot below (I intentionally made it crash by opening multiple FlexASIO's at once, your stacktrace will hopefully look different).
If that's still not it, I might have to set up a GCC/MingW environment, but, I hope it doesn't come to that.

image

@AGENTE44
Copy link
Author

Hi
I'm actually coding in CODEBLOCK's IDE, have null experience with VS
as a novice (or hobbyst I should say) programmer, I'm not familiar with the debuging tools/techniques, sorry for that inconvenient

I don't want to lie by giving you inexact information, I can perform some logical and very superficial tests to locate the conflictive function (of the xt library) but I'm unable to go further or deal with the bare metal

after the multiple XtServiceOpenDevice() call test (and the crash in the second call with FlexASIO) it is probably that something was not initialized correctly, and other critical functions like XtDeviceOpenStream() are condemned to crash (so it is not necessary a problem with XtDeviceOpenStream() as I thought at first)

I can try to look for another unstable function with the FlexASIO device if that helps

did you tried the ASIO driver tester? it was able to detect the error before operating with the flexASIO (without crashing of course), error that I'm still trying to detect with the xt library

xt5

@sjoerdvankreel
Copy link
Owner

@AGENTE44

<< did you tried the ASIO driver tester?

Just did. Absolutely no problems whatsoever, not with FlexASIO nor any other ASIO driver, x86 and x64.
The zip file i attached in the previous post contains a runnable debug binary (.exe). What happens if you just run that thing? I'm hoping for some "debug it now" window to pop up, who knows, maybe it will allow you to step into codeblocks.

@dechamps

Does any of this stuff ring a bell for you? I mean with the VB-Audio ASIO tester, xt-audio is completely out of the equation, but I'm hoping that "unanticipated host error" might be an a-ha moment for you.

@dechamps
Copy link

I'm hoping that "unanticipated host error" might be an a-ha moment for you

Well, that just means FlexASIO failed to initialize, why can be caused by any number of things, most of which are purely backend-side and have nothing to do with user code. I would need a FlexASIO log to understand why FlexASIO failed to initialize in this particular case. This is usually not indicative of an issue with the application, which should handle this error just like any other runtime failure.

@sjoerdvankreel
Copy link
Owner

@AGENTE44

Any chance you could produce that log?

@AGENTE44
Copy link
Author

you mean executing ConsoleApplication4.exe?
I dont have the libraries:

VCRUNTIME140_1D.dll
VCRUNTIME140D.dll
MSVCP140D.dll
ucrtbased.dll

can you provide a link to a MS instaler?

@AGENTE44
Copy link
Author

Ok I gather some more info

I'm currently using an external audio interface to capture microphone, and the internal soundcard of a laptop as playback device, and I had to disable anything else to be able to work with some real-time audio effect software
no problem so far, even with the ASIO Link Pro, ASIO4ALL, and Realtek ASIO (this last works horrible but it doesnt crash)

This is the settings I have with FlexASIO

xt7

I did read about the FlexASIO.log, so I generate one file for the sjoerdvankreel 's first test code

FlexASIO_1.log

it's probably that my selected output device is not working, or is not a good entry point (or something like that...)
I tested another output device (like the "Auriculares()" one shown in the screenshoot) and the test code passed suscesfully
it may have something to do with the WDM-KS backend, right???
hope this info can be usefull

@sjoerdvankreel
Copy link
Owner

@AGENTE44

<< I dont have the libraries:

You need this thing https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170#visual-studio-2015-2017-2019-and-2022. Alternatively if that doesn't work out i can do a static linked build.

Btw just curious, you say you're a novice programmer but then why use all those non-native toolchains like codeblocks and gcc? Are you just switching to windows from another platform?

<< it may have something to do with the WDM-KS backend

Maybe. You should test them in this order from least to most user-hostile :)

  1. directsound
  2. wasapi shared
  3. wasapi exclusive
  4. wdm-ks

@dechamps

Anything interesting in that log above?

@dechamps
Copy link

dechamps commented May 23, 2024

@AGENTE44 You should really take things one step at a time.

If FlexASIO itself is not working, then obviously it won't work regardless of which ASIO application you try to use it in (be it the VB-Audio ASIO Tester, the xt sample app, your code, or even FlexASIOTest).

Before you can try your own app with FlexASIO, you need to make sure FlexASIO itself works, regardless of the app.

The default configuration of FlexASIO (i.e. no config file at all, or an empty one), is usually the most reliable one. So I'd suggest you start with that.

WDM-KS is the least reliable FlexASIO backend by far, and it's known to be broken in various ways. Starting right off the bat with WDM-KS is an odd thing to do, and is really asking for trouble.

(From your log I suspect the reason why WDM-KS doesn't work is because you are trying to use it on your default Windows audio device, a case that is explicitly documented to not work. But that's besides the point.)

If you can't get FlexASIO to work in a released ASIO app, then it's a bug in FlexASIO (or a known FlexASIO issue such as the one I just mentioned), and you should report it against FlexASIO, not here.

If you can get FlexASIO to work in a released ASIO app, but it doesn't work with your own app, then it makes sense to start debugging your app (and perhaps xt-audio).

In any case, the FlexASIO log can be quite effective as a convenient debugging aid.

Also, just to make sure things are clear: crashing when more than one instance of FlexASIO exists at any given time is to be expected, and is not a use case that FlexASIO intends to support - see dechamps/FlexASIO#230. My understanding from the linked discussion with @sjoerdvankreel is that xt-audio will not be changed to avoid this situation, either. In other words it is not considered a bug in FlexASIO nor in xt-audio. Which is a bit sad, but that's the way it is for now. So, if you want to avoid this problem, you're gonna have to work around it yourself in your code, i.e. make sure that the way you use xt-audio in your app does not result in more than one instance of a single ASIO driver existing at any given time.

I'm worried that this thread is all over the place, to the point where I'm not even sure which issue we're discussing anymore.

@sjoerdvankreel
Copy link
Owner

@dechamps

<< Starting right off the bat with WDM-KS is an odd thing to do, and is really asking for trouble.

Second that.

<< My understanding from the linked discussion with @sjoerdvankreel is that xt-audio will not be changed to avoid this situation, either

True, but also not the cause of the demo code crashing. To be absolutely clear, that sample opens FlexASIO exactly 1 time, and neatly closes it.

<< I'm worried that this thread is all over the place, to the point where I'm not even sure which issue we're discussing anymore.

The issue at hand is a crash in the above mentioned sample code for xt-audio with FlexASIO as a backend. That sample code opens and closes FlexASIO exactly once. However I do agree with you that things are getting fuzzy, especially with problems popping up with multiple hosts.

@AGENTE44

If you're up for it, we can try to pinpoint this together.
For example we could start with FlexASIO + FlexASIO GUI, moving from DirectSound->WASAPI->WDMKS, then repeat that
for the VB Audio Tester, then repeat that for xt-audio. I'll be happy to help out any step of the way.
But it's gonna involve a lot of back-and-forth.

@AGENTE44
Copy link
Author

no problem sjoerdvankreel, please take all your time you need

I did more tests with FlexASIO GUI, and everything is normal in all combinations with DirectSound, WASAPI and MME: I got between "supported" and "not supported" messages, but NO CRASHES.... however, the only crashes I got is when you select both input and output devices as "None" (your test code stop at XtServiceOpenDevice() , and returning 0x3), I think FlexASIO should protect you from the "None" option

I discover that I'm having problem only with WDM-KS, in the following output devices

xt8

only when one of those output devices is selected (and only with the WDM-KS backend) I got the 0xC0000409 crash
I believe the next output devices are just labels to identify the devices in different languages (I got no crash here)
the ASIOVADPRO are virtual devices (I got no crash here)

I can summarize the following crash conditions:

  • WDM-KS backend
  • selected any of the internal output devices (using the real hardware name in the list)
  • 1rst call to XtServiceOpenDevice() respond OK (no error detected)
  • XtDeviceSupportsFormat() respond OK (valid format)
  • XtDeviceOpenStream() CRASH!!!
  • 2nd call to XtServiceOpenDevice() also CRASH!!! (that doesn't happen with ASIO link pro, ASIO4ALLv2 and RealtekASIO)

by the way, Xt.Gui still crashing me for all FlexASIO backends options
PD: I still cant make ConsoleApplication4.exe to work :-( (the installer didn't come with the missing files)

greetings

@dechamps
Copy link

dechamps commented May 25, 2024

XtDeviceOpenStream() CRASH!!!

That definitely shouldn't happen. There are two possibilities:

  1. FlexASIO itself is crashing; or
  2. FlexASIO is cleanly returning an error but some user code (either yours or xt-audio) is not handling the error correctly and crashing instead.

A stack trace would be ideal to understand exactly what code is crashing. You should be able to obtain one if you trigger the crash under a debugger. Failing that, a FlexASIO log would at least show if the crash happens before or after FlexASIO returns control to the caller. In the log you posted in #26 (comment) the crash happens after, which suggests FlexASIO is not at fault, but I don't know if that log refers to the same scenario or not.

2nd call to XtServiceOpenDevice() also CRASH!!!

That one is expected if you didn't close the previous instance before opening a new one, see dechamps/FlexASIO#230. The next release of FlexASIO won't have that problem, but I still wouldn't recommend doing this because ASIO drivers are not required to support this scenario. (And please definitely don't do that kind of stuff concurrently from multiple threads - dechamps/FlexASIO#185.)

Xt.Gui still crashing me for all FlexASIO backends options

From what I understand (@sjoerdvankreel will correct me if I'm wrong), this is also because of dechamps/FlexASIO#230 and is therefore expected.

@AGENTE44
Copy link
Author

That one is expected if you didn't close the previous instance before opening a new one, see dechamps/FlexASIO#230. The next release of FlexASIO won't have that problem, but I still wouldn't recommend doing this because ASIO drivers are not required to support this scenario. (And please definitely don't do that kind of stuff concurrently from multiple threads - dechamps/FlexASIO#185.)

I guess the 2nd call to XtServiceOpenDevice() is just a confirmation of the unstability of the xt-lib or FlexASIO, after the 1rst call
at least, ASIO link pro sends you an error code in the second XtServiceOpenDevice()
ASIO4ALLv2 and RealtekASIO doesn't return any error code, in fact, its giving me different device pointer (have no idea what this means)

no intention to do that practice in my program anyway, I understand ASIO works with 1 input and 1 output device at the time
the mistery here is that FlexASIO opens the device correctly, reports a valid device format and crash when open the stream
this happens only with the WDM-KS and one of the marked output devices above

greetings

@sjoerdvankreel
Copy link
Owner

Ok so I just figured it out, and the hard crash is, in fact, a bug in the xt-audio library proper.
@dechamps give me a couple minutes to write down what's going on in another comment. It might still be of interest to you.

But first,

@AGENTE44
<< I guess the 2nd call to XtServiceOpenDevice() is just a confirmation of the unstability of the xt-lib or FlexASIO

Actually neither and also unrelated to your crash.
Let me try to explain:

  • The ASIO specification disallows any application to open more than 1 ASIO driver at the same time (doesn't matter if it's the same driver or a different one).
  • FlexASIO makes use of this restriction by crashing the application if you try to open it more than once anyway. It is fully allowed by the ASIO spec to do so.
  • The next FlexASIO version will play a bit nicer, and let's you open up more than 1 instance simultaneously. Again, it is not required to allow this by the ASIO spec, but it's sure nice anyway. Many other ASIO drivers also allow it.
  • Xt-audio doesn't care either way. It allows you to open multiple ASIO drivers at once, but it does not require you to do so. It's a nice-to-have for running multiple different drivers in parallel. However if you want to be fully ASIO-compliant you should not make use of this capability of xt-audio. And I should probably document that somewhere.
  • The XtGui demo app, on the other hand, actually requires an ASIO driver to be instantiated twice. This is in fact a bug, but I don't care enough about it to fix it. Especially not with the next FlexASIO version coming up.
  • If you're interested there's loads of discussion over here Crash in PortAudioDebugRedirector dechamps/FlexASIO#230.

@dechamps
<< And please definitely don't do that kind of stuff concurrently from multiple threads

Actually xt-audio is so strict here that that's not even possible. Whatever calls XtAudioInit() becomes the main thread and all API calls must be made through the main thread, with the exception of a very select set of audio stream functions. Probably for precisely the same reasons that portaudio is thread-hostile. A lot of audio COM stuff requires to run in the single-threaded apartment. WASAPI docs are full of comments like "final release must be from the same thread that first created the object" etc etc.

I hope that clarifies. Now on to my next post which should actually describe what's going on ;)

@sjoerdvankreel
Copy link
Owner

Ok, so here goes. I should have understood this from the FlexASIO logfile alone last time, but alas.

  • Me being a practical guy, I assume any cleanup function will never fail. Anything that's called freeWhatever(), closeWhatever(), destroyWhatever(), or in this case, disposeBuffers(), I take those to succeed at face value, and if it doesn't, xt-audio crashes the process. There's a reason cleanup functions return void in any language except C. I mean what are you to do when your c++ destructor fails? Or your c#'s using-block, or java's try-with-resources or whatever. Write a log and carry on, mostly.
  • This approach works good enough in practice, for all backends including ASIO. Even if, again, it doesn't follow the spec to-the-letter.
  • However this only works for resources that were actually successfully initialized! It is fully reasonable for an IASIO implementation to say, "nope, cannot disposeBuffers(), because I have none". @dechamps I'm sure you see where this is going.

Following the demo code and the FlexASIO log, here's the sequence of events:

  1. XtServiceOpenDevice
2024-05-22T23:16:52.8132214-04:00 10952 5684 --- ENTERING CONTEXT: CFlexASIO()
2024-05-22T23:16:52.8132530-04:00 10952 5684 --- EXITING CONTEXT: CFlexASIO() [OK]
2024-05-22T23:16:52.8132950-04:00 10952 5684 --- ENTERING CONTEXT: init()
... loads of portaudio stuff ...
2024-05-22T23:16:52.9727664-04:00 10952 5684 --- EXITING CONTEXT: init() [OK]
  1. XtDeviceOpenStream
2024-05-22T23:16:52.9751923-04:00 10952 5684 --- ENTERING CONTEXT: createBuffers()
2024-05-22T23:16:52.9752213-04:00 10952 5684 Request to create buffers for 2 channels, size 441 samples
2024-05-22T23:16:52.9752518-04:00 10952 5684 Allocated 2 buffer sets, 0/2 (I/O) channels per buffer set, 441 samples per channel, 4/4 (I/O) bytes per sample, memory range: 007C7A20-007C95B0
2024-05-22T23:16:52.9752868-04:00 10952 5684 ASIO buffer #0 is output channel 0 - first half: 007C7A20-007C8104 - second half: 007C87E8-007C8ECC
2024-05-22T23:16:52.9753149-04:00 10952 5684 ASIO buffer #1 is output channel 1 - first half: 007C8104-007C87E8 - second half: 007C8ECC-007C95B0
2024-05-22T23:16:52.9753417-04:00 10952 5684 CFlexASIO::OpenStream(inputEnabled = 0, outputEnabled = 1, sampleRate = 44100, framesPerBuffer = 441, callback = 6F21263F, callbackUserData = 007932A8)
... loads of portaudio stuff ...
2024-05-22T23:16:52.9777989-04:00 10952 5684 Destroying buffers
2024-05-22T23:16:52.9778355-04:00 10952 5684 --- EXITING CONTEXT: createBuffers() (-999 [ASE_HWMalfunction] unable to open PortAudio stream: Invalid device)
2024-05-22T23:16:52.9779163-04:00 10952 5684 --- ENTERING CONTEXT: disposeBuffers()
2024-05-22T23:16:52.9779510-04:00 10952 5684 --- EXITING CONTEXT: disposeBuffers() (-997 [ASE_InvalidMode] disposeBuffers() called before createBuffers())

So from here, it's clear that FlexASIO returns ASE_HWMalfunction back to xt-audio, buffers are not successfully initialized, yet xt-audio calls disposeBuffers() anyway. Then that freaks out with ASE_InvalidMode, causing xt-audio to take down the process.

Note to self: the problematic code is over here

auto result = std::make_unique<AsioStream>();
and
{ XT_ASSERT(XtiIsAsioSuccess(_asio->disposeBuffers())); }
.

@AGENTE44
Actually like FlexASIO, xt-audio also contains a logging facility, and I was stupid enough not to tell you to turn it on immediately. Goes to show how little time I spent with this library these day.
Had we turned on xt-audio logging immediately, you'd have seen something like this

Device.cpp:154: in function OpenStreamCore: errort
Stream.cpp:7: in function ~AsioStream: XtiIsAsioSuccess(ASE_InvalidMode)

And the whole issue would probably been cleared out in a matter of hours, not weeks.

So, to summarize:

  • FlexASIO neatly returns "(-999 [ASE_HWMalfunction] unable to open PortAudio stream: Invalid device)"
  • Xt-Audio turns that into a hard crash ( I will fix that on my side )
  • Once fixed in xt-audio, @AGENTE44 's code will no longer crash, but you still will not be able to use the device in that particular wdm-ks configuration

@dechamps
Copy link

Nice catch! Yeah, in order to facilitate debugging FlexASIO will take every opportunity to tell the host application it's doing something that it thinks is wrong, and calling disposeBuffers() after createBuffers() returned an error is definitely wrong. Glad we finally have all the answers.

The silver lining is FlexASIO successfully surfaced a bug in your library :D Which is indeed the whole point. Who knows, maybe other drivers would have crashed on disposeBuffers() instead of returning an error like FlexASIO does.

@sjoerdvankreel
Copy link
Owner

Just (hopefully) implemented the fix. Turned out to be as simple as this:
81f2388#diff-c8341b8afd0600f82d8a243f705aec93189a0f2116724084dce33bad38bb6247.

@AGENTE44
Thanks for reporting and continuous cooperation.
I have attached new binaries (of native windows xt-audio.dll only).
Expected results: xt-audio backs out with a nice error code instead of a hard crash.

@dechamps
<< Glad we finally have all the answers. The silver lining is FlexASIO successfully surfaced a bug in your library :D
Definately. This was a nasty one. Also to you, thanks for your patience.

@AGENTE44
I'm really hoping that you can re-test the demo code while replacing xt-audio by the attached dll's.
I'm hesitant to release without confirmation because it's a bit of work, making the linux build, publishing the mvn central and the nuget packages, probably lost my API keys long ago etc.

@dechamps
Assuming the issue is fixed on xt-audio side, I'm hoping you may be able to help @AGENTE44 out a bit with the underlying problem.

@AGENTE44
Just a word of practicality: unless you're still targeting windows XP (or Vista, WASAPI wasnt so great back then), there's absolutely no reason to go with WDM-KS. WASAPI exclusive mode is a thin layer atop Windows Driver Model, WDM-KS gets you nothing in terms of smaller buffer sizes or lower latency or whatever compared to wasapi exclusive. OTOH, wasapi exclusive provides all that stuff alongside a much better user experience. Of course, if your goal is somehow to target old systems or just to stress your tools to see how they fare, there still might be something going on here. But for all practical purposes, anything post-vista, just ditch WDM-KS.

Thanks again to the both of you.

core.zip

@dechamps
Copy link

FYI FlexASIO 1.10, which I just released, should work with multiple instances at the same time.

@AGENTE44
Copy link
Author

Ok I confirm the error code for XtDeviceOpenStream() with no crash (and FlexASIO 1.9)
(I have tested only the x86 dll version for the moment)

xt9

Then I Tried to use the new dll with the current Xt.Gui without success (but I understand that it was expected)
Then I updated the FlexASIO 1.9 to 1.10, with success (test code and Xt.Gui), but VB-AUDIO tester FAILED (all backends!!!)
(by the way, I installed the new FlexASIO without uninstalling the previous)

I know FlexASIO belongs to another thread, but I'll post this extra info anyway

I realized dechamps released another verion FlexASIO 1.10a
so I installed again the new FlexASIO without uninstalling the previous one, with the following results:
(always replicating the initial errors with my WDM-KS problematic devices)

Test code : It was able to open the stream (NO error code for XtDeviceOpenStream() as above) <- A-HA dechamps did something here!!!
Xt.Gui : initiates correctly, everything works normally
VB-AUDIO tester : I dont' have the same message that I post previously, it says that is running, but it seems the callback is not executing (so the test is frozen), WASAPI runs normally

I think dechamps should put some attention on this?


Just a word of practicality: unless you're still targeting windows XP (or Vista, WASAPI wasnt so great back then), there's absolutely no reason to go with WDM-KS. WASAPI exclusive mode is a thin layer atop Windows Driver Model, WDM-KS gets you nothing in terms of smaller buffer sizes or lower latency or whatever compared to wasapi exclusive. OTOH, wasapi exclusive provides all that stuff alongside a much better user experience. Of course, if your goal is somehow to target old systems or just to stress your tools to see how they fare, there still might be something going on here. But for all practical purposes, anything post-vista, just ditch WDM-KS.

as I mentioned before, I have no particular preference over these drivers and backends because I'm not the final user! I'm doing all hard-testing to ensure everything runs as smooth as possible in all scenarios (by the way, do you know more generic ASIO drivers out there to test?) in fact, I'm kind of disappointed about ASIO because I'm interested in multi device streaming (guess WASAPI is the only reliable option now), but who knows... some ASIO developer may change that in the future...

I think the new dll fixed this little bug
so let me know if you want to sign this issue as resolved.

greetings

@dechamps
Copy link

Then I updated the FlexASIO 1.9 to 1.10, with success (test code and Xt.Gui), but VB-AUDIO tester FAILED (all backends!!!)

Yeah this is dechamps/FlexASIO#231, which is the reason why I released 1.10a.

VB-AUDIO tester : I dont' have the same message that I post previously, it says that is running, but it seems the callback is not executing (so the test is frozen), WASAPI runs normally

This is almost certainly a FlexASIO issue and you should report it against FlexASIO (along with a log). Since it affects VB-Audio tester it has nothing to do with your app. But again, I'm not too surprised you're seeing issues with FlexASIO WDM-KS, which is known to be quite buggy, sadly.

@ofsjoerdk
Copy link

@AGENTE44

<< I have no particular preference over these drivers and backends because I'm not the final user!
Understood. May I ask, what is the project that you're working on?

<< do you know more generic ASIO drivers out there to test?
Actually FlexASIO https://github.com/dechamps/FlexASIO lists all others that I know of, being ASIO4ALL, ASIO2KS, ASIO2WASAPI. There may be more, I haven't searched.

<< in fact, I'm kind of disappointed about ASIO because I'm interested in multi device streaming
With hardware vendor supplied ASIO drivers this is kind of no-go "officially", but xt-audio let's you do it anyway. Sometimes it works, sometimes it doesn't. However with generic asio drivers this is very much possible. The trick is for the ASIO driver, to present multiple devices as a single many-channel device to the host. I am positive that for example ASIO4ALL can do this. Judging from the FlexASIO gui screenshot, it looks to me that FlexASIO can do it, too, but I don't know FlexASIO well enough to comment. @dechamps can you clarify?

<< (guess WASAPI is the only reliable option now)
If you decide to go that route, you should look into xt-audio's stream aggregation feature. I bet it's similar under the hood to for example ASIO4ALL combined devices. Except with DSound/WASAPI instead of kernel streaming.

<< some ASIO developer may change that in the future
I wouldn't count on it. Latest ASIO sdk https://www.steinberg.net/developers/ is from 2019. But barring minor changes, it looks like the thing's been set in stone for ages, even before 2019.

<< let me know if you want to sign this issue as resolved
I will do so as soon as I have published the maven and nuget packages. But yeah, I do consider it resolved.

And now, on to some unsolicited advice!

There's a BIG reason why ASIO in principle disallows multi-driver setups. In short, it's called "hardware clock".
If you're after a rock-solid many-input many-output setup, get your hands on a big expensive multichannel firewire device or some such. The important thing is, it should be a single piece of hardware with vendor-supplied ASIO drivers.

Anything that tries to pass off many different devices as a "single big device" is bound to glitch eventually, if you just stream it long enough. This goes for xt-audio's stream aggregation feature, and I'm 99% sure it also pertains to generic ASIO drivers such as FlexASIO or ASIO4ALL, and also convenience features like this https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ee416764(v=vs.85)?redirectedfrom=MSDN.

Thing is, different pieces of hardware (usb, firewire, PCI, whatever) each come with their own internal clock. Those clocks are 99.999% perfect, but never 100%. So clock drift and skew will occur eventually. If you open separate audio streams on those, one will for example run at 47999.999 Hz and the other one at 48000.001Hz. Even worse, those values are not even constant over time. The way xt-audio deals with this is to designate one of many streams as "master", and zero-pad or drop samples on the other one. I wouldn't be surprised if other systems take similar measures. After all, this problem is generally not solvable except for creating a hypothetical "infinite delay line".

I have to admit there's one function in the ASIO sdk that I never quite grasped, and it's called "setClockSource". Surely it has something todo with the aforementioned stuff, but I find it hard to correlate with ASIO's (in principle) single driver model. @dechamps how's that one implemented in FlexASIO?

@dechamps
Copy link

dechamps commented May 28, 2024

The trick is for the ASIO driver, to present multiple devices as a single many-channel device to the host. I am positive that for example ASIO4ALL can do this. Judging from the FlexASIO gui screenshot, it looks to me that FlexASIO can do it, too, but I don't know FlexASIO well enough to comment.

No, it can't. See dechamps/FlexASIO#58.

After all, this problem is generally not solvable except for creating a hypothetical "infinite delay line".

You can do it by resampling the audio on-the-fly, but that makes things way more complicated, more computationally intensive, and also slightly lossy.

I have to admit there's one function in the ASIO sdk that I never quite grasped, and it's called "setClockSource".

I think it has to do with hardware devices that have multiple user-selectable clocks. For example, a given interface with lots of I/O could get its clock from an embedded clock, from USB Audio, from one of its S/PDIF or AES/EBU ports, or from a dedicated word clock port. This ASIO API would provide a way for an application to show the available clocks to the user for a particular device so that they can switch between them. I suspect it's never used in practice, though - I've never seen an ASIO Host Application surface a UI for this. Most likely a device manufacturer would want to surface this through their ASIO Control Panel instead.

Universal ASIO drivers do not get to pick which clock they use (the underlying system APIs do not offer this functionality), so it doesn't make sense for FlexASIO to implement this function.

@ofsjoerdk
Copy link

<< You can do it by resampling the audio on-the-fly, but that makes things way more complicated and more computationally intensive.

This is clever! However doesn't that rely on the hardware being able to accurately report skew and drift? I always assumed drivers would just say "yeah sure I'm at 48k". Are you saying it's actually possible to pick up minor deviations like that through the ASIO API? Or would this involve resampling by timing on the host side? That'd be a major PITA.

<< I think it has to do with hardware devices that have multiple user-selectable clocks

A-ha! So it's about 1 hardware with multiple clocks. I always thought it was about multiple hardware with 1 clock, used for syncing. Explains my confusion. And so, you learn something new every day :)

<< Universal ASIO drivers do not get to pick which clock they use
In the ASIO4ALL case i bet it's even worse -- there's multiple of them.

@dechamps
Copy link

dechamps commented May 28, 2024

Or would this involve resampling by timing on the host side?

Yes, that's what I mean. I don't know if that has ever been done to combine realt-time audio streams with different clocks, but that has definitely been done many times with great success to synchronize an audio stream to a video stream: see e.g. ReClock, JRiver VideoClock, MPDN Rate Tuner, mpv --video-sync=display-resample, and others.

Obviously this is very tricky to do correctly. Must be a very fun project for someone motivated though!

In the ASIO4ALL case i bet it's even worse -- there's multiple of them.

Yeah, and ASIO4ALL does not do anything clever in this case - the audio will glitch eventually.

In FlexASIO, you can still get in this situation if the input and output devices have different clocks.

@ofsjoerdk
Copy link

@dechamps
<< Must be a very fun project for someone motivated though!

Yeah... I'm not that motivated :) In fact subsample syncing like that strikes me as way more complicated than even my runtime code generation endeavour.

Meanwhile, stuff went south over here just like I expected. Long lost my nuget keys, mvn-central, and apparently something gnu-gpg is expired, too. It's been years since i touched that stuff.

@AGENTE44
And it'll probably also be a couple days for me to re-setup stuff. Meanwhile I leave this ticket open, please dont close it.

@AGENTE44
Copy link
Author

Understood. May I ask, what is the project that you're working on?

It's a project that's been a little sluggish and dormant for a while, I still need to do some fine tunning, but I'll let you know when is back on track with your library, which by the way, I'll put it to work under stress (I want to use your dll to replace my old OpenAL library)

I am aware of the sync issue among separated clocks, and that there's no solution without introducing some delays, but I want to try a few ideas now that I have a little more control over the streams

greetings

@sjoerdvankreel
Copy link
Owner

Just FYI I'm in contact with sonatype/nexus. They're in a bit of a restructuring so it'll take some time for me to publish the java version of the library. Once that's settled I can do a proper 2.1 release and close this issue.

@sjoerdvankreel
Copy link
Owner

Closed with 2.2.

Just FYI: 2.2 contains this bugfix and another minor (glibc related) one, but it also drops x86 support and (probably of no interest to you) maven support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants