Search guides and the APICtrl K
  1. API reference
  2. Hosting plugins

host_au.h

Hosting an Audio Unit (AUv2, and AUv3 through AUv2's API).

#include <sonore/host_au.h>
On this page

Design notes

The macOS half of host.h, in the same shape as the other three formats: a scan that describes without loading, a loader, and an AuPlugin that is a HostedPlugin like ClapPlugin, Vst3Plugin and Lv2Plugin -- prepare, process, parameters and their edits, state, presets, latency and tail, bypass, and the plugin's own editor in an NSView the caller owns. host.h includes this file at its end; a host that wants AU need include nothing else, and loadPlugin() takes a description whose format is "AU".

Written blind, and built to be checked

There is no Mac in this loop and macOS CI is not running, so NOT ONE LINE of the Apple half has executed. It is compiled -- by MSVC, for macOS, against the declarations in tests/au_shim (tests/mac_syntax_mac_host.cpp) -- which proves every name exists and every call fits its declaration, and proves nothing about whether Apple's runtime agrees. Every Apple call's status is checked and every failure lands in lastError() or the error string a loader is handed, so a run on a Mac says what went wrong instead of quietly hosting nothing. tests/mac_host_selftest.cpp is that run: it loads Apple's own AUDelay and DLSMusicDevice and prints what each step returned.

The parts that need no Mac -- the ids, the parameter mapping, the channel negotiation, the MIDI a unit emits, the error names -- are portable functions in host::detail, run by tests/mac_host_test.cpp on every platform. The Apple half is the thinnest layer that can call them.

How an AU is found

Not by file. AUs live in a system registry: AudioComponentFindNext walks it by type -- effect 'aufx', instrument 'aumu', music effect 'aumf', MIDI processor 'aumi', generator 'augn' -- and finds .component bundles, Apple's built-in units and AUv3 app extensions alike, the last of which have no bundle a folder scan could see. So AudioUnitPluginFormat::findAllComponents is the scan, and the id that identifies one is its registry triple, "type:subtype:manufacturer" ("aufx:dely:appl"). A .component in a folder host.h's scanDirectory walks is described too, from its Info.plist's AudioComponents list, so a folder scan and the plugin cache see AUs as they see everything else.

Why the frameworks are opened, not linked

host.h is included by every host on the Mac, CLAP-only ones too. Linking AudioToolbox, CoreFoundation and libobjc for this file would make every one of them name three frameworks it never asked for, and an installed SDK's consumers would all break at link time. So the functions are found with dlsym once, typed from Apple's own declarations (decltype(&::AudioUnitRender) and so on, which reads the header and references no symbol), exactly as gfx/window_cocoa.h finds CoreGraphics. A missing symbol is reported by name.

Threading, as host.h states it

Loading, prepare, parameters, state, presets and the editor are main-thread. process() is the audio thread and allocates nothing: buffers, the output buffer list and the MIDI out buffer are all sized in prepare(). An AUv3, or any unit whose component says it must be created asynchronously, is created with AudioComponentInstantiate, and the loader waits for it by RUNNING the main run loop when it is on the main thread -- an out-of-process unit's completion can need that loop, and a loader that blocked it would wait out its own timeout.

Types 2

class AuPlugin final : public HostedPlugin

One instantiated Audio Unit, driven as host.h drives every format.

Main-thread for everything but process(). AU-specific extras: lastError() says what the last thing that failed was and with which OSStatus, by name; renderFailures() counts blocks the unit refused to render (those leave the block as it came, as a block too long does).

The Audio Unit format, as one object to ask.

findAllComponents() is the scan: the system registry, by type -- effects, instruments, music effects, MIDI processors and generators -- which finds .component bundles, Apple's own units and AUv3 app extensions alike. A description it returns has an empty path, because an AU is identified by its id alone. createInstance() is loadPlugin() for one; describeBundle() reads one .component without running it.

Off macOS every call answers empty or null and says why: Audio Units are a macOS component format and there is nothing to find.

Functions 2

↑↓ to move↵ to openEvery public name in the headers, and every guide