@@ -54,6 +54,9 @@ typedef uint32_t (*audio_length_t)(void);
5454/** @brief Maximum length (including NUL) for an audio device’s display name. */
5555#define MAX_AUDIO_DEVICE_NAME 32
5656
57+ /** @brief Opaque channel handle. */
58+ typedef struct mixer_stream mixer_stream_t ;
59+
5760/**
5861 * @brief Registered audio device descriptor.
5962 *
@@ -95,23 +98,93 @@ typedef struct audio_device_t {
9598 * @brief Register a new audio device.
9699 *
97100 * 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.
101+ * of the storage; the struct must remain valid for the lifetime of the device
99102 *
100- * @param newdev Pointer to the device descriptor to register (must not be NULL).
103+ * @param newdev Pointer to the device descriptor to register (must not be NULL)
101104 * @return true on success, false on failure.
102105 */
103106bool register_audio_device (audio_device_t * newdev );
104107
105108/**
106- * @brief Find a registered audio device by name.
109+ * @brief Find a registered audio device by name
107110 *
108- * @param name NUL-terminated device name to search for.
109- * @return Pointer to the matching device, or NULL if not found.
111+ * @param name NUL-terminated device name to search for
112+ * @return Pointer to the matching device, or NULL if not found
110113 */
111114audio_device_t * find_audio_device (const char * name );
112115
113116/**
114- * @brief Get the first registered audio device, if any.
115- * @return Pointer to the first device in the list, or NULL if none.
117+ * @brief Get the first registered audio device, if any
118+ * @return Pointer to the first device in the list, or NULL if none
116119 */
117120audio_device_t * find_first_audio_device (void );
121+
122+ /**
123+ * @brief Initialise the mixer and register the idle tick
124+ *
125+ * Consumes queued frames from all active channels, applies gain/mute,
126+ * mixes them with 32-bit accumulation using SSE2, clips to 16-bit,
127+ * and pushes the result to the first audio device until the desired
128+ * latency is met. This is the sole hot path of the software mixer.
129+ *
130+ * @param dev Audio device to attach the mixer to
131+ * @param target_latency_ms Desired steady-state output latency in ms
132+ * @param idle_period_ms Foreground idle period in ms (mix cadence)
133+ * @param max_channels Maximum number of concurrently open channels
134+ * @return true on success, false if no audio device or allocation failed
135+ */
136+ bool mixer_init (audio_device_t * dev , uint32_t target_latency_ms , uint32_t idle_period_ms , uint32_t max_channels );
137+
138+ /**
139+ * @brief Open a channel slot for a producer
140+ *
141+ * Single producer per channel, the mixer is the sole consumer
142+ * @return Channel handle or NULL if none available
143+ */
144+ mixer_stream_t * mixer_create_stream (void );
145+
146+ /**
147+ * @brief Close a channel (drains remaining data then frees the slot)
148+ */
149+ void mixer_free_stream (mixer_stream_t * ch );
150+
151+ /**
152+ * @brief Submit interleaved S16LE stereo frames to a channel (non-blocking)
153+ *
154+ * Identical signature and semantics to audio_push_t; returns frames accepted
155+ */
156+ size_t mixer_push (mixer_stream_t * ch , const int16_t * frames , size_t total_frames );
157+
158+ /**
159+ * @brief Set per-channel gain (Q8.8; 256 == 1.0).
160+ */
161+ void mixer_set_gain (mixer_stream_t * ch , uint16_t q8_8_gain );
162+
163+ /**
164+ * @brief Mute/unmute a channel; muted channels do not contribute to the mix.
165+ */
166+ void mixer_set_mute (mixer_stream_t * ch , bool mute );
167+
168+ /**
169+ * @brief Query frames currently queued in a channel ring.
170+ */
171+ uint32_t mixer_stream_queue_length (mixer_stream_t * ch );
172+
173+ /**
174+ * @brief Return the audio device used by the mixer (first device) or NULL.
175+ */
176+ audio_device_t * mixer_device (void );
177+
178+ /**
179+ * @brief Foreground idle callback to drive the mixer.
180+ *
181+ * Called periodically by the process idle scheduler to top up the
182+ * output device with freshly mixed audio. Consumes queued frames
183+ * from all active mixer channels, applies gain/mute, and pushes
184+ * the mixed stream to the first audio device until the desired
185+ * latency is reached.
186+ *
187+ * This function is not intended to be called directly; it is
188+ * registered with @ref proc_register_idle by @ref mixer_init.
189+ */
190+ void mixer_idle (void );
0 commit comments