Skip to content

Conversation

@pkviet
Copy link
Member

@pkviet pkviet commented Oct 15, 2025

Description

ASIO is a driver standard developed by Steinberg for low-latency audio. It is commonly used in pro audio.
It was unfortunately not possible for a long time to write a native ASIO host in obs because of license issues.
This has changed thanks to a partnership between the project and Yamaha Steinberg:
https://www.steinberg.net/press/2025/obs-collaboration/
The ASIO sdk is now released under dual licensing, including GPL v3 which is compatible with obs-studio.

Historical aside. When I got involved with obs coding, after working on surround sound support, my first plugin
endeavor was to write an asio source, which was developed eventually in collaboration with Andersama. It was a great learning experience. The ASIO sdk is notoriously tricky with lots of pitfalls for hosts and drivers alike. It was so daunting that at that time (early 2018) we relied on third-party libraries (RTAudio, Bassasio, portaudio) and now JUCE. The last incarnation of our asio plugin for obs (based on JUCE) was mostly coded by Andersama. It has been superseded in many ways by another third-party plugin based also on JUCE, atkaudio which has lot of capabilities but again relies on a third-party library. And anyway our ultimate goal had always been to add support for ASIO into obs.

This PR brings ASIO support in obs-studio natively: no third-party library is used but Steinberg SDK is leveraged directly.
For the host implementation, we have taken cues from JUCE ASIO host which documents a lot of pitfalls.

Our ASIO host provides:

  • an asio source where inputs from asio devices can be captured with also channel selection.
  • an asio output.

The asio output in turn allows:

  • track monitoring with channel selection too,
  • a special monitoring track which automatically mixes all monitored sources and can be selected in the asio output.

Technical note

The asio callback processes both audio from host to device and from device to host at the same time. The main difference with wasapi, is that any monitored audio sent to the device is not automatically mixed; it is the responsibility of the host to do the mixing. That is why asio can not be seamlessly integrated into libobs/audio-monitoring and that we resorted to creating an obs-output for asio.
This output is controlled through a frontend plugin which instead of adding an entry into the tool menu (as is customary) is callable from Settings > Audio alongside monitoring devices (wasapi on windows).

Screenshots:

ASIO source
obs64_2025-09-02_17-25-32

ASIO source with channel selection
obs64_2025-09-02_17-25-51

ASIO source with device selection
obs64_2025-09-02_17-25-58

ASIO monitoring integrated to audio settings
obs64_2025-10-15_20-46-35

ASIO monitoring panel
obs64_2025-10-15_20-52-18

ASIO monitoring panel with track channel selection. Not the special monitoring track
obs64_2025-10-15_20-52-40

Motivation and Context

ASIO brings the following advantages:

  • low-latency capture,
  • low-latency monitoring (the wasapi monitoring has long been a source of user complaints),
  • capability to do complex channel routing.

How Has This Been Tested?

Tested on windows 11 pro with several asio devices:

  • Steinberg IXO 22
  • Steinberg UR22C
  • ESI U22XT
  • Behringer XR18
  • Tascam US-122 MKII
  • virtual drivers such as Rearoute from Reaper, Dante virtual card

Testers are welcome to report their results with their interface and I'll update the list.

Types of changes

  • New feature (non-breaking change which adds functionality)

Checklist:

  • My code has been run through clang-format.
  • I have read the contributing document.
  • My code is not on the master branch.
  • The code has been tested.
  • All commit messages are properly formatted and commits squashed where appropriate.
  • I have included updates to all appropriate documentation.

@pkviet pkviet force-pushed the asio_host branch 3 times, most recently from b408fbf to 763a7f3 Compare October 15, 2025 20:07
@Fenrirthviti Fenrirthviti added the Seeking Testers Build artifacts on CI label Oct 15, 2025
@pkviet pkviet added the New Feature New feature or plugin label Oct 15, 2025
@pkviet pkviet added this to the OBS Studio 32.0 milestone Oct 15, 2025
@pkviet pkviet force-pushed the asio_host branch 5 times, most recently from 4c9de0e to aa3d977 Compare October 17, 2025 19:30
@pkviet
Copy link
Member Author

pkviet commented Oct 17, 2025

Update

  • Fixed a lot of bugs; thanks to @prgmitchell , indrit (on discord), @WizardCM
  • On @WizardCM suggestion, i added a message when a driver fails to load (usually because the device is disconnected,
    or just because of flaky drivers - there's a lot of them in ASIO landscape , or because the ASIO driver is being used by another host.)
obs64_2025-10-17_21-01-58

@pkviet pkviet force-pushed the asio_host branch 5 times, most recently from 44c4228 to 3c02361 Compare October 19, 2025 13:19
@pkviet
Copy link
Member Author

pkviet commented Oct 19, 2025

Update 10-19-25
Fixed some bugs with output.
Factored a lot of the input and output functions.
Fixed a bug with drivers which set a different default sample rate than that from obs

Copy link
Member

@PatTheMav PatTheMav left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like I need to see the code "in action" to better gauge its correctness. I there something like an "ASIO virtual device" or something I can install in my VM and then use this plugin with it?

@pkviet pkviet force-pushed the asio_host branch 3 times, most recently from 4e0365f to 60aa7f2 Compare November 9, 2025 09:50
@pkviet
Copy link
Member Author

pkviet commented Nov 9, 2025

General architecture

VISIO_2025-11-09_12-58-15

All the audio processing is done in the own ASIO driver thread, NOT obs audio thread. This ensures the lowest latency.
One big difference with WASAPI is that both input and output buffers are processed concurrently.
On OBS side we need to ensure there is sufficient data to fill the buffers to avoid xruns. This is done through 2 deques, one on the capture side (ASIO Input source) and another on the play side (ASIO Output).
The play deque is filled in the audio thread by OBS with output audio from tracks or from monitoring.
The capture deque is filled in the asio driver thread but delivered to obs on the audio thread at each audio tick (1024 samples usually).
As already explained above, the ASIO driver does no mixing, so it is not possible to push separately all monitored sources; they must be mixed on our side. This is why a special "monitoring" track has been added. When compared with WASAPI, we have as a bonus that the monitored sources have the same sync as in outputs since they are processed in the obs main audio callback at the same time.

The main ASIO SDK issue:

  • this old sdk (it dates back to 1996, so pre-historic times) assumes that the host is a DAW and that it will load a single driver at a time.
  • conversely, the drivers are also supposed to be single client to minimize latency and not split the processing among several hosts. (A few ASIO drivers fortunately are now multi-client, that is, allow concurrent use by several hosts at the same time: ex: RME or Lynx.)
  • As a result of these limitations, it will not in general be possible to open an ASIO interface both in obs and a DAW. Workarounds do exist : for instance use Rearoute virtual ASIO driver, provided by Cockos Reaper.
  • The single driver host architecture of the SDK is a big issue for OBS because we need a multi-client host; a setup with a single ASIO device + one virtual ASIO driver such as VB-cable or ReaRoute allowing routing from DAWS, is a reasonable scenario that we need to support.
  • We had therefore to work around the ASIO callbacks because they don't pass a 'this' pointer allowing us to identify the ASIO driver. Our solution was to template callbacks, each driver having its own set.

The scanning phase.

The scan just checks the registry to list all installed ASIO drivers.
There is no check at that time of whether a device is actually connected or not.
The SDK has no way for us to check the connection state apart from actually loading the device.
There is then an error message but unfortunately the SDK has no explicit message regarding the disconnected state ...
If a device is erroring during loading, we disable its audio processing. But we don't discard it from the devices list because it could be: (1) the device is being concurrently used by another host, like a DAW; (2) a genuine disconnection, the USB cable being loose ... So obs should stick to the source settings, to allow the user to recover their setup.

The loading phase.

The driver is loaded during the creation phase when a driver is picked by the source.
During this loading some basic tests are done (in asio_device_test function) to ensure the device will stream properly during the real operating.
The driver is then opened (asio_device_open), meaning that all settings are applied, correct sample rate, buffer size, buffers are created... The device is started once all this initialization is done, meaning that processing can start. If audio callbacks are not triggered by the driver within 300 ms, the driver is stopped.

The streaming phase.

The driver calls repeatedly the bufferSwitch callback; this is where the main processing logic is done on our side (asio_device_process_buffer): there we copy the buffers coming from the device into the 'capture deque', and we copy the 'play deque' into the output buffers of the device.

@pkviet pkviet force-pushed the asio_host branch 4 times, most recently from 6b842cd to 4b17680 Compare November 9, 2025 17:50
@pkviet pkviet force-pushed the asio_host branch 3 times, most recently from 75250b3 to feaba5b Compare November 26, 2025 14:19
This adds:
- an ASIO Input source, allowing audio capture of devices using
Steinberg ASIO audio SDK on windows. This allows low latency capture.
- an ASIO output, which will allow routing audio from OBS to any ASIO
device. A per channel routing is provided.
The UI to setup the ASIO output is provided in a later commit.

Signed-off-by: pkv <[email protected]>
This adds an ASIO output entry in Tools Menu allowing to setup audio
output from obs to an ASIO device.

Signed-off-by: pkv <[email protected]>
On windows, this adds an additional audio track (Track 7) which is used
to output a mix of monitored sources. Currently the mixing is left to
WASAPI on windows for WASAPI monitoring devices.
But ASIO SDK doesn't allow multiple clients (although individual drivers
 might allow it) and therefore can not mix them. So we have to do the
mixing on obs side.

Signed-off-by: pkv <[email protected]>
This enables a monitoring track for output.

Signed-off-by: pkv <[email protected]>
This adds a QToolButton to the Audio Settings on Windows.
This triggers in turn a dedicated settings for the ASIO monitoring
output.
If no ASIO driver is detected in the system, the panel displays an
explanatory message.
The panel allows to:
- select an ASIO monitoring device;
- for each output channel of the ASIO device, one can select any channel
from any of the 6 tracks or from the monitoring mix.

Signed-off-by: pkv <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

New Feature New feature or plugin Seeking Testers Build artifacts on CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants