]> git.proxmox.com Git - mirror_qemu.git/blame - audio/audio.c
audio merge (malc)
[mirror_qemu.git] / audio / audio.c
CommitLineData
85571bc7
FB
1/*
2 * QEMU Audio subsystem
3 *
4 * Copyright (c) 2003-2004 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#include <assert.h>
25#include <limits.h>
26#include "vl.h"
27
28#define AUDIO_CAP "audio"
29#include "audio/audio.h"
30
31#define USE_SDL_AUDIO
32#define USE_WAV_AUDIO
33
34#if defined __linux__ || (defined _BSD && !defined __APPLE__)
35#define USE_OSS_AUDIO
36#endif
37
38#ifdef USE_OSS_AUDIO
39#include "audio/ossaudio.h"
40#endif
41
42#ifdef USE_SDL_AUDIO
43#include "audio/sdlaudio.h"
44#endif
45
46#ifdef USE_WAV_AUDIO
47#include "audio/wavaudio.h"
48#endif
49
50#ifdef USE_FMOD_AUDIO
51#include "audio/fmodaudio.h"
52#endif
53
54#define QC_AUDIO_DRV "QEMU_AUDIO_DRV"
55#define QC_VOICES "QEMU_VOICES"
56#define QC_FIXED_FORMAT "QEMU_FIXED_FORMAT"
57#define QC_FIXED_FREQ "QEMU_FIXED_FREQ"
58
59extern void SB16_init (void);
60
61#ifdef USE_ADLIB
62extern void Adlib_init (void);
63#endif
64
65#ifdef USE_GUS
66extern void GUS_init (void);
67#endif
68
69static void (*hw_ctors[]) (void) = {
70 SB16_init,
71#ifdef USE_ADLIB
72 Adlib_init,
73#endif
74#ifdef USE_GUS
75 GUS_init,
76#endif
77 NULL
78};
79
80static HWVoice *hw_voice;
81
82AudioState audio_state = {
83 1, /* use fixed settings */
84 44100, /* fixed frequency */
85 2, /* fixed channels */
86 AUD_FMT_S16, /* fixed format */
87 1, /* number of hw voices */
88 -1 /* voice size */
89};
90
91/* http://www.df.lth.se/~john_e/gems/gem002d.html */
92/* http://www.multi-platforms.com/Tips/PopCount.htm */
93uint32_t popcount (uint32_t u)
94{
95 u = ((u&0x55555555) + ((u>>1)&0x55555555));
96 u = ((u&0x33333333) + ((u>>2)&0x33333333));
97 u = ((u&0x0f0f0f0f) + ((u>>4)&0x0f0f0f0f));
98 u = ((u&0x00ff00ff) + ((u>>8)&0x00ff00ff));
99 u = ( u&0x0000ffff) + (u>>16);
100 return u;
101}
102
103inline uint32_t lsbindex (uint32_t u)
104{
105 return popcount ((u&-u)-1);
106}
107
108int audio_get_conf_int (const char *key, int defval)
109{
110 int val = defval;
111 char *strval;
112
113 strval = getenv (key);
114 if (strval) {
115 val = atoi (strval);
116 }
117
118 return val;
119}
120
121const char *audio_get_conf_str (const char *key, const char *defval)
122{
123 const char *val = getenv (key);
124 if (!val)
125 return defval;
126 else
127 return val;
128}
129
130void audio_log (const char *fmt, ...)
131{
132 va_list ap;
133 va_start (ap, fmt);
134 vfprintf (stderr, fmt, ap);
135 va_end (ap);
136}
137
138/*
139 * Soft Voice
140 */
141void pcm_sw_free_resources (SWVoice *sw)
142{
143 if (sw->buf) qemu_free (sw->buf);
144 if (sw->rate) st_rate_stop (sw->rate);
145 sw->buf = NULL;
146 sw->rate = NULL;
147}
148
149int pcm_sw_alloc_resources (SWVoice *sw)
150{
151 sw->buf = qemu_mallocz (sw->hw->samples * sizeof (st_sample_t));
152 if (!sw->buf)
153 return -1;
154
155 sw->rate = st_rate_start (sw->freq, sw->hw->freq);
156 if (!sw->rate) {
157 qemu_free (sw->buf);
158 sw->buf = NULL;
159 return -1;
160 }
161 return 0;
162}
163
164void pcm_sw_fini (SWVoice *sw)
165{
166 pcm_sw_free_resources (sw);
167}
168
169int pcm_sw_init (SWVoice *sw, HWVoice *hw, int freq,
170 int nchannels, audfmt_e fmt)
171{
172 int bits = 8, sign = 0;
173
174 switch (fmt) {
175 case AUD_FMT_S8:
176 sign = 1;
177 case AUD_FMT_U8:
178 break;
179
180 case AUD_FMT_S16:
181 sign = 1;
182 case AUD_FMT_U16:
183 bits = 16;
184 break;
185 }
186
187 sw->hw = hw;
188 sw->freq = freq;
189 sw->fmt = fmt;
190 sw->nchannels = nchannels;
191 sw->shift = (nchannels == 2) + (bits == 16);
192 sw->align = (1 << sw->shift) - 1;
193 sw->left = 0;
194 sw->pos = 0;
195 sw->wpos = 0;
196 sw->live = 0;
197 sw->ratio = (sw->hw->freq * ((int64_t) INT_MAX)) / sw->freq;
198 sw->bytes_per_second = sw->freq << sw->shift;
199 sw->conv = mixeng_conv[nchannels == 2][sign][bits == 16];
200
201 pcm_sw_free_resources (sw);
202 return pcm_sw_alloc_resources (sw);
203}
204
205/* Hard voice */
206void pcm_hw_free_resources (HWVoice *hw)
207{
208 if (hw->mix_buf)
209 qemu_free (hw->mix_buf);
210 hw->mix_buf = NULL;
211}
212
213int pcm_hw_alloc_resources (HWVoice *hw)
214{
215 hw->mix_buf = qemu_mallocz (hw->samples * sizeof (st_sample_t));
216 if (!hw->mix_buf)
217 return -1;
218 return 0;
219}
220
221
222void pcm_hw_fini (HWVoice *hw)
223{
224 if (hw->active) {
225 ldebug ("pcm_hw_fini: %d %d %d\n", hw->freq, hw->nchannels, hw->fmt);
226 pcm_hw_free_resources (hw);
227 hw->pcm_ops->fini (hw);
228 memset (hw, 0, audio_state.drv->voice_size);
229 }
230}
231
232void pcm_hw_gc (HWVoice *hw)
233{
234 if (hw->nb_voices)
235 return;
236
237 pcm_hw_fini (hw);
238}
239
240int pcm_hw_get_live (HWVoice *hw)
241{
242 int i, alive = 0, live = hw->samples;
243
244 for (i = 0; i < hw->nb_voices; i++) {
245 if (hw->pvoice[i]->live) {
246 live = audio_MIN (hw->pvoice[i]->live, live);
247 alive += 1;
248 }
249 }
250
251 if (alive)
252 return live;
253 else
254 return -1;
255}
256
257int pcm_hw_get_live2 (HWVoice *hw, int *nb_active)
258{
259 int i, alive = 0, live = hw->samples;
260
261 *nb_active = 0;
262 for (i = 0; i < hw->nb_voices; i++) {
263 if (hw->pvoice[i]->live) {
264 if (hw->pvoice[i]->live < live) {
265 *nb_active = hw->pvoice[i]->active != 0;
266 live = hw->pvoice[i]->live;
267 }
268 alive += 1;
269 }
270 }
271
272 if (alive)
273 return live;
274 else
275 return -1;
276}
277
278void pcm_hw_dec_live (HWVoice *hw, int decr)
279{
280 int i;
281
282 for (i = 0; i < hw->nb_voices; i++) {
283 if (hw->pvoice[i]->live) {
284 hw->pvoice[i]->live -= decr;
285 }
286 }
287}
288
289void pcm_hw_clear (HWVoice *hw, void *buf, int len)
290{
291 if (!len)
292 return;
293
294 switch (hw->fmt) {
295 case AUD_FMT_S16:
296 case AUD_FMT_S8:
297 memset (buf, len << hw->shift, 0x00);
298 break;
299
300 case AUD_FMT_U8:
301 memset (buf, len << hw->shift, 0x80);
302 break;
303
304 case AUD_FMT_U16:
305 {
306 unsigned int i;
307 uint16_t *p = buf;
308 int shift = hw->nchannels - 1;
309
310 for (i = 0; i < len << shift; i++) {
311 p[i] = INT16_MAX;
312 }
313 }
314 break;
315 }
316}
317
318int pcm_hw_write (SWVoice *sw, void *buf, int size)
319{
320 int hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, blck;
321 int ret = 0, pos = 0;
322 if (!sw)
323 return size;
324
325 hwsamples = sw->hw->samples;
326 samples = size >> sw->shift;
327
328 if (!sw->live) {
329 sw->wpos = sw->hw->rpos;
330 }
331 wpos = sw->wpos;
332 live = sw->live;
333 dead = hwsamples - live;
334 swlim = (dead * ((int64_t) INT_MAX)) / sw->ratio;
335 swlim = audio_MIN (swlim, samples);
336
337 ldebug ("size=%d live=%d dead=%d swlim=%d wpos=%d\n",
338 size, live, dead, swlim, wpos);
339 if (swlim)
340 sw->conv (sw->buf, buf, swlim);
341
342 while (swlim) {
343 dead = hwsamples - live;
344 left = hwsamples - wpos;
345 blck = audio_MIN (dead, left);
346 if (!blck) {
347 /* dolog ("swlim=%d\n", swlim); */
348 break;
349 }
350 isamp = swlim;
351 osamp = blck;
352 st_rate_flow (sw->rate, sw->buf + pos, sw->hw->mix_buf + wpos, &isamp, &osamp);
353 ret += isamp;
354 swlim -= isamp;
355 pos += isamp;
356 live += osamp;
357 wpos = (wpos + osamp) % hwsamples;
358 }
359
360 sw->wpos = wpos;
361 sw->live = live;
362 return ret << sw->shift;
363}
364
365int pcm_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
366{
367 int sign = 0, bits = 8;
368
369 pcm_hw_fini (hw);
370 ldebug ("pcm_hw_init: %d %d %d\n", freq, nchannels, fmt);
371 if (hw->pcm_ops->init (hw, freq, nchannels, fmt)) {
372 memset (hw, 0, audio_state.drv->voice_size);
373 return -1;
374 }
375
376 switch (hw->fmt) {
377 case AUD_FMT_S8:
378 sign = 1;
379 case AUD_FMT_U8:
380 break;
381
382 case AUD_FMT_S16:
383 sign = 1;
384 case AUD_FMT_U16:
385 bits = 16;
386 break;
387 }
388
389 hw->nb_voices = 0;
390 hw->active = 1;
391 hw->shift = (hw->nchannels == 2) + (bits == 16);
392 hw->bytes_per_second = hw->freq << hw->shift;
393 hw->align = (1 << hw->shift) - 1;
394 hw->samples = hw->bufsize >> hw->shift;
395 hw->clip = mixeng_clip[hw->nchannels == 2][sign][bits == 16];
396 if (pcm_hw_alloc_resources (hw)) {
397 pcm_hw_fini (hw);
398 return -1;
399 }
400 return 0;
401}
402
403static int dist (void *hw)
404{
405 if (hw) {
406 return (((uint8_t *) hw - (uint8_t *) hw_voice)
407 / audio_state.voice_size) + 1;
408 }
409 else {
410 return 0;
411 }
412}
413
414#define ADVANCE(hw) hw ? advance (hw, audio_state.voice_size) : hw_voice
415
416HWVoice *pcm_hw_find_any (HWVoice *hw)
417{
418 int i = dist (hw);
419 for (; i < audio_state.nb_hw_voices; i++) {
420 hw = ADVANCE (hw);
421 return hw;
422 }
423 return NULL;
424}
425
426HWVoice *pcm_hw_find_any_active (HWVoice *hw)
427{
428 int i = dist (hw);
429 for (; i < audio_state.nb_hw_voices; i++) {
430 hw = ADVANCE (hw);
431 if (hw->active)
432 return hw;
433 }
434 return NULL;
435}
436
437HWVoice *pcm_hw_find_any_active_enabled (HWVoice *hw)
438{
439 int i = dist (hw);
440 for (; i < audio_state.nb_hw_voices; i++) {
441 hw = ADVANCE (hw);
442 if (hw->active && hw->enabled)
443 return hw;
444 }
445 return NULL;
446}
447
448HWVoice *pcm_hw_find_any_passive (HWVoice *hw)
449{
450 int i = dist (hw);
451 for (; i < audio_state.nb_hw_voices; i++) {
452 hw = ADVANCE (hw);
453 if (!hw->active)
454 return hw;
455 }
456 return NULL;
457}
458
459HWVoice *pcm_hw_find_specific (HWVoice *hw, int freq,
460 int nchannels, audfmt_e fmt)
461{
462 while ((hw = pcm_hw_find_any_active (hw))) {
463 if (hw->freq == freq &&
464 hw->nchannels == nchannels &&
465 hw->fmt == fmt)
466 return hw;
467 }
468 return NULL;
469}
470
471HWVoice *pcm_hw_add (int freq, int nchannels, audfmt_e fmt)
472{
473 HWVoice *hw;
474
475 if (audio_state.fixed_format) {
476 freq = audio_state.fixed_freq;
477 nchannels = audio_state.fixed_channels;
478 fmt = audio_state.fixed_fmt;
479 }
480
481 hw = pcm_hw_find_specific (NULL, freq, nchannels, fmt);
482
483 if (hw)
484 return hw;
485
486 hw = pcm_hw_find_any_passive (NULL);
487 if (hw) {
488 hw->pcm_ops = audio_state.drv->pcm_ops;
489 if (!hw->pcm_ops)
490 return NULL;
491
492 if (pcm_hw_init (hw, freq, nchannels, fmt)) {
493 pcm_hw_gc (hw);
494 return NULL;
495 }
496 else
497 return hw;
498 }
499
500 return pcm_hw_find_any (NULL);
501}
502
503int pcm_hw_add_sw (HWVoice *hw, SWVoice *sw)
504{
505 SWVoice **pvoice = qemu_mallocz ((hw->nb_voices + 1) * sizeof (sw));
506 if (!pvoice)
507 return -1;
508
509 memcpy (pvoice, hw->pvoice, hw->nb_voices * sizeof (sw));
510 qemu_free (hw->pvoice);
511 hw->pvoice = pvoice;
512 hw->pvoice[hw->nb_voices++] = sw;
513 return 0;
514}
515
516int pcm_hw_del_sw (HWVoice *hw, SWVoice *sw)
517{
518 int i, j;
519 if (hw->nb_voices > 1) {
520 SWVoice **pvoice = qemu_mallocz ((hw->nb_voices - 1) * sizeof (sw));
521
522 if (!pvoice) {
523 dolog ("Can not maintain consistent state (not enough memory)\n");
524 return -1;
525 }
526
527 for (i = 0, j = 0; i < hw->nb_voices; i++) {
528 if (j >= hw->nb_voices - 1) {
529 dolog ("Can not maintain consistent state "
530 "(invariant violated)\n");
531 return -1;
532 }
533 if (hw->pvoice[i] != sw)
534 pvoice[j++] = hw->pvoice[i];
535 }
536 qemu_free (hw->pvoice);
537 hw->pvoice = pvoice;
538 hw->nb_voices -= 1;
539 }
540 else {
541 qemu_free (hw->pvoice);
542 hw->pvoice = NULL;
543 hw->nb_voices = 0;
544 }
545 return 0;
546}
547
548SWVoice *pcm_create_voice_pair (int freq, int nchannels, audfmt_e fmt)
549{
550 SWVoice *sw;
551 HWVoice *hw;
552
553 sw = qemu_mallocz (sizeof (*sw));
554 if (!sw)
555 goto err1;
556
557 hw = pcm_hw_add (freq, nchannels, fmt);
558 if (!hw)
559 goto err2;
560
561 if (pcm_hw_add_sw (hw, sw))
562 goto err3;
563
564 if (pcm_sw_init (sw, hw, freq, nchannels, fmt))
565 goto err4;
566
567 return sw;
568
569err4:
570 pcm_hw_del_sw (hw, sw);
571err3:
572 pcm_hw_gc (hw);
573err2:
574 qemu_free (sw);
575err1:
576 return NULL;
577}
578
579SWVoice *AUD_open (SWVoice *sw, const char *name,
580 int freq, int nchannels, audfmt_e fmt)
581{
582 if (!audio_state.drv) {
583 return NULL;
584 }
585
586 if (sw && freq == sw->freq && sw->nchannels == nchannels && sw->fmt == fmt) {
587 return sw;
588 }
589
590 if (sw) {
591 ldebug ("Different format %s %d %d %d\n",
592 name,
593 sw->freq == freq,
594 sw->nchannels == nchannels,
595 sw->fmt == fmt);
596 }
597
598 if (nchannels != 1 && nchannels != 2) {
599 dolog ("Bogus channel count %d for voice %s\n", nchannels, name);
600 return NULL;
601 }
602
603 if (!audio_state.fixed_format && sw) {
604 pcm_sw_fini (sw);
605 pcm_hw_del_sw (sw->hw, sw);
606 pcm_hw_gc (sw->hw);
607 if (sw->name) {
608 qemu_free (sw->name);
609 sw->name = NULL;
610 }
611 qemu_free (sw);
612 sw = NULL;
613 }
614
615 if (sw) {
616 HWVoice *hw = sw->hw;
617 if (!hw) {
618 dolog ("Internal logic error voice %s has no hardware store\n",
619 name);
620 return sw;
621 }
622
623 if (pcm_sw_init (sw, hw, freq, nchannels, fmt)) {
624 pcm_sw_fini (sw);
625 pcm_hw_del_sw (hw, sw);
626 pcm_hw_gc (hw);
627 if (sw->name) {
628 qemu_free (sw->name);
629 sw->name = NULL;
630 }
631 qemu_free (sw);
632 return NULL;
633 }
634 }
635 else {
636 sw = pcm_create_voice_pair (freq, nchannels, fmt);
637 if (!sw) {
638 dolog ("Failed to create voice %s\n", name);
639 return NULL;
640 }
641 }
642
643 if (sw->name) {
644 qemu_free (sw->name);
645 sw->name = NULL;
646 }
647 sw->name = qemu_strdup (name);
648 return sw;
649}
650
651int AUD_write (SWVoice *sw, void *buf, int size)
652{
653 int bytes;
654
655 if (!sw->hw->enabled)
656 dolog ("Writing to disabled voice %s\n", sw->name);
657 bytes = sw->hw->pcm_ops->write (sw, buf, size);
658 return bytes;
659}
660
661void AUD_run (void)
662{
663 HWVoice *hw = NULL;
664
665 while ((hw = pcm_hw_find_any_active_enabled (hw))) {
666 int i;
667 if (hw->pending_disable && pcm_hw_get_live (hw) <= 0) {
668 hw->enabled = 0;
669 hw->pcm_ops->ctl (hw, VOICE_DISABLE);
670 for (i = 0; i < hw->nb_voices; i++) {
671 hw->pvoice[i]->live = 0;
672 /* hw->pvoice[i]->old_ticks = 0; */
673 }
674 continue;
675 }
676
677 hw->pcm_ops->run (hw);
678 assert (hw->rpos < hw->samples);
679 for (i = 0; i < hw->nb_voices; i++) {
680 SWVoice *sw = hw->pvoice[i];
681 if (!sw->active && !sw->live && sw->old_ticks) {
682 int64_t delta = qemu_get_clock (vm_clock) - sw->old_ticks;
683 if (delta > audio_state.ticks_threshold) {
684 ldebug ("resetting old_ticks for %s\n", sw->name);
685 sw->old_ticks = 0;
686 }
687 }
688 }
689 }
690}
691
692int AUD_get_free (SWVoice *sw)
693{
694 int free;
695
696 if (!sw)
697 return 4096;
698
699 free = ((sw->hw->samples - sw->live) << sw->hw->shift) * sw->ratio
700 / INT_MAX;
701
702 free &= ~sw->hw->align;
703 if (!free) return 0;
704
705 return free;
706}
707
708int AUD_get_buffer_size (SWVoice *sw)
709{
710 return sw->hw->bufsize;
711}
712
713void AUD_adjust (SWVoice *sw, int bytes)
714{
715 if (!sw)
716 return;
717 sw->old_ticks += (ticks_per_sec * (int64_t) bytes) / sw->bytes_per_second;
718}
719
720void AUD_reset (SWVoice *sw)
721{
722 sw->active = 0;
723 sw->old_ticks = 0;
724}
725
726int AUD_calc_elapsed (SWVoice *sw)
727{
728 int64_t now, delta, bytes;
729 int dead, swlim;
730
731 if (!sw)
732 return 0;
733
734 now = qemu_get_clock (vm_clock);
735 delta = now - sw->old_ticks;
736 bytes = (delta * sw->bytes_per_second) / ticks_per_sec;
737 if (delta < 0) {
738 dolog ("whoops delta(<0)=%lld\n", delta);
739 return 0;
740 }
741
742 dead = sw->hw->samples - sw->live;
743 swlim = ((dead * (int64_t) INT_MAX) / sw->ratio);
744
745 if (bytes > swlim) {
746 return swlim;
747 }
748 else {
749 return bytes;
750 }
751}
752
753void AUD_enable (SWVoice *sw, int on)
754{
755 int i;
756 HWVoice *hw;
757
758 if (!sw)
759 return;
760
761 hw = sw->hw;
762 if (on) {
763 if (!sw->live)
764 sw->wpos = sw->hw->rpos;
765 if (!sw->old_ticks) {
766 sw->old_ticks = qemu_get_clock (vm_clock);
767 }
768 }
769
770 if (sw->active != on) {
771 if (on) {
772 hw->pending_disable = 0;
773 if (!hw->enabled) {
774 hw->enabled = 1;
775 for (i = 0; i < hw->nb_voices; i++) {
776 ldebug ("resetting voice\n");
777 sw = hw->pvoice[i];
778 sw->old_ticks = qemu_get_clock (vm_clock);
779 }
780 hw->pcm_ops->ctl (hw, VOICE_ENABLE);
781 }
782 }
783 else {
784 if (hw->enabled && !hw->pending_disable) {
785 int nb_active = 0;
786 for (i = 0; i < hw->nb_voices; i++) {
787 nb_active += hw->pvoice[i]->active != 0;
788 }
789
790 if (nb_active == 1) {
791 hw->pending_disable = 1;
792 }
793 }
794 }
795 sw->active = on;
796 }
797}
798
799static struct audio_output_driver *drvtab[] = {
800#ifdef USE_OSS_AUDIO
801 &oss_output_driver,
802#endif
803#ifdef USE_FMOD_AUDIO
804 &fmod_output_driver,
805#endif
806#ifdef USE_SDL_AUDIO
807 &sdl_output_driver,
808#endif
809#ifdef USE_WAV_AUDIO
810 &wav_output_driver,
811#endif
812};
813
814static int voice_init (struct audio_output_driver *drv)
815{
816 audio_state.opaque = drv->init ();
817 if (audio_state.opaque) {
818 if (audio_state.nb_hw_voices > drv->max_voices) {
819 dolog ("`%s' does not support %d multiple hardware channels\n"
820 "Resetting to %d\n",
821 drv->name, audio_state.nb_hw_voices, drv->max_voices);
822 audio_state.nb_hw_voices = drv->max_voices;
823 }
824 hw_voice = qemu_mallocz (audio_state.nb_hw_voices * drv->voice_size);
825 if (hw_voice) {
826 audio_state.drv = drv;
827 return 1;
828 }
829 else {
830 dolog ("Not enough memory for %d `%s' voices (each %d bytes)\n",
831 audio_state.nb_hw_voices, drv->name, drv->voice_size);
832 drv->fini (audio_state.opaque);
833 return 0;
834 }
835 }
836 else {
837 dolog ("Could not init `%s' audio\n", drv->name);
838 return 0;
839 }
840}
841
842static void audio_vm_stop_handler (void *opaque, int reason)
843{
844 HWVoice *hw = NULL;
845
846 while ((hw = pcm_hw_find_any (hw))) {
847 if (!hw->pcm_ops)
848 continue;
849
850 hw->pcm_ops->ctl (hw, reason ? VOICE_ENABLE : VOICE_DISABLE);
851 }
852}
853
854static void audio_atexit (void)
855{
856 HWVoice *hw = NULL;
857
858 while ((hw = pcm_hw_find_any (hw))) {
859 if (!hw->pcm_ops)
860 continue;
861
862 hw->pcm_ops->ctl (hw, VOICE_DISABLE);
863 hw->pcm_ops->fini (hw);
864 }
865 audio_state.drv->fini (audio_state.opaque);
866}
867
868static void audio_save (QEMUFile *f, void *opaque)
869{
870}
871
872static int audio_load (QEMUFile *f, void *opaque, int version_id)
873{
874 if (version_id != 1)
875 return -EINVAL;
876
877 return 0;
878}
879
880void AUD_init (void)
881{
882 int i;
883 int done = 0;
884 const char *drvname;
885
886 audio_state.fixed_format =
887 !!audio_get_conf_int (QC_FIXED_FORMAT, audio_state.fixed_format);
888 audio_state.fixed_freq =
889 audio_get_conf_int (QC_FIXED_FREQ, audio_state.fixed_freq);
890 audio_state.nb_hw_voices =
891 audio_get_conf_int (QC_VOICES, audio_state.nb_hw_voices);
892
893 if (audio_state.nb_hw_voices <= 0) {
894 dolog ("Bogus number of voices %d, resetting to 1\n",
895 audio_state.nb_hw_voices);
896 }
897
898 drvname = audio_get_conf_str (QC_AUDIO_DRV, NULL);
899 if (drvname) {
900 int found = 0;
901 for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
902 if (!strcmp (drvname, drvtab[i]->name)) {
903 done = voice_init (drvtab[i]);
904 found = 1;
905 break;
906 }
907 }
908 if (!found) {
909 dolog ("Unknown audio driver `%s'\n", drvname);
910 }
911 }
912
913 qemu_add_vm_stop_handler (audio_vm_stop_handler, NULL);
914 atexit (audio_atexit);
915
916 if (!done) {
917 for (i = 0; !done && i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
918 if (drvtab[i]->can_be_default)
919 done = voice_init (drvtab[i]);
920 }
921 }
922
923 audio_state.ticks_threshold = ticks_per_sec / 50;
924 audio_state.freq_threshold = 100;
925
926 register_savevm ("audio", 0, 1, audio_save, audio_load, NULL);
927 if (!done) {
928 dolog ("Can not initialize audio subsystem\n");
929 return;
930 }
931
932 for (i = 0; hw_ctors[i]; i++) {
933 hw_ctors[i] ();
934 }
935}