No ASIO input until reselecting input channel

Hi,

The DemoRunner with an ASIO device selected doesn’t record any audio until I deselect the “Active Input Channel” and reselect it. I have just one audio interface (an Audient ID22) to test this with, so I can’t say for sure that this is a JUCE bug. However, I have no issues recording audio in Presonus Studio One.

How to reproduce?

  1. Build DemoRunner with ASIO enabled
  2. In DemoRunner, open Settings panel
  3. For Audio device type, select ASIO
  4. For Device, select your audio device, in my case “Audient USB Audio ASIO Driver”
  5. Open AudioRecordingDemo.h demo
  6. Notice that there is no audio being recorded
  7. Open Settings panel again
  8. For Active input channels, deselect and reselect “Analogue 1 + 2”
  9. Open AudioRecordingDemo.h demo again
  10. Notice that audio is being recorded

I built and tried the DemoRunner for JUCE 7.0.9, 7.0.7 and 7.0.5 and I experience the same behaviour for all of these.

Best,

Jelle

Could someone from the JUCE team let me know the status on this issue?

This is in my backlog, but I’ve got a few other bits and pieces to take a look at first.

We’re going to be focusing primarily on JUCE 8 features for a while now, so that’s going to take precedence over most non-critical bugs.

Thanks for your response, @reuk. I understand that your main focus is on JUCE 8 at the moment.

I’d like to highlight that, while the issue may appear non-critical, currently users with ASIO devices are not able to use our application at all. The reason for this is that our application is designed so that users are not allowed to alter input channel settings, as we always enable all channels. Consequently, our application becomes unusable for users with ASIO devices. I’m considering exploring a workaround involving an immediate disablement and re-enablement of all channels on startup, but this approach doesn’t feel optimal to me.

I would appreciate it if this bug could be labeled as critical. Alternatively, could you recommend a suitable workaround?

I have a bunch of ASIO drivers installed on my Windows 11 computer, including the ASIO4ALL v2 driver, Realtek ASIO, and a Generic Low Latency ASIO Driver.

ASIO4ALL v2 won’t open my laptop’s audio input at all, but the other two drivers seem to receive input correctly, without needing to disable and re-enable the input.

My guess is that this issue is somewhat driver-specific. Unfortunately, I don’t have an Audient device, so I can’t debug that at the moment. (I can install the driver, but I can’t actually enable it without an Audient device attached.) Do you know which drivers your customers are using when they see problems?

@reuk

In addition to the Audient ID22, we’ve also performed tests using a Focusrite Scarlett Solo 4th gen and a Focusrite 6i6 MK2 interface. The DemoRunner consistently shows the same behavior across all three audio interfaces. We have identified that the recording issue is specific to channel 2. While channel 1 records immediately, channel 2 only records when you disable and re-enable the channel 1 + 2 pair in the Active Input Channels.

I experience no issues when running Waveform 12, which uses Tracktion Engine and JUCE but doesn’t use juce::AudioDeviceManager.

Could you please investigate this issue again?

I’ve investigated a bit more with an Apollo Solo using the ASIO driver on Windows 11. The observed behaviour seems to be the product of several different aspects of the DemoRunner.

When I enable ASIO in the DemoRunner, the AudioDeviceSelectorComponent calls setCurrentAudioDeviceType on the AudioDeviceManager. In turn, this attempts to apply the last selected AudioDeviceSetup for an ASIO device. At this point, there is no previously-selected device, so a ‘blank’ setup is used, indicating that sensible defaults should be used. The defaults are taken from the values passed to AudioDeviceManager::initialise, which in the DemoRunner is 1 input and 2 output channels.

All of the above seems fairly reasonable to me. However, the UI in the DemoRunner is currently a bit misleading. The DemoRunner enables the “showChannelsAsStereoPairs” option when creating the AudioDeviceSelectorComponent, and this displays a given channel pair as “on” if either of the member channels is enabled. If I disable that option, then the DemoRunner shows only a single input as active by default. There’s definitely scope to improve the UI here, but this seems fairly specific to the AudioDeviceSelectorComponent.

It sounds like you’re not using the AudioDeviceSelectorComponent, so I guess the UX issue above doesn’t affect you. How are you initialising the AudioDeviceManager, and how are you specifying a channel layout? Are you enabling all channels after calling setCurrentAudioDeviceType to switch to the ASIO device type? Are you making sure not to use the default input/output arrangement?

FWIW if I run the AudioRecordingDemo on its own (outside of DemoRunner) with ASIO enabled, and put the following in the constructor, then the audio callbacks to the AudioLiveScrollingDisplay have 6 ins and 10 outs as expected (all channels available to the device), with input received correctly on channel 2.

audioDeviceManager.setCurrentAudioDeviceType ("ASIO", true);
AudioDeviceManaqer::AudioDeviceSetup setup;
setup.inputDeviceName = setup.outputDeviceName = "Universal Audio Thunderbolt";
setup.inputChannels.setRange (0, 64, true);
setup.outputChannels.setRange (0, 64, true);
setup.useDefaultInputChannels = setup.useDefaultOutputChannels = false;
audioDeviceManager.setAudioDeviceSetup (setup, true);

Hi Reuk,

Thank you for investigating this.

The UX problem outlined in your description of the AudioDeviceSelectorComponent is, as turned out, not connected to our specific bug. We just discovered that we were encountering an entirely different issue within our own codebase. Initially, we believed the DemoRunner was showing a reproduction of our bug due to the similar behavior, but it turned out that both issues were entirely independent of each other. Our utilization of a modified version of the AudioDeviceSelectorComponent fork, coupled with a misunderstanding of the class’s behavior for ASIO devices, resulted in a bug within our modifications.