# `tecs.platform.audionative` The `tecsaudio` binding behind the audio backend contract. Loading this module loads `libtecsaudio` through `tecs.internal.nativelibrary`, so a build that cannot find the library raises here rather than anywhere later. `tecs.audio` requires it through `pcall` for exactly that reason and falls back to `tecs.platform.audiobackend.silent` when it is absent. Commands cross as one contiguous C array per flush and finished voices come back as a second one. Nothing in the library ever calls a Nupp function: a `cpal` output callback runs on a thread the Lua virtual machine never created, and entering Nupp from there is undefined. Every observation is therefore pulled by `drain` from the frame thread instead, which is why this binding declares no function pointer anywhere. ```nupp local backend = assert(tecs.platform.audionative.open(48000, 2, 32)) ``` ## Functions ### `devices` _function_ ```nupp function devices(): audiobackend.Devices ``` Returns the device provider backed by the library. Building it opens nothing and lists nothing: every call on the returned record reaches the platform, and none of them runs here. That matters because listing devices goes through the same platform machinery an open goes through, so resolving a provider has to stay clear of it. #### Returns | Type | Description | | --- | --- | | `audiobackend.Devices` | a provider naming the platform's devices and opening its microphones | ### `offlineDevices` _function_ ```nupp function offlineDevices(): audiobackend.Devices ``` Returns a provider whose captures touch no recording device. Its listings are empty, and `open` answers with a capture whose frames the caller supplies through `write`. This is what a test that has to prove the capture seam reaches for, and it is deliberately not what `tecs.audio` resolves: opening a real recording device can block inside the platform's audio daemon, and a headless suite must not be able to. #### Returns | Type | Description | | --- | --- | | `audiobackend.Devices` | a provider naming no devices and opening device-free captures | ### `open` _function_ ```nupp function open(frequency: integer, channels: integer, maxVoices: integer): audiobackend.Backend?, string? ``` Opens the platform's default output and returns it as a backend. #### Arguments | Name | Type | Description | | --- | --- | --- | | `frequency` | `integer` | the requested output frequency in frames per second | | `channels` | `integer` | the requested number of output channels | | `maxVoices` | `integer` | the greatest number of voices the mixer holds at once | #### Returns | Type | Description | | --- | --- | | `audiobackend.Backend?` | the backend, or nil when the library opened nothing | | `string?` | the reason, when the first return is nil | ### `openOffline` _function_ ```nupp function openOffline(frequency: integer, channels: integer, maxVoices: integer): audiobackend.Backend?, string? ``` Opens a backend that touches no output device. Every command still crosses and every query still answers; the mix goes nowhere unless the caller renders it, which nothing on this side does. This is what a test that has to prove the seam without needing a sound card reaches for, and it is deliberately not what `tecs.audio` opens: opening a real output can block inside the platform's audio daemon, and a headless suite must not be able to. #### Arguments | Name | Type | Description | | --- | --- | --- | | `frequency` | `integer` | the output frequency in frames per second | | `channels` | `integer` | the number of output channels | | `maxVoices` | `integer` | the greatest number of voices the mixer holds at once | #### Returns | Type | Description | | --- | --- | | `audiobackend.Backend?` | the backend, or nil when the library refused | | `string?` | the reason, when the first return is nil |