ASIO Failure on Windows 10 - Thunderbolt 3

I am investigating a fault with our Juce based application, which exhibits when used with a particular Thunderbolt 3 external audio interface, namely the Universal Audio Arrow.

In fact, the behavior not only exhibits in our application, but also in the AudioPluginHost application whose source ships with Juce.

Universal Audio Arrow (Thunderbolt 3)
Windows 10
Visual Studio 2017
ASIO correctly enabled - ASIO SDK v2.3.3
Juce public release v5.4.7

When using buffer sizes of 512 of lower, the device driver issues a kAsioResyncRequest to the host. The request does not appear to be issued as a result of a user interaction, nor does it occur after a fixed time.

The ASIO SDK manual says:

“the driver detected underruns and requires a resynchronization”.

The driver went out of sync, such that the timestamp is no longer valid. This is a request to re- start the engine and slave devices (sequencer).

However, Juce never successfully recovers from this scenario. It appears to attempt to restart the engine, but an error occurs when re-creating the buffers. Here is the console output:

    ASIO: kAsioResyncRequest
    ASIO: restart request!
    ASIO: stopping
    The thread 0x3138 has exited with code 0 (0x0).
    ASIO: clock: Computer (cur)
    ASIO:  Resetting
    ASIO: disposing buffers
    ASIO: creating buffers: 16, 128
    ASIO: error: create buffers 2 - Invalid Mode
    ASIO: error: Can't create i/o buffers - Invalid Mode

The error code returned by the call to the createBuffers() is ASE_InvalidMode. Again from the ASIO SDK manual:

If bufferSize is not supported, or one or more of the bufferInfos elements contain invalid settings, ASE_InvalidMode will be returned.

However, Juce does not appear to be passing invalid state to the driver. The contents of the bufferInfos struct are:

|buffers|0x000002577ea3afa8 {0x0000000000000000, 0x0000000000000000}|void *[2]|
|[0]|0x0000000000000000|void *|
|[1]|0x0000000000000000|void *|

and currentBlockSizeSamples == 128 which is totally valid. In fact, when debugging the code from the start wherein the initial call to createBuffers() succeeds, it uses the exact same values.

So as far as I can gather Juce is attempting to reset the device, but at the point of buffer creation, the device is in a state where it is not prepared to deal with that request. Presumably the Juce state machine is out of sync with the devices state machine?

Additional Info:
It is also worth noting that an almost identical error exhibits when the user changes the buffer size from the third-party control panel. I have found this useful when debugging because it can be used to exploit the fault on request. The only difference is that the driver issues a kAsioResetRequest rather than the kAsioResyncRequest. But in fairness, Juce handles both messages in the same way:

/**N.B. All that resetRequest() does is starts a timer 500 ms.
 * The driver callback thread then exits and the timer callback attempts
 * to handle the resetting of the state machine in the main thread */`
case kAsioResetRequest:
    JUCE_ASIO_LOG ("kAsioResetRequest");
    resetRequest(); return 1;
case kAsioResyncRequest:
    JUCE_ASIO_LOG ("kAsioResyncRequest");
    resetRequest(); return 1;

In addition, it is worth noting that this error can be recovered manually when pressing the Reset Device button in the AudioHostPlugins Audio Settings panel. I think that whatever it is that’s being done correctly in that user thread, should essentially be replicated when Juce performs the reset in response to the driver requests.

Similar Issues:
This user appeared to report a very similar issue a long while ago, but it’s not clear whether it was ever fixed.

@jules - Please can you have a look into this?

Thank you kindly :wink:


FYI I tried extend the timer to several seconds to ensure that the external device had time to recover into a sensible state, but this was unsuccessful :frowning:

A support request has now been issued to Universal Audio, with the hope that they will be able to provide further details of why the kAsioResyncRequest is issued.

UPDATE: Universal Audio have now responded to say that they have assigned this to their development team and will be back in touch with further information.

Hi there. I am wondering if anyone has managed to take a look at this?

I thought perhaps I could have a look at the timestamps in the buffer switching events to check for long any obviously large delta’s, but Juce doesn’t appear to be utilising that data. Is this the case or am I misreading the code?

    static ASIOTime* JUCE_ASIOCALLBACK bufferSwitchTimeInfoCallback (ASIOTime*, long index, long)
        if (auto* d = currentASIODev[deviceIndex])
            d->callback (index);

        return {};

    static void JUCE_ASIOCALLBACK bufferSwitchCallback (long index, long)
        if (auto* d = currentASIODev[deviceIndex])
            d->callback (index);

Should the ASIOTime structure not contain some useful information?

Cheers :slight_smile:

We have quite many Windows10/ASIO/Thunderbolt3 users complaining about various issue our standalone plugins.
We still have to investigate the issue better, but we have no similar issues on USB and Firewire devices.

1 Like

Please, could you share here their response when you get it? :slight_smile:

1 Like

Hi! I think we have the same problem with our standalone applications on Windows/Thunderbolt systems. Did you ever get a reply from UAD?

Dear All,

I still haven’t heard anything back from UAD. I will send another email out to them today. Hopefully we can get some traction on this.

@psjoberg what devices are you seeing this issue occurring with?

1 Like

Hey @dstephenson. Thanks for the reply.

So far it seems to happen with Apollo(twin) and Arrow devices, but those are the only ones I’ve tried.

1 Like

Hey @psjoberg
My support ticket is Request #424787

Perhaps if you could get in touch with UA yourself and link back to this forum and also mention my support ticket, then we might be able to make a little more noise :slight_smile:

1 Like

Thank you! Will do!