@samitouri / QOSamiQemu / commits / 2842da1dc0

audio: split AudioMixengBackend code in audio-mixeng-be.c

Allow to build the audio/ base classes without the resampling/mixing/queuing code. Reviewed-by: Mark Cave-Ayland <mark.caveayland@nutanix.com> Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Marc-André Lureau committed Nov 10, 2025 at 15:02 UTC 2842da1dc0c18fb5aa17660f13949d4c635ba0c9
6 files changed +2158 -2048
audio/audio-be.c
+2
@@ -5,6 +5,7 @@
5 #include "qemu/audio-capture.h"
6 #include "qapi/error.h"
7 #include "trace.h"
8 +#include "qapi-types-audio.h"
9
10 bool audio_be_check(AudioBackend **be, Error **errp)
11 {
@@ -248,6 +249,7 @@ AudioBackend *audio_be_new(Audiodev *dev, Error **errp)
249
250 if (!be) {
251 error_setg(errp, "Unknown audio driver `%s'", drvname);
252 + qapi_free_Audiodev(dev);
253 return NULL;
254 }
255
audio/audio-mixeng-be.c new
+1976
@@ -0,0 +1,1976 @@
1 +/*
2 + * SPDX-License-Identifier: MIT
3 + *
4 + * Copyright (c) 2003-2005 Vassili Karpov (malc)
5 + */
6 +
7 +#include "qemu/osdep.h"
8 +#include "qemu/audio.h"
9 +#include "migration/vmstate.h"
10 +#include "qemu/bswap.h"
11 +#include "qemu/timer.h"
12 +#include "qapi/error.h"
13 +#include "qapi/clone-visitor.h"
14 +#include "qapi/qobject-input-visitor.h"
15 +#include "qapi/qapi-visit-audio.h"
16 +#include "qapi/qapi-commands-audio.h"
17 +#include "qobject/qdict.h"
18 +#include "qemu/error-report.h"
19 +#include "qemu/log.h"
20 +#include "qemu/module.h"
21 +#include "qemu/help_option.h"
22 +#include "qom/object.h"
23 +#include "system/system.h"
24 +#include "system/replay.h"
25 +#include "system/runstate.h"
26 +#include "trace.h"
27 +
28 +#define AUDIO_CAP "audio"
29 +#include "audio_int.h"
30 +
31 +/* #define DEBUG_OUT */
32 +/* #define DEBUG_CAPTURE */
33 +/* #define DEBUG_POLL */
34 +
35 +#define SW_NAME(sw) (sw)->name ? (sw)->name : "unknown"
36 +
37 +const struct mixeng_volume nominal_volume = {
38 + .mute = 0,
39 +#ifdef FLOAT_MIXENG
40 + .r = 1.0,
41 + .l = 1.0,
42 +#else
43 + .r = 1ULL << 32,
44 + .l = 1ULL << 32,
45 +#endif
46 +};
47 +
48 +int audio_bug (const char *funcname, int cond)
49 +{
50 + if (cond) {
51 + static int shown;
52 +
53 + AUD_log (NULL, "A bug was just triggered in %s\n", funcname);
54 + if (!shown) {
55 + shown = 1;
56 + AUD_log (NULL, "Save all your work and restart without audio\n");
57 + AUD_log (NULL, "I am sorry\n");
58 + }
59 + AUD_log (NULL, "Context:\n");
60 + }
61 +
62 + return cond;
63 +}
64 +
65 +static inline int audio_bits_to_index (int bits)
66 +{
67 + switch (bits) {
68 + case 8:
69 + return 0;
70 +
71 + case 16:
72 + return 1;
73 +
74 + case 32:
75 + return 2;
76 +
77 + default:
78 + audio_bug ("bits_to_index", 1);
79 + AUD_log (NULL, "invalid bits %d\n", bits);
80 + return 0;
81 + }
82 +}
83 +
84 +void AUD_vlog (const char *cap, const char *fmt, va_list ap)
85 +{
86 + if (cap) {
87 + fprintf(stderr, "%s: ", cap);
88 + }
89 +
90 + vfprintf(stderr, fmt, ap);
91 +}
92 +
93 +void AUD_log (const char *cap, const char *fmt, ...)
94 +{
95 + va_list ap;
96 +
97 + va_start (ap, fmt);
98 + AUD_vlog (cap, fmt, ap);
99 + va_end (ap);
100 +}
101 +
102 +static void audio_print_settings (const struct audsettings *as)
103 +{
104 + dolog ("frequency=%d nchannels=%d fmt=", as->freq, as->nchannels);
105 +
106 + switch (as->fmt) {
107 + case AUDIO_FORMAT_S8:
108 + AUD_log (NULL, "S8");
109 + break;
110 + case AUDIO_FORMAT_U8:
111 + AUD_log (NULL, "U8");
112 + break;
113 + case AUDIO_FORMAT_S16:
114 + AUD_log (NULL, "S16");
115 + break;
116 + case AUDIO_FORMAT_U16:
117 + AUD_log (NULL, "U16");
118 + break;
119 + case AUDIO_FORMAT_S32:
120 + AUD_log (NULL, "S32");
121 + break;
122 + case AUDIO_FORMAT_U32:
123 + AUD_log (NULL, "U32");
124 + break;
125 + case AUDIO_FORMAT_F32:
126 + AUD_log (NULL, "F32");
127 + break;
128 + default:
129 + AUD_log (NULL, "invalid(%d)", as->fmt);
130 + break;
131 + }
132 +
133 + AUD_log (NULL, " endianness=");
134 + switch (as->endianness) {
135 + case 0:
136 + AUD_log (NULL, "little");
137 + break;
138 + case 1:
139 + AUD_log (NULL, "big");
140 + break;
141 + default:
142 + AUD_log (NULL, "invalid");
143 + break;
144 + }
145 + AUD_log (NULL, "\n");
146 +}
147 +
148 +static int audio_validate_settings (const struct audsettings *as)
149 +{
150 + int invalid;
151 +
152 + invalid = as->nchannels < 1;
153 + invalid |= as->endianness != 0 && as->endianness != 1;
154 +
155 + switch (as->fmt) {
156 + case AUDIO_FORMAT_S8:
157 + case AUDIO_FORMAT_U8:
158 + case AUDIO_FORMAT_S16:
159 + case AUDIO_FORMAT_U16:
160 + case AUDIO_FORMAT_S32:
161 + case AUDIO_FORMAT_U32:
162 + case AUDIO_FORMAT_F32:
163 + break;
164 + default:
165 + invalid = 1;
166 + break;
167 + }
168 +
169 + invalid |= as->freq <= 0;
170 + return invalid ? -1 : 0;
171 +}
172 +
173 +static int audio_pcm_info_eq (struct audio_pcm_info *info, const struct audsettings *as)
174 +{
175 + int bits = 8;
176 + bool is_signed = false, is_float = false;
177 +
178 + switch (as->fmt) {
179 + case AUDIO_FORMAT_S8:
180 + is_signed = true;
181 + /* fall through */
182 + case AUDIO_FORMAT_U8:
183 + break;
184 +
185 + case AUDIO_FORMAT_S16:
186 + is_signed = true;
187 + /* fall through */
188 + case AUDIO_FORMAT_U16:
189 + bits = 16;
190 + break;
191 +
192 + case AUDIO_FORMAT_F32:
193 + is_float = true;
194 + /* fall through */
195 + case AUDIO_FORMAT_S32:
196 + is_signed = true;
197 + /* fall through */
198 + case AUDIO_FORMAT_U32:
199 + bits = 32;
200 + break;
201 +
202 + default:
203 + abort();
204 + }
205 + return info->freq == as->freq
206 + && info->nchannels == as->nchannels
207 + && info->is_signed == is_signed
208 + && info->is_float == is_float
209 + && info->bits == bits
210 + && info->swap_endianness == (as->endianness != HOST_BIG_ENDIAN);
211 +}
212 +
213 +void audio_pcm_init_info (struct audio_pcm_info *info, const struct audsettings *as)
214 +{
215 + int bits = 8, mul;
216 + bool is_signed = false, is_float = false;
217 +
218 + switch (as->fmt) {
219 + case AUDIO_FORMAT_S8:
220 + is_signed = true;
221 + /* fall through */
222 + case AUDIO_FORMAT_U8:
223 + mul = 1;
224 + break;
225 +
226 + case AUDIO_FORMAT_S16:
227 + is_signed = true;
228 + /* fall through */
229 + case AUDIO_FORMAT_U16:
230 + bits = 16;
231 + mul = 2;
232 + break;
233 +
234 + case AUDIO_FORMAT_F32:
235 + is_float = true;
236 + /* fall through */
237 + case AUDIO_FORMAT_S32:
238 + is_signed = true;
239 + /* fall through */
240 + case AUDIO_FORMAT_U32:
241 + bits = 32;
242 + mul = 4;
243 + break;
244 +
245 + default:
246 + abort();
247 + }
248 +
249 + info->freq = as->freq;
250 + info->bits = bits;
251 + info->is_signed = is_signed;
252 + info->is_float = is_float;
253 + info->nchannels = as->nchannels;
254 + info->bytes_per_frame = as->nchannels * mul;
255 + info->bytes_per_second = info->freq * info->bytes_per_frame;
256 + info->swap_endianness = (as->endianness != HOST_BIG_ENDIAN);
257 +}
258 +
259 +void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
260 +{
261 + if (!len) {
262 + return;
263 + }
264 +
265 + if (info->is_signed || info->is_float) {
266 + memset(buf, 0x00, len * info->bytes_per_frame);
267 + } else {
268 + switch (info->bits) {
269 + case 8:
270 + memset(buf, 0x80, len * info->bytes_per_frame);
271 + break;
272 +
273 + case 16:
274 + {
275 + int i;
276 + uint16_t *p = buf;
277 + short s = INT16_MAX;
278 +
279 + if (info->swap_endianness) {
280 + s = bswap16 (s);
281 + }
282 +
283 + for (i = 0; i < len * info->nchannels; i++) {
284 + p[i] = s;
285 + }
286 + }
287 + break;
288 +
289 + case 32:
290 + {
291 + int i;
292 + uint32_t *p = buf;
293 + int32_t s = INT32_MAX;
294 +
295 + if (info->swap_endianness) {
296 + s = bswap32 (s);
297 + }
298 +
299 + for (i = 0; i < len * info->nchannels; i++) {
300 + p[i] = s;
301 + }
302 + }
303 + break;
304 +
305 + default:
306 + AUD_log (NULL, "audio_pcm_info_clear_buf: invalid bits %d\n",
307 + info->bits);
308 + break;
309 + }
310 + }
311 +}
312 +
313 +/*
314 + * Capture
315 + */
316 +static CaptureVoiceOut *audio_pcm_capture_find_specific(AudioMixengBackend *s,
317 + struct audsettings *as)
318 +{
319 + CaptureVoiceOut *cap;
320 +
321 + for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) {
322 + if (audio_pcm_info_eq (&cap->hw.info, as)) {
323 + return cap;
324 + }
325 + }
326 + return NULL;
327 +}
328 +
329 +static void audio_notify_capture (CaptureVoiceOut *cap, audcnotification_e cmd)
330 +{
331 + struct capture_callback *cb;
332 +
333 +#ifdef DEBUG_CAPTURE
334 + dolog ("notification %d sent\n", cmd);
335 +#endif
336 + for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
337 + cb->ops.notify (cb->opaque, cmd);
338 + }
339 +}
340 +
341 +static void audio_capture_maybe_changed(CaptureVoiceOut *cap, bool enabled)
342 +{
343 + if (cap->hw.enabled != enabled) {
344 + audcnotification_e cmd;
345 + cap->hw.enabled = enabled;
346 + cmd = enabled ? AUD_CNOTIFY_ENABLE : AUD_CNOTIFY_DISABLE;
347 + audio_notify_capture (cap, cmd);
348 + }
349 +}
350 +
351 +static void audio_recalc_and_notify_capture (CaptureVoiceOut *cap)
352 +{
353 + HWVoiceOut *hw = &cap->hw;
354 + SWVoiceOut *sw;
355 + bool enabled = false;
356 +
357 + for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
358 + if (sw->active) {
359 + enabled = true;
360 + break;
361 + }
362 + }
363 + audio_capture_maybe_changed (cap, enabled);
364 +}
365 +
366 +static void audio_detach_capture (HWVoiceOut *hw)
367 +{
368 + SWVoiceCap *sc = hw->cap_head.lh_first;
369 +
370 + while (sc) {
371 + SWVoiceCap *sc1 = sc->entries.le_next;
372 + SWVoiceOut *sw = &sc->sw;
373 + CaptureVoiceOut *cap = sc->cap;
374 + int was_active = sw->active;
375 +
376 + if (sw->rate) {
377 + st_rate_stop (sw->rate);
378 + sw->rate = NULL;
379 + }
380 +
381 + QLIST_REMOVE (sw, entries);
382 + QLIST_REMOVE (sc, entries);
383 + g_free (sc);
384 + if (was_active) {
385 + /* We have removed soft voice from the capture:
386 + this might have changed the overall status of the capture
387 + since this might have been the only active voice */
388 + audio_recalc_and_notify_capture (cap);
389 + }
390 + sc = sc1;
391 + }
392 +}
393 +
394 +static int audio_attach_capture (HWVoiceOut *hw)
395 +{
396 + AudioMixengBackend *s = hw->s;
397 + CaptureVoiceOut *cap;
398 +
399 + audio_detach_capture (hw);
400 + for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) {
401 + SWVoiceCap *sc;
402 + SWVoiceOut *sw;
403 + HWVoiceOut *hw_cap = &cap->hw;
404 +
405 + sc = g_malloc0(sizeof(*sc));
406 +
407 + sc->cap = cap;
408 + sw = &sc->sw;
409 + sw->hw = hw_cap;
410 + sw->info = hw->info;
411 + sw->empty = true;
412 + sw->active = hw->enabled;
413 + sw->vol = nominal_volume;
414 + sw->rate = st_rate_start (sw->info.freq, hw_cap->info.freq);
415 + QLIST_INSERT_HEAD (&hw_cap->sw_head, sw, entries);
416 + QLIST_INSERT_HEAD (&hw->cap_head, sc, entries);
417 +#ifdef DEBUG_CAPTURE
418 + sw->name = g_strdup_printf ("for %p %d,%d,%d",
419 + hw, sw->info.freq, sw->info.bits,
420 + sw->info.nchannels);
421 + dolog ("Added %s active = %d\n", sw->name, sw->active);
422 +#endif
423 + if (sw->active) {
424 + audio_capture_maybe_changed (cap, 1);
425 + }
426 + }
427 + return 0;
428 +}
429 +
430 +/*
431 + * Hard voice (capture)
432 + */
433 +static size_t audio_pcm_hw_find_min_in (HWVoiceIn *hw)
434 +{
435 + SWVoiceIn *sw;
436 + size_t m = hw->total_samples_captured;
437 +
438 + for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
439 + if (sw->active) {
440 + m = MIN (m, sw->total_hw_samples_acquired);
441 + }
442 + }
443 + return m;
444 +}
445 +
446 +static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw)
447 +{
448 + size_t live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw);
449 + if (audio_bug(__func__, live > hw->conv_buf.size)) {
450 + dolog("live=%zu hw->conv_buf.size=%zu\n", live, hw->conv_buf.size);
451 + return 0;
452 + }
453 + return live;
454 +}
455 +
456 +static size_t audio_pcm_hw_conv_in(HWVoiceIn *hw, void *pcm_buf, size_t samples)
457 +{
458 + size_t conv = 0;
459 + STSampleBuffer *conv_buf = &hw->conv_buf;
460 +
461 + while (samples) {
462 + uint8_t *src = advance(pcm_buf, conv * hw->info.bytes_per_frame);
463 + size_t proc = MIN(samples, conv_buf->size - conv_buf->pos);
464 +
465 + hw->conv(conv_buf->buffer + conv_buf->pos, src, proc);
466 + conv_buf->pos = (conv_buf->pos + proc) % conv_buf->size;
467 + samples -= proc;
468 + conv += proc;
469 + }
470 +
471 + return conv;
472 +}
473 +
474 +/*
475 + * Soft voice (capture)
476 + */
477 +static void audio_pcm_sw_resample_in(SWVoiceIn *sw,
478 + size_t frames_in_max, size_t frames_out_max,
479 + size_t *total_in, size_t *total_out)
480 +{
481 + HWVoiceIn *hw = sw->hw;
482 + struct st_sample *src, *dst;
483 + size_t live, rpos, frames_in, frames_out;
484 +
485 + live = hw->total_samples_captured - sw->total_hw_samples_acquired;
486 + rpos = audio_ring_posb(hw->conv_buf.pos, live, hw->conv_buf.size);
487 +
488 + /* resample conv_buf from rpos to end of buffer */
489 + src = hw->conv_buf.buffer + rpos;
490 + frames_in = MIN(frames_in_max, hw->conv_buf.size - rpos);
491 + dst = sw->resample_buf.buffer;
492 + frames_out = frames_out_max;
493 + st_rate_flow(sw->rate, src, dst, &frames_in, &frames_out);
494 + rpos += frames_in;
495 + *total_in = frames_in;
496 + *total_out = frames_out;
497 +
498 + /* resample conv_buf from start of buffer if there are input frames left */
499 + if (frames_in_max - frames_in && rpos == hw->conv_buf.size) {
500 + src = hw->conv_buf.buffer;
501 + frames_in = frames_in_max - frames_in;
502 + dst += frames_out;
503 + frames_out = frames_out_max - frames_out;
504 + st_rate_flow(sw->rate, src, dst, &frames_in, &frames_out);
505 + *total_in += frames_in;
506 + *total_out += frames_out;
507 + }
508 +}
509 +
510 +static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t buf_len)
511 +{
512 + HWVoiceIn *hw = sw->hw;
513 + size_t live, frames_out_max, total_in, total_out;
514 +
515 + live = hw->total_samples_captured - sw->total_hw_samples_acquired;
516 + if (!live) {
517 + return 0;
518 + }
519 + if (audio_bug(__func__, live > hw->conv_buf.size)) {
520 + dolog("live_in=%zu hw->conv_buf.size=%zu\n", live, hw->conv_buf.size);
521 + return 0;
522 + }
523 +
524 + frames_out_max = MIN(buf_len / sw->info.bytes_per_frame,
525 + sw->resample_buf.size);
526 +
527 + audio_pcm_sw_resample_in(sw, live, frames_out_max, &total_in, &total_out);
528 +
529 + if (!hw->pcm_ops->volume_in) {
530 + mixeng_volume(sw->resample_buf.buffer, total_out, &sw->vol);
531 + }
532 + sw->clip(buf, sw->resample_buf.buffer, total_out);
533 +
534 + sw->total_hw_samples_acquired += total_in;
535 + return total_out * sw->info.bytes_per_frame;
536 +}
537 +
538 +/*
539 + * Hard voice (playback)
540 + */
541 +static size_t audio_pcm_hw_find_min_out (HWVoiceOut *hw, int *nb_livep)
542 +{
543 + SWVoiceOut *sw;
544 + size_t m = SIZE_MAX;
545 + int nb_live = 0;
546 +
547 + for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
548 + if (sw->active || !sw->empty) {
549 + m = MIN (m, sw->total_hw_samples_mixed);
550 + nb_live += 1;
551 + }
552 + }
553 +
554 + *nb_livep = nb_live;
555 + return m;
556 +}
557 +
558 +static size_t audio_pcm_hw_get_live_out (HWVoiceOut *hw, int *nb_live)
559 +{
560 + size_t smin;
561 + int nb_live1;
562 +
563 + smin = audio_pcm_hw_find_min_out (hw, &nb_live1);
564 + if (nb_live) {
565 + *nb_live = nb_live1;
566 + }
567 +
568 + if (nb_live1) {
569 + size_t live = smin;
570 +
571 + if (audio_bug(__func__, live > hw->mix_buf.size)) {
572 + dolog("live=%zu hw->mix_buf.size=%zu\n", live, hw->mix_buf.size);
573 + return 0;
574 + }
575 + return live;
576 + }
577 + return 0;
578 +}
579 +
580 +static size_t audio_pcm_hw_get_free(HWVoiceOut *hw)
581 +{
582 + return (hw->pcm_ops->buffer_get_free ? hw->pcm_ops->buffer_get_free(hw) :
583 + INT_MAX) / hw->info.bytes_per_frame;
584 +}
585 +
586 +static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len)
587 +{
588 + size_t clipped = 0;
589 + size_t pos = hw->mix_buf.pos;
590 +
591 + while (len) {
592 + st_sample *src = hw->mix_buf.buffer + pos;
593 + uint8_t *dst = advance(pcm_buf, clipped * hw->info.bytes_per_frame);
594 + size_t samples_till_end_of_buf = hw->mix_buf.size - pos;
595 + size_t samples_to_clip = MIN(len, samples_till_end_of_buf);
596 +
597 + hw->clip(dst, src, samples_to_clip);
598 +
599 + pos = (pos + samples_to_clip) % hw->mix_buf.size;
600 + len -= samples_to_clip;
601 + clipped += samples_to_clip;
602 + }
603 +}
604 +
605 +/*
606 + * Soft voice (playback)
607 + */
608 +static void audio_pcm_sw_resample_out(SWVoiceOut *sw,
609 + size_t frames_in_max, size_t frames_out_max,
610 + size_t *total_in, size_t *total_out)
611 +{
612 + HWVoiceOut *hw = sw->hw;
613 + struct st_sample *src, *dst;
614 + size_t live, wpos, frames_in, frames_out;
615 +
616 + live = sw->total_hw_samples_mixed;
617 + wpos = (hw->mix_buf.pos + live) % hw->mix_buf.size;
618 +
619 + /* write to mix_buf from wpos to end of buffer */
620 + src = sw->resample_buf.buffer;
621 + frames_in = frames_in_max;
622 + dst = hw->mix_buf.buffer + wpos;
623 + frames_out = MIN(frames_out_max, hw->mix_buf.size - wpos);
624 + st_rate_flow_mix(sw->rate, src, dst, &frames_in, &frames_out);
625 + wpos += frames_out;
626 + *total_in = frames_in;
627 + *total_out = frames_out;
628 +
629 + /* write to mix_buf from start of buffer if there are input frames left */
630 + if (frames_in_max - frames_in > 0 && wpos == hw->mix_buf.size) {
631 + src += frames_in;
632 + frames_in = frames_in_max - frames_in;
633 + dst = hw->mix_buf.buffer;
634 + frames_out = frames_out_max - frames_out;
635 + st_rate_flow_mix(sw->rate, src, dst, &frames_in, &frames_out);
636 + *total_in += frames_in;
637 + *total_out += frames_out;
638 + }
639 +}
640 +
641 +static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t buf_len)
642 +{
643 + HWVoiceOut *hw = sw->hw;
644 + size_t live, dead, hw_free, sw_max, fe_max;
645 + size_t frames_in_max, frames_out_max, total_in, total_out;
646 +
647 + live = sw->total_hw_samples_mixed;
648 + if (audio_bug(__func__, live > hw->mix_buf.size)) {
649 + dolog("live=%zu hw->mix_buf.size=%zu\n", live, hw->mix_buf.size);
650 + return 0;
651 + }
652 +
653 + if (live == hw->mix_buf.size) {
654 +#ifdef DEBUG_OUT
655 + dolog ("%s is full %zu\n", sw->name, live);
656 +#endif
657 + return 0;
658 + }
659 +
660 + dead = hw->mix_buf.size - live;
661 + hw_free = audio_pcm_hw_get_free(hw);
662 + hw_free = hw_free > live ? hw_free - live : 0;
663 + frames_out_max = MIN(dead, hw_free);
664 + sw_max = st_rate_frames_in(sw->rate, frames_out_max);
665 + fe_max = MIN(buf_len / sw->info.bytes_per_frame + sw->resample_buf.pos,
666 + sw->resample_buf.size);
667 + frames_in_max = MIN(sw_max, fe_max);
668 +
669 + if (!frames_in_max) {
670 + return 0;
671 + }
672 +
673 + if (frames_in_max > sw->resample_buf.pos) {
674 + sw->conv(sw->resample_buf.buffer + sw->resample_buf.pos,
675 + buf, frames_in_max - sw->resample_buf.pos);
676 + if (!sw->hw->pcm_ops->volume_out) {
677 + mixeng_volume(sw->resample_buf.buffer + sw->resample_buf.pos,
678 + frames_in_max - sw->resample_buf.pos, &sw->vol);
679 + }
680 + }
681 +
682 + audio_pcm_sw_resample_out(sw, frames_in_max, frames_out_max,
683 + &total_in, &total_out);
684 +
685 + sw->total_hw_samples_mixed += total_out;
686 + sw->empty = sw->total_hw_samples_mixed == 0;
687 +
688 + /*
689 + * Upsampling may leave one audio frame in the resample buffer. Decrement
690 + * total_in by one if there was a leftover frame from the previous resample
691 + * pass in the resample buffer. Increment total_in by one if the current
692 + * resample pass left one frame in the resample buffer.
693 + */
694 + if (frames_in_max - total_in == 1) {
695 + /* copy one leftover audio frame to the beginning of the buffer */
696 + *sw->resample_buf.buffer = *(sw->resample_buf.buffer + total_in);
697 + total_in += 1 - sw->resample_buf.pos;
698 + sw->resample_buf.pos = 1;
699 + } else if (total_in >= sw->resample_buf.pos) {
700 + total_in -= sw->resample_buf.pos;
701 + sw->resample_buf.pos = 0;
702 + }
703 +
704 +#ifdef DEBUG_OUT
705 + dolog (
706 + "%s: write size %zu written %zu total mixed %zu\n",
707 + SW_NAME(sw),
708 + buf_len / sw->info.bytes_per_frame,
709 + total_in,
710 + sw->total_hw_samples_mixed
711 + );
712 +#endif
713 +
714 + return total_in * sw->info.bytes_per_frame;
715 +}
716 +
717 +#ifdef DEBUG_AUDIO
718 +static void audio_pcm_print_info (const char *cap, struct audio_pcm_info *info)
719 +{
720 + dolog("%s: bits %d, sign %d, float %d, freq %d, nchan %d\n",
721 + cap, info->bits, info->is_signed, info->is_float, info->freq,
722 + info->nchannels);
723 +}
724 +#endif
725 +
726 +#define DAC
727 +#include "audio_template.h"
728 +#undef DAC
729 +#include "audio_template.h"
730 +
731 +/*
732 + * Timer
733 + */
734 +static int audio_is_timer_needed(AudioMixengBackend *s)
735 +{
736 + HWVoiceIn *hwi = NULL;
737 + HWVoiceOut *hwo = NULL;
738 +
739 + while ((hwo = audio_pcm_hw_find_any_enabled_out(s, hwo))) {
740 + if (!hwo->poll_mode) {
741 + return 1;
742 + }
743 + }
744 + while ((hwi = audio_pcm_hw_find_any_enabled_in(s, hwi))) {
745 + if (!hwi->poll_mode) {
746 + return 1;
747 + }
748 + }
749 + return 0;
750 +}
751 +
752 +static void audio_reset_timer(AudioMixengBackend *s)
753 +{
754 + if (audio_is_timer_needed(s)) {
755 + timer_mod_anticipate_ns(s->ts,
756 + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->period_ticks);
757 + if (!s->timer_running) {
758 + s->timer_running = true;
759 + s->timer_last = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
760 + trace_audio_timer_start(s->period_ticks / SCALE_MS);
761 + }
762 + } else {
763 + timer_del(s->ts);
764 + if (s->timer_running) {
765 + s->timer_running = false;
766 + trace_audio_timer_stop();
767 + }
768 + }
769 +}
770 +
771 +static void audio_timer (void *opaque)
772 +{
773 + int64_t now, diff;
774 + AudioMixengBackend *s = opaque;
775 +
776 + now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
777 + diff = now - s->timer_last;
778 + if (diff > s->period_ticks * 3 / 2) {
779 + trace_audio_timer_delayed(diff / SCALE_MS);
780 + }
781 + s->timer_last = now;
782 +
783 + audio_run(s, "timer");
784 + audio_reset_timer(s);
785 +}
786 +
787 +/*
788 + * Public API
789 + */
790 +static size_t audio_mixeng_backend_write(AudioBackend *be, SWVoiceOut *sw,
791 + void *buf, size_t size)
792 +{
793 + HWVoiceOut *hw;
794 +
795 + if (!sw) {
796 + /* XXX: Consider options */
797 + return size;
798 + }
799 + hw = sw->hw;
800 +
801 + if (!hw->enabled) {
802 + dolog("Writing to disabled voice %s\n", SW_NAME(sw));
803 + return 0;
804 + }
805 +
806 + if (audio_get_pdo_out(hw->s->dev)->mixing_engine) {
807 + return audio_pcm_sw_write(sw, buf, size);
808 + } else {
809 + return hw->pcm_ops->write(hw, buf, size);
810 + }
811 +}
812 +
813 +static size_t audio_mixeng_backend_read(AudioBackend *be,
814 + SWVoiceIn *sw, void *buf, size_t size)
815 +{
816 + HWVoiceIn *hw;
817 +
818 + if (!sw) {
819 + /* XXX: Consider options */
820 + return size;
821 + }
822 + hw = sw->hw;
823 +
824 + if (!hw->enabled) {
825 + dolog("Reading from disabled voice %s\n", SW_NAME(sw));
826 + return 0;
827 + }
828 +
829 + if (audio_get_pdo_in(hw->s->dev)->mixing_engine) {
830 + return audio_pcm_sw_read(sw, buf, size);
831 + } else {
832 + return hw->pcm_ops->read(hw, buf, size);
833 + }
834 +
835 +}
836 +
837 +static int audio_mixeng_backend_get_buffer_size_out(AudioBackend *be, SWVoiceOut *sw)
838 +{
839 + if (!sw) {
840 + return 0;
841 + }
842 +
843 + if (audio_get_pdo_out(sw->s->dev)->mixing_engine) {
844 + return sw->resample_buf.size * sw->info.bytes_per_frame;
845 + }
846 +
847 + return sw->hw->samples * sw->hw->info.bytes_per_frame;
848 +}
849 +
850 +static void audio_mixeng_backend_set_active_out(AudioBackend *be, SWVoiceOut *sw,
851 + bool on)
852 +{
853 + HWVoiceOut *hw;
854 +
855 + if (!sw) {
856 + return;
857 + }
858 +
859 + hw = sw->hw;
860 + if (sw->active != on) {
861 + AudioMixengBackend *s = sw->s;
862 + SWVoiceOut *temp_sw;
863 + SWVoiceCap *sc;
864 +
865 + if (on) {
866 + hw->pending_disable = 0;
867 + if (!hw->enabled) {
868 + hw->enabled = true;
869 + if (runstate_is_running()) {
870 + if (hw->pcm_ops->enable_out) {
871 + hw->pcm_ops->enable_out(hw, true);
872 + }
873 + audio_reset_timer (s);
874 + }
875 + }
876 + } else {
877 + if (hw->enabled) {
878 + int nb_active = 0;
879 +
880 + for (temp_sw = hw->sw_head.lh_first; temp_sw;
881 + temp_sw = temp_sw->entries.le_next) {
882 + nb_active += temp_sw->active != 0;
883 + }
884 +
885 + hw->pending_disable = nb_active == 1;
886 + }
887 + }
888 +
889 + for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {
890 + sc->sw.active = hw->enabled;
891 + if (hw->enabled) {
892 + audio_capture_maybe_changed (sc->cap, 1);
893 + }
894 + }
895 + sw->active = on;
896 + }
897 +
898 +}
899 +
900 +static void audio_mixeng_backend_set_active_in(AudioBackend *be, SWVoiceIn *sw, bool on)
901 +{
902 + HWVoiceIn *hw;
903 +
904 + if (!sw) {
905 + return;
906 + }
907 +
908 + hw = sw->hw;
909 + if (sw->active != on) {
910 + AudioMixengBackend *s = sw->s;
911 + SWVoiceIn *temp_sw;
912 +
913 + if (on) {
914 + if (!hw->enabled) {
915 + hw->enabled = true;
916 + if (runstate_is_running()) {
917 + if (hw->pcm_ops->enable_in) {
918 + hw->pcm_ops->enable_in(hw, true);
919 + }
920 + audio_reset_timer (s);
921 + }
922 + }
923 + sw->total_hw_samples_acquired = hw->total_samples_captured;
924 + } else {
925 + if (hw->enabled) {
926 + int nb_active = 0;
927 +
928 + for (temp_sw = hw->sw_head.lh_first; temp_sw;
929 + temp_sw = temp_sw->entries.le_next) {
930 + nb_active += temp_sw->active != 0;
931 + }
932 +
933 + if (nb_active == 1) {
934 + hw->enabled = false;
935 + if (hw->pcm_ops->enable_in) {
936 + hw->pcm_ops->enable_in(hw, false);
937 + }
938 + }
939 + }
940 + }
941 + sw->active = on;
942 + }
943 +}
944 +
945 +static size_t audio_get_avail(SWVoiceIn *sw)
946 +{
947 + size_t live;
948 +
949 + if (!sw) {
950 + return 0;
951 + }
952 +
953 + live = sw->hw->total_samples_captured - sw->total_hw_samples_acquired;
954 + if (audio_bug(__func__, live > sw->hw->conv_buf.size)) {
955 + dolog("live=%zu sw->hw->conv_buf.size=%zu\n", live,
956 + sw->hw->conv_buf.size);
957 + return 0;
958 + }
959 +
960 + ldebug (
961 + "%s: get_avail live %zu frontend frames %u\n",
962 + SW_NAME (sw),
963 + live, st_rate_frames_out(sw->rate, live)
964 + );
965 +
966 + return live;
967 +}
968 +
969 +static size_t audio_get_free(SWVoiceOut *sw)
970 +{
971 + size_t live, dead;
972 +
973 + if (!sw) {
974 + return 0;
975 + }
976 +
977 + live = sw->total_hw_samples_mixed;
978 +
979 + if (audio_bug(__func__, live > sw->hw->mix_buf.size)) {
980 + dolog("live=%zu sw->hw->mix_buf.size=%zu\n", live,
981 + sw->hw->mix_buf.size);
982 + return 0;
983 + }
984 +
985 + dead = sw->hw->mix_buf.size - live;
986 +
987 +#ifdef DEBUG_OUT
988 + dolog("%s: get_free live %zu dead %zu frontend frames %u\n",
989 + SW_NAME(sw), live, dead, st_rate_frames_in(sw->rate, dead));
990 +#endif
991 +
992 + return dead;
993 +}
994 +
995 +static void audio_capture_mix_and_clear(HWVoiceOut *hw, size_t rpos,
996 + size_t samples)
997 +{
998 + size_t n;
999 +
1000 + if (hw->enabled) {
1001 + SWVoiceCap *sc;
1002 +
1003 + for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {
1004 + SWVoiceOut *sw = &sc->sw;
1005 + size_t rpos2 = rpos;
1006 +
1007 + n = samples;
1008 + while (n) {
1009 + size_t till_end_of_hw = hw->mix_buf.size - rpos2;
1010 + size_t to_read = MIN(till_end_of_hw, n);
1011 + size_t live, frames_in, frames_out;
1012 +
1013 + sw->resample_buf.buffer = hw->mix_buf.buffer + rpos2;
1014 + sw->resample_buf.size = to_read;
1015 + live = sw->total_hw_samples_mixed;
1016 +
1017 + audio_pcm_sw_resample_out(sw,
1018 + to_read, sw->hw->mix_buf.size - live,
1019 + &frames_in, &frames_out);
1020 +
1021 + sw->total_hw_samples_mixed += frames_out;
1022 + sw->empty = sw->total_hw_samples_mixed == 0;
1023 +
1024 + if (to_read - frames_in) {
1025 + dolog("Could not mix %zu frames into a capture "
1026 + "buffer, mixed %zu\n",
1027 + to_read, frames_in);
1028 + break;
1029 + }
1030 + n -= to_read;
1031 + rpos2 = (rpos2 + to_read) % hw->mix_buf.size;
1032 + }
1033 + }
1034 + }
1035 +
1036 + n = MIN(samples, hw->mix_buf.size - rpos);
1037 + mixeng_clear(hw->mix_buf.buffer + rpos, n);
1038 + mixeng_clear(hw->mix_buf.buffer, samples - n);
1039 +}
1040 +
1041 +static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live)
1042 +{
1043 + size_t clipped = 0;
1044 +
1045 + while (live) {
1046 + size_t size = live * hw->info.bytes_per_frame;
1047 + size_t decr, proc;
1048 + void *buf = hw->pcm_ops->get_buffer_out(hw, &size);
1049 +
1050 + if (size == 0) {
1051 + break;
1052 + }
1053 +
1054 + decr = MIN(size / hw->info.bytes_per_frame, live);
1055 + if (buf) {
1056 + audio_pcm_hw_clip_out(hw, buf, decr);
1057 + }
1058 + proc = hw->pcm_ops->put_buffer_out(hw, buf,
1059 + decr * hw->info.bytes_per_frame) /
1060 + hw->info.bytes_per_frame;
1061 +
1062 + live -= proc;
1063 + clipped += proc;
1064 + hw->mix_buf.pos = (hw->mix_buf.pos + proc) % hw->mix_buf.size;
1065 +
1066 + if (proc == 0 || proc < decr) {
1067 + break;
1068 + }
1069 + }
1070 +
1071 + if (hw->pcm_ops->run_buffer_out) {
1072 + hw->pcm_ops->run_buffer_out(hw);
1073 + }
1074 +
1075 + return clipped;
1076 +}
1077 +
1078 +static void audio_run_out(AudioMixengBackend *s)
1079 +{
1080 + HWVoiceOut *hw = NULL;
1081 + SWVoiceOut *sw;
1082 +
1083 + while ((hw = audio_pcm_hw_find_any_enabled_out(s, hw))) {
1084 + size_t played, live, prev_rpos;
1085 + size_t hw_free = audio_pcm_hw_get_free(hw);
1086 + int nb_live;
1087 +
1088 + if (!audio_get_pdo_out(s->dev)->mixing_engine) {
1089 + /* there is exactly 1 sw for each hw with no mixeng */
1090 + sw = hw->sw_head.lh_first;
1091 +
1092 + if (hw->pending_disable) {
1093 + hw->enabled = false;
1094 + hw->pending_disable = false;
1095 + if (hw->pcm_ops->enable_out) {
1096 + hw->pcm_ops->enable_out(hw, false);
1097 + }
1098 + }
1099 +
1100 + if (sw->active) {
1101 + sw->callback.fn(sw->callback.opaque,
1102 + hw_free * sw->info.bytes_per_frame);
1103 + }
1104 +
1105 + if (hw->pcm_ops->run_buffer_out) {
1106 + hw->pcm_ops->run_buffer_out(hw);
1107 + }
1108 +
1109 + continue;
1110 + }
1111 +
1112 + for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
1113 + if (sw->active) {
1114 + size_t sw_free = audio_get_free(sw);
1115 + size_t free;
1116 +
1117 + if (hw_free > sw->total_hw_samples_mixed) {
1118 + free = st_rate_frames_in(sw->rate,
1119 + MIN(sw_free, hw_free - sw->total_hw_samples_mixed));
1120 + } else {
1121 + free = 0;
1122 + }
1123 + if (free > sw->resample_buf.pos) {
1124 + free = MIN(free, sw->resample_buf.size)
1125 + - sw->resample_buf.pos;
1126 + sw->callback.fn(sw->callback.opaque,
1127 + free * sw->info.bytes_per_frame);
1128 + }
1129 + }
1130 + }
1131 +
1132 + live = audio_pcm_hw_get_live_out (hw, &nb_live);
1133 + if (!nb_live) {
1134 + live = 0;
1135 + }
1136 +
1137 + if (audio_bug(__func__, live > hw->mix_buf.size)) {
1138 + dolog("live=%zu hw->mix_buf.size=%zu\n", live, hw->mix_buf.size);
1139 + continue;
1140 + }
1141 +
1142 + if (hw->pending_disable && !nb_live) {
1143 + SWVoiceCap *sc;
1144 +#ifdef DEBUG_OUT
1145 + dolog ("Disabling voice\n");
1146 +#endif
1147 + hw->enabled = false;
1148 + hw->pending_disable = false;
1149 + if (hw->pcm_ops->enable_out) {
1150 + hw->pcm_ops->enable_out(hw, false);
1151 + }
1152 + for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {
1153 + sc->sw.active = false;
1154 + audio_recalc_and_notify_capture (sc->cap);
1155 + }
1156 + continue;
1157 + }
1158 +
1159 + if (!live) {
1160 + if (hw->pcm_ops->run_buffer_out) {
1161 + hw->pcm_ops->run_buffer_out(hw);
1162 + }
1163 + continue;
1164 + }
1165 +
1166 + prev_rpos = hw->mix_buf.pos;
1167 + played = audio_pcm_hw_run_out(hw, live);
1168 + replay_audio_out(&played);
1169 + if (audio_bug(__func__, hw->mix_buf.pos >= hw->mix_buf.size)) {
1170 + dolog("hw->mix_buf.pos=%zu hw->mix_buf.size=%zu played=%zu\n",
1171 + hw->mix_buf.pos, hw->mix_buf.size, played);
1172 + hw->mix_buf.pos = 0;
1173 + }
1174 +
1175 +#ifdef DEBUG_OUT
1176 + dolog("played=%zu\n", played);
1177 +#endif
1178 +
1179 + if (played) {
1180 + audio_capture_mix_and_clear (hw, prev_rpos, played);
1181 + }
1182 +
1183 + for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
1184 + if (!sw->active && sw->empty) {
1185 + continue;
1186 + }
1187 +
1188 + if (audio_bug(__func__, played > sw->total_hw_samples_mixed)) {
1189 + dolog("played=%zu sw->total_hw_samples_mixed=%zu\n",
1190 + played, sw->total_hw_samples_mixed);
1191 + played = sw->total_hw_samples_mixed;
1192 + }
1193 +
1194 + sw->total_hw_samples_mixed -= played;
1195 +
1196 + if (!sw->total_hw_samples_mixed) {
1197 + sw->empty = true;
1198 + }
1199 + }
1200 + }
1201 +}
1202 +
1203 +static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples)
1204 +{
1205 + size_t conv = 0;
1206 +
1207 + if (hw->pcm_ops->run_buffer_in) {
1208 + hw->pcm_ops->run_buffer_in(hw);
1209 + }
1210 +
1211 + while (samples) {
1212 + size_t proc;
1213 + size_t size = samples * hw->info.bytes_per_frame;
1214 + void *buf = hw->pcm_ops->get_buffer_in(hw, &size);
1215 +
1216 + assert(size % hw->info.bytes_per_frame == 0);
1217 + if (size == 0) {
1218 + break;
1219 + }
1220 +
1221 + proc = audio_pcm_hw_conv_in(hw, buf, size / hw->info.bytes_per_frame);
1222 +
1223 + samples -= proc;
1224 + conv += proc;
1225 + hw->pcm_ops->put_buffer_in(hw, buf, proc * hw->info.bytes_per_frame);
1226 + }
1227 +
1228 + return conv;
1229 +}
1230 +
1231 +static void audio_run_in(AudioMixengBackend *s)
1232 +{
1233 + HWVoiceIn *hw = NULL;
1234 +
1235 + if (!audio_get_pdo_in(s->dev)->mixing_engine) {
1236 + while ((hw = audio_pcm_hw_find_any_enabled_in(s, hw))) {
1237 + /* there is exactly 1 sw for each hw with no mixeng */
1238 + SWVoiceIn *sw = hw->sw_head.lh_first;
1239 + if (sw->active) {
1240 + sw->callback.fn(sw->callback.opaque, INT_MAX);
1241 + }
1242 + }
1243 + return;
1244 + }
1245 +
1246 + while ((hw = audio_pcm_hw_find_any_enabled_in(s, hw))) {
1247 + SWVoiceIn *sw;
1248 + size_t captured = 0, min;
1249 + int pos;
1250 +
1251 + if (replay_mode != REPLAY_MODE_PLAY) {
1252 + captured = audio_pcm_hw_run_in(
1253 + hw, hw->conv_buf.size - audio_pcm_hw_get_live_in(hw));
1254 + }
1255 +
1256 + replay_audio_in_start(&captured);
1257 + assert(captured <= hw->conv_buf.size);
1258 + if (replay_mode == REPLAY_MODE_PLAY) {
1259 + hw->conv_buf.pos = (hw->conv_buf.pos + captured) % hw->conv_buf.size;
1260 + }
1261 + for (pos = (hw->conv_buf.pos - captured + hw->conv_buf.size) % hw->conv_buf.size;
1262 + pos != hw->conv_buf.pos;
1263 + pos = (pos + 1) % hw->conv_buf.size) {
1264 + uint64_t left, right;
1265 +
1266 + if (replay_mode == REPLAY_MODE_RECORD) {
1267 + audio_sample_to_uint64(hw->conv_buf.buffer, pos, &left, &right);
1268 + }
1269 + replay_audio_in_sample_lr(&left, &right);
1270 + if (replay_mode == REPLAY_MODE_PLAY) {
1271 + audio_sample_from_uint64(hw->conv_buf.buffer, pos, left, right);
1272 + }
1273 + }
1274 + replay_audio_in_finish();
1275 +
1276 + min = audio_pcm_hw_find_min_in (hw);
1277 + hw->total_samples_captured += captured - min;
1278 +
1279 + for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
1280 + sw->total_hw_samples_acquired -= min;
1281 +
1282 + if (sw->active) {
1283 + size_t sw_avail = audio_get_avail(sw);
1284 + size_t avail;
1285 +
1286 + avail = st_rate_frames_out(sw->rate, sw_avail);
1287 + if (avail > 0) {
1288 + avail = MIN(avail, sw->resample_buf.size);
1289 + sw->callback.fn(sw->callback.opaque,
1290 + avail * sw->info.bytes_per_frame);
1291 + }
1292 + }
1293 + }
1294 + }
1295 +}
1296 +
1297 +static void audio_run_capture(AudioMixengBackend *s)
1298 +{
1299 + CaptureVoiceOut *cap;
1300 +
1301 + for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) {
1302 + size_t live, rpos, captured;
1303 + HWVoiceOut *hw = &cap->hw;
1304 + SWVoiceOut *sw;
1305 +
1306 + captured = live = audio_pcm_hw_get_live_out (hw, NULL);
1307 + rpos = hw->mix_buf.pos;
1308 + while (live) {
1309 + size_t left = hw->mix_buf.size - rpos;
1310 + size_t to_capture = MIN(live, left);
1311 + struct st_sample *src;
1312 + struct capture_callback *cb;
1313 +
1314 + src = hw->mix_buf.buffer + rpos;
1315 + hw->clip (cap->buf, src, to_capture);
1316 + mixeng_clear (src, to_capture);
1317 +
1318 + for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
1319 + cb->ops.capture (cb->opaque, cap->buf,
1320 + to_capture * hw->info.bytes_per_frame);
1321 + }
1322 + rpos = (rpos + to_capture) % hw->mix_buf.size;
1323 + live -= to_capture;
1324 + }
1325 + hw->mix_buf.pos = rpos;
1326 +
1327 + for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
1328 + if (!sw->active && sw->empty) {
1329 + continue;
1330 + }
1331 +
1332 + if (audio_bug(__func__, captured > sw->total_hw_samples_mixed)) {
1333 + dolog("captured=%zu sw->total_hw_samples_mixed=%zu\n",
1334 + captured, sw->total_hw_samples_mixed);
1335 + captured = sw->total_hw_samples_mixed;
1336 + }
1337 +
1338 + sw->total_hw_samples_mixed -= captured;
1339 + sw->empty = sw->total_hw_samples_mixed == 0;
1340 + }
1341 + }
1342 +}
1343 +
1344 +void audio_run(AudioMixengBackend *s, const char *msg)
1345 +{
1346 + audio_run_out(s);
1347 + audio_run_in(s);
1348 + audio_run_capture(s);
1349 +
1350 +#ifdef DEBUG_POLL
1351 + {
1352 + static double prevtime;
1353 + double currtime;
1354 + struct timeval tv;
1355 +
1356 + if (gettimeofday (&tv, NULL)) {
1357 + perror ("audio_run: gettimeofday");
1358 + return;
1359 + }
1360 +
1361 + currtime = tv.tv_sec + tv.tv_usec * 1e-6;
1362 + dolog ("Elapsed since last %s: %f\n", msg, currtime - prevtime);
1363 + prevtime = currtime;
1364 + }
1365 +#endif
1366 +}
1367 +
1368 +void audio_generic_run_buffer_in(HWVoiceIn *hw)
1369 +{
1370 + if (unlikely(!hw->buf_emul)) {
1371 + hw->size_emul = hw->samples * hw->info.bytes_per_frame;
1372 + hw->buf_emul = g_malloc(hw->size_emul);
1373 + hw->pos_emul = hw->pending_emul = 0;
1374 + }
1375 +
1376 + while (hw->pending_emul < hw->size_emul) {
1377 + size_t read_len = MIN(hw->size_emul - hw->pos_emul,
1378 + hw->size_emul - hw->pending_emul);
1379 + size_t read = hw->pcm_ops->read(hw, hw->buf_emul + hw->pos_emul,
1380 + read_len);
1381 + hw->pending_emul += read;
1382 + hw->pos_emul = (hw->pos_emul + read) % hw->size_emul;
1383 + if (read < read_len) {
1384 + break;
1385 + }
1386 + }
1387 +}
1388 +
1389 +void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size)
1390 +{
1391 + size_t start;
1392 +
1393 + start = audio_ring_posb(hw->pos_emul, hw->pending_emul, hw->size_emul);
1394 + assert(start < hw->size_emul);
1395 +
1396 + *size = MIN(*size, hw->pending_emul);
1397 + *size = MIN(*size, hw->size_emul - start);
1398 + return hw->buf_emul + start;
1399 +}
1400 +
1401 +void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size)
1402 +{
1403 + assert(size <= hw->pending_emul);
1404 + hw->pending_emul -= size;
1405 +}
1406 +
1407 +size_t audio_generic_buffer_get_free(HWVoiceOut *hw)
1408 +{
1409 + if (hw->buf_emul) {
1410 + return hw->size_emul - hw->pending_emul;
1411 + } else {
1412 + return hw->samples * hw->info.bytes_per_frame;
1413 + }
1414 +}
1415 +
1416 +void audio_generic_run_buffer_out(HWVoiceOut *hw)
1417 +{
1418 + while (hw->pending_emul) {
1419 + size_t write_len, written, start;
1420 +
1421 + start = audio_ring_posb(hw->pos_emul, hw->pending_emul, hw->size_emul);
1422 + assert(start < hw->size_emul);
1423 +
1424 + write_len = MIN(hw->pending_emul, hw->size_emul - start);
1425 +
1426 + written = hw->pcm_ops->write(hw, hw->buf_emul + start, write_len);
1427 + hw->pending_emul -= written;
1428 +
1429 + if (written < write_len) {
1430 + break;
1431 + }
1432 + }
1433 +}
1434 +
1435 +void *audio_generic_get_buffer_out(HWVoiceOut *hw, size_t *size)
1436 +{
1437 + if (unlikely(!hw->buf_emul)) {
1438 + hw->size_emul = hw->samples * hw->info.bytes_per_frame;
1439 + hw->buf_emul = g_malloc(hw->size_emul);
1440 + hw->pos_emul = hw->pending_emul = 0;
1441 + }
1442 +
1443 + *size = MIN(hw->size_emul - hw->pending_emul,
1444 + hw->size_emul - hw->pos_emul);
1445 + return hw->buf_emul + hw->pos_emul;
1446 +}
1447 +
1448 +size_t audio_generic_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size)
1449 +{
1450 + assert(buf == hw->buf_emul + hw->pos_emul &&
1451 + size + hw->pending_emul <= hw->size_emul);
1452 +
1453 + hw->pending_emul += size;
1454 + hw->pos_emul = (hw->pos_emul + size) % hw->size_emul;
1455 +
1456 + return size;
1457 +}
1458 +
1459 +size_t audio_generic_write(HWVoiceOut *hw, void *buf, size_t size)
1460 +{
1461 + size_t total = 0;
1462 +
1463 + if (hw->pcm_ops->buffer_get_free) {
1464 + size_t free = hw->pcm_ops->buffer_get_free(hw);
1465 +
1466 + size = MIN(size, free);
1467 + }
1468 +
1469 + while (total < size) {
1470 + size_t dst_size = size - total;
1471 + size_t copy_size, proc;
1472 + void *dst = hw->pcm_ops->get_buffer_out(hw, &dst_size);
1473 +
1474 + if (dst_size == 0) {
1475 + break;
1476 + }
1477 +
1478 + copy_size = MIN(size - total, dst_size);
1479 + if (dst) {
1480 + memcpy(dst, (char *)buf + total, copy_size);
1481 + }
1482 + proc = hw->pcm_ops->put_buffer_out(hw, dst, copy_size);
1483 + total += proc;
1484 +
1485 + if (proc == 0 || proc < copy_size) {
1486 + break;
1487 + }
1488 + }
1489 +
1490 + return total;
1491 +}
1492 +
1493 +size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size)
1494 +{
1495 + size_t total = 0;
1496 +
1497 + if (hw->pcm_ops->run_buffer_in) {
1498 + hw->pcm_ops->run_buffer_in(hw);
1499 + }
1500 +
1501 + while (total < size) {
1502 + size_t src_size = size - total;
1503 + void *src = hw->pcm_ops->get_buffer_in(hw, &src_size);
1504 +
1505 + if (src_size == 0) {
1506 + break;
1507 + }
1508 +
1509 + memcpy((char *)buf + total, src, src_size);
1510 + hw->pcm_ops->put_buffer_in(hw, src, src_size);
1511 + total += src_size;
1512 + }
1513 +
1514 + return total;
1515 +}
1516 +
1517 +static bool audio_mixeng_backend_realize(AudioBackend *abe,
1518 + Audiodev *dev, Error **errp)
1519 +{
1520 + AudioMixengBackend *be = AUDIO_MIXENG_BACKEND(abe);
1521 + audio_driver *drv = AUDIO_MIXENG_BACKEND_GET_CLASS(be)->driver;
1522 +
1523 + be->dev = dev;
1524 + be->drv_opaque = drv->init(be->dev, errp);
1525 + if (!be->drv_opaque) {
1526 + return false;
1527 + }
1528 +
1529 + if (!drv->pcm_ops->get_buffer_in) {
1530 + drv->pcm_ops->get_buffer_in = audio_generic_get_buffer_in;
1531 + drv->pcm_ops->put_buffer_in = audio_generic_put_buffer_in;
1532 + }
1533 + if (!drv->pcm_ops->get_buffer_out) {
1534 + drv->pcm_ops->get_buffer_out = audio_generic_get_buffer_out;
1535 + drv->pcm_ops->put_buffer_out = audio_generic_put_buffer_out;
1536 + }
1537 +
1538 + audio_init_nb_voices_out(be, drv, 1);
1539 + audio_init_nb_voices_in(be, drv, 0);
1540 + be->drv = drv;
1541 +
1542 + if (be->dev->timer_period <= 0) {
1543 + be->period_ticks = 1;
1544 + } else {
1545 + be->period_ticks = be->dev->timer_period * (int64_t)SCALE_US;
1546 + }
1547 +
1548 + return true;
1549 +}
1550 +
1551 +static void audio_vm_change_state_handler (void *opaque, bool running,
1552 + RunState state)
1553 +{
1554 + AudioMixengBackend *s = opaque;
1555 + HWVoiceOut *hwo = NULL;
1556 + HWVoiceIn *hwi = NULL;
1557 +
1558 + while ((hwo = audio_pcm_hw_find_any_enabled_out(s, hwo))) {
1559 + if (hwo->pcm_ops->enable_out) {
1560 + hwo->pcm_ops->enable_out(hwo, running);
1561 + }
1562 + }
1563 +
1564 + while ((hwi = audio_pcm_hw_find_any_enabled_in(s, hwi))) {
1565 + if (hwi->pcm_ops->enable_in) {
1566 + hwi->pcm_ops->enable_in(hwi, running);
1567 + }
1568 + }
1569 + audio_reset_timer (s);
1570 +}
1571 +
1572 +static const VMStateDescription vmstate_audio;
1573 +
1574 +static const char *audio_mixeng_backend_get_id(AudioBackend *be)
1575 +{
1576 + return AUDIO_MIXENG_BACKEND(be)->dev->id;
1577 +}
1578 +
1579 +static CaptureVoiceOut *audio_mixeng_backend_add_capture(
1580 + AudioBackend *be,
1581 + struct audsettings *as,
1582 + struct audio_capture_ops *ops,
1583 + void *cb_opaque);
1584 +
1585 +static void audio_mixeng_backend_del_capture(
1586 + AudioBackend *be,
1587 + CaptureVoiceOut *cap,
1588 + void *cb_opaque);
1589 +
1590 +static void audio_mixeng_backend_set_volume_out(AudioBackend *be, SWVoiceOut *sw,
1591 + Volume *vol);
1592 +static void audio_mixeng_backend_set_volume_in(AudioBackend *be, SWVoiceIn *sw,
1593 + Volume *vol);
1594 +
1595 +static void audio_mixeng_backend_class_init(ObjectClass *klass, const void *data)
1596 +{
1597 + AudioBackendClass *be = AUDIO_BACKEND_CLASS(klass);
1598 +
1599 + be->realize = audio_mixeng_backend_realize;
1600 + be->get_id = audio_mixeng_backend_get_id;
1601 + be->open_in = audio_mixeng_backend_open_in;
1602 + be->open_out = audio_mixeng_backend_open_out;
1603 + be->close_in = audio_mixeng_backend_close_in;
1604 + be->close_out = audio_mixeng_backend_close_out;
1605 + be->is_active_out = audio_mixeng_backend_is_active_out;
1606 + be->is_active_in = audio_mixeng_backend_is_active_in;
1607 + be->set_active_out = audio_mixeng_backend_set_active_out;
1608 + be->set_active_in = audio_mixeng_backend_set_active_in;
1609 + be->set_volume_out = audio_mixeng_backend_set_volume_out;
1610 + be->set_volume_in = audio_mixeng_backend_set_volume_in;
1611 + be->read = audio_mixeng_backend_read;
1612 + be->write = audio_mixeng_backend_write;
1613 + be->get_buffer_size_out = audio_mixeng_backend_get_buffer_size_out;
1614 + be->add_capture = audio_mixeng_backend_add_capture;
1615 + be->del_capture = audio_mixeng_backend_del_capture;
1616 +}
1617 +
1618 +static void audio_mixeng_backend_init(Object *obj)
1619 +{
1620 + AudioMixengBackend *s = AUDIO_MIXENG_BACKEND(obj);
1621 +
1622 + QLIST_INIT(&s->hw_head_out);
1623 + QLIST_INIT(&s->hw_head_in);
1624 + QLIST_INIT(&s->cap_head);
1625 + s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s);
1626 +
1627 + s->vmse = qemu_add_vm_change_state_handler(audio_vm_change_state_handler, s);
1628 + assert(s->vmse != NULL);
1629 +
1630 + vmstate_register_any(NULL, &vmstate_audio, s);
1631 +}
1632 +
1633 +static void audio_mixeng_backend_finalize(Object *obj)
1634 +{
1635 + AudioMixengBackend *s = AUDIO_MIXENG_BACKEND(obj);
1636 + HWVoiceOut *hwo, *hwon;
1637 + HWVoiceIn *hwi, *hwin;
1638 +
1639 + QLIST_FOREACH_SAFE(hwo, &s->hw_head_out, entries, hwon) {
1640 + SWVoiceCap *sc;
1641 +
1642 + if (hwo->enabled && hwo->pcm_ops->enable_out) {
1643 + hwo->pcm_ops->enable_out(hwo, false);
1644 + }
1645 + hwo->pcm_ops->fini_out (hwo);
1646 +
1647 + for (sc = hwo->cap_head.lh_first; sc; sc = sc->entries.le_next) {
1648 + CaptureVoiceOut *cap = sc->cap;
1649 + struct capture_callback *cb;
1650 +
1651 + for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
1652 + cb->ops.destroy (cb->opaque);
1653 + }
1654 + }
1655 + QLIST_REMOVE(hwo, entries);
1656 + }
1657 +
1658 + QLIST_FOREACH_SAFE(hwi, &s->hw_head_in, entries, hwin) {
1659 + if (hwi->enabled && hwi->pcm_ops->enable_in) {
1660 + hwi->pcm_ops->enable_in(hwi, false);
1661 + }
1662 + hwi->pcm_ops->fini_in (hwi);
1663 + QLIST_REMOVE(hwi, entries);
1664 + }
1665 +
1666 + if (s->drv) {
1667 + s->drv->fini (s->drv_opaque);
1668 + s->drv = NULL;
1669 + }
1670 +
1671 + if (s->dev) {
1672 + qapi_free_Audiodev(s->dev);
1673 + s->dev = NULL;
1674 + }
1675 +
1676 + if (s->ts) {
1677 + timer_free(s->ts);
1678 + s->ts = NULL;
1679 + }
1680 +
1681 + if (s->vmse) {
1682 + qemu_del_vm_change_state_handler(s->vmse);
1683 + s->vmse = NULL;
1684 + }
1685 +
1686 + vmstate_unregister(NULL, &vmstate_audio, s);
1687 +}
1688 +
1689 +static bool vmstate_audio_needed(void *opaque)
1690 +{
1691 + /*
1692 + * Never needed, this vmstate only exists in case
1693 + * an old qemu sends it to us.
1694 + */
1695 + return false;
1696 +}
1697 +
1698 +static const VMStateDescription vmstate_audio = {
1699 + .name = "audio",
1700 + .version_id = 1,
1701 + .minimum_version_id = 1,
1702 + .needed = vmstate_audio_needed,
1703 + .fields = (const VMStateField[]) {
1704 + VMSTATE_END_OF_LIST()
1705 + }
1706 +};
1707 +
1708 +static struct audio_pcm_ops capture_pcm_ops;
1709 +
1710 +static CaptureVoiceOut *audio_mixeng_backend_add_capture(
1711 + AudioBackend *be,
1712 + struct audsettings *as,
1713 + struct audio_capture_ops *ops,
1714 + void *cb_opaque)
1715 +{
1716 + AudioMixengBackend *s = AUDIO_MIXENG_BACKEND(be);
1717 + CaptureVoiceOut *cap;
1718 + struct capture_callback *cb;
1719 +
1720 + if (!s) {
1721 + error_report("Capturing without setting an audiodev is not supported");
1722 + abort();
1723 + }
1724 +
1725 + if (!audio_get_pdo_out(s->dev)->mixing_engine) {
1726 + dolog("Can't capture with mixeng disabled\n");
1727 + return NULL;
1728 + }
1729 +
1730 + if (audio_validate_settings (as)) {
1731 + dolog ("Invalid settings were passed when trying to add capture\n");
1732 + audio_print_settings (as);
1733 + return NULL;
1734 + }
1735 +
1736 + cb = g_malloc0(sizeof(*cb));
1737 + cb->ops = *ops;
1738 + cb->opaque = cb_opaque;
1739 +
1740 + cap = audio_pcm_capture_find_specific(s, as);
1741 + if (cap) {
1742 + QLIST_INSERT_HEAD (&cap->cb_head, cb, entries);
1743 + } else {
1744 + HWVoiceOut *hw;
1745 +
1746 + cap = g_malloc0(sizeof(*cap));
1747 +
1748 + hw = &cap->hw;
1749 + hw->s = s;
1750 + hw->pcm_ops = &capture_pcm_ops;
1751 + QLIST_INIT (&hw->sw_head);
1752 + QLIST_INIT (&cap->cb_head);
1753 +
1754 + /* XXX find a more elegant way */
1755 + hw->samples = 4096 * 4;
1756 + audio_pcm_hw_alloc_resources_out(hw);
1757 +
1758 + audio_pcm_init_info (&hw->info, as);
1759 +
1760 + cap->buf = g_malloc0_n(hw->mix_buf.size, hw->info.bytes_per_frame);
1761 +
1762 + if (hw->info.is_float) {
1763 + hw->clip = mixeng_clip_float[hw->info.nchannels == 2]
1764 + [hw->info.swap_endianness];
1765 + } else {
1766 + hw->clip = mixeng_clip
1767 + [hw->info.nchannels == 2]
1768 + [hw->info.is_signed]
1769 + [hw->info.swap_endianness]
1770 + [audio_bits_to_index(hw->info.bits)];
1771 + }
1772 +
1773 + QLIST_INSERT_HEAD (&s->cap_head, cap, entries);
1774 + QLIST_INSERT_HEAD (&cap->cb_head, cb, entries);
1775 +
1776 + QLIST_FOREACH(hw, &s->hw_head_out, entries) {
1777 + audio_attach_capture (hw);
1778 + }
1779 + }
1780 +
1781 + return cap;
1782 +}
1783 +
1784 +static void audio_mixeng_backend_del_capture(
1785 + AudioBackend *be,
1786 + CaptureVoiceOut *cap,
1787 + void *cb_opaque)
1788 +{
1789 + struct capture_callback *cb;
1790 +
1791 + for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
1792 + if (cb->opaque == cb_opaque) {
1793 + cb->ops.destroy (cb_opaque);
1794 + QLIST_REMOVE (cb, entries);
1795 + g_free (cb);
1796 +
1797 + if (!cap->cb_head.lh_first) {
1798 + SWVoiceOut *sw = cap->hw.sw_head.lh_first, *sw1;
1799 +
1800 + while (sw) {
1801 + SWVoiceCap *sc = (SWVoiceCap *) sw;
1802 +#ifdef DEBUG_CAPTURE
1803 + dolog ("freeing %s\n", sw->name);
1804 +#endif
1805 +
1806 + sw1 = sw->entries.le_next;
1807 + if (sw->rate) {
1808 + st_rate_stop (sw->rate);
1809 + sw->rate = NULL;
1810 + }
1811 + QLIST_REMOVE (sw, entries);
1812 + QLIST_REMOVE (sc, entries);
1813 + g_free (sc);
1814 + sw = sw1;
1815 + }
1816 + QLIST_REMOVE (cap, entries);
1817 + g_free(cap->hw.mix_buf.buffer);
1818 + g_free (cap->buf);
1819 + g_free (cap);
1820 + }
1821 + return;
1822 + }
1823 + }
1824 +}
1825 +
1826 +static void audio_mixeng_backend_set_volume_out(AudioBackend *be, SWVoiceOut *sw,
1827 + Volume *vol)
1828 +{
1829 + if (sw) {
1830 + HWVoiceOut *hw = sw->hw;
1831 +
1832 + sw->vol.mute = vol->mute;
1833 + sw->vol.l = nominal_volume.l * vol->vol[0] / 255;
1834 + sw->vol.r = nominal_volume.l * vol->vol[vol->channels > 1 ? 1 : 0] /
1835 + 255;
1836 +
1837 + if (hw->pcm_ops->volume_out) {
1838 + hw->pcm_ops->volume_out(hw, vol);
1839 + }
1840 + }
1841 +}
1842 +
1843 +static void audio_mixeng_backend_set_volume_in(AudioBackend *be, SWVoiceIn *sw,
1844 + Volume *vol)
1845 +{
1846 + if (sw) {
1847 + HWVoiceIn *hw = sw->hw;
1848 +
1849 + sw->vol.mute = vol->mute;
1850 + sw->vol.l = nominal_volume.l * vol->vol[0] / 255;
1851 + sw->vol.r = nominal_volume.r * vol->vol[vol->channels > 1 ? 1 : 0] /
1852 + 255;
1853 +
1854 + if (hw->pcm_ops->volume_in) {
1855 + hw->pcm_ops->volume_in(hw, vol);
1856 + }
1857 + }
1858 +}
1859 +
1860 +audsettings audiodev_to_audsettings(AudiodevPerDirectionOptions *pdo)
1861 +{
1862 + return (audsettings) {
1863 + .freq = pdo->frequency,
1864 + .nchannels = pdo->channels,
1865 + .fmt = pdo->format,
1866 + .endianness = HOST_BIG_ENDIAN,
1867 + };
1868 +}
1869 +
1870 +int audioformat_bytes_per_sample(AudioFormat fmt)
1871 +{
1872 + switch (fmt) {
1873 + case AUDIO_FORMAT_U8:
1874 + case AUDIO_FORMAT_S8:
1875 + return 1;
1876 +
1877 + case AUDIO_FORMAT_U16:
1878 + case AUDIO_FORMAT_S16:
1879 + return 2;
1880 +
1881 + case AUDIO_FORMAT_U32:
1882 + case AUDIO_FORMAT_S32:
1883 + case AUDIO_FORMAT_F32:
1884 + return 4;
1885 +
1886 + case AUDIO_FORMAT__MAX:
1887 + ;
1888 + }
1889 + abort();
1890 +}
1891 +
1892 +
1893 +/* frames = freq * usec / 1e6 */
1894 +int audio_buffer_frames(AudiodevPerDirectionOptions *pdo,
1895 + audsettings *as, int def_usecs)
1896 +{
1897 + uint64_t usecs = pdo->has_buffer_length ? pdo->buffer_length : def_usecs;
1898 + return (as->freq * usecs + 500000) / 1000000;
1899 +}
1900 +
1901 +/* samples = channels * frames = channels * freq * usec / 1e6 */
1902 +int audio_buffer_samples(AudiodevPerDirectionOptions *pdo,
1903 + audsettings *as, int def_usecs)
1904 +{
1905 + return as->nchannels * audio_buffer_frames(pdo, as, def_usecs);
1906 +}
1907 +
1908 +/*
1909 + * bytes = bytes_per_sample * samples =
1910 + * bytes_per_sample * channels * freq * usec / 1e6
1911 + */
1912 +int audio_buffer_bytes(AudiodevPerDirectionOptions *pdo,
1913 + audsettings *as, int def_usecs)
1914 +{
1915 + return audio_buffer_samples(pdo, as, def_usecs) *
1916 + audioformat_bytes_per_sample(as->fmt);
1917 +}
1918 +
1919 +void audio_rate_start(RateCtl *rate)
1920 +{
1921 + memset(rate, 0, sizeof(RateCtl));
1922 + rate->start_ticks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
1923 +}
1924 +
1925 +size_t audio_rate_peek_bytes(RateCtl *rate, struct audio_pcm_info *info)
1926 +{
1927 + int64_t now;
1928 + int64_t ticks;
1929 + int64_t bytes;
1930 + int64_t frames;
1931 +
1932 + now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
1933 + ticks = now - rate->start_ticks;
1934 + bytes = muldiv64(ticks, info->bytes_per_second, NANOSECONDS_PER_SECOND);
1935 + frames = (bytes - rate->bytes_sent) / info->bytes_per_frame;
1936 + rate->peeked_frames = frames;
1937 +
1938 + return frames < 0 ? 0 : frames * info->bytes_per_frame;
1939 +}
1940 +
1941 +void audio_rate_add_bytes(RateCtl *rate, size_t bytes_used)
1942 +{
1943 + if (rate->peeked_frames < 0 || rate->peeked_frames > 65536) {
1944 + AUD_log(NULL, "Resetting rate control (%" PRId64 " frames)\n",
1945 + rate->peeked_frames);
1946 + audio_rate_start(rate);
1947 + }
1948 +
1949 + rate->bytes_sent += bytes_used;
1950 +}
1951 +
1952 +size_t audio_rate_get_bytes(RateCtl *rate, struct audio_pcm_info *info,
1953 + size_t bytes_avail)
1954 +{
1955 + size_t bytes;
1956 +
1957 + bytes = audio_rate_peek_bytes(rate, info);
1958 + bytes = MIN(bytes, bytes_avail);
1959 + audio_rate_add_bytes(rate, bytes);
1960 +
1961 + return bytes;
1962 +}
1963 +
1964 +static const TypeInfo audio_types[] = {
1965 + {
1966 + .name = TYPE_AUDIO_MIXENG_BACKEND,
1967 + .parent = TYPE_AUDIO_BACKEND,
1968 + .instance_size = sizeof(AudioMixengBackend),
1969 + .instance_init = audio_mixeng_backend_init,
1970 + .instance_finalize = audio_mixeng_backend_finalize,
1971 + .class_size = sizeof(AudioMixengBackendClass),
1972 + .class_init = audio_mixeng_backend_class_init,
1973 + },
1974 +};
1975 +
1976 +DEFINE_TYPES(audio_types)
audio/audio.c
+177 -2046
@@ -1,1751 +1,55 @@
1 -/*
2 - * QEMU Audio subsystem
3 - *
4 - * Copyright (c) 2003-2005 Vassili Karpov (malc)
5 - *
6 - * Permission is hereby granted, free of charge, to any person obtaining a copy
7 - * of this software and associated documentation files (the "Software"), to deal
8 - * in the Software without restriction, including without limitation the rights
9 - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 - * copies of the Software, and to permit persons to whom the Software is
11 - * furnished to do so, subject to the following conditions:
12 - *
13 - * The above copyright notice and this permission notice shall be included in
14 - * all copies or substantial portions of the Software.
15 - *
16 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 - * THE SOFTWARE.
23 - */
24 -
25 -#include "qemu/osdep.h"
26 -#include "qemu/audio.h"
27 -#include "migration/vmstate.h"
28 -#include "qemu/timer.h"
29 -#include "qapi/error.h"
30 -#include "qapi/clone-visitor.h"
31 -#include "qapi/qobject-input-visitor.h"
32 -#include "qapi/qapi-visit-audio.h"
33 -#include "qapi/qapi-commands-audio.h"
34 -#include "qobject/qdict.h"
35 -#include "qemu/bswap.h"
36 -#include "qemu/error-report.h"
37 -#include "qemu/log.h"
38 -#include "qemu/module.h"
39 -#include "qemu/help_option.h"
40 -#include "qom/object.h"
41 -#include "system/system.h"
42 -#include "system/replay.h"
43 -#include "system/runstate.h"
44 -#include "trace.h"
45 -
46 -#define AUDIO_CAP "audio"
47 -#include "audio_int.h"
48 -
49 -/* #define DEBUG_LIVE */
50 -/* #define DEBUG_OUT */
51 -/* #define DEBUG_CAPTURE */
52 -/* #define DEBUG_POLL */
53 -
54 -#define SW_NAME(sw) (sw)->name ? (sw)->name : "unknown"
55 -
56 -
57 -/* Order of CONFIG_AUDIO_DRIVERS is import.
58 - The 1st one is the one used by default, that is the reason
59 - that we generate the list.
60 -*/
61 -const char *audio_prio_list[] = {
62 -#ifdef CONFIG_GIO
63 - "dbus",
64 -#endif
65 - "spice",
66 - CONFIG_AUDIO_DRIVERS
67 - "none",
68 - NULL
69 -};
70 -
71 -typedef struct AudiodevListEntry {
72 - Audiodev *dev;
73 - QSIMPLEQ_ENTRY(AudiodevListEntry) next;
74 -} AudiodevListEntry;
75 -
76 -typedef QSIMPLEQ_HEAD(, AudiodevListEntry) AudiodevListHead;
77 -
78 -static AudiodevListHead audiodevs =
79 - QSIMPLEQ_HEAD_INITIALIZER(audiodevs);
80 -static AudiodevListHead default_audiodevs =
81 - QSIMPLEQ_HEAD_INITIALIZER(default_audiodevs);
82 -
83 -static AudioBackendClass *audio_be_class_by_name(const char *name)
84 -{
85 - g_autofree char *tname = g_strconcat("audio-", name, NULL);
86 - ObjectClass *oc = module_object_class_by_name(tname);
87 -
88 - if (!oc || !object_class_dynamic_cast(oc, TYPE_AUDIO_BACKEND)) {
89 - return NULL;
90 - }
91 -
92 - return AUDIO_BACKEND_CLASS(oc);
93 -}
94 -
95 -static AudioBackend *default_audio_be;
96 -
97 -const struct mixeng_volume nominal_volume = {
98 - .mute = 0,
99 -#ifdef FLOAT_MIXENG
100 - .r = 1.0,
101 - .l = 1.0,
102 -#else
103 - .r = 1ULL << 32,
104 - .l = 1ULL << 32,
105 -#endif
106 -};
107 -
108 -int audio_bug (const char *funcname, int cond)
109 -{
110 - if (cond) {
111 - static int shown;
112 -
113 - AUD_log (NULL, "A bug was just triggered in %s\n", funcname);
114 - if (!shown) {
115 - shown = 1;
116 - AUD_log (NULL, "Save all your work and restart without audio\n");
117 - AUD_log (NULL, "I am sorry\n");
118 - }
119 - AUD_log (NULL, "Context:\n");
120 - }
121 -
122 - return cond;
123 -}
124 -
125 -static inline int audio_bits_to_index (int bits)
126 -{
127 - switch (bits) {
128 - case 8:
129 - return 0;
130 -
131 - case 16:
132 - return 1;
133 -
134 - case 32:
135 - return 2;
136 -
137 - default:
138 - audio_bug ("bits_to_index", 1);
139 - AUD_log (NULL, "invalid bits %d\n", bits);
140 - return 0;
141 - }
142 -}
143 -
144 -void AUD_vlog (const char *cap, const char *fmt, va_list ap)
145 -{
146 - if (cap) {
147 - fprintf(stderr, "%s: ", cap);
148 - }
149 -
150 - vfprintf(stderr, fmt, ap);
151 -}
152 -
153 -void AUD_log (const char *cap, const char *fmt, ...)
154 -{
155 - va_list ap;
156 -
157 - va_start (ap, fmt);
158 - AUD_vlog (cap, fmt, ap);
159 - va_end (ap);
160 -}
161 -
162 -static void audio_print_settings (const struct audsettings *as)
163 -{
164 - dolog ("frequency=%d nchannels=%d fmt=", as->freq, as->nchannels);
165 -
166 - switch (as->fmt) {
167 - case AUDIO_FORMAT_S8:
168 - AUD_log (NULL, "S8");
169 - break;
170 - case AUDIO_FORMAT_U8:
171 - AUD_log (NULL, "U8");
172 - break;
173 - case AUDIO_FORMAT_S16:
174 - AUD_log (NULL, "S16");
175 - break;
176 - case AUDIO_FORMAT_U16:
177 - AUD_log (NULL, "U16");
178 - break;
179 - case AUDIO_FORMAT_S32:
180 - AUD_log (NULL, "S32");
181 - break;
182 - case AUDIO_FORMAT_U32:
183 - AUD_log (NULL, "U32");
184 - break;
185 - case AUDIO_FORMAT_F32:
186 - AUD_log (NULL, "F32");
187 - break;
188 - default:
189 - AUD_log (NULL, "invalid(%d)", as->fmt);
190 - break;
191 - }
192 -
193 - AUD_log (NULL, " endianness=");
194 - switch (as->endianness) {
195 - case 0:
196 - AUD_log (NULL, "little");
197 - break;
198 - case 1:
199 - AUD_log (NULL, "big");
200 - break;
201 - default:
202 - AUD_log (NULL, "invalid");
203 - break;
204 - }
205 - AUD_log (NULL, "\n");
206 -}
207 -
208 -static int audio_validate_settings (const struct audsettings *as)
209 -{
210 - int invalid;
211 -
212 - invalid = as->nchannels < 1;
213 - invalid |= as->endianness != 0 && as->endianness != 1;
214 -
215 - switch (as->fmt) {
216 - case AUDIO_FORMAT_S8:
217 - case AUDIO_FORMAT_U8:
218 - case AUDIO_FORMAT_S16:
219 - case AUDIO_FORMAT_U16:
220 - case AUDIO_FORMAT_S32:
221 - case AUDIO_FORMAT_U32:
222 - case AUDIO_FORMAT_F32:
223 - break;
224 - default:
225 - invalid = 1;
226 - break;
227 - }
228 -
229 - invalid |= as->freq <= 0;
230 - return invalid ? -1 : 0;
231 -}
232 -
233 -static int audio_pcm_info_eq (struct audio_pcm_info *info, const struct audsettings *as)
234 -{
235 - int bits = 8;
236 - bool is_signed = false, is_float = false;
237 -
238 - switch (as->fmt) {
239 - case AUDIO_FORMAT_S8:
240 - is_signed = true;
241 - /* fall through */
242 - case AUDIO_FORMAT_U8:
243 - break;
244 -
245 - case AUDIO_FORMAT_S16:
246 - is_signed = true;
247 - /* fall through */
248 - case AUDIO_FORMAT_U16:
249 - bits = 16;
250 - break;
251 -
252 - case AUDIO_FORMAT_F32:
253 - is_float = true;
254 - /* fall through */
255 - case AUDIO_FORMAT_S32:
256 - is_signed = true;
257 - /* fall through */
258 - case AUDIO_FORMAT_U32:
259 - bits = 32;
260 - break;
261 -
262 - default:
263 - abort();
264 - }
265 - return info->freq == as->freq
266 - && info->nchannels == as->nchannels
267 - && info->is_signed == is_signed
268 - && info->is_float == is_float
269 - && info->bits == bits
270 - && info->swap_endianness == (as->endianness != HOST_BIG_ENDIAN);
271 -}
272 -
273 -void audio_pcm_init_info (struct audio_pcm_info *info, const struct audsettings *as)
274 -{
275 - int bits = 8, mul;
276 - bool is_signed = false, is_float = false;
277 -
278 - switch (as->fmt) {
279 - case AUDIO_FORMAT_S8:
280 - is_signed = true;
281 - /* fall through */
282 - case AUDIO_FORMAT_U8:
283 - mul = 1;
284 - break;
285 -
286 - case AUDIO_FORMAT_S16:
287 - is_signed = true;
288 - /* fall through */
289 - case AUDIO_FORMAT_U16:
290 - bits = 16;
291 - mul = 2;
292 - break;
293 -
294 - case AUDIO_FORMAT_F32:
295 - is_float = true;
296 - /* fall through */
297 - case AUDIO_FORMAT_S32:
298 - is_signed = true;
299 - /* fall through */
300 - case AUDIO_FORMAT_U32:
301 - bits = 32;
302 - mul = 4;
303 - break;
304 -
305 - default:
306 - abort();
307 - }
308 -
309 - info->freq = as->freq;
310 - info->bits = bits;
311 - info->is_signed = is_signed;
312 - info->is_float = is_float;
313 - info->nchannels = as->nchannels;
314 - info->bytes_per_frame = as->nchannels * mul;
315 - info->bytes_per_second = info->freq * info->bytes_per_frame;
316 - info->swap_endianness = (as->endianness != HOST_BIG_ENDIAN);
317 -}
318 -
319 -void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
320 -{
321 - if (!len) {
322 - return;
323 - }
324 -
325 - if (info->is_signed || info->is_float) {
326 - memset(buf, 0x00, len * info->bytes_per_frame);
327 - } else {
328 - switch (info->bits) {
329 - case 8:
330 - memset(buf, 0x80, len * info->bytes_per_frame);
331 - break;
332 -
333 - case 16:
334 - {
335 - int i;
336 - uint16_t *p = buf;
337 - short s = INT16_MAX;
338 -
339 - if (info->swap_endianness) {
340 - s = bswap16 (s);
341 - }
342 -
343 - for (i = 0; i < len * info->nchannels; i++) {
344 - p[i] = s;
345 - }
346 - }
347 - break;
348 -
349 - case 32:
350 - {
351 - int i;
352 - uint32_t *p = buf;
353 - int32_t s = INT32_MAX;
354 -
355 - if (info->swap_endianness) {
356 - s = bswap32 (s);
357 - }
358 -
359 - for (i = 0; i < len * info->nchannels; i++) {
360 - p[i] = s;
361 - }
362 - }
363 - break;
364 -
365 - default:
366 - AUD_log (NULL, "audio_pcm_info_clear_buf: invalid bits %d\n",
367 - info->bits);
368 - break;
369 - }
370 - }
371 -}
372 -
373 -/*
374 - * Capture
375 - */
376 -static CaptureVoiceOut *audio_pcm_capture_find_specific(AudioMixengBackend *s,
377 - struct audsettings *as)
378 -{
379 - CaptureVoiceOut *cap;
380 -
381 - for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) {
382 - if (audio_pcm_info_eq (&cap->hw.info, as)) {
383 - return cap;
384 - }
385 - }
386 - return NULL;
387 -}
388 -
389 -static void audio_notify_capture (CaptureVoiceOut *cap, audcnotification_e cmd)
390 -{
391 - struct capture_callback *cb;
392 -
393 -#ifdef DEBUG_CAPTURE
394 - dolog ("notification %d sent\n", cmd);
395 -#endif
396 - for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
397 - cb->ops.notify (cb->opaque, cmd);
398 - }
399 -}
400 -
401 -static void audio_capture_maybe_changed(CaptureVoiceOut *cap, bool enabled)
402 -{
403 - if (cap->hw.enabled != enabled) {
404 - audcnotification_e cmd;
405 - cap->hw.enabled = enabled;
406 - cmd = enabled ? AUD_CNOTIFY_ENABLE : AUD_CNOTIFY_DISABLE;
407 - audio_notify_capture (cap, cmd);
408 - }
409 -}
410 -
411 -static void audio_recalc_and_notify_capture (CaptureVoiceOut *cap)
412 -{
413 - HWVoiceOut *hw = &cap->hw;
414 - SWVoiceOut *sw;
415 - bool enabled = false;
416 -
417 - for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
418 - if (sw->active) {
419 - enabled = true;
420 - break;
421 - }
422 - }
423 - audio_capture_maybe_changed (cap, enabled);
424 -}
425 -
426 -static void audio_detach_capture (HWVoiceOut *hw)
427 -{
428 - SWVoiceCap *sc = hw->cap_head.lh_first;
429 -
430 - while (sc) {
431 - SWVoiceCap *sc1 = sc->entries.le_next;
432 - SWVoiceOut *sw = &sc->sw;
433 - CaptureVoiceOut *cap = sc->cap;
434 - int was_active = sw->active;
435 -
436 - if (sw->rate) {
437 - st_rate_stop (sw->rate);
438 - sw->rate = NULL;
439 - }
440 -
441 - QLIST_REMOVE (sw, entries);
442 - QLIST_REMOVE (sc, entries);
443 - g_free (sc);
444 - if (was_active) {
445 - /* We have removed soft voice from the capture:
446 - this might have changed the overall status of the capture
447 - since this might have been the only active voice */
448 - audio_recalc_and_notify_capture (cap);
449 - }
450 - sc = sc1;
451 - }
452 -}
453 -
454 -static int audio_attach_capture (HWVoiceOut *hw)
455 -{
456 - AudioMixengBackend *s = hw->s;
457 - CaptureVoiceOut *cap;
458 -
459 - audio_detach_capture (hw);
460 - for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) {
461 - SWVoiceCap *sc;
462 - SWVoiceOut *sw;
463 - HWVoiceOut *hw_cap = &cap->hw;
464 -
465 - sc = g_malloc0(sizeof(*sc));
466 -
467 - sc->cap = cap;
468 - sw = &sc->sw;
469 - sw->hw = hw_cap;
470 - sw->info = hw->info;
471 - sw->empty = true;
472 - sw->active = hw->enabled;
473 - sw->vol = nominal_volume;
474 - sw->rate = st_rate_start (sw->info.freq, hw_cap->info.freq);
475 - QLIST_INSERT_HEAD (&hw_cap->sw_head, sw, entries);
476 - QLIST_INSERT_HEAD (&hw->cap_head, sc, entries);
477 -#ifdef DEBUG_CAPTURE
478 - sw->name = g_strdup_printf ("for %p %d,%d,%d",
479 - hw, sw->info.freq, sw->info.bits,
480 - sw->info.nchannels);
481 - dolog ("Added %s active = %d\n", sw->name, sw->active);
482 -#endif
483 - if (sw->active) {
484 - audio_capture_maybe_changed (cap, 1);
485 - }
486 - }
487 - return 0;
488 -}
489 -
490 -/*
491 - * Hard voice (capture)
492 - */
493 -static size_t audio_pcm_hw_find_min_in (HWVoiceIn *hw)
494 -{
495 - SWVoiceIn *sw;
496 - size_t m = hw->total_samples_captured;
497 -
498 - for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
499 - if (sw->active) {
500 - m = MIN (m, sw->total_hw_samples_acquired);
501 - }
502 - }
503 - return m;
504 -}
505 -
506 -static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw)
507 -{
508 - size_t live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw);
509 - if (audio_bug(__func__, live > hw->conv_buf.size)) {
510 - dolog("live=%zu hw->conv_buf.size=%zu\n", live, hw->conv_buf.size);
511 - return 0;
512 - }
513 - return live;
514 -}
515 -
516 -static size_t audio_pcm_hw_conv_in(HWVoiceIn *hw, void *pcm_buf, size_t samples)
517 -{
518 - size_t conv = 0;
519 - STSampleBuffer *conv_buf = &hw->conv_buf;
520 -
521 - while (samples) {
522 - uint8_t *src = advance(pcm_buf, conv * hw->info.bytes_per_frame);
523 - size_t proc = MIN(samples, conv_buf->size - conv_buf->pos);
524 -
525 - hw->conv(conv_buf->buffer + conv_buf->pos, src, proc);
526 - conv_buf->pos = (conv_buf->pos + proc) % conv_buf->size;
527 - samples -= proc;
528 - conv += proc;
529 - }
530 -
531 - return conv;
532 -}
533 -
534 -/*
535 - * Soft voice (capture)
536 - */
537 -static void audio_pcm_sw_resample_in(SWVoiceIn *sw,
538 - size_t frames_in_max, size_t frames_out_max,
539 - size_t *total_in, size_t *total_out)
540 -{
541 - HWVoiceIn *hw = sw->hw;
542 - struct st_sample *src, *dst;
543 - size_t live, rpos, frames_in, frames_out;
544 -
545 - live = hw->total_samples_captured - sw->total_hw_samples_acquired;
546 - rpos = audio_ring_posb(hw->conv_buf.pos, live, hw->conv_buf.size);
547 -
548 - /* resample conv_buf from rpos to end of buffer */
549 - src = hw->conv_buf.buffer + rpos;
550 - frames_in = MIN(frames_in_max, hw->conv_buf.size - rpos);
551 - dst = sw->resample_buf.buffer;
552 - frames_out = frames_out_max;
553 - st_rate_flow(sw->rate, src, dst, &frames_in, &frames_out);
554 - rpos += frames_in;
555 - *total_in = frames_in;
556 - *total_out = frames_out;
557 -
558 - /* resample conv_buf from start of buffer if there are input frames left */
559 - if (frames_in_max - frames_in && rpos == hw->conv_buf.size) {
560 - src = hw->conv_buf.buffer;
561 - frames_in = frames_in_max - frames_in;
562 - dst += frames_out;
563 - frames_out = frames_out_max - frames_out;
564 - st_rate_flow(sw->rate, src, dst, &frames_in, &frames_out);
565 - *total_in += frames_in;
566 - *total_out += frames_out;
567 - }
568 -}
569 -
570 -static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t buf_len)
571 -{
572 - HWVoiceIn *hw = sw->hw;
573 - size_t live, frames_out_max, total_in, total_out;
574 -
575 - live = hw->total_samples_captured - sw->total_hw_samples_acquired;
576 - if (!live) {
577 - return 0;
578 - }
579 - if (audio_bug(__func__, live > hw->conv_buf.size)) {
580 - dolog("live_in=%zu hw->conv_buf.size=%zu\n", live, hw->conv_buf.size);
581 - return 0;
582 - }
583 -
584 - frames_out_max = MIN(buf_len / sw->info.bytes_per_frame,
585 - sw->resample_buf.size);
586 -
587 - audio_pcm_sw_resample_in(sw, live, frames_out_max, &total_in, &total_out);
588 -
589 - if (!hw->pcm_ops->volume_in) {
590 - mixeng_volume(sw->resample_buf.buffer, total_out, &sw->vol);
591 - }
592 - sw->clip(buf, sw->resample_buf.buffer, total_out);
593 -
594 - sw->total_hw_samples_acquired += total_in;
595 - return total_out * sw->info.bytes_per_frame;
596 -}
597 -
598 -/*
599 - * Hard voice (playback)
600 - */
601 -static size_t audio_pcm_hw_find_min_out (HWVoiceOut *hw, int *nb_livep)
602 -{
603 - SWVoiceOut *sw;
604 - size_t m = SIZE_MAX;
605 - int nb_live = 0;
606 -
607 - for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
608 - if (sw->active || !sw->empty) {
609 - m = MIN (m, sw->total_hw_samples_mixed);
610 - nb_live += 1;
611 - }
612 - }
613 -
614 - *nb_livep = nb_live;
615 - return m;
616 -}
617 -
618 -static size_t audio_pcm_hw_get_live_out (HWVoiceOut *hw, int *nb_live)
619 -{
620 - size_t smin;
621 - int nb_live1;
622 -
623 - smin = audio_pcm_hw_find_min_out (hw, &nb_live1);
624 - if (nb_live) {
625 - *nb_live = nb_live1;
626 - }
627 -
628 - if (nb_live1) {
629 - size_t live = smin;
630 -
631 - if (audio_bug(__func__, live > hw->mix_buf.size)) {
632 - dolog("live=%zu hw->mix_buf.size=%zu\n", live, hw->mix_buf.size);
633 - return 0;
634 - }
635 - return live;
636 - }
637 - return 0;
638 -}
639 -
640 -static size_t audio_pcm_hw_get_free(HWVoiceOut *hw)
641 -{
642 - return (hw->pcm_ops->buffer_get_free ? hw->pcm_ops->buffer_get_free(hw) :
643 - INT_MAX) / hw->info.bytes_per_frame;
644 -}
645 -
646 -static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len)
647 -{
648 - size_t clipped = 0;
649 - size_t pos = hw->mix_buf.pos;
650 -
651 - while (len) {
652 - st_sample *src = hw->mix_buf.buffer + pos;
653 - uint8_t *dst = advance(pcm_buf, clipped * hw->info.bytes_per_frame);
654 - size_t samples_till_end_of_buf = hw->mix_buf.size - pos;
655 - size_t samples_to_clip = MIN(len, samples_till_end_of_buf);
656 -
657 - hw->clip(dst, src, samples_to_clip);
658 -
659 - pos = (pos + samples_to_clip) % hw->mix_buf.size;
660 - len -= samples_to_clip;
661 - clipped += samples_to_clip;
662 - }
663 -}
664 -
665 -/*
666 - * Soft voice (playback)
667 - */
668 -static void audio_pcm_sw_resample_out(SWVoiceOut *sw,
669 - size_t frames_in_max, size_t frames_out_max,
670 - size_t *total_in, size_t *total_out)
671 -{
672 - HWVoiceOut *hw = sw->hw;
673 - struct st_sample *src, *dst;
674 - size_t live, wpos, frames_in, frames_out;
675 -
676 - live = sw->total_hw_samples_mixed;
677 - wpos = (hw->mix_buf.pos + live) % hw->mix_buf.size;
678 -
679 - /* write to mix_buf from wpos to end of buffer */
680 - src = sw->resample_buf.buffer;
681 - frames_in = frames_in_max;
682 - dst = hw->mix_buf.buffer + wpos;
683 - frames_out = MIN(frames_out_max, hw->mix_buf.size - wpos);
684 - st_rate_flow_mix(sw->rate, src, dst, &frames_in, &frames_out);
685 - wpos += frames_out;
686 - *total_in = frames_in;
687 - *total_out = frames_out;
688 -
689 - /* write to mix_buf from start of buffer if there are input frames left */
690 - if (frames_in_max - frames_in > 0 && wpos == hw->mix_buf.size) {
691 - src += frames_in;
692 - frames_in = frames_in_max - frames_in;
693 - dst = hw->mix_buf.buffer;
694 - frames_out = frames_out_max - frames_out;
695 - st_rate_flow_mix(sw->rate, src, dst, &frames_in, &frames_out);
696 - *total_in += frames_in;
697 - *total_out += frames_out;
698 - }
699 -}
700 -
701 -static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t buf_len)
702 -{
703 - HWVoiceOut *hw = sw->hw;
704 - size_t live, dead, hw_free, sw_max, fe_max;
705 - size_t frames_in_max, frames_out_max, total_in, total_out;
706 -
707 - live = sw->total_hw_samples_mixed;
708 - if (audio_bug(__func__, live > hw->mix_buf.size)) {
709 - dolog("live=%zu hw->mix_buf.size=%zu\n", live, hw->mix_buf.size);
710 - return 0;
711 - }
712 -
713 - if (live == hw->mix_buf.size) {
714 -#ifdef DEBUG_OUT
715 - dolog ("%s is full %zu\n", sw->name, live);
716 -#endif
717 - return 0;
718 - }
719 -
720 - dead = hw->mix_buf.size - live;
721 - hw_free = audio_pcm_hw_get_free(hw);
722 - hw_free = hw_free > live ? hw_free - live : 0;
723 - frames_out_max = MIN(dead, hw_free);
724 - sw_max = st_rate_frames_in(sw->rate, frames_out_max);
725 - fe_max = MIN(buf_len / sw->info.bytes_per_frame + sw->resample_buf.pos,
726 - sw->resample_buf.size);
727 - frames_in_max = MIN(sw_max, fe_max);
728 -
729 - if (!frames_in_max) {
730 - return 0;
731 - }
732 -
733 - if (frames_in_max > sw->resample_buf.pos) {
734 - sw->conv(sw->resample_buf.buffer + sw->resample_buf.pos,
735 - buf, frames_in_max - sw->resample_buf.pos);
736 - if (!sw->hw->pcm_ops->volume_out) {
737 - mixeng_volume(sw->resample_buf.buffer + sw->resample_buf.pos,
738 - frames_in_max - sw->resample_buf.pos, &sw->vol);
739 - }
740 - }
741 -
742 - audio_pcm_sw_resample_out(sw, frames_in_max, frames_out_max,
743 - &total_in, &total_out);
744 -
745 - sw->total_hw_samples_mixed += total_out;
746 - sw->empty = sw->total_hw_samples_mixed == 0;
747 -
748 - /*
749 - * Upsampling may leave one audio frame in the resample buffer. Decrement
750 - * total_in by one if there was a leftover frame from the previous resample
751 - * pass in the resample buffer. Increment total_in by one if the current
752 - * resample pass left one frame in the resample buffer.
753 - */
754 - if (frames_in_max - total_in == 1) {
755 - /* copy one leftover audio frame to the beginning of the buffer */
756 - *sw->resample_buf.buffer = *(sw->resample_buf.buffer + total_in);
757 - total_in += 1 - sw->resample_buf.pos;
758 - sw->resample_buf.pos = 1;
759 - } else if (total_in >= sw->resample_buf.pos) {
760 - total_in -= sw->resample_buf.pos;
761 - sw->resample_buf.pos = 0;
762 - }
763 -
764 -#ifdef DEBUG_OUT
765 - dolog (
766 - "%s: write size %zu written %zu total mixed %zu\n",
767 - SW_NAME(sw),
768 - buf_len / sw->info.bytes_per_frame,
769 - total_in,
770 - sw->total_hw_samples_mixed
771 - );
772 -#endif
773 -
774 - return total_in * sw->info.bytes_per_frame;
775 -}
776 -
777 -#ifdef DEBUG_AUDIO
778 -static void audio_pcm_print_info (const char *cap, struct audio_pcm_info *info)
779 -{
780 - dolog("%s: bits %d, sign %d, float %d, freq %d, nchan %d\n",
781 - cap, info->bits, info->is_signed, info->is_float, info->freq,
782 - info->nchannels);
783 -}
784 -#endif
785 -
786 -#define DAC
787 -#include "audio_template.h"
788 -#undef DAC
789 -#include "audio_template.h"
790 -
791 -/*
792 - * Timer
793 - */
794 -static int audio_is_timer_needed(AudioMixengBackend *s)
795 -{
796 - HWVoiceIn *hwi = NULL;
797 - HWVoiceOut *hwo = NULL;
798 -
799 - while ((hwo = audio_pcm_hw_find_any_enabled_out(s, hwo))) {
800 - if (!hwo->poll_mode) {
801 - return 1;
802 - }
803 - }
804 - while ((hwi = audio_pcm_hw_find_any_enabled_in(s, hwi))) {
805 - if (!hwi->poll_mode) {
806 - return 1;
807 - }
808 - }
809 - return 0;
810 -}
811 -
812 -static void audio_reset_timer(AudioMixengBackend *s)
813 -{
814 - if (audio_is_timer_needed(s)) {
815 - timer_mod_anticipate_ns(s->ts,
816 - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->period_ticks);
817 - if (!s->timer_running) {
818 - s->timer_running = true;
819 - s->timer_last = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
820 - trace_audio_timer_start(s->period_ticks / SCALE_MS);
821 - }
822 - } else {
823 - timer_del(s->ts);
824 - if (s->timer_running) {
825 - s->timer_running = false;
826 - trace_audio_timer_stop();
827 - }
828 - }
829 -}
830 -
831 -static void audio_timer (void *opaque)
832 -{
833 - int64_t now, diff;
834 - AudioMixengBackend *s = opaque;
835 -
836 - now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
837 - diff = now - s->timer_last;
838 - if (diff > s->period_ticks * 3 / 2) {
839 - trace_audio_timer_delayed(diff / SCALE_MS);
840 - }
841 - s->timer_last = now;
842 -
843 - audio_run(s, "timer");
844 - audio_reset_timer(s);
845 -}
846 -
847 -/*
848 - * Public API
849 - */
850 -static size_t audio_mixeng_backend_write(AudioBackend *be, SWVoiceOut *sw,
851 - void *buf, size_t size)
852 -{
853 - HWVoiceOut *hw;
854 -
855 - if (!sw) {
856 - /* XXX: Consider options */
857 - return size;
858 - }
859 - hw = sw->hw;
860 -
861 - if (!hw->enabled) {
862 - dolog("Writing to disabled voice %s\n", SW_NAME(sw));
863 - return 0;
864 - }
865 -
866 - if (audio_get_pdo_out(hw->s->dev)->mixing_engine) {
867 - return audio_pcm_sw_write(sw, buf, size);
868 - } else {
869 - return hw->pcm_ops->write(hw, buf, size);
870 - }
871 -}
872 -
873 -static size_t audio_mixeng_backend_read(AudioBackend *be,
874 - SWVoiceIn *sw, void *buf, size_t size)
875 -{
876 - HWVoiceIn *hw;
877 -
878 - if (!sw) {
879 - /* XXX: Consider options */
880 - return size;
881 - }
882 - hw = sw->hw;
883 -
884 - if (!hw->enabled) {
885 - dolog("Reading from disabled voice %s\n", SW_NAME(sw));
886 - return 0;
887 - }
888 -
889 - if (audio_get_pdo_in(hw->s->dev)->mixing_engine) {
890 - return audio_pcm_sw_read(sw, buf, size);
891 - } else {
892 - return hw->pcm_ops->read(hw, buf, size);
893 - }
894 -
895 -}
896 -
897 -static int audio_mixeng_backend_get_buffer_size_out(AudioBackend *be, SWVoiceOut *sw)
898 -{
899 - if (!sw) {
900 - return 0;
901 - }
902 -
903 - if (audio_get_pdo_out(sw->s->dev)->mixing_engine) {
904 - return sw->resample_buf.size * sw->info.bytes_per_frame;
905 - }
906 -
907 - return sw->hw->samples * sw->hw->info.bytes_per_frame;
908 -}
909 -
910 -static void audio_mixeng_backend_set_active_out(AudioBackend *be, SWVoiceOut *sw,
911 - bool on)
912 -{
913 - HWVoiceOut *hw;
914 -
915 - if (!sw) {
916 - return;
917 - }
918 -
919 - hw = sw->hw;
920 - if (sw->active != on) {
921 - AudioMixengBackend *s = sw->s;
922 - SWVoiceOut *temp_sw;
923 - SWVoiceCap *sc;
924 -
925 - if (on) {
926 - hw->pending_disable = 0;
927 - if (!hw->enabled) {
928 - hw->enabled = true;
929 - if (runstate_is_running()) {
930 - if (hw->pcm_ops->enable_out) {
931 - hw->pcm_ops->enable_out(hw, true);
932 - }
933 - audio_reset_timer (s);
934 - }
935 - }
936 - } else {
937 - if (hw->enabled) {
938 - int nb_active = 0;
939 -
940 - for (temp_sw = hw->sw_head.lh_first; temp_sw;
941 - temp_sw = temp_sw->entries.le_next) {
942 - nb_active += temp_sw->active != 0;
943 - }
944 -
945 - hw->pending_disable = nb_active == 1;
946 - }
947 - }
948 -
949 - for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {
950 - sc->sw.active = hw->enabled;
951 - if (hw->enabled) {
952 - audio_capture_maybe_changed (sc->cap, 1);
953 - }
954 - }
955 - sw->active = on;
956 - }
957 -
958 -}
959 -
960 -static void audio_mixeng_backend_set_active_in(AudioBackend *be, SWVoiceIn *sw, bool on)
961 -{
962 - HWVoiceIn *hw;
963 -
964 - if (!sw) {
965 - return;
966 - }
967 -
968 - hw = sw->hw;
969 - if (sw->active != on) {
970 - AudioMixengBackend *s = sw->s;
971 - SWVoiceIn *temp_sw;
972 -
973 - if (on) {
974 - if (!hw->enabled) {
975 - hw->enabled = true;
976 - if (runstate_is_running()) {
977 - if (hw->pcm_ops->enable_in) {
978 - hw->pcm_ops->enable_in(hw, true);
979 - }
980 - audio_reset_timer (s);
981 - }
982 - }
983 - sw->total_hw_samples_acquired = hw->total_samples_captured;
984 - } else {
985 - if (hw->enabled) {
986 - int nb_active = 0;
987 -
988 - for (temp_sw = hw->sw_head.lh_first; temp_sw;
989 - temp_sw = temp_sw->entries.le_next) {
990 - nb_active += temp_sw->active != 0;
991 - }
992 -
993 - if (nb_active == 1) {
994 - hw->enabled = false;
995 - if (hw->pcm_ops->enable_in) {
996 - hw->pcm_ops->enable_in(hw, false);
997 - }
998 - }
999 - }
1000 - }
1001 - sw->active = on;
1002 - }
1003 -}
1004 -
1005 -static size_t audio_get_avail(SWVoiceIn *sw)
1006 -{
1007 - size_t live;
1008 -
1009 - if (!sw) {
1010 - return 0;
1011 - }
1012 -
1013 - live = sw->hw->total_samples_captured - sw->total_hw_samples_acquired;
1014 - if (audio_bug(__func__, live > sw->hw->conv_buf.size)) {
1015 - dolog("live=%zu sw->hw->conv_buf.size=%zu\n", live,
1016 - sw->hw->conv_buf.size);
1017 - return 0;
1018 - }
1019 -
1020 - ldebug (
1021 - "%s: get_avail live %zu frontend frames %u\n",
1022 - SW_NAME (sw),
1023 - live, st_rate_frames_out(sw->rate, live)
1024 - );
1025 -
1026 - return live;
1027 -}
1028 -
1029 -static size_t audio_get_free(SWVoiceOut *sw)
1030 -{
1031 - size_t live, dead;
1032 -
1033 - if (!sw) {
1034 - return 0;
1035 - }
1036 -
1037 - live = sw->total_hw_samples_mixed;
1038 -
1039 - if (audio_bug(__func__, live > sw->hw->mix_buf.size)) {
1040 - dolog("live=%zu sw->hw->mix_buf.size=%zu\n", live,
1041 - sw->hw->mix_buf.size);
1042 - return 0;
1043 - }
1044 -
1045 - dead = sw->hw->mix_buf.size - live;
1046 -
1047 -#ifdef DEBUG_OUT
1048 - dolog("%s: get_free live %zu dead %zu frontend frames %u\n",
1049 - SW_NAME(sw), live, dead, st_rate_frames_in(sw->rate, dead));
1050 -#endif
1051 -
1052 - return dead;
1053 -}
1054 -
1055 -static void audio_capture_mix_and_clear(HWVoiceOut *hw, size_t rpos,
1056 - size_t samples)
1057 -{
1058 - size_t n;
1059 -
1060 - if (hw->enabled) {
1061 - SWVoiceCap *sc;
1062 -
1063 - for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {
1064 - SWVoiceOut *sw = &sc->sw;
1065 - size_t rpos2 = rpos;
1066 -
1067 - n = samples;
1068 - while (n) {
1069 - size_t till_end_of_hw = hw->mix_buf.size - rpos2;
1070 - size_t to_read = MIN(till_end_of_hw, n);
1071 - size_t live, frames_in, frames_out;
1072 -
1073 - sw->resample_buf.buffer = hw->mix_buf.buffer + rpos2;
1074 - sw->resample_buf.size = to_read;
1075 - live = sw->total_hw_samples_mixed;
1076 -
1077 - audio_pcm_sw_resample_out(sw,
1078 - to_read, sw->hw->mix_buf.size - live,
1079 - &frames_in, &frames_out);
1080 -
1081 - sw->total_hw_samples_mixed += frames_out;
1082 - sw->empty = sw->total_hw_samples_mixed == 0;
1083 -
1084 - if (to_read - frames_in) {
1085 - dolog("Could not mix %zu frames into a capture "
1086 - "buffer, mixed %zu\n",
1087 - to_read, frames_in);
1088 - break;
1089 - }
1090 - n -= to_read;
1091 - rpos2 = (rpos2 + to_read) % hw->mix_buf.size;
1092 - }
1093 - }
1094 - }
1095 -
1096 - n = MIN(samples, hw->mix_buf.size - rpos);
1097 - mixeng_clear(hw->mix_buf.buffer + rpos, n);
1098 - mixeng_clear(hw->mix_buf.buffer, samples - n);
1099 -}
1100 -
1101 -static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live)
1102 -{
1103 - size_t clipped = 0;
1104 -
1105 - while (live) {
1106 - size_t size = live * hw->info.bytes_per_frame;
1107 - size_t decr, proc;
1108 - void *buf = hw->pcm_ops->get_buffer_out(hw, &size);
1109 -
1110 - if (size == 0) {
1111 - break;
1112 - }
1113 -
1114 - decr = MIN(size / hw->info.bytes_per_frame, live);
1115 - if (buf) {
1116 - audio_pcm_hw_clip_out(hw, buf, decr);
1117 - }
1118 - proc = hw->pcm_ops->put_buffer_out(hw, buf,
1119 - decr * hw->info.bytes_per_frame) /
1120 - hw->info.bytes_per_frame;
1121 -
1122 - live -= proc;
1123 - clipped += proc;
1124 - hw->mix_buf.pos = (hw->mix_buf.pos + proc) % hw->mix_buf.size;
1125 -
1126 - if (proc == 0 || proc < decr) {
1127 - break;
1128 - }
1129 - }
1130 -
1131 - if (hw->pcm_ops->run_buffer_out) {
1132 - hw->pcm_ops->run_buffer_out(hw);
1133 - }
1134 -
1135 - return clipped;
1136 -}
1137 -
1138 -static void audio_run_out(AudioMixengBackend *s)
1139 -{
1140 - HWVoiceOut *hw = NULL;
1141 - SWVoiceOut *sw;
1142 -
1143 - while ((hw = audio_pcm_hw_find_any_enabled_out(s, hw))) {
1144 - size_t played, live, prev_rpos;
1145 - size_t hw_free = audio_pcm_hw_get_free(hw);
1146 - int nb_live;
1147 -
1148 - if (!audio_get_pdo_out(s->dev)->mixing_engine) {
1149 - /* there is exactly 1 sw for each hw with no mixeng */
1150 - sw = hw->sw_head.lh_first;
1151 -
1152 - if (hw->pending_disable) {
1153 - hw->enabled = false;
1154 - hw->pending_disable = false;
1155 - if (hw->pcm_ops->enable_out) {
1156 - hw->pcm_ops->enable_out(hw, false);
1157 - }
1158 - }
1159 -
1160 - if (sw->active) {
1161 - sw->callback.fn(sw->callback.opaque,
1162 - hw_free * sw->info.bytes_per_frame);
1163 - }
1164 -
1165 - if (hw->pcm_ops->run_buffer_out) {
1166 - hw->pcm_ops->run_buffer_out(hw);
1167 - }
1168 -
1169 - continue;
1170 - }
1171 -
1172 - for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
1173 - if (sw->active) {
1174 - size_t sw_free = audio_get_free(sw);
1175 - size_t free;
1176 -
1177 - if (hw_free > sw->total_hw_samples_mixed) {
1178 - free = st_rate_frames_in(sw->rate,
1179 - MIN(sw_free, hw_free - sw->total_hw_samples_mixed));
1180 - } else {
1181 - free = 0;
1182 - }
1183 - if (free > sw->resample_buf.pos) {
1184 - free = MIN(free, sw->resample_buf.size)
1185 - - sw->resample_buf.pos;
1186 - sw->callback.fn(sw->callback.opaque,
1187 - free * sw->info.bytes_per_frame);
1188 - }
1189 - }
1190 - }
1191 -
1192 - live = audio_pcm_hw_get_live_out (hw, &nb_live);
1193 - if (!nb_live) {
1194 - live = 0;
1195 - }
1196 -
1197 - if (audio_bug(__func__, live > hw->mix_buf.size)) {
1198 - dolog("live=%zu hw->mix_buf.size=%zu\n", live, hw->mix_buf.size);
1199 - continue;
1200 - }
1201 -
1202 - if (hw->pending_disable && !nb_live) {
1203 - SWVoiceCap *sc;
1204 -#ifdef DEBUG_OUT
1205 - dolog ("Disabling voice\n");
1206 -#endif
1207 - hw->enabled = false;
1208 - hw->pending_disable = false;
1209 - if (hw->pcm_ops->enable_out) {
1210 - hw->pcm_ops->enable_out(hw, false);
1211 - }
1212 - for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {
1213 - sc->sw.active = false;
1214 - audio_recalc_and_notify_capture (sc->cap);
1215 - }
1216 - continue;
1217 - }
1218 -
1219 - if (!live) {
1220 - if (hw->pcm_ops->run_buffer_out) {
1221 - hw->pcm_ops->run_buffer_out(hw);
1222 - }
1223 - continue;
1224 - }
1225 -
1226 - prev_rpos = hw->mix_buf.pos;
1227 - played = audio_pcm_hw_run_out(hw, live);
1228 - replay_audio_out(&played);
1229 - if (audio_bug(__func__, hw->mix_buf.pos >= hw->mix_buf.size)) {
1230 - dolog("hw->mix_buf.pos=%zu hw->mix_buf.size=%zu played=%zu\n",
1231 - hw->mix_buf.pos, hw->mix_buf.size, played);
1232 - hw->mix_buf.pos = 0;
1233 - }
1234 -
1235 -#ifdef DEBUG_OUT
1236 - dolog("played=%zu\n", played);
1237 -#endif
1238 -
1239 - if (played) {
1240 - audio_capture_mix_and_clear (hw, prev_rpos, played);
1241 - }
1242 -
1243 - for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
1244 - if (!sw->active && sw->empty) {
1245 - continue;
1246 - }
1247 -
1248 - if (audio_bug(__func__, played > sw->total_hw_samples_mixed)) {
1249 - dolog("played=%zu sw->total_hw_samples_mixed=%zu\n",
1250 - played, sw->total_hw_samples_mixed);
1251 - played = sw->total_hw_samples_mixed;
1252 - }
1253 -
1254 - sw->total_hw_samples_mixed -= played;
1255 -
1256 - if (!sw->total_hw_samples_mixed) {
1257 - sw->empty = true;
1258 - }
1259 - }
1260 - }
1261 -}
1262 -
1263 -static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples)
1264 -{
1265 - size_t conv = 0;
1266 -
1267 - if (hw->pcm_ops->run_buffer_in) {
1268 - hw->pcm_ops->run_buffer_in(hw);
1269 - }
1270 -
1271 - while (samples) {
1272 - size_t proc;
1273 - size_t size = samples * hw->info.bytes_per_frame;
1274 - void *buf = hw->pcm_ops->get_buffer_in(hw, &size);
1275 -
1276 - assert(size % hw->info.bytes_per_frame == 0);
1277 - if (size == 0) {
1278 - break;
1279 - }
1280 -
1281 - proc = audio_pcm_hw_conv_in(hw, buf, size / hw->info.bytes_per_frame);
1282 -
1283 - samples -= proc;
1284 - conv += proc;
1285 - hw->pcm_ops->put_buffer_in(hw, buf, proc * hw->info.bytes_per_frame);
1286 - }
1287 -
1288 - return conv;
1289 -}
1290 -
1291 -static void audio_run_in(AudioMixengBackend *s)
1292 -{
1293 - HWVoiceIn *hw = NULL;
1294 -
1295 - if (!audio_get_pdo_in(s->dev)->mixing_engine) {
1296 - while ((hw = audio_pcm_hw_find_any_enabled_in(s, hw))) {
1297 - /* there is exactly 1 sw for each hw with no mixeng */
1298 - SWVoiceIn *sw = hw->sw_head.lh_first;
1299 - if (sw->active) {
1300 - sw->callback.fn(sw->callback.opaque, INT_MAX);
1301 - }
1302 - }
1303 - return;
1304 - }
1305 -
1306 - while ((hw = audio_pcm_hw_find_any_enabled_in(s, hw))) {
1307 - SWVoiceIn *sw;
1308 - size_t captured = 0, min;
1309 - int pos;
1310 -
1311 - if (replay_mode != REPLAY_MODE_PLAY) {
1312 - captured = audio_pcm_hw_run_in(
1313 - hw, hw->conv_buf.size - audio_pcm_hw_get_live_in(hw));
1314 - }
1315 -
1316 - replay_audio_in_start(&captured);
1317 - assert(captured <= hw->conv_buf.size);
1318 - if (replay_mode == REPLAY_MODE_PLAY) {
1319 - hw->conv_buf.pos = (hw->conv_buf.pos + captured) % hw->conv_buf.size;
1320 - }
1321 - for (pos = (hw->conv_buf.pos - captured + hw->conv_buf.size) % hw->conv_buf.size;
1322 - pos != hw->conv_buf.pos;
1323 - pos = (pos + 1) % hw->conv_buf.size) {
1324 - uint64_t left, right;
1325 -
1326 - if (replay_mode == REPLAY_MODE_RECORD) {
1327 - audio_sample_to_uint64(hw->conv_buf.buffer, pos, &left, &right);
1328 - }
1329 - replay_audio_in_sample_lr(&left, &right);
1330 - if (replay_mode == REPLAY_MODE_PLAY) {
1331 - audio_sample_from_uint64(hw->conv_buf.buffer, pos, left, right);
1332 - }
1333 - }
1334 - replay_audio_in_finish();
1335 -
1336 - min = audio_pcm_hw_find_min_in (hw);
1337 - hw->total_samples_captured += captured - min;
1338 -
1339 - for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
1340 - sw->total_hw_samples_acquired -= min;
1341 -
1342 - if (sw->active) {
1343 - size_t sw_avail = audio_get_avail(sw);
1344 - size_t avail;
1345 -
1346 - avail = st_rate_frames_out(sw->rate, sw_avail);
1347 - if (avail > 0) {
1348 - avail = MIN(avail, sw->resample_buf.size);
1349 - sw->callback.fn(sw->callback.opaque,
1350 - avail * sw->info.bytes_per_frame);
1351 - }
1352 - }
1353 - }
1354 - }
1355 -}
1356 -
1357 -static void audio_run_capture(AudioMixengBackend *s)
1358 -{
1359 - CaptureVoiceOut *cap;
1360 -
1361 - for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) {
1362 - size_t live, rpos, captured;
1363 - HWVoiceOut *hw = &cap->hw;
1364 - SWVoiceOut *sw;
1365 -
1366 - captured = live = audio_pcm_hw_get_live_out (hw, NULL);
1367 - rpos = hw->mix_buf.pos;
1368 - while (live) {
1369 - size_t left = hw->mix_buf.size - rpos;
1370 - size_t to_capture = MIN(live, left);
1371 - struct st_sample *src;
1372 - struct capture_callback *cb;
1373 -
1374 - src = hw->mix_buf.buffer + rpos;
1375 - hw->clip (cap->buf, src, to_capture);
1376 - mixeng_clear (src, to_capture);
1377 -
1378 - for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
1379 - cb->ops.capture (cb->opaque, cap->buf,
1380 - to_capture * hw->info.bytes_per_frame);
1381 - }
1382 - rpos = (rpos + to_capture) % hw->mix_buf.size;
1383 - live -= to_capture;
1384 - }
1385 - hw->mix_buf.pos = rpos;
1386 -
1387 - for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
1388 - if (!sw->active && sw->empty) {
1389 - continue;
1390 - }
1391 -
1392 - if (audio_bug(__func__, captured > sw->total_hw_samples_mixed)) {
1393 - dolog("captured=%zu sw->total_hw_samples_mixed=%zu\n",
1394 - captured, sw->total_hw_samples_mixed);
1395 - captured = sw->total_hw_samples_mixed;
1396 - }
1397 -
1398 - sw->total_hw_samples_mixed -= captured;
1399 - sw->empty = sw->total_hw_samples_mixed == 0;
1400 - }
1401 - }
1402 -}
1403 -
1404 -void audio_run(AudioMixengBackend *s, const char *msg)
1405 -{
1406 - audio_run_out(s);
1407 - audio_run_in(s);
1408 - audio_run_capture(s);
1409 -
1410 -#ifdef DEBUG_POLL
1411 - {
1412 - static double prevtime;
1413 - double currtime;
1414 - struct timeval tv;
1415 -
1416 - if (gettimeofday (&tv, NULL)) {
1417 - perror ("audio_run: gettimeofday");
1418 - return;
1419 - }
1420 -
1421 - currtime = tv.tv_sec + tv.tv_usec * 1e-6;
1422 - dolog ("Elapsed since last %s: %f\n", msg, currtime - prevtime);
1423 - prevtime = currtime;
1424 - }
1425 -#endif
1426 -}
1427 -
1428 -void audio_generic_run_buffer_in(HWVoiceIn *hw)
1429 -{
1430 - if (unlikely(!hw->buf_emul)) {
1431 - hw->size_emul = hw->samples * hw->info.bytes_per_frame;
1432 - hw->buf_emul = g_malloc(hw->size_emul);
1433 - hw->pos_emul = hw->pending_emul = 0;
1434 - }
1435 -
1436 - while (hw->pending_emul < hw->size_emul) {
1437 - size_t read_len = MIN(hw->size_emul - hw->pos_emul,
1438 - hw->size_emul - hw->pending_emul);
1439 - size_t read = hw->pcm_ops->read(hw, hw->buf_emul + hw->pos_emul,
1440 - read_len);
1441 - hw->pending_emul += read;
1442 - hw->pos_emul = (hw->pos_emul + read) % hw->size_emul;
1443 - if (read < read_len) {
1444 - break;
1445 - }
1446 - }
1447 -}
1448 -
1449 -void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size)
1450 -{
1451 - size_t start;
1452 -
1453 - start = audio_ring_posb(hw->pos_emul, hw->pending_emul, hw->size_emul);
1454 - assert(start < hw->size_emul);
1455 -
1456 - *size = MIN(*size, hw->pending_emul);
1457 - *size = MIN(*size, hw->size_emul - start);
1458 - return hw->buf_emul + start;
1459 -}
1460 -
1461 -void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size)
1462 -{
1463 - assert(size <= hw->pending_emul);
1464 - hw->pending_emul -= size;
1465 -}
1466 -
1467 -size_t audio_generic_buffer_get_free(HWVoiceOut *hw)
1468 -{
1469 - if (hw->buf_emul) {
1470 - return hw->size_emul - hw->pending_emul;
1471 - } else {
1472 - return hw->samples * hw->info.bytes_per_frame;
1473 - }
1474 -}
1475 -
1476 -void audio_generic_run_buffer_out(HWVoiceOut *hw)
1477 -{
1478 - while (hw->pending_emul) {
1479 - size_t write_len, written, start;
1480 -
1481 - start = audio_ring_posb(hw->pos_emul, hw->pending_emul, hw->size_emul);
1482 - assert(start < hw->size_emul);
1483 -
1484 - write_len = MIN(hw->pending_emul, hw->size_emul - start);
1485 -
1486 - written = hw->pcm_ops->write(hw, hw->buf_emul + start, write_len);
1487 - hw->pending_emul -= written;
1488 -
1489 - if (written < write_len) {
1490 - break;
1491 - }
1492 - }
1493 -}
1494 -
1495 -void *audio_generic_get_buffer_out(HWVoiceOut *hw, size_t *size)
1496 -{
1497 - if (unlikely(!hw->buf_emul)) {
1498 - hw->size_emul = hw->samples * hw->info.bytes_per_frame;
1499 - hw->buf_emul = g_malloc(hw->size_emul);
1500 - hw->pos_emul = hw->pending_emul = 0;
1501 - }
1502 -
1503 - *size = MIN(hw->size_emul - hw->pending_emul,
1504 - hw->size_emul - hw->pos_emul);
1505 - return hw->buf_emul + hw->pos_emul;
1506 -}
1507 -
1508 -size_t audio_generic_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size)
1509 -{
1510 - assert(buf == hw->buf_emul + hw->pos_emul &&
1511 - size + hw->pending_emul <= hw->size_emul);
1512 -
1513 - hw->pending_emul += size;
1514 - hw->pos_emul = (hw->pos_emul + size) % hw->size_emul;
1515 -
1516 - return size;
1517 -}
1518 -
1519 -size_t audio_generic_write(HWVoiceOut *hw, void *buf, size_t size)
1520 -{
1521 - size_t total = 0;
1522 -
1523 - if (hw->pcm_ops->buffer_get_free) {
1524 - size_t free = hw->pcm_ops->buffer_get_free(hw);
1525 -
1526 - size = MIN(size, free);
1527 - }
1528 -
1529 - while (total < size) {
1530 - size_t dst_size = size - total;
1531 - size_t copy_size, proc;
1532 - void *dst = hw->pcm_ops->get_buffer_out(hw, &dst_size);
1533 -
1534 - if (dst_size == 0) {
1535 - break;
1536 - }
1537 -
1538 - copy_size = MIN(size - total, dst_size);
1539 - if (dst) {
1540 - memcpy(dst, (char *)buf + total, copy_size);
1541 - }
1542 - proc = hw->pcm_ops->put_buffer_out(hw, dst, copy_size);
1543 - total += proc;
1544 -
1545 - if (proc == 0 || proc < copy_size) {
1546 - break;
1547 - }
1548 - }
1549 -
1550 - return total;
1551 -}
1552 -
1553 -size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size)
1554 -{
1555 - size_t total = 0;
1556 -
1557 - if (hw->pcm_ops->run_buffer_in) {
1558 - hw->pcm_ops->run_buffer_in(hw);
1559 - }
1560 -
1561 - while (total < size) {
1562 - size_t src_size = size - total;
1563 - void *src = hw->pcm_ops->get_buffer_in(hw, &src_size);
1564 -
1565 - if (src_size == 0) {
1566 - break;
1567 - }
1568 -
1569 - memcpy((char *)buf + total, src, src_size);
1570 - hw->pcm_ops->put_buffer_in(hw, src, src_size);
1571 - total += src_size;
1572 - }
1573 -
1574 - return total;
1575 -}
1576 -
1577 -static bool audio_mixeng_backend_realize(AudioBackend *abe,
1578 - Audiodev *dev, Error **errp)
1579 -{
1580 - AudioMixengBackend *be = AUDIO_MIXENG_BACKEND(abe);
1581 - audio_driver *drv = AUDIO_MIXENG_BACKEND_GET_CLASS(be)->driver;
1582 -
1583 - be->dev = dev;
1584 - be->drv_opaque = drv->init(be->dev, errp);
1585 - if (!be->drv_opaque) {
1586 - return false;
1587 - }
1588 -
1589 - if (!drv->pcm_ops->get_buffer_in) {
1590 - drv->pcm_ops->get_buffer_in = audio_generic_get_buffer_in;
1591 - drv->pcm_ops->put_buffer_in = audio_generic_put_buffer_in;
1592 - }
1593 - if (!drv->pcm_ops->get_buffer_out) {
1594 - drv->pcm_ops->get_buffer_out = audio_generic_get_buffer_out;
1595 - drv->pcm_ops->put_buffer_out = audio_generic_put_buffer_out;
1596 - }
1597 -
1598 - audio_init_nb_voices_out(be, drv, 1);
1599 - audio_init_nb_voices_in(be, drv, 0);
1600 - be->drv = drv;
1601 -
1602 - if (be->dev->timer_period <= 0) {
1603 - be->period_ticks = 1;
1604 - } else {
1605 - be->period_ticks = be->dev->timer_period * (int64_t)SCALE_US;
1606 - }
1607 -
1608 - return true;
1609 -}
1610 -
1611 -static void audio_vm_change_state_handler (void *opaque, bool running,
1612 - RunState state)
1613 -{
1614 - AudioMixengBackend *s = opaque;
1615 - HWVoiceOut *hwo = NULL;
1616 - HWVoiceIn *hwi = NULL;
1617 -
1618 - while ((hwo = audio_pcm_hw_find_any_enabled_out(s, hwo))) {
1619 - if (hwo->pcm_ops->enable_out) {
1620 - hwo->pcm_ops->enable_out(hwo, running);
1621 - }
1622 - }
1623 -
1624 - while ((hwi = audio_pcm_hw_find_any_enabled_in(s, hwi))) {
1625 - if (hwi->pcm_ops->enable_in) {
1626 - hwi->pcm_ops->enable_in(hwi, running);
1627 - }
1628 - }
1629 - audio_reset_timer (s);
1630 -}
1631 -
1632 -static const VMStateDescription vmstate_audio;
1633 -
1634 -static const char *audio_mixeng_backend_get_id(AudioBackend *be)
1635 -{
1636 - return AUDIO_MIXENG_BACKEND(be)->dev->id;
1637 -}
1638 -
1639 -static CaptureVoiceOut *audio_mixeng_backend_add_capture(
1640 - AudioBackend *be,
1641 - struct audsettings *as,
1642 - struct audio_capture_ops *ops,
1643 - void *cb_opaque);
1644 -
1645 -static void audio_mixeng_backend_del_capture(
1646 - AudioBackend *be,
1647 - CaptureVoiceOut *cap,
1648 - void *cb_opaque);
1649 -
1650 -static void audio_mixeng_backend_set_volume_out(AudioBackend *be, SWVoiceOut *sw,
1651 - Volume *vol);
1652 -static void audio_mixeng_backend_set_volume_in(AudioBackend *be, SWVoiceIn *sw,
1653 - Volume *vol);
1654 -
1655 -static void audio_mixeng_backend_class_init(ObjectClass *klass, const void *data)
1656 -{
1657 - AudioBackendClass *be = AUDIO_BACKEND_CLASS(klass);
1658 -
1659 - be->realize = audio_mixeng_backend_realize;
1660 - be->get_id = audio_mixeng_backend_get_id;
1661 - be->open_in = audio_mixeng_backend_open_in;
1662 - be->open_out = audio_mixeng_backend_open_out;
1663 - be->close_in = audio_mixeng_backend_close_in;
1664 - be->close_out = audio_mixeng_backend_close_out;
1665 - be->is_active_out = audio_mixeng_backend_is_active_out;
1666 - be->is_active_in = audio_mixeng_backend_is_active_in;
1667 - be->set_active_out = audio_mixeng_backend_set_active_out;
1668 - be->set_active_in = audio_mixeng_backend_set_active_in;
1669 - be->set_volume_out = audio_mixeng_backend_set_volume_out;
1670 - be->set_volume_in = audio_mixeng_backend_set_volume_in;
1671 - be->read = audio_mixeng_backend_read;
1672 - be->write = audio_mixeng_backend_write;
1673 - be->get_buffer_size_out = audio_mixeng_backend_get_buffer_size_out;
1674 - be->add_capture = audio_mixeng_backend_add_capture;
1675 - be->del_capture = audio_mixeng_backend_del_capture;
1676 -}
1677 -
1678 -static void audio_mixeng_backend_init(Object *obj)
1679 -{
1680 - AudioMixengBackend *s = AUDIO_MIXENG_BACKEND(obj);
1681 -
1682 - QLIST_INIT(&s->hw_head_out);
1683 - QLIST_INIT(&s->hw_head_in);
1684 - QLIST_INIT(&s->cap_head);
1685 - s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s);
1686 -
1687 - s->vmse = qemu_add_vm_change_state_handler(audio_vm_change_state_handler, s);
1688 - assert(s->vmse != NULL);
1689 -
1690 - vmstate_register_any(NULL, &vmstate_audio, s);
1691 -}
1692 -
1693 -static void audio_mixeng_backend_finalize(Object *obj)
1694 -{
1695 - AudioMixengBackend *s = AUDIO_MIXENG_BACKEND(obj);
1696 - HWVoiceOut *hwo, *hwon;
1697 - HWVoiceIn *hwi, *hwin;
1698 -
1699 - QLIST_FOREACH_SAFE(hwo, &s->hw_head_out, entries, hwon) {
1700 - SWVoiceCap *sc;
1 +/* SPDX-License-Identifier: MIT */
2
1702 - if (hwo->enabled && hwo->pcm_ops->enable_out) {
1703 - hwo->pcm_ops->enable_out(hwo, false);
1704 - }
1705 - hwo->pcm_ops->fini_out (hwo);
1706 -
1707 - for (sc = hwo->cap_head.lh_first; sc; sc = sc->entries.le_next) {
1708 - CaptureVoiceOut *cap = sc->cap;
1709 - struct capture_callback *cb;
3 +#include "qemu/osdep.h"
4 +#include "qemu/audio.h"
5 +#include "qemu/help_option.h"
6 +#include "qapi/clone-visitor.h"
7 +#include "qapi/qobject-input-visitor.h"
8 +#include "qapi/qapi-visit-audio.h"
9 +#include "qapi/qapi-commands-audio.h"
10 +#include "qobject/qdict.h"
11 +#include "system/system.h"
12
1711 - for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
1712 - cb->ops.destroy (cb->opaque);
1713 - }
1714 - }
1715 - QLIST_REMOVE(hwo, entries);
1716 - }
13 +/* Order of CONFIG_AUDIO_DRIVERS is import.
14 + The 1st one is the one used by default, that is the reason
15 + that we generate the list.
16 +*/
17 +const char *audio_prio_list[] = {
18 +#ifdef CONFIG_GIO
19 + "dbus",
20 +#endif
21 + "spice",
22 + CONFIG_AUDIO_DRIVERS
23 + "none",
24 + NULL
25 +};
26
1718 - QLIST_FOREACH_SAFE(hwi, &s->hw_head_in, entries, hwin) {
1719 - if (hwi->enabled && hwi->pcm_ops->enable_in) {
1720 - hwi->pcm_ops->enable_in(hwi, false);
1721 - }
1722 - hwi->pcm_ops->fini_in (hwi);
1723 - QLIST_REMOVE(hwi, entries);
1724 - }
27 +typedef struct AudiodevListEntry {
28 + Audiodev *dev;
29 + QSIMPLEQ_ENTRY(AudiodevListEntry) next;
30 +} AudiodevListEntry;
31
1726 - if (s->drv) {
1727 - s->drv->fini (s->drv_opaque);
1728 - s->drv = NULL;
1729 - }
32 +typedef QSIMPLEQ_HEAD(, AudiodevListEntry) AudiodevListHead;
33
1731 - if (s->dev) {
1732 - qapi_free_Audiodev(s->dev);
1733 - s->dev = NULL;
1734 - }
34 +static AudiodevListHead audiodevs =
35 + QSIMPLEQ_HEAD_INITIALIZER(audiodevs);
36 +static AudiodevListHead default_audiodevs =
37 + QSIMPLEQ_HEAD_INITIALIZER(default_audiodevs);
38
1736 - if (s->ts) {
1737 - timer_free(s->ts);
1738 - s->ts = NULL;
1739 - }
39 +static AudioBackendClass *audio_be_class_by_name(const char *name)
40 +{
41 + g_autofree char *tname = g_strconcat("audio-", name, NULL);
42 + ObjectClass *oc = module_object_class_by_name(tname);
43
1741 - if (s->vmse) {
1742 - qemu_del_vm_change_state_handler(s->vmse);
1743 - s->vmse = NULL;
44 + if (!oc || !object_class_dynamic_cast(oc, TYPE_AUDIO_BACKEND)) {
45 + return NULL;
46 }
47
1746 - vmstate_unregister(NULL, &vmstate_audio, s);
48 + return AUDIO_BACKEND_CLASS(oc);
49 }
50
51 +static AudioBackend *default_audio_be;
52 +
53 static Object *get_audiodevs_root(void)
54 {
55 return object_get_container("audiodevs");
@@ -1758,25 +62,6 @@ void audio_cleanup(void)
62 object_unparent(get_audiodevs_root());
63 }
64
1761 -static bool vmstate_audio_needed(void *opaque)
1762 -{
1763 - /*
1764 - * Never needed, this vmstate only exists in case
1765 - * an old qemu sends it to us.
1766 - */
1767 - return false;
1768 -}
1769 -
1770 -static const VMStateDescription vmstate_audio = {
1771 - .name = "audio",
1772 - .version_id = 1,
1773 - .minimum_version_id = 1,
1774 - .needed = vmstate_audio_needed,
1775 - .fields = (const VMStateField[]) {
1776 - VMSTATE_END_OF_LIST()
1777 - }
1778 -};
1779 -
65 void audio_create_default_audiodevs(void)
66 {
67 for (int i = 0; audio_prio_list[i]; i++) {
@@ -1817,15 +102,13 @@ static AudioBackend *audio_init(Audiodev *dev, Error **errp)
102 assert(!default_audio_be);
103 for (;;) {
104 AudiodevListEntry *e = QSIMPLEQ_FIRST(&default_audiodevs);
1820 -
105 if (!e) {
106 error_setg(errp, "no default audio driver available");
107 return NULL;
108 }
1825 - dev = e->dev;
109 QSIMPLEQ_REMOVE_HEAD(&default_audiodevs, next);
110 + be = audio_be_new(e->dev, NULL);
111 g_free(e);
1828 - be = audio_be_new(dev, NULL);
112 if (be) {
113 break;
114 }
@@ -1856,156 +139,35 @@ AudioBackend *audio_get_default_audio_be(Error **errp)
139 return default_audio_be;
140 }
141
1859 -static struct audio_pcm_ops capture_pcm_ops;
1860 -
1861 -static CaptureVoiceOut *audio_mixeng_backend_add_capture(
1862 - AudioBackend *be,
1863 - struct audsettings *as,
1864 - struct audio_capture_ops *ops,
1865 - void *cb_opaque)
1866 -{
1867 - AudioMixengBackend *s = AUDIO_MIXENG_BACKEND(be);
1868 - CaptureVoiceOut *cap;
1869 - struct capture_callback *cb;
1870 -
1871 - if (!s) {
1872 - error_report("Capturing without setting an audiodev is not supported");
1873 - abort();
1874 - }
1875 -
1876 - if (!audio_get_pdo_out(s->dev)->mixing_engine) {
1877 - dolog("Can't capture with mixeng disabled\n");
1878 - return NULL;
1879 - }
1880 -
1881 - if (audio_validate_settings (as)) {
1882 - dolog ("Invalid settings were passed when trying to add capture\n");
1883 - audio_print_settings (as);
1884 - return NULL;
1885 - }
1886 -
1887 - cb = g_malloc0(sizeof(*cb));
1888 - cb->ops = *ops;
1889 - cb->opaque = cb_opaque;
1890 -
1891 - cap = audio_pcm_capture_find_specific(s, as);
1892 - if (cap) {
1893 - QLIST_INSERT_HEAD (&cap->cb_head, cb, entries);
1894 - } else {
1895 - HWVoiceOut *hw;
1896 -
1897 - cap = g_malloc0(sizeof(*cap));
1898 -
1899 - hw = &cap->hw;
1900 - hw->s = s;
1901 - hw->pcm_ops = &capture_pcm_ops;
1902 - QLIST_INIT (&hw->sw_head);
1903 - QLIST_INIT (&cap->cb_head);
1904 -
1905 - /* XXX find a more elegant way */
1906 - hw->samples = 4096 * 4;
1907 - audio_pcm_hw_alloc_resources_out(hw);
1908 -
1909 - audio_pcm_init_info (&hw->info, as);
1910 -
1911 - cap->buf = g_malloc0_n(hw->mix_buf.size, hw->info.bytes_per_frame);
1912 -
1913 - if (hw->info.is_float) {
1914 - hw->clip = mixeng_clip_float[hw->info.nchannels == 2]
1915 - [hw->info.swap_endianness];
1916 - } else {
1917 - hw->clip = mixeng_clip
1918 - [hw->info.nchannels == 2]
1919 - [hw->info.is_signed]
1920 - [hw->info.swap_endianness]
1921 - [audio_bits_to_index(hw->info.bits)];
1922 - }
1923 -
1924 - QLIST_INSERT_HEAD (&s->cap_head, cap, entries);
1925 - QLIST_INSERT_HEAD (&cap->cb_head, cb, entries);
1926 -
1927 - QLIST_FOREACH(hw, &s->hw_head_out, entries) {
1928 - audio_attach_capture (hw);
1929 - }
1930 - }
1931 -
1932 - return cap;
1933 -}
1934 -
1935 -static void audio_mixeng_backend_del_capture(
1936 - AudioBackend *be,
1937 - CaptureVoiceOut *cap,
1938 - void *cb_opaque)
142 +void audio_help(void)
143 {
1940 - struct capture_callback *cb;
1941 -
1942 - for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
1943 - if (cb->opaque == cb_opaque) {
1944 - cb->ops.destroy (cb_opaque);
1945 - QLIST_REMOVE (cb, entries);
1946 - g_free (cb);
144 + int i;
145
1948 - if (!cap->cb_head.lh_first) {
1949 - SWVoiceOut *sw = cap->hw.sw_head.lh_first, *sw1;
146 + printf("Available audio drivers:\n");
147
1951 - while (sw) {
1952 - SWVoiceCap *sc = (SWVoiceCap *) sw;
1953 -#ifdef DEBUG_CAPTURE
1954 - dolog ("freeing %s\n", sw->name);
1955 -#endif
148 + for (i = 0; i < AUDIODEV_DRIVER__MAX; i++) {
149 + const char *name = AudiodevDriver_str(i);
150 + AudioBackendClass *be = audio_be_class_by_name(name);
151
1957 - sw1 = sw->entries.le_next;
1958 - if (sw->rate) {
1959 - st_rate_stop (sw->rate);
1960 - sw->rate = NULL;
1961 - }
1962 - QLIST_REMOVE (sw, entries);
1963 - QLIST_REMOVE (sc, entries);
1964 - g_free (sc);
1965 - sw = sw1;
1966 - }
1967 - QLIST_REMOVE (cap, entries);
1968 - g_free(cap->hw.mix_buf.buffer);
1969 - g_free (cap->buf);
1970 - g_free (cap);
1971 - }
1972 - return;
152 + if (be) {
153 + printf("%s\n", name);
154 }
155 }
156 }
157
1977 -static void audio_mixeng_backend_set_volume_out(AudioBackend *be, SWVoiceOut *sw,
1978 - Volume *vol)
158 +void audio_parse_option(const char *opt)
159 {
1980 - if (sw) {
1981 - HWVoiceOut *hw = sw->hw;
1982 -
1983 - sw->vol.mute = vol->mute;
1984 - sw->vol.l = nominal_volume.l * vol->vol[0] / 255;
1985 - sw->vol.r = nominal_volume.l * vol->vol[vol->channels > 1 ? 1 : 0] /
1986 - 255;
160 + Audiodev *dev = NULL;
161
1988 - if (hw->pcm_ops->volume_out) {
1989 - hw->pcm_ops->volume_out(hw, vol);
1990 - }
162 + if (is_help_option(opt)) {
163 + audio_help();
164 + exit(EXIT_SUCCESS);
165 }
1992 -}
1993 -
1994 -static void audio_mixeng_backend_set_volume_in(AudioBackend *be, SWVoiceIn *sw,
1995 - Volume *vol)
1996 -{
1997 - if (sw) {
1998 - HWVoiceIn *hw = sw->hw;
1999 -
2000 - sw->vol.mute = vol->mute;
2001 - sw->vol.l = nominal_volume.l * vol->vol[0] / 255;
2002 - sw->vol.r = nominal_volume.r * vol->vol[vol->channels > 1 ? 1 : 0] /
2003 - 255;
166 + Visitor *v = qobject_input_visitor_new_str(opt, "driver", &error_fatal);
167 + visit_type_Audiodev(v, NULL, &dev, &error_fatal);
168 + visit_free(v);
169
2005 - if (hw->pcm_ops->volume_in) {
2006 - hw->pcm_ops->volume_in(hw, vol);
2007 - }
2008 - }
170 + audio_add_audiodev(dev);
171 }
172
173 static void audio_create_pdos(Audiodev *dev)
@@ -2104,6 +266,124 @@ static void audio_validate_per_direction_opts(
266 }
267 }
268
269 +static AudiodevPerDirectionOptions *audio_get_pdo_out(Audiodev *dev)
270 +{
271 + switch (dev->driver) {
272 + case AUDIODEV_DRIVER_NONE:
273 + return dev->u.none.out;
274 +#ifdef CONFIG_AUDIO_ALSA
275 + case AUDIODEV_DRIVER_ALSA:
276 + return qapi_AudiodevAlsaPerDirectionOptions_base(dev->u.alsa.out);
277 +#endif
278 +#ifdef CONFIG_AUDIO_COREAUDIO
279 + case AUDIODEV_DRIVER_COREAUDIO:
280 + return qapi_AudiodevCoreaudioPerDirectionOptions_base(
281 + dev->u.coreaudio.out);
282 +#endif
283 +#ifdef CONFIG_DBUS_DISPLAY
284 + case AUDIODEV_DRIVER_DBUS:
285 + return dev->u.dbus.out;
286 +#endif
287 +#ifdef CONFIG_AUDIO_DSOUND
288 + case AUDIODEV_DRIVER_DSOUND:
289 + return dev->u.dsound.out;
290 +#endif
291 +#ifdef CONFIG_AUDIO_JACK
292 + case AUDIODEV_DRIVER_JACK:
293 + return qapi_AudiodevJackPerDirectionOptions_base(dev->u.jack.out);
294 +#endif
295 +#ifdef CONFIG_AUDIO_OSS
296 + case AUDIODEV_DRIVER_OSS:
297 + return qapi_AudiodevOssPerDirectionOptions_base(dev->u.oss.out);
298 +#endif
299 +#ifdef CONFIG_AUDIO_PA
300 + case AUDIODEV_DRIVER_PA:
301 + return qapi_AudiodevPaPerDirectionOptions_base(dev->u.pa.out);
302 +#endif
303 +#ifdef CONFIG_AUDIO_PIPEWIRE
304 + case AUDIODEV_DRIVER_PIPEWIRE:
305 + return qapi_AudiodevPipewirePerDirectionOptions_base(dev->u.pipewire.out);
306 +#endif
307 +#ifdef CONFIG_AUDIO_SDL
308 + case AUDIODEV_DRIVER_SDL:
309 + return qapi_AudiodevSdlPerDirectionOptions_base(dev->u.sdl.out);
310 +#endif
311 +#ifdef CONFIG_AUDIO_SNDIO
312 + case AUDIODEV_DRIVER_SNDIO:
313 + return dev->u.sndio.out;
314 +#endif
315 +#ifdef CONFIG_SPICE
316 + case AUDIODEV_DRIVER_SPICE:
317 + return dev->u.spice.out;
318 +#endif
319 + case AUDIODEV_DRIVER_WAV:
320 + return dev->u.wav.out;
321 +
322 + case AUDIODEV_DRIVER__MAX:
323 + break;
324 + }
325 + abort();
326 +}
327 +
328 +static AudiodevPerDirectionOptions *audio_get_pdo_in(Audiodev *dev)
329 +{
330 + switch (dev->driver) {
331 + case AUDIODEV_DRIVER_NONE:
332 + return dev->u.none.in;
333 +#ifdef CONFIG_AUDIO_ALSA
334 + case AUDIODEV_DRIVER_ALSA:
335 + return qapi_AudiodevAlsaPerDirectionOptions_base(dev->u.alsa.in);
336 +#endif
337 +#ifdef CONFIG_AUDIO_COREAUDIO
338 + case AUDIODEV_DRIVER_COREAUDIO:
339 + return qapi_AudiodevCoreaudioPerDirectionOptions_base(
340 + dev->u.coreaudio.in);
341 +#endif
342 +#ifdef CONFIG_DBUS_DISPLAY
343 + case AUDIODEV_DRIVER_DBUS:
344 + return dev->u.dbus.in;
345 +#endif
346 +#ifdef CONFIG_AUDIO_DSOUND
347 + case AUDIODEV_DRIVER_DSOUND:
348 + return dev->u.dsound.in;
349 +#endif
350 +#ifdef CONFIG_AUDIO_JACK
351 + case AUDIODEV_DRIVER_JACK:
352 + return qapi_AudiodevJackPerDirectionOptions_base(dev->u.jack.in);
353 +#endif
354 +#ifdef CONFIG_AUDIO_OSS
355 + case AUDIODEV_DRIVER_OSS:
356 + return qapi_AudiodevOssPerDirectionOptions_base(dev->u.oss.in);
357 +#endif
358 +#ifdef CONFIG_AUDIO_PA
359 + case AUDIODEV_DRIVER_PA:
360 + return qapi_AudiodevPaPerDirectionOptions_base(dev->u.pa.in);
361 +#endif
362 +#ifdef CONFIG_AUDIO_PIPEWIRE
363 + case AUDIODEV_DRIVER_PIPEWIRE:
364 + return qapi_AudiodevPipewirePerDirectionOptions_base(dev->u.pipewire.in);
365 +#endif
366 +#ifdef CONFIG_AUDIO_SDL
367 + case AUDIODEV_DRIVER_SDL:
368 + return qapi_AudiodevSdlPerDirectionOptions_base(dev->u.sdl.in);
369 +#endif
370 +#ifdef CONFIG_AUDIO_SNDIO
371 + case AUDIODEV_DRIVER_SNDIO:
372 + return dev->u.sndio.in;
373 +#endif
374 +#ifdef CONFIG_SPICE
375 + case AUDIODEV_DRIVER_SPICE:
376 + return dev->u.spice.in;
377 +#endif
378 + case AUDIODEV_DRIVER_WAV:
379 + return dev->u.wav.in;
380 +
381 + case AUDIODEV_DRIVER__MAX:
382 + break;
383 + }
384 + abort();
385 +}
386 +
387 static void audio_validate_opts(Audiodev *dev, Error **errp)
388 {
389 Error *err = NULL;
@@ -2128,37 +408,6 @@ static void audio_validate_opts(Audiodev *dev, Error **errp)
408 }
409 }
410
2131 -void audio_help(void)
2132 -{
2133 - int i;
2134 -
2135 - printf("Available audio drivers:\n");
2136 -
2137 - for (i = 0; i < AUDIODEV_DRIVER__MAX; i++) {
2138 - const char *name = AudiodevDriver_str(i);
2139 - AudioBackendClass *be = audio_be_class_by_name(name);
2140 -
2141 - if (be) {
2142 - printf("%s\n", name);
2143 - }
2144 - }
2145 -}
2146 -
2147 -void audio_parse_option(const char *opt)
2148 -{
2149 - Audiodev *dev = NULL;
2150 -
2151 - if (is_help_option(opt)) {
2152 - audio_help();
2153 - exit(EXIT_SUCCESS);
2154 - }
2155 - Visitor *v = qobject_input_visitor_new_str(opt, "driver", &error_fatal);
2156 - visit_type_Audiodev(v, NULL, &dev, &error_fatal);
2157 - visit_free(v);
2158 -
2159 - audio_add_audiodev(dev);
2160 -}
2161 -
411 void audio_add_audiodev(Audiodev *dev)
412 {
413 AudiodevListEntry *e;
@@ -2190,65 +439,6 @@ void audio_init_audiodevs(void)
439 }
440 }
441
2193 -audsettings audiodev_to_audsettings(AudiodevPerDirectionOptions *pdo)
2194 -{
2195 - return (audsettings) {
2196 - .freq = pdo->frequency,
2197 - .nchannels = pdo->channels,
2198 - .fmt = pdo->format,
2199 - .endianness = HOST_BIG_ENDIAN,
2200 - };
2201 -}
2202 -
2203 -int audioformat_bytes_per_sample(AudioFormat fmt)
2204 -{
2205 - switch (fmt) {
2206 - case AUDIO_FORMAT_U8:
2207 - case AUDIO_FORMAT_S8:
2208 - return 1;
2209 -
2210 - case AUDIO_FORMAT_U16:
2211 - case AUDIO_FORMAT_S16:
2212 - return 2;
2213 -
2214 - case AUDIO_FORMAT_U32:
2215 - case AUDIO_FORMAT_S32:
2216 - case AUDIO_FORMAT_F32:
2217 - return 4;
2218 -
2219 - case AUDIO_FORMAT__MAX:
2220 - ;
2221 - }
2222 - abort();
2223 -}
2224 -
2225 -
2226 -/* frames = freq * usec / 1e6 */
2227 -int audio_buffer_frames(AudiodevPerDirectionOptions *pdo,
2228 - audsettings *as, int def_usecs)
2229 -{
2230 - uint64_t usecs = pdo->has_buffer_length ? pdo->buffer_length : def_usecs;
2231 - return (as->freq * usecs + 500000) / 1000000;
2232 -}
2233 -
2234 -/* samples = channels * frames = channels * freq * usec / 1e6 */
2235 -int audio_buffer_samples(AudiodevPerDirectionOptions *pdo,
2236 - audsettings *as, int def_usecs)
2237 -{
2238 - return as->nchannels * audio_buffer_frames(pdo, as, def_usecs);
2239 -}
2240 -
2241 -/*
2242 - * bytes = bytes_per_sample * samples =
2243 - * bytes_per_sample * channels * freq * usec / 1e6
2244 - */
2245 -int audio_buffer_bytes(AudiodevPerDirectionOptions *pdo,
2246 - audsettings *as, int def_usecs)
2247 -{
2248 - return audio_buffer_samples(pdo, as, def_usecs) *
2249 - audioformat_bytes_per_sample(as->fmt);
2250 -}
2251 -
442 AudioBackend *audio_be_by_name(const char *name, Error **errp)
443 {
444 Object *obj = object_resolve_path_component(get_audiodevs_root(), name);
@@ -2269,51 +459,6 @@ const char *audio_application_name(void)
459 return vm_name ? vm_name : "qemu";
460 }
461
2272 -void audio_rate_start(RateCtl *rate)
2273 -{
2274 - memset(rate, 0, sizeof(RateCtl));
2275 - rate->start_ticks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
2276 -}
2277 -
2278 -size_t audio_rate_peek_bytes(RateCtl *rate, struct audio_pcm_info *info)
2279 -{
2280 - int64_t now;
2281 - int64_t ticks;
2282 - int64_t bytes;
2283 - int64_t frames;
2284 -
2285 - now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
2286 - ticks = now - rate->start_ticks;
2287 - bytes = muldiv64(ticks, info->bytes_per_second, NANOSECONDS_PER_SECOND);
2288 - frames = (bytes - rate->bytes_sent) / info->bytes_per_frame;
2289 - rate->peeked_frames = frames;
2290 -
2291 - return frames < 0 ? 0 : frames * info->bytes_per_frame;
2292 -}
2293 -
2294 -void audio_rate_add_bytes(RateCtl *rate, size_t bytes_used)
2295 -{
2296 - if (rate->peeked_frames < 0 || rate->peeked_frames > 65536) {
2297 - AUD_log(NULL, "Resetting rate control (%" PRId64 " frames)\n",
2298 - rate->peeked_frames);
2299 - audio_rate_start(rate);
2300 - }
2301 -
2302 - rate->bytes_sent += bytes_used;
2303 -}
2304 -
2305 -size_t audio_rate_get_bytes(RateCtl *rate, struct audio_pcm_info *info,
2306 - size_t bytes_avail)
2307 -{
2308 - size_t bytes;
2309 -
2310 - bytes = audio_rate_peek_bytes(rate, info);
2311 - bytes = MIN(bytes, bytes_avail);
2312 - audio_rate_add_bytes(rate, bytes);
2313 -
2314 - return bytes;
2315 -}
2316 -
462 AudiodevList *qmp_query_audiodevs(Error **errp)
463 {
464 AudiodevList *ret = NULL;
@@ -2323,17 +468,3 @@ AudiodevList *qmp_query_audiodevs(Error **errp)
468 }
469 return ret;
470 }
2326 -
2327 -static const TypeInfo audio_types[] = {
2328 - {
2329 - .name = TYPE_AUDIO_MIXENG_BACKEND,
2330 - .parent = TYPE_AUDIO_BACKEND,
2331 - .instance_size = sizeof(AudioMixengBackend),
2332 - .instance_init = audio_mixeng_backend_init,
2333 - .instance_finalize = audio_mixeng_backend_finalize,
2334 - .class_size = sizeof(AudioMixengBackendClass),
2335 - .class_init = audio_mixeng_backend_class_init,
2336 - }
2337 -};
2338 -
2339 -DEFINE_TYPES(audio_types)
audio/audio_int.h
-2
@@ -266,8 +266,6 @@ int audio_bug (const char *funcname, int cond);
266
267 void audio_run(AudioMixengBackend *s, const char *msg);
268
269 -const char *audio_application_name(void);
270 -
269 typedef struct RateCtl {
270 int64_t start_ticks;
271 int64_t bytes_sent;
audio/meson.build
+1
@@ -2,6 +2,7 @@ audio_ss = ss.source_set()
2 audio_ss.add(files(
3 'audio.c',
4 'audio-be.c',
5 + 'audio-mixeng-be.c',
6 'mixeng.c',
7 'noaudio.c',
8 'wavaudio.c',
include/qemu/audio.h
+2
@@ -183,6 +183,8 @@ bool audio_be_set_dbus_server(AudioBackend *be,
183 Error **errp);
184 #endif
185
186 +const char *audio_application_name(void);
187 +
188 #define DEFINE_AUDIO_PROPERTIES(_s, _f) \
189 DEFINE_PROP_AUDIODEV("audiodev", _s, _f)
190