Help needed with my C++ ASIO output code: many drivers are crashing internally

Hello all. I have written an ASIO output driver in C++ for low-latency audio playback in my software.

And while it works great for my Audigy Rx drivers, as well as with ASIO4ALL, it is crashing with many other drivers, including:

  • Yamaha Steinberg CI1
  • C-Media (CM6631A)
  • FL Studio (not a real hardware driver)

The drivers appear to be crashing internally whenever I try to stop/release them, even when I do nothing in response to the callback messages. This takes down my entire application, even though ASIO is running in its own separate thread. I’ve tried adding lots of Sleep() commands in case the driver couldn’t keep up, but to no avail.

Can anyone please help me with how to avoid this? I strongly believe they are vendor driver bugs (a driver should never crash, no matter what inputs you give it, it should return error codes instead), however I may well be using the API wrong. Although I’ve followed host\sample\hostsample.cpp as closely as possible. Other closed-source ASIO applications seem to work okay, but I can’t analyze what they’re doing differently for obvious reasons.

Stack trace example:

I am using the direct COM interface, since this is a C++ project.

Initialization code:

    //_active.classID retrieved from choosing one of HKLM\SOFTWARE\ASIO\*\CLSID entries
    CLSID classID;
    if(CLSIDFromString((LPOLESTR)_active.classID, (LPCLSID)&classID) != S_OK) return false;
    if(CoCreateInstance(classID, 0, CLSCTX_INPROC_SERVER, classID, (void**)&_asio) != S_OK) return false;

    if(!_asio->init((void*)_context)) return false;  //_context is a valid, visible window handle (HWND)
    if(_asio->getSampleRate(&_active.sampleRate) != ASE_OK) return false;
    if(_asio->getChannels(&_active.inputChannels, &_active.outputChannels) != ASE_OK) return false;
    if(_asio->getBufferSize(
      &_active.minimumBufferSize, &_active.maximumBufferSize,
      &_active.preferredBufferSize, &_active.granularity
    ) != ASE_OK) return false;

    _frequency = _active.sampleRate;
    _latency = _latency < _active.minimumBufferSize ? _active.minimumBufferSize : _latency;
    _latency = _latency > _active.maximumBufferSize ? _active.maximumBufferSize : _latency;

    for(auto n : range(_channels)) {
      _channel[n].isInput = false;
      _channel[n].channelNum = n;
      _channel[n].buffers[0] = nullptr;
      _channel[n].buffers[1] = nullptr;
    }
    ASIOCallbacks callbacks;
    callbacks.bufferSwitch = &AudioASIO::_bufferSwitch;
    callbacks.sampleRateDidChange = &AudioASIO::_sampleRateDidChange;
    callbacks.asioMessage = &AudioASIO::_asioMessage;
    callbacks.bufferSwitchTimeInfo = &AudioASIO::_bufferSwitchTimeInfo;
    if(_asio->createBuffers(_channel, _channels, _latency, &callbacks) != ASE_OK) return false;
    if(_asio->getLatencies(&_active.inputLatency, &_active.outputLatency) != ASE_OK) return false;

    ASIOChannelInfo channelInformation = {};
    channelInformation.channel = 0;
    channelInformation.isInput = false;
    if(_asio->getChannelInfo(&channelInformation) != ASE_OK) return false;
    _sampleFormat = channelInformation.type;

    if(_asio->start() != ASE_OK) return false;
    return true;

Termination code:

    _asio->stop();  //crashes here
    _asio->disposeBuffers();  //if I don't call stop, it crashes here
    _asio->Release();  //if I don't call disposeBuffers, it crashes here

Hi,

Thanks. Accidentially I saw your post today. I detected the same issue in Nov. 2015 for

  • M-Audio
  • JRiver

drivers which let our software completely crash upon startup. Due to the urgent issues which we had at customers we did a deep dive. Yes, in case of buggy drivers the ASIO SDK let the complete application crash. The reason is that the ASIO SDK does not contain an exception handling which gracefully handles protection errors. As a result the ASIO SDK software points to addresses into the nowhere. Due to the urgency we had to enhance the ASIO SDK with an exception handling. With that, buggy drivers are handled gracefully and the application skipps those drivers and continues. Since then we had no fault reports anymore for our software.

I reported our enhancements to Steinberg immediately in Nov. 2015. However, nobody took action. I even discussed the changes personally with a management member in April 2016 which promised to forward the issue to the right people. Again, no response. After almost one year of attempts to reach the right people I gave up. My conclusion has been that Steinberg has no interests to listen to users and consequently have no interests to maintain and improve the ASIO SDK despite all applications are impacted even Steinberg’s own applications. I have documented all our changes in order to show that we comply to the contract agreement.

Please understand that I cannot share our enhancement of the ASIO SDK here. This is the job of the Steinberg team to distribute fixes.

But I have again touched base to Steinberg to communicate the enhancements now (July 2018). Hopefully, now after almost 3 years after the first notification somebody may listen. May be my response here may help, too.

The key issue is that there is no email address available to report issues. Your post in this forum from exactly one year ago (July 2017) shows that this forum is not sufficient to report issues because nobody from Steinberg checks it and takes action.



Arne, Yvan, could you please take a look at this issue?

Please note that byuu software is not just regular software. It’s bsnes and higan — the world’s most accurate and incredibly popular open-source emulators of Nintendo’s 8/16-bit game consoles.

According to byuu, the ASIO code used in bsnes and higan is 100% functionally identical to Steinberg’s SDK example code.

On my system, those crashes are 100% reproduceable. My sound card is ESI Juli@ (PCI) with the latest driver 1.21 under Windows 10 Pro (64 bit).

In emulation, minimal latency is crucially important, and audio latency is an important part of the overal latency. ASIO is a natural way to achieve minimal latency, but it causes bsnes crashes immediately after trying to switch to ASIO via its settings (bsnes → Settings → Drivers → Audio → Driver → ASIO).

Right now, byuu has just removed ASIO today from the next bsnes v109.2 and higan v106.214. Please help.

Thanks.

Did you try to assign the callbacks.* with a wrapping lambda function?
-R