Skip to content

Support all 18 ASIO PCM sample types - #649

Open
L0FKA wants to merge 1 commit into
mdias:masterfrom
L0FKA:feat/more-asio-sample-formats
Open

L0FKA wants to merge 1 commit into
mdias:masterfrom
L0FKA:feat/more-asio-sample-formats

Conversation

@L0FKA

@L0FKA L0FKA commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Support all 18 ASIO PCM sample types

Drivers whose native sample type is big-endian (ASIOST*MSB) or a 32-bit container with fewer valid bits
(ASIOSTInt32{LSB,MSB}{16,18,20,24}) are refused today with "ASIO sample type N is not currently supported".
Only five LSB types work. This adds the other thirteen PCM types. DSD and unknown types are still refused.

What changes

  • Conversion: a scalar codec handles byte order, container width, valid bits and sign extension, with clamped
    float<->int conversion (NaN becomes 0). It only fills conversion pairs that have no converter today. The five
    existing LSB types keep their current kernels, so output on common hardware is unchanged.
  • Sizes: GetAsioSampleTypeNumBytes returns the container size for all 18 types. Before, channels of the new
    types were skipped before conversion.
  • Format negotiation: a driver type is accepted when converters exist in both directions. IEEE-float game formats
    are still accepted only on float hardware, so integer interfaces keep integer game formats as before.
  • Failure handling:
    • CopyConvertFormat returns false for a missing converter (it returned true and wrote nothing).
    • Render and capture write silence for a channel whose conversion fails, instead of leaving stale samples.
    • The size check no longer rejects ASIOSTInt16MSB, which is enum value 0.
  • Logging: one line per client at init gives the game format, ASIO type, container size, and whether the path is a
    straight copy or a conversion. Example:
    Render conversion: game tag=65534 ... bits=32 valid bits=24 channels=2 ASIO=ASIOSTInt32LSB container bytes=4 path=identical-type copy ASIOSTInt32LSB -> ASIOSTInt32LSB

Testing

  • Offline: a standalone test (not added to the solution) covered all 18x18 pairs: round trips against independent
    reference encoders, strides with canary bytes, dirty container padding, exact byte order, NaN/Inf clamping, and
    DSD/unknown refusal. That is 99,883 checks. A deliberately wrong byte order fails it, as a control.

Not tested: none of the 13 new types on real hardware; I don't have such an interface. Reports from users with
big-endian or 32-bit-container drivers would be very welcome. (Im sure its sound mathematically but there might be interface-related quirks, etc)

Drivers whose native type is big-endian or a 32-bit container with 16/18/20/24
valid bits were refused. Add a generic scalar codec (byte order, container
width, valid bits, sign extension, clamped float<->int with NaN -> 0) that fills
only the conversion cells the existing kernels leave empty; the existing five
LSB types keep their current kernels.

- GetAsioSampleTypeNumBytes returns the container size for all 18 types, so
  their channels are no longer skipped. DSD and unknown types stay refused.
- IsWaveFormatSupported accepts a native type when converters exist both ways.
  IEEE float game formats are still accepted only on float hardware.
- CopyConvertFormat returns false for a missing converter (it returned true),
  and the size check no longer rejects ASIOSTInt16MSB (enum value 0).
- Render and capture write silence for a channel whose conversion fails.
- Log one line per client at init: game format, ASIO type, container size, and
  whether it is a straight copy or a conversion.
@mdias

mdias commented Oct 26, 2026

Copy link
Copy Markdown
Owner

This one is not good. Code doesn't seem to be optimal or easily human readable.
For instance, you pay the full price of 2 endianness conversions, byte by byte, even if the interface is already talking the same endianness as your CPU.

@L0FKA

L0FKA commented Oct 26, 2026

Copy link
Copy Markdown
Contributor Author

Game and upstream modern ASIO devices wont use more than 5 types realistically so this would pand as a dead code... or just a proof "we can". If Idea is not entierly foreign - let me review the code again to see if I can make it pretty and efficient. Game side wants PCM 16/24/32 or even float32 (wdm side, yes I have direct replacement coded for wdm<>paASIO backend).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants