Audio¶
TinyUSB supports USB Audio Class 1.0 and 2.0 streaming in device and host roles.
Device driver¶
The descriptors define the topology, formats, channels, rates, controls, and alternate settings; the application supplies or consumes the audio samples.
Start from an example¶
Audio descriptors and buffer sizes are tightly coupled. Copy the closest example, confirm that it enumerates, and then change one property at a time:
Audio Test Microphone – one-channel UAC2 microphone;
Audio 4-Channel Microphone – four-channel microphone;
USB Speaker with Feedback – speaker with feedback;
USB Audio Headset – bidirectional headset;
Audio Multi-Rate Microphone – UAC1 at full speed, UAC2 at high speed, with multiple rates.
Configuration¶
Set CFG_TUD_AUDIO to the number of audio functions, at most three. The
principal options are:
Option |
Default |
What it controls |
|---|---|---|
|
|
Largest class control payload, such as a RANGE or channel-cluster response. Increase it to fit the largest advertised control. |
|
|
Enables microphone/device-to-host streaming. |
|
|
Enables speaker/host-to-device streaming. |
|
Required per enabled direction |
Maximum endpoint packet size across that function’s alternate settings. |
|
|
Software FIFO size. Required for each enabled direction; a value below
the maximum endpoint size (the default |
|
|
Adapts IN packet consumption to the FIFO fill level to reduce underruns/overruns. |
|
|
Enables an explicit feedback endpoint, normally required by an asynchronous speaker. |
|
|
Enables the AudioControl interrupt endpoint for status notifications. |
For each enabled direction, define the maximum endpoint size used by any
advertised alternate setting, for example
CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX. A software FIFO such as
CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ must be at least that large. Use
TUD_AUDIO_EP_SIZE() as the examples do; high-speed audio has more service
intervals per millisecond than full-speed audio.
Data path¶
Operation |
Main API |
|---|---|
|
Tests whether function zero is configured and returns its Audio Class version, read from the AudioControl interface descriptor. |
|
Reports and removes speaker bytes from the OUT software FIFO. The read count can be shorter than requested. |
|
Copies microphone bytes into the IN software FIFO and returns the number written. When the FIFO is full the oldest unsent bytes are overwritten, so pace writes to the stream. |
|
Discards queued samples in the selected endpoint FIFO, useful when a streaming alternate setting closes. |
|
Returns the underlying FIFO object for advanced zero-copy or DMA integration; the application must preserve its invariants. |
|
Supplies the feedback value for one audio function when application feedback mode is used. Pass 16.16 samples per frame at full speed, or per microframe at high speed. UAC1 functions send it as 3-byte 10.14; UAC2 functions always send 4-byte 16.16. |
|
Updates internally calculated feedback from elapsed master-clock cycles and returns the current 16.16 value, or zero on error. |
|
Selects a function explicitly with |
The host starts and stops a stream by selecting interface alternate settings.
Use tud_audio_set_itf_cb() and tud_audio_set_itf_close_ep_cb() to start
or stop the application-side I2S/DMA path. Do not produce or consume samples
merely because the device is mounted; wait until the streaming interface is
active.
tud_audio_feedback_interval_isr() runs in interrupt context from the SOF
handler. The optional tud_audio_rx_done_isr() and
tud_audio_tx_done_isr() callbacks usually run in interrupt context but may
run in the context of the call that arms the endpoint; see Using Device Classes.
Control requests¶
Implement the tud_audio_get_req_*_cb() and tud_audio_set_req_*_cb()
callbacks for every control advertised by the descriptors, such as clock
frequency, clock validity, mute, and volume. A descriptor that advertises a
control but stalls its normal requests is likely to be rejected or behave
poorly on a host.
Asynchronous speakers normally need a feedback endpoint. Enable
CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP and either configure the feedback method
through tud_audio_feedback_params_cb() or provide feedback with
tud_audio_n_fb_set(). Begin with the speaker-feedback example; incorrect
feedback causes periodic underruns or overruns even when the nominal sample
rates match.
Specifications used: USB Device Class Definition for Audio Devices, Release 1.0 and Release 2.0, plus Audio Data Formats, Release 2.0.
Host driver¶
The host driver discovers one playback stream and one capture stream in each
supported AudioControl function. It presents each usable alternate setting
and discrete sample rate as a complete format, sample_rate, and
channels configuration. The application selects one of these tuples;
TinyUSB manages interface alternate settings, endpoints, packet sizing, and
explicit feedback.
Start from USB Audio Host Example. It discovers configurations, selects signed 16-bit capture and playback streams, and cycles through microphone, speaker, and loopback operation.
Configuration¶
Set CFG_TUH_AUDIO to enable the driver. The principal options are:
Option |
Default |
What it controls |
|---|---|---|
|
|
Enables the Audio host class. A nonzero value includes the driver. |
|
UAC1 |
Bitmask of |
|
|
Maximum number of mounted AudioControl functions. |
|
|
Maximum number of nonzero-bandwidth alternate settings retained per logical stream. |
|
|
Maximum discrete sample rates retained per UAC1 alternate setting or UAC2 Clock Source. |
|
|
Largest capture/playback packet the driver can submit. Capture
alternate settings whose |
|
|
Per-stream FIFO depth. Playback sends silence when a complete packet is unavailable; capture overwrites the oldest complete frames when the FIFO is full. |
Increase the endpoint buffers for high channel counts, sample rates, or sample widths. All buffers are statically allocated, so these maxima directly affect RAM use.
Stream lifecycle¶
After tuh_audio_mount_cb(), enumerate stream indices from zero through
tuh_audio_stream_count() - 1. Use tuh_audio_stream_direction() to
distinguish TUH_AUDIO_STREAM_PLAYBACK (host to device) from
TUH_AUDIO_STREAM_CAPTURE (device to host). Then enumerate the stream’s
configurations with tuh_audio_config_count() and
tuh_audio_config_get().
For each stream:
Call
tuh_audio_configure()with a supported configuration index while the stream is stopped.Call
tuh_audio_start(). Atruereturn means that startup was submitted, not that it completed.Wait for
TUH_AUDIO_EVENT_START_COMPLETEintuh_audio_event_cb()and check that its transfer result is successful before handling samples.Use the non-blocking frame FIFO APIs while the stream runs.
Call
tuh_audio_stop()and wait forTUH_AUDIO_EVENT_STOP_COMPLETEbefore reconfiguring the stream.
Capture and playback streams in the same AudioControl function must use the
same sample rate while they run concurrently. tuh_audio_active_config()
returns TUSB_INDEX_INVALID_8 when no configuration is selected.
Audio data is counted in frames, not bytes. One frame contains one sample for
every channel; obtain its byte size with tuh_audio_config_frame_size().
tuh_audio_read() removes whole frames from a capture FIFO, while
tuh_audio_write() queues whole frames for playback. Their return values
may be shorter than requested. Use tuh_audio_read_available() and
tuh_audio_write_available() to service the FIFOs from the application task;
the transfer callbacks are notifications and need not drive FIFO servicing.
If the capture FIFO overflows while a task other than the one running
tuh_task() reads it, a read can mix old and new samples; keep up with
capture.
Callbacks and failures¶
tuh_audio_descriptor_cb() runs during enumeration, before the mount
callback. Its descriptor pointers are valid only during the call. Copy any
entity IDs or descriptor fields needed for later raw controls, but do not
submit control transfers from this callback.
tuh_audio_capture_cb() and tuh_audio_playback_cb() report successful
isochronous transfers. tuh_audio_event_cb() reports asynchronous start and
stop completion and TUH_AUDIO_EVENT_XFER_FAILED. A failed stream has been
stopped; the application may reconfigure or restart it. Clear all saved
indices and associated state in tuh_audio_umount_cb() because an index may
be reused by a later device.
Run tuh_task() continuously. Isochronous transfers follow the endpoint’s
polling interval, and delaying the host task can exhaust the FIFO even when its
average producer and consumer rates match.
Feature Unit controls¶
The driver discovers master mute and volume capabilities before the mount
callback. Test mute with tuh_audio_mute_supported() and retrieve the
cached volume range with tuh_audio_volume_range_get(). Volume values use
signed 1/256 dB units; TUH_AUDIO_VOLUME_SILENCE represents silence, and
TUH_AUDIO_CHANNEL_MASTER selects the master channel.
The asynchronous tuh_audio_mute_*() and tuh_audio_volume_*() APIs use
a completion callback. Their synchronous helpers block until completion and
should only be used while audio streaming is stopped; synchronous transfers
can disrupt isochronous traffic. Use tuh_audio_control_xfer() for other
class-specific entity controls. Buffers passed to asynchronous controls must
remain valid until their completion callbacks run.
Supported formats and limitations¶
The host accepts Type-I PCM in signed 8-, 16-, packed 24-, 24-in-32-, and 32-bit little-endian formats. UAC1 descriptors must list discrete sample rates; continuous ranges are not supported. UAC2 requires a directly connected Clock Source. Clock Selectors, Clock Multipliers, Sampling Rate Converters, Clock Validity, and Valid Alternate Settings controls are not handled.
Explicit feedback endpoints using 10.14 or 16.16 values are supported.
Implicit-feedback IN endpoints are treated as ordinary capture endpoints and
do not pace playback. MaxPacketsOnly endpoints are not supported: OUT
packets are not padded to wMaxPacketSize, and padding in IN packets is not
removed from the captured data.