Skip to content

Commit 4ba746b

Browse files
audio driver interface
1 parent f5d381b commit 4ba746b

File tree

5 files changed

+450
-110
lines changed

5 files changed

+450
-110
lines changed

include/audio.h

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
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);

include/kernel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
#include "serial.h"
8686
#include "debug_ringbuffer.h"
8787
#include "module.h"
88+
#include "audio.h"
8889

8990
#define assert(expr, message) if (!(expr)) { \
9091
kprintf("Assertion failure at %s:%d: %s\n", __FILE__, __LINE__, message); \

0 commit comments

Comments
 (0)