asio_format.h
ASIO sample formats, and the conversion to and from them.
#include <sonore/asio_format.h>- 25other declarations
- Guides: Platforms and formats
On this page
Design notes
Why this is its own header
audio_asio.h is entirely inside #if defined(_WIN32), because a driver vtable reached through CoCreateInstance cannot mean anything anywhere else. The FORMAT CONVERSION is not like that. It is integer arithmetic, it is the part most likely to be subtly wrong, and it is the part that produces a full-scale buzz rather than an error message when it is. Leaving it inside the guard would mean the only machine able to test it is the only machine with the hardware -- which is the same as saying it is never tested.
So it lives here, compiled everywhere, exercised by the round-trip test on both legs of the gate. audio_asio.h includes this and calls into it; there is one copy of each conversion, and the copy is the one under test.
No Steinberg code. The type CODES are numbers stated in the published ASIO documentation -- the same category of fact as an HTTP status code -- and everything else here is written from the format names.
Functions 8
- fn
inline bool formatIsSupported(long type)Whether this build converts that format at all.asio::formatIsSupported · asio_format.h:52 - fn
inline size_t formatBytes(long type)How many bytes one sample of that format occupies in a driver buffer.asio::formatBytes · asio_format.h:59 - fn
inline float formatScale(long type)The full-scale magnitude of the integer formats.asio::formatScale · asio_format.h:77More
The Lsb16/18/20/24 variants are the awkward ones: a 32-bit container holding a smaller word, RIGHT-aligned. An interface that reports kAsioInt32Lsb24 wants 24 bits of range in a 32-bit slot, and writing 32 bits into it is 256x too loud -- which is not distortion, it is a number that wraps every few samples.
- fn
inline void writeSamples(void* destination, long type, const float* source, size_t stride, size_t frames)A run of float samples into a driver buffer:framesof them, readstridefloats apart fromsource(2 for one side of interleaved stereo), written to frames 0..frames-1 ofdestinationin the driver's format.asio::writeSamples · asio_format.h:128More
Clamped before conversion, not after. A sample above full scale wraps to the opposite sign when it is truncated into an integer, and a wrap is a full-scale click rather than the clipping a listener would forgive.
The scale is (max + 1) and the written value uses (max), so +1.0 lands on the largest representable positive rather than one past it. The asymmetry is real and is in every fixed-point audio format: there is one more negative code than positive.
A RUN, because that is what the buffer switch converts: two channels each way, a block each. It went through writeSample one sample at a time, which picked the format again for every sample and kept nothing in a register from one to the next: 1.6 to 1.9 ns a sample, seven times what the standalone spends on a whole 256-frame block around a DSP that does nothing. Here the format is picked once and each loop is that format's arithmetic alone. writeSample is a run of one, so this is still the only copy of each conversion.
- fn
inline void readSamples(const void* source, long type, float* destination, size_t stride, size_t frames)The exact inverse, a run at a time: frames 0..frames-1 of a driver buffer out as floats, writtenasio::readSamples · asio_format.h:176strideapart intodestination. A format this build does not convert reads as silence, not garbage. - fn
inline void writeSample(void* destination, size_t i, long type, float v)One float sample into a driver buffer, at frameasio::writeSample · asio_format.h:224i: a run of one (see writeSamples, for the clamp and the scale). - fn
inline float readSample(const void* source, size_t i, long type)The exact inverse: one sample of a driver buffer back out as a float.asio::readSample · asio_format.h:229 - fn
inline long hostMessageReply(long selector, long value, bool* wantsReset)What a host answers to the driver's asioMessage(selector, value).asio::hostMessageReply · asio_format.h:278More
wantsResetis set when the driver asked for the stream to be rebuilt -- the caller tears down and reopens on its own thread, never inside this callback, which may arrive on the driver's.- ResetRequest: supported. The driver will not apply its change until we reopen it, so saying yes and doing nothing is what hangs a control panel.
- BufferSizeChange: NOT supported, on purpose. Answering 0 is what the interface specifies for a host that cannot resize live, and a driver that gets it falls back to ResetRequest -- the path we do support.
- ResyncRequest: acknowledged. It invalidates the driver's timestamps, and nothing here reads them.
- LatenciesChanged: acknowledged; latencies are asked for when needed, never cached.
- SupportsTimeInfo / TimeCode: no. We register bufferSwitch, not bufferSwitchTimeInfo, and saying yes would make the driver call the null one.
Constants 17
- const
kAsioInt16Lsb = 16The sample formats a driver may hand back.asio::kAsioInt16Lsb · asio_format.h:40More
Only the little-endian ones that exist on real hardware are named. A big endian ASIO driver is a PowerPC-era Mac artefact, and float64 is in the specification but not on any interface you can buy; both are refused BY NAME in formatIsSupported rather than converted wrongly, because a wrong conversion is audible and an honest refusal is not.
- const
kAsioInt24Lsb = 17The sample formats a driver may hand back.asio::kAsioInt24Lsb · asio_format.h:41More
Only the little-endian ones that exist on real hardware are named. A big endian ASIO driver is a PowerPC-era Mac artefact, and float64 is in the specification but not on any interface you can buy; both are refused BY NAME in formatIsSupported rather than converted wrongly, because a wrong conversion is audible and an honest refusal is not.
- const
kAsioInt32Lsb = 18The sample formats a driver may hand back.asio::kAsioInt32Lsb · asio_format.h:42More
Only the little-endian ones that exist on real hardware are named. A big endian ASIO driver is a PowerPC-era Mac artefact, and float64 is in the specification but not on any interface you can buy; both are refused BY NAME in formatIsSupported rather than converted wrongly, because a wrong conversion is audible and an honest refusal is not.
- const
kAsioFloat32Lsb = 19The sample formats a driver may hand back.asio::kAsioFloat32Lsb · asio_format.h:43More
Only the little-endian ones that exist on real hardware are named. A big endian ASIO driver is a PowerPC-era Mac artefact, and float64 is in the specification but not on any interface you can buy; both are refused BY NAME in formatIsSupported rather than converted wrongly, because a wrong conversion is audible and an honest refusal is not.
- const
kAsioFloat64Lsb = 20The sample formats a driver may hand back.asio::kAsioFloat64Lsb · asio_format.h:44More
Only the little-endian ones that exist on real hardware are named. A big endian ASIO driver is a PowerPC-era Mac artefact, and float64 is in the specification but not on any interface you can buy; both are refused BY NAME in formatIsSupported rather than converted wrongly, because a wrong conversion is audible and an honest refusal is not.
- const
kAsioInt32Lsb16 = 21The sample formats a driver may hand back.asio::kAsioInt32Lsb16 · asio_format.h:45More
Only the little-endian ones that exist on real hardware are named. A big endian ASIO driver is a PowerPC-era Mac artefact, and float64 is in the specification but not on any interface you can buy; both are refused BY NAME in formatIsSupported rather than converted wrongly, because a wrong conversion is audible and an honest refusal is not.
- const
kAsioInt32Lsb18 = 22The sample formats a driver may hand back.asio::kAsioInt32Lsb18 · asio_format.h:46More
Only the little-endian ones that exist on real hardware are named. A big endian ASIO driver is a PowerPC-era Mac artefact, and float64 is in the specification but not on any interface you can buy; both are refused BY NAME in formatIsSupported rather than converted wrongly, because a wrong conversion is audible and an honest refusal is not.
- const
kAsioInt32Lsb20 = 23The sample formats a driver may hand back.asio::kAsioInt32Lsb20 · asio_format.h:47More
Only the little-endian ones that exist on real hardware are named. A big endian ASIO driver is a PowerPC-era Mac artefact, and float64 is in the specification but not on any interface you can buy; both are refused BY NAME in formatIsSupported rather than converted wrongly, because a wrong conversion is audible and an honest refusal is not.
- const
kAsioInt32Lsb24 = 24The sample formats a driver may hand back.asio::kAsioInt32Lsb24 · asio_format.h:48More
Only the little-endian ones that exist on real hardware are named. A big endian ASIO driver is a PowerPC-era Mac artefact, and float64 is in the specification but not on any interface you can buy; both are refused BY NAME in formatIsSupported rather than converted wrongly, because a wrong conversion is audible and an honest refusal is not.
- const
kAsioSelectorSupported = 1asio::kAsioSelectorSupported · asio_format.h:248 - const
kAsioEngineVersion = 2asio::kAsioEngineVersion · asio_format.h:249 - const
kAsioResetRequest = 3asio::kAsioResetRequest · asio_format.h:250 - const
kAsioBufferSizeChange = 4asio::kAsioBufferSizeChange · asio_format.h:251 - const
kAsioResyncRequest = 5asio::kAsioResyncRequest · asio_format.h:252 - const
kAsioLatenciesChanged = 6asio::kAsioLatenciesChanged · asio_format.h:253 - const
kAsioSupportsTimeInfo = 7asio::kAsioSupportsTimeInfo · asio_format.h:254 - const
kAsioSupportsTimeCode = 8asio::kAsioSupportsTimeCode · asio_format.h:255