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