|
| 1 | +/** |
| 2 | + * @file audio.h |
| 3 | + * @author Craig Edwards |
| 4 | + * @copyright Copyright (c) 2012–2025 |
| 5 | + * @brief Minimal audio device abstraction for Retro Rocket. |
| 6 | + * |
| 7 | + * Provides a tiny, device-agnostic API for pushing interleaved stereo |
| 8 | + * S16LE frames to an output, querying the current sample rate, pausing, |
| 9 | + * resuming, and reporting buffered time. All frame counts refer to |
| 10 | + * **stereo frames** (L+R), not individual samples. |
| 11 | + */ |
| 12 | +#pragma once |
| 13 | +#include <kernel.h> |
| 14 | + |
| 15 | +/** |
| 16 | + * @brief Callback: enqueue interleaved S16LE stereo frames (non-blocking). |
| 17 | + * |
| 18 | + * Implementations should accept as many frames as possible immediately and |
| 19 | + * return the number actually taken (which may be less than requested). |
| 20 | + * |
| 21 | + * @param frames Pointer to interleaved S16LE frames (L,R). |
| 22 | + * @param total_frames Number of stereo frames to enqueue. |
| 23 | + * @return Number of frames accepted this call. |
| 24 | + */ |
| 25 | +typedef size_t (*audio_push_t)(const int16_t *frames, size_t total_frames); |
| 26 | + |
| 27 | +/** |
| 28 | + * @brief Callback: query the device’s current output rate in Hz. |
| 29 | + * @return Active sample rate (e.g., 44100 or 48000). |
| 30 | + */ |
| 31 | +typedef uint32_t (*audio_freq_t)(void); |
| 32 | + |
| 33 | +/** |
| 34 | + * @brief Callback: immediate stop and clear of all buffered audio. |
| 35 | + */ |
| 36 | +typedef void (*audio_stop_t)(void); |
| 37 | + |
| 38 | +/** |
| 39 | + * @brief Callback: pause output without clearing buffers. |
| 40 | + */ |
| 41 | +typedef void (*audio_pause_t)(void); |
| 42 | + |
| 43 | +/** |
| 44 | + * @brief Callback: resume output after a pause. |
| 45 | + */ |
| 46 | +typedef void (*audio_resume_t)(void); |
| 47 | + |
| 48 | +/** |
| 49 | + * @brief Callback: total buffered audio time (software queue + DMA) in ms. |
| 50 | + * @return Milliseconds of audio ahead of the DAC. |
| 51 | + */ |
| 52 | +typedef uint32_t (*audio_length_t)(void); |
| 53 | + |
| 54 | +/** @brief Maximum length (including NUL) for an audio device’s display name. */ |
| 55 | +#define MAX_AUDIO_DEVICE_NAME 32 |
| 56 | + |
| 57 | +/** |
| 58 | + * @brief Registered audio device descriptor. |
| 59 | + * |
| 60 | + * Drivers populate one of these and register it with the audio subsystem. |
| 61 | + * The list of devices is kept as an intrusive singly-linked list via @ref next. |
| 62 | + * |
| 63 | + * @note PCM format is S16LE, interleaved (L,R,L,R,…). All counts are frames. |
| 64 | + */ |
| 65 | +typedef struct audio_device_t { |
| 66 | + /** Driver-specific context pointer (may be NULL). */ |
| 67 | + void *opaque; |
| 68 | + |
| 69 | + /** Human-readable device name (NUL-terminated, max @ref MAX_AUDIO_DEVICE_NAME). */ |
| 70 | + char name[MAX_AUDIO_DEVICE_NAME]; |
| 71 | + |
| 72 | + /** Non-blocking PCM enqueue (S16LE stereo frames). */ |
| 73 | + audio_push_t play; |
| 74 | + |
| 75 | + /** Current output sample rate in Hz. */ |
| 76 | + audio_freq_t frequency; |
| 77 | + |
| 78 | + /** Immediate stop + clear of queued/buffered data. */ |
| 79 | + audio_stop_t stop; |
| 80 | + |
| 81 | + /** Pause output (retain queued/buffered data). */ |
| 82 | + audio_pause_t pause; |
| 83 | + |
| 84 | + /** Resume output after pause. */ |
| 85 | + audio_resume_t resume; |
| 86 | + |
| 87 | + /** Buffered time (software queue + DMA in flight) in milliseconds. */ |
| 88 | + audio_length_t queue_length; |
| 89 | + |
| 90 | + /** Next device in the global list. */ |
| 91 | + struct audio_device_t *next; |
| 92 | +} audio_device_t; |
| 93 | + |
| 94 | +/** |
| 95 | + * @brief Register a new audio device. |
| 96 | + * |
| 97 | + * Inserts @p newdev into the global device list. The caller retains ownership |
| 98 | + * of the storage; the struct must remain valid for the lifetime of the device. |
| 99 | + * |
| 100 | + * @param newdev Pointer to the device descriptor to register (must not be NULL). |
| 101 | + * @return true on success, false on failure. |
| 102 | + */ |
| 103 | +bool register_audio_device(audio_device_t *newdev); |
| 104 | + |
| 105 | +/** |
| 106 | + * @brief Find a registered audio device by name. |
| 107 | + * |
| 108 | + * @param name NUL-terminated device name to search for. |
| 109 | + * @return Pointer to the matching device, or NULL if not found. |
| 110 | + */ |
| 111 | +audio_device_t *find_audio_device(const char *name); |
| 112 | + |
| 113 | +/** |
| 114 | + * @brief Get the first registered audio device, if any. |
| 115 | + * @return Pointer to the first device in the list, or NULL if none. |
| 116 | + */ |
| 117 | +audio_device_t *find_first_audio_device(void); |
0 commit comments