summaryrefslogtreecommitdiff
path: root/examples/host/audio_host/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'examples/host/audio_host/README.md')
-rw-r--r--examples/host/audio_host/README.md122
1 files changed, 122 insertions, 0 deletions
diff --git a/examples/host/audio_host/README.md b/examples/host/audio_host/README.md
new file mode 100644
index 000000000..7f72aabaf
--- /dev/null
+++ b/examples/host/audio_host/README.md
@@ -0,0 +1,122 @@
+# USB Audio Host Example
+
+This example demonstrates how to use TinyUSB's USB Audio Host driver (TUH_AUDIO) to capture audio from a UAC 1.0 or UAC 2.0 USB microphone and echo it back to the speaker, using a WASAPI/ALSA-like high-level API. The application never touches USB interfaces, alternate settings, or endpoint addresses — it only selects supported `{format, sample_rate, channels}` configurations by stream index.
+
+## Features
+
+- Enumerates and mounts USB Audio Class 1.0 and 2.0 devices
+- Discovers the device's logical streams (capture/playback) and their supported configurations (discrete tuples only)
+- Reports each stream's mute/volume capabilities and cached volume range
+- Configures and starts an S16_LE capture stream (44.1 kHz preferred, 48 kHz fallback; stereo preferred, mono accepted)
+- Echoes captured audio to an S16_LE playback stream at the same sample rate (same channel count preferred, mono/stereo conversion otherwise)
+- Frame-based FIFO API: the main loop reads capture when its FIFO is half full and fills playback when its FIFO is half drained; USB transfer callbacks are not used for FIFO servicing
+- Cycles the streams through three phases (5 s each): mic-only (capture, data dropped), spk-only (sine test tone), and echo (capture looped back to playback)
+
+## Supported Devices
+
+This example supports UAC1 devices whose Type I Format descriptor lists discrete sampling frequencies (`bSamFreqType > 0`) and UAC2 devices using a directly connected Clock Source, such as:
+
+- USB microphones
+- USB headsets (mono microphone + speaker)
+- USB audio interfaces
+
+The echo needs a matching S16_LE playback stream at the capture sample rate; devices without one run capture-only. The sample rate and channel preferences are configured by the `SAMPLE_RATES` / `AUDIO_MAX_CHANNELS` macros in `src/audio_app.c` (44.1 kHz stereo by default). Non-PCM formats are rejected by the driver.
+
+## Limitations and trade-offs
+
+- Explicit feedback endpoints are supported with both 10.14 and 16.16 feedback values. An implicit-feedback IN endpoint is treated as an ordinary audio-data endpoint and is not used to pace playback.
+- UAC1 Type I Format descriptors with `bSamFreqType == 0` are unsupported; the driver requires a list of discrete sampling frequencies.
+- UAC2 supports direct Clock Sources. Clock Selectors, Clock Multipliers, Sampling Rate Converters, Clock Validity, and Valid Alternate Settings controls are not handled.
+- UAC2 sampling-frequency RANGE responses are expanded into at most `CFG_TUH_AUDIO_MAX_SAM_FREQ` discrete configurations. A read-only Clock Source exposes only its current frequency.
+- Master mute and volume controls are discovered before the mount callback. A Feature Unit with volume only on its logical channels is also supported: the range is read from the first controlled channel, and a stream-volume SET writes every logical channel when no writable master control exists. The typed API assumes all logical channels share one range; applications needing different per-channel ranges can use the raw control API. UAC2 volume discovery supports the common RANGE response containing one subrange.
+- The `MaxPacketsOnly` endpoint attribute is not supported. OUT transfers are not padded to `wMaxPacketSize`, and padding in IN transfers is not removed from the reported audio data.
+
+## Building
+
+### Using CMake (recommended)
+
+```bash
+cd examples/host/audio_host
+mkdir -p build && cd build
+cmake -DBOARD=<your_board> -G Ninja ..
+cmake --build .
+```
+
+Replace `<your_board>` with your target board name (e.g., `raspberry_pi_pico`, `stm32f407disco`, etc.)
+
+### Using Make
+
+```bash
+cd examples/host/audio_host
+make BOARD=<your_board> all
+```
+
+## Flashing
+
+```bash
+# Using CMake: list the board-specific flash targets, then select one
+ninja -t targets
+ninja audio_host-jlink # example for a board with J-Link support
+
+# Using Make
+make BOARD=<your_board> flash
+```
+
+## Usage
+
+1. Build and flash the example to your board
+2. Connect a USB Audio device (UAC 1.0 or 2.0) to the USB host port
+3. Open a serial terminal to view output
+4. The example will:
+ - Print each stream's mute/volume capabilities, cached volume range, and supported configurations when mounted
+ - Look for an S16_LE capture configuration at a preferred sample rate (44.1 kHz first, 48 kHz fallback; stereo preferred, mono accepted) and configure it
+ - Echo captured audio to an S16_LE playback configuration at the same sample rate (same channel count preferred, converted otherwise)
+ - Read/unmute the microphone and speaker Feature Units and set supported stream volumes near -6 dB; a channel-only Feature Unit is updated one logical channel at a time
+ - Service both FIFOs from `audio_app_task()` at their half-full/half-drained watermarks; a sine test tone plays on the playback stream when no capture stream is echoing
+ - Cycle through the three phases (mic-only / spk-only / echo, 5 s each) with `tuh_audio_start()` / `tuh_audio_stop()`; their asynchronous results are printed from `tuh_audio_event_cb()`, and a failed stream is restarted automatically after 100 ms
+
+## Serial Output Example
+
+```
+TinyUSB Host USB Audio Example
+Connect a USB Audio Device (UAC 1.0 or 2.0) to test
+Audio device mounted: idx=0 addr=1
+ capture stream 1, configurations: 2
+ master mute supported
+ volume range: min=-23040 max=1536 res=256 (1/256 dB)
+ [0] format=1 rate=44100 channels=2
+ [1] format=1 rate=48000 channels=2
+ playback stream 0, configurations: 2
+ master mute supported
+ volume range: min=-23040 max=1536 res=256 (1/256 dB)
+ [0] format=1 rate=44100 channels=2
+ [1] format=1 rate=48000 channels=2
+ Configuring 44100 S16_LE capture (2 channels)
+ Microphone configured
+ Microphone master mute: off
+ Microphone master volume: 0 (1/256 dB)
+ Microphone volume set: -1536 (1/256 dB)
+ Configuring 44100 S16_LE playback (2 channels)
+ Speaker configured
+ Speaker master mute: off
+ Speaker master volume: 0 (1/256 dB)
+ Speaker volume set: -1536 (1/256 dB)
+```
+
+## Configuration
+
+Edit `src/tusb_config.h` to modify:
+- `CFG_TUH_AUDIO_MAX`: Maximum number of audio devices supported
+- `CFG_TUH_AUDIO_PROTOCOLS`: Bitmask selecting UAC1 and/or UAC2 support; the example enables both
+- `CFG_TUH_AUDIO_MAX_SAM_FREQ`: Maximum number of discrete frequencies retained per alternate setting or UAC2 Clock Source
+- `CFG_TUH_AUDIO_EPIN_BUFSIZE`: Maximum size of one capture transfer the driver submits (configurations needing a larger per-poll-interval packet are rejected)
+- `CFG_TUH_AUDIO_EPOUT_BUFSIZE`: Maximum size of one playback transfer the driver submits
+- `CFG_TUH_AUDIO_STREAM_BUFSIZE`: Per-stream FIFO depth in bytes (default 1024, i.e. four 256 B packets); capture overwrites the oldest frames when full
+
+## Notes
+
+- `tuh_audio_descriptor_cb()` exposes the validated Audio Control descriptor block during enumeration. Applications that need raw entity controls must copy the required entity IDs or descriptor fields before the callback returns, then use `tuh_audio_control_xfer()` after the device mounts.
+- While a stream is running, the driver keeps one isochronous transfer in flight and re-submits on completion, so transfers follow the endpoint's `bInterval`. `tuh_audio_capture_cb()` / `tuh_audio_playback_cb()` only count completed transfers; `audio_app_task()` services the FIFOs independently from the main loop. `tuh_audio_event_cb()` reports asynchronous start/stop results and unrecoverable transfer failures. The example restarts a failed stream automatically 100 ms later.
+- Capture and playback streams running concurrently in the same Audio Control instance must use the same sample rate.
+- `tuh_audio_read()` / `tuh_audio_write()` are non-blocking FIFO operations: they return the number of whole frames actually read/queued. `tuh_audio_read_available()` reports captured frames ready to read; `tuh_audio_write_available()` reports free playback capacity. `tuh_audio_write()` only queues data; the playback transfer-completion chain sends it, or sends silence when the FIFO does not contain a complete polling interval without consuming the partial data.
+- Isochronous transfers require the host to poll `tuh_task()` continuously; the capture FIFO absorbs short scheduling gaps and overwrites the oldest frames when full.