Commit 1d14ffa97eacd3cb722271eaf6f093038396eac4

Authored by bellard
1 parent 3b0d4f61

merged 15a_aqemu.patch audio patch (malc)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1584 c046a42c-6fe2-441c-8c8c-71466251a162

Too many changes to show.

To preserve performance only 9 of 28 files are displayed.

Changelog
  1 +version 0.7.3:
  2 +
  3 + - Mac OS X cocoa improvements (Mike Kronenberg)
  4 + - DirectSound driver (malc)
  5 + - new audio options: '-soundhw' and 'audio-help' (malc)
  6 + - ES1370 PCI audio device (malc)
  7 +
1 version 0.7.2: 8 version 0.7.2:
2 9
3 - x86_64 fixes (Win2000 and Linux 2.6 boot in 32 bit) 10 - x86_64 fixes (Win2000 and Linux 2.6 boot in 32 bit)
Makefile.target
@@ -262,7 +262,7 @@ endif @@ -262,7 +262,7 @@ endif
262 VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o 262 VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o
263 VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o 263 VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o
264 264
265 -SOUND_HW = sb16.o 265 +SOUND_HW = sb16.o es1370.o
266 AUDIODRV = audio.o noaudio.o wavaudio.o 266 AUDIODRV = audio.o noaudio.o wavaudio.o
267 ifdef CONFIG_SDL 267 ifdef CONFIG_SDL
268 AUDIODRV += sdlaudio.o 268 AUDIODRV += sdlaudio.o
@@ -270,29 +270,38 @@ endif @@ -270,29 +270,38 @@ endif
270 ifdef CONFIG_OSS 270 ifdef CONFIG_OSS
271 AUDIODRV += ossaudio.o 271 AUDIODRV += ossaudio.o
272 endif 272 endif
273 -  
274 -pc.o: DEFINES := -DUSE_SB16 $(DEFINES)  
275 -  
276 -ifdef CONFIG_ADLIB  
277 -SOUND_HW += fmopl.o adlib.o 273 +ifdef CONFIG_COREAUDIO
  274 +AUDIODRV += coreaudio.o
  275 +endif
  276 +ifdef CONFIG_ALSA
  277 +AUDIODRV += alsaaudio.o
  278 +LIBS += -lasound
  279 +endif
  280 +ifdef CONFIG_DSOUND
  281 +AUDIODRV += dsoundaudio.o
  282 +LIBS += -lole32 -ldxguid
278 endif 283 endif
279 -  
280 ifdef CONFIG_FMOD 284 ifdef CONFIG_FMOD
281 AUDIODRV += fmodaudio.o 285 AUDIODRV += fmodaudio.o
282 audio.o fmodaudio.o: DEFINES := -I$(CONFIG_FMOD_INC) $(DEFINES) 286 audio.o fmodaudio.o: DEFINES := -I$(CONFIG_FMOD_INC) $(DEFINES)
283 LIBS += $(CONFIG_FMOD_LIB) 287 LIBS += $(CONFIG_FMOD_LIB)
284 endif 288 endif
  289 +ifdef CONFIG_ADLIB
  290 +SOUND_HW += fmopl.o adlib.o
  291 +endif
285 292
286 ifeq ($(TARGET_BASE_ARCH), i386) 293 ifeq ($(TARGET_BASE_ARCH), i386)
287 # Hardware support 294 # Hardware support
288 VL_OBJS+= ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV) 295 VL_OBJS+= ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
289 VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o 296 VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o
290 VL_OBJS+= cirrus_vga.o mixeng.o apic.o parallel.o 297 VL_OBJS+= cirrus_vga.o mixeng.o apic.o parallel.o
  298 +DEFINES += -DHAS_AUDIO
291 endif 299 endif
292 ifeq ($(TARGET_BASE_ARCH), ppc) 300 ifeq ($(TARGET_BASE_ARCH), ppc)
293 VL_OBJS+= ppc.o ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV) 301 VL_OBJS+= ppc.o ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
294 VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o 302 VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
295 VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o mixeng.o 303 VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o mixeng.o
  304 +DEFINES += -DHAS_AUDIO
296 endif 305 endif
297 ifeq ($(TARGET_ARCH), mips) 306 ifeq ($(TARGET_ARCH), mips)
298 VL_OBJS+= mips_r4k.o dma.o vga.o serial.o ne2000.o i8254.o i8259.o 307 VL_OBJS+= mips_r4k.o dma.o vga.o serial.o ne2000.o i8254.o i8259.o
@@ -317,7 +326,10 @@ VL_OBJS+=sdl.o @@ -317,7 +326,10 @@ VL_OBJS+=sdl.o
317 endif 326 endif
318 ifdef CONFIG_COCOA 327 ifdef CONFIG_COCOA
319 VL_OBJS+=cocoa.o 328 VL_OBJS+=cocoa.o
320 -COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa 329 +COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa -framework IOKit
  330 +ifdef CONFIG_COREAUDIO
  331 +COCOA_LIBS+=-framework CoreAudio
  332 +endif
321 endif 333 endif
322 ifdef CONFIG_SLIRP 334 ifdef CONFIG_SLIRP
323 DEFINES+=-I$(SRC_PATH)/slirp 335 DEFINES+=-I$(SRC_PATH)/slirp
@@ -349,6 +361,10 @@ ifeq ($(ARCH),ia64) @@ -349,6 +361,10 @@ ifeq ($(ARCH),ia64)
349 VL_LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/ia64.ld 361 VL_LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/ia64.ld
350 endif 362 endif
351 363
  364 +ifdef CONFIG_WIN32
  365 +SDL_LIBS := $(filter-out -mwindows, $(SDL_LIBS)) -mconsole
  366 +endif
  367 +
352 $(QEMU_SYSTEM): $(VL_OBJS) libqemu.a 368 $(QEMU_SYSTEM): $(VL_OBJS) libqemu.a
353 $(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS) 369 $(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS)
354 370
@@ -364,6 +380,9 @@ sdlaudio.o: sdlaudio.c @@ -364,6 +380,9 @@ sdlaudio.o: sdlaudio.c
364 depend: $(SRCS) 380 depend: $(SRCS)
365 $(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend 381 $(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend
366 382
  383 +vldepend: $(VL_OBJS:.o=.c)
  384 + $(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend
  385 +
367 # libqemu 386 # libqemu
368 387
369 libqemu.a: $(LIBOBJS) 388 libqemu.a: $(LIBOBJS)
@@ -415,8 +434,6 @@ op.o: op.c op_template.c op_mem.c @@ -415,8 +434,6 @@ op.o: op.c op_template.c op_mem.c
415 op_helper.o: op_helper_mem.c 434 op_helper.o: op_helper_mem.c
416 endif 435 endif
417 436
418 -mixeng.o: mixeng.c mixeng.h mixeng_template.h  
419 -  
420 %.o: %.c 437 %.o: %.c
421 $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $< 438 $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
422 439
@@ -434,3 +451,9 @@ endif @@ -434,3 +451,9 @@ endif
434 ifneq ($(wildcard .depend),) 451 ifneq ($(wildcard .depend),)
435 include .depend 452 include .depend
436 endif 453 endif
  454 +
  455 +ifeq (0, 1)
  456 +audio.o sdlaudio.o dsoundaudio.o ossaudio.o wavaudio.o noaudio.o \
  457 +fmodaudio.o alsaaudio.o mixeng.o: \
  458 +CFLAGS := $(CFLAGS) -Wall -Werror -W -Wsign-compare
  459 +endif
audio/alsaaudio.c 0 โ†’ 100644
  1 +/*
  2 + * QEMU ALSA audio driver
  3 + *
  4 + * Copyright (c) 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 +#include <alsa/asoundlib.h>
  25 +#include "vl.h"
  26 +
  27 +#define AUDIO_CAP "alsa"
  28 +#include "audio_int.h"
  29 +
  30 +typedef struct ALSAVoiceOut {
  31 + HWVoiceOut hw;
  32 + void *pcm_buf;
  33 + snd_pcm_t *handle;
  34 + int can_pause;
  35 + int was_enabled;
  36 +} ALSAVoiceOut;
  37 +
  38 +typedef struct ALSAVoiceIn {
  39 + HWVoiceIn hw;
  40 + snd_pcm_t *handle;
  41 + void *pcm_buf;
  42 + int can_pause;
  43 +} ALSAVoiceIn;
  44 +
  45 +static struct {
  46 + int size_in_usec_in;
  47 + int size_in_usec_out;
  48 + const char *pcm_name_in;
  49 + const char *pcm_name_out;
  50 + unsigned int buffer_size_in;
  51 + unsigned int period_size_in;
  52 + unsigned int buffer_size_out;
  53 + unsigned int period_size_out;
  54 + unsigned int threshold;
  55 +
  56 + int buffer_size_in_overriden;
  57 + int period_size_in_overriden;
  58 +
  59 + int buffer_size_out_overriden;
  60 + int period_size_out_overriden;
  61 +} conf = {
  62 +#ifdef HIGH_LATENCY
  63 + .size_in_usec_in = 1,
  64 + .size_in_usec_out = 1,
  65 +#endif
  66 + .pcm_name_out = "hw:0,0",
  67 + .pcm_name_in = "hw:0,0",
  68 +#ifdef HIGH_LATENCY
  69 + .buffer_size_in = 400000,
  70 + .period_size_in = 400000 / 4,
  71 + .buffer_size_out = 400000,
  72 + .period_size_out = 400000 / 4,
  73 +#else
  74 +#define DEFAULT_BUFFER_SIZE 1024
  75 +#define DEFAULT_PERIOD_SIZE 256
  76 + .buffer_size_in = DEFAULT_BUFFER_SIZE,
  77 + .period_size_in = DEFAULT_PERIOD_SIZE,
  78 + .buffer_size_out = DEFAULT_BUFFER_SIZE,
  79 + .period_size_out = DEFAULT_PERIOD_SIZE,
  80 + .buffer_size_in_overriden = 0,
  81 + .buffer_size_out_overriden = 0,
  82 + .period_size_in_overriden = 0,
  83 + .period_size_out_overriden = 0,
  84 +#endif
  85 + .threshold = 0
  86 +};
  87 +
  88 +struct alsa_params_req {
  89 + int freq;
  90 + audfmt_e fmt;
  91 + int nchannels;
  92 + unsigned int buffer_size;
  93 + unsigned int period_size;
  94 +};
  95 +
  96 +struct alsa_params_obt {
  97 + int freq;
  98 + audfmt_e fmt;
  99 + int nchannels;
  100 + int can_pause;
  101 + snd_pcm_uframes_t buffer_size;
  102 +};
  103 +
  104 +static void GCC_FMT_ATTR (2, 3) alsa_logerr (int err, const char *fmt, ...)
  105 +{
  106 + va_list ap;
  107 +
  108 + va_start (ap, fmt);
  109 + AUD_vlog (AUDIO_CAP, fmt, ap);
  110 + va_end (ap);
  111 +
  112 + AUD_log (AUDIO_CAP, "Reason: %s\n", snd_strerror (err));
  113 +}
  114 +
  115 +static void GCC_FMT_ATTR (3, 4) alsa_logerr2 (
  116 + int err,
  117 + const char *typ,
  118 + const char *fmt,
  119 + ...
  120 + )
  121 +{
  122 + va_list ap;
  123 +
  124 + AUD_log (AUDIO_CAP, "Can not initialize %s\n", typ);
  125 +
  126 + va_start (ap, fmt);
  127 + AUD_vlog (AUDIO_CAP, fmt, ap);
  128 + va_end (ap);
  129 +
  130 + AUD_log (AUDIO_CAP, "Reason: %s\n", snd_strerror (err));
  131 +}
  132 +
  133 +static void alsa_anal_close (snd_pcm_t **handlep)
  134 +{
  135 + int err = snd_pcm_close (*handlep);
  136 + if (err) {
  137 + alsa_logerr (err, "Failed to close PCM handle %p\n", *handlep);
  138 + }
  139 + *handlep = NULL;
  140 +}
  141 +
  142 +static int alsa_write (SWVoiceOut *sw, void *buf, int len)
  143 +{
  144 + return audio_pcm_sw_write (sw, buf, len);
  145 +}
  146 +
  147 +static int aud_to_alsafmt (audfmt_e fmt)
  148 +{
  149 + switch (fmt) {
  150 + case AUD_FMT_S8:
  151 + return SND_PCM_FORMAT_S8;
  152 +
  153 + case AUD_FMT_U8:
  154 + return SND_PCM_FORMAT_U8;
  155 +
  156 + case AUD_FMT_S16:
  157 + return SND_PCM_FORMAT_S16_LE;
  158 +
  159 + case AUD_FMT_U16:
  160 + return SND_PCM_FORMAT_U16_LE;
  161 +
  162 + default:
  163 + dolog ("Internal logic error: Bad audio format %d\n", fmt);
  164 +#ifdef DEBUG_AUDIO
  165 + abort ();
  166 +#endif
  167 + return SND_PCM_FORMAT_U8;
  168 + }
  169 +}
  170 +
  171 +static int alsa_to_audfmt (int alsafmt, audfmt_e *fmt, int *endianness)
  172 +{
  173 + switch (alsafmt) {
  174 + case SND_PCM_FORMAT_S8:
  175 + *endianness = 0;
  176 + *fmt = AUD_FMT_S8;
  177 + break;
  178 +
  179 + case SND_PCM_FORMAT_U8:
  180 + *endianness = 0;
  181 + *fmt = AUD_FMT_U8;
  182 + break;
  183 +
  184 + case SND_PCM_FORMAT_S16_LE:
  185 + *endianness = 0;
  186 + *fmt = AUD_FMT_S16;
  187 + break;
  188 +
  189 + case SND_PCM_FORMAT_U16_LE:
  190 + *endianness = 0;
  191 + *fmt = AUD_FMT_U16;
  192 + break;
  193 +
  194 + case SND_PCM_FORMAT_S16_BE:
  195 + *endianness = 1;
  196 + *fmt = AUD_FMT_S16;
  197 + break;
  198 +
  199 + case SND_PCM_FORMAT_U16_BE:
  200 + *endianness = 1;
  201 + *fmt = AUD_FMT_U16;
  202 + break;
  203 +
  204 + default:
  205 + dolog ("Unrecognized audio format %d\n", alsafmt);
  206 + return -1;
  207 + }
  208 +
  209 + return 0;
  210 +}
  211 +
  212 +#ifdef DEBUG_MISMATCHES
  213 +static void alsa_dump_info (struct alsa_params_req *req,
  214 + struct alsa_params_obt *obt)
  215 +{
  216 + dolog ("parameter | requested value | obtained value\n");
  217 + dolog ("format | %10d | %10d\n", req->fmt, obt->fmt);
  218 + dolog ("channels | %10d | %10d\n",
  219 + req->nchannels, obt->nchannels);
  220 + dolog ("frequency | %10d | %10d\n", req->freq, obt->freq);
  221 + dolog ("============================================\n");
  222 + dolog ("requested: buffer size %d period size %d\n",
  223 + req->buffer_size, req->period_size);
  224 + dolog ("obtained: buffer size %ld\n", obt->buffer_size);
  225 +}
  226 +#endif
  227 +
  228 +static void alsa_set_threshold (snd_pcm_t *handle, snd_pcm_uframes_t threshold)
  229 +{
  230 + int err;
  231 + snd_pcm_sw_params_t *sw_params;
  232 +
  233 + snd_pcm_sw_params_alloca (&sw_params);
  234 +
  235 + err = snd_pcm_sw_params_current (handle, sw_params);
  236 + if (err < 0) {
  237 + dolog ("Can not fully initialize DAC\n");
  238 + alsa_logerr (err, "Failed to get current software parameters\n");
  239 + return;
  240 + }
  241 +
  242 + err = snd_pcm_sw_params_set_start_threshold (handle, sw_params, threshold);
  243 + if (err < 0) {
  244 + dolog ("Can not fully initialize DAC\n");
  245 + alsa_logerr (err, "Failed to set software threshold to %ld\n",
  246 + threshold);
  247 + return;
  248 + }
  249 +
  250 + err = snd_pcm_sw_params (handle, sw_params);
  251 + if (err < 0) {
  252 + dolog ("Can not fully initialize DAC\n");
  253 + alsa_logerr (err, "Failed to set software parameters\n");
  254 + return;
  255 + }
  256 +}
  257 +
  258 +static int alsa_open (int in, struct alsa_params_req *req,
  259 + struct alsa_params_obt *obt, snd_pcm_t **handlep)
  260 +{
  261 + snd_pcm_t *handle;
  262 + snd_pcm_hw_params_t *hw_params;
  263 + int err, freq, nchannels;
  264 + const char *pcm_name = in ? conf.pcm_name_in : conf.pcm_name_out;
  265 + unsigned int period_size, buffer_size;
  266 + snd_pcm_uframes_t obt_buffer_size;
  267 + const char *typ = in ? "ADC" : "DAC";
  268 +
  269 + freq = req->freq;
  270 + period_size = req->period_size;
  271 + buffer_size = req->buffer_size;
  272 + nchannels = req->nchannels;
  273 +
  274 + snd_pcm_hw_params_alloca (&hw_params);
  275 +
  276 + err = snd_pcm_open (
  277 + &handle,
  278 + pcm_name,
  279 + in ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
  280 + SND_PCM_NONBLOCK
  281 + );
  282 + if (err < 0) {
  283 + alsa_logerr2 (err, typ, "Failed to open `%s':\n", pcm_name);
  284 + return -1;
  285 + }
  286 +
  287 + err = snd_pcm_hw_params_any (handle, hw_params);
  288 + if (err < 0) {
  289 + alsa_logerr2 (err, typ, "Failed to initialize hardware parameters\n");
  290 + goto err;
  291 + }
  292 +
  293 + err = snd_pcm_hw_params_set_access (
  294 + handle,
  295 + hw_params,
  296 + SND_PCM_ACCESS_RW_INTERLEAVED
  297 + );
  298 + if (err < 0) {
  299 + alsa_logerr2 (err, typ, "Failed to set access type\n");
  300 + goto err;
  301 + }
  302 +
  303 + err = snd_pcm_hw_params_set_format (handle, hw_params, req->fmt);
  304 + if (err < 0) {
  305 + alsa_logerr2 (err, typ, "Failed to set format %d\n", req->fmt);
  306 + goto err;
  307 + }
  308 +
  309 + err = snd_pcm_hw_params_set_rate_near (handle, hw_params, &freq, 0);
  310 + if (err < 0) {
  311 + alsa_logerr2 (err, typ, "Failed to set frequency %d\n", req->freq);
  312 + goto err;
  313 + }
  314 +
  315 + err = snd_pcm_hw_params_set_channels_near (
  316 + handle,
  317 + hw_params,
  318 + &nchannels
  319 + );
  320 + if (err < 0) {
  321 + alsa_logerr2 (err, typ, "Failed to set number of channels %d\n",
  322 + req->nchannels);
  323 + goto err;
  324 + }
  325 +
  326 + if (nchannels != 1 && nchannels != 2) {
  327 + alsa_logerr2 (err, typ,
  328 + "Can not handle obtained number of channels %d\n",
  329 + nchannels);
  330 + goto err;
  331 + }
  332 +
  333 + if (!((in && conf.size_in_usec_in) || (!in && conf.size_in_usec_out))) {
  334 + if (!buffer_size) {
  335 + buffer_size = DEFAULT_BUFFER_SIZE;
  336 + period_size= DEFAULT_PERIOD_SIZE;
  337 + }
  338 + }
  339 +
  340 + if (buffer_size) {
  341 + if ((in && conf.size_in_usec_in) || (!in && conf.size_in_usec_out)) {
  342 + if (period_size) {
  343 + err = snd_pcm_hw_params_set_period_time_near (
  344 + handle,
  345 + hw_params,
  346 + &period_size,
  347 + 0);
  348 + if (err < 0) {
  349 + alsa_logerr2 (err, typ,
  350 + "Failed to set period time %d\n",
  351 + req->period_size);
  352 + goto err;
  353 + }
  354 + }
  355 +
  356 + err = snd_pcm_hw_params_set_buffer_time_near (
  357 + handle,
  358 + hw_params,
  359 + &buffer_size,
  360 + 0);
  361 +
  362 + if (err < 0) {
  363 + alsa_logerr2 (err, typ,
  364 + "Failed to set buffer time %d\n",
  365 + req->buffer_size);
  366 + goto err;
  367 + }
  368 + }
  369 + else {
  370 + int dir;
  371 + snd_pcm_uframes_t minval;
  372 +
  373 + if (period_size) {
  374 + minval = period_size;
  375 + dir = 0;
  376 +
  377 + err = snd_pcm_hw_params_get_period_size_min (
  378 + hw_params,
  379 + &minval,
  380 + &dir
  381 + );
  382 + if (err < 0) {
  383 + alsa_logerr (
  384 + err,
  385 + "Can not get minmal period size for %s\n",
  386 + typ
  387 + );
  388 + }
  389 + else {
  390 + if (period_size < minval) {
  391 + if ((in && conf.period_size_in_overriden)
  392 + || (!in && conf.period_size_out_overriden)) {
  393 + dolog ("%s period size(%d) is less "
  394 + "than minmal period size(%ld)\n",
  395 + typ,
  396 + period_size,
  397 + minval);
  398 + }
  399 + period_size = minval;
  400 + }
  401 + }
  402 +
  403 + err = snd_pcm_hw_params_set_period_size (
  404 + handle,
  405 + hw_params,
  406 + period_size,
  407 + 0
  408 + );
  409 + if (err < 0) {
  410 + alsa_logerr2 (err, typ, "Failed to set period size %d\n",
  411 + req->period_size);
  412 + goto err;
  413 + }
  414 + }
  415 +
  416 + minval = buffer_size;
  417 + err = snd_pcm_hw_params_get_buffer_size_min (
  418 + hw_params,
  419 + &minval
  420 + );
  421 + if (err < 0) {
  422 + alsa_logerr (err, "Can not get minmal buffer size for %s\n",
  423 + typ);
  424 + }
  425 + else {
  426 + if (buffer_size < minval) {
  427 + if ((in && conf.buffer_size_in_overriden)
  428 + || (!in && conf.buffer_size_out_overriden)) {
  429 + dolog (
  430 + "%s buffer size(%d) is less "
  431 + "than minimal buffer size(%ld)\n",
  432 + typ,
  433 + buffer_size,
  434 + minval
  435 + );
  436 + }
  437 + buffer_size = minval;
  438 + }
  439 + }
  440 +
  441 + err = snd_pcm_hw_params_set_buffer_size (
  442 + handle,
  443 + hw_params,
  444 + buffer_size
  445 + );
  446 + if (err < 0) {
  447 + alsa_logerr2 (err, typ, "Failed to set buffer size %d\n",
  448 + req->buffer_size);
  449 + goto err;
  450 + }
  451 + }
  452 + }
  453 + else {
  454 + dolog ("warning: buffer size is not set\n");
  455 + }
  456 +
  457 + err = snd_pcm_hw_params (handle, hw_params);
  458 + if (err < 0) {
  459 + alsa_logerr2 (err, typ, "Failed to apply audio parameters\n");
  460 + goto err;
  461 + }
  462 +
  463 + err = snd_pcm_hw_params_get_buffer_size (hw_params, &obt_buffer_size);
  464 + if (err < 0) {
  465 + alsa_logerr2 (err, typ, "Failed to get buffer size\n");
  466 + goto err;
  467 + }
  468 +
  469 + err = snd_pcm_prepare (handle);
  470 + if (err < 0) {
  471 + alsa_logerr2 (err, typ, "Can not prepare handle %p\n", handle);
  472 + goto err;
  473 + }
  474 +
  475 + obt->can_pause = snd_pcm_hw_params_can_pause (hw_params);
  476 + if (obt->can_pause < 0) {
  477 + alsa_logerr (err, "Can not get pause capability for %s\n", typ);
  478 + obt->can_pause = 0;
  479 + }
  480 +
  481 + if (!in && conf.threshold) {
  482 + snd_pcm_uframes_t threshold;
  483 + int bytes_per_sec;
  484 +
  485 + bytes_per_sec = freq
  486 + << (nchannels == 2)
  487 + << (req->fmt == AUD_FMT_S16 || req->fmt == AUD_FMT_U16);
  488 +
  489 + threshold = (conf.threshold * bytes_per_sec) / 1000;
  490 + alsa_set_threshold (handle, threshold);
  491 + }
  492 +
  493 + obt->fmt = req->fmt;
  494 + obt->nchannels = nchannels;
  495 + obt->freq = freq;
  496 + obt->buffer_size = snd_pcm_frames_to_bytes (handle, obt_buffer_size);
  497 + *handlep = handle;
  498 +
  499 + if (obt->fmt != req->fmt ||
  500 + obt->nchannels != req->nchannels ||
  501 + obt->freq != req->freq) {
  502 +#ifdef DEBUG_MISMATCHES
  503 + dolog ("Audio paramters mismatch for %s\n", typ);
  504 + alsa_dump_info (req, obt);
  505 +#endif
  506 + }
  507 +
  508 +#ifdef DEBUG
  509 + alsa_dump_info (req, obt);
  510 +#endif
  511 + return 0;
  512 +
  513 + err:
  514 + alsa_anal_close (&handle);
  515 + return -1;
  516 +}
  517 +
  518 +static int alsa_recover (snd_pcm_t *handle)
  519 +{
  520 + int err = snd_pcm_prepare (handle);
  521 + if (err < 0) {
  522 + alsa_logerr (err, "Failed to prepare handle %p\n", handle);
  523 + return -1;
  524 + }
  525 + return 0;
  526 +}
  527 +
  528 +static int alsa_run_out (HWVoiceOut *hw)
  529 +{
  530 + ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
  531 + int rpos, live, decr;
  532 + int samples;
  533 + uint8_t *dst;
  534 + st_sample_t *src;
  535 + snd_pcm_sframes_t avail;
  536 +
  537 + live = audio_pcm_hw_get_live_out (hw);
  538 + if (!live) {
  539 + return 0;
  540 + }
  541 +
  542 + avail = snd_pcm_avail_update (alsa->handle);
  543 + if (avail < 0) {
  544 + if (avail == -EPIPE) {
  545 + if (!alsa_recover (alsa->handle)) {
  546 + avail = snd_pcm_avail_update (alsa->handle);
  547 + if (avail >= 0) {
  548 + goto ok;
  549 + }
  550 + }
  551 + }
  552 +
  553 + alsa_logerr (avail, "Can not get amount free space\n");
  554 + return 0;
  555 + }
  556 +
  557 + ok:
  558 + decr = audio_MIN (live, avail);
  559 + samples = decr;
  560 + rpos = hw->rpos;
  561 + while (samples) {
  562 + int left_till_end_samples = hw->samples - rpos;
  563 + int convert_samples = audio_MIN (samples, left_till_end_samples);
  564 + snd_pcm_sframes_t written;
  565 +
  566 + src = hw->mix_buf + rpos;
  567 + dst = advance (alsa->pcm_buf, rpos << hw->info.shift);
  568 +
  569 + hw->clip (dst, src, convert_samples);
  570 +
  571 + again:
  572 + written = snd_pcm_writei (alsa->handle, dst, convert_samples);
  573 +
  574 + if (written < 0) {
  575 + switch (written) {
  576 + case -EPIPE:
  577 + if (!alsa_recover (alsa->handle)) {
  578 + goto again;
  579 + }
  580 + dolog (
  581 + "Failed to write %d frames to %p, handle %p not prepared\n",
  582 + convert_samples,
  583 + dst,
  584 + alsa->handle
  585 + );
  586 + goto exit;
  587 +
  588 + case -EAGAIN:
  589 + goto again;
  590 +
  591 + default:
  592 + alsa_logerr (written, "Failed to write %d frames to %p\n",
  593 + convert_samples, dst);
  594 + goto exit;
  595 + }
  596 + }
  597 +
  598 + mixeng_clear (src, written);
  599 + rpos = (rpos + written) % hw->samples;
  600 + samples -= written;
  601 + }
  602 +
  603 + exit:
  604 + hw->rpos = rpos;
  605 + return decr;
  606 +}
  607 +
  608 +static void alsa_fini_out (HWVoiceOut *hw)
  609 +{
  610 + ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
  611 +
  612 + ldebug ("alsa_fini\n");
  613 + alsa_anal_close (&alsa->handle);
  614 +
  615 + if (alsa->pcm_buf) {
  616 + qemu_free (alsa->pcm_buf);
  617 + alsa->pcm_buf = NULL;
  618 + }
  619 +}
  620 +
  621 +static int alsa_init_out (HWVoiceOut *hw, int freq, int nchannels, audfmt_e fmt)
  622 +{
  623 + ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
  624 + struct alsa_params_req req;
  625 + struct alsa_params_obt obt;
  626 + audfmt_e effective_fmt;
  627 + int endianness;
  628 + int err;
  629 + snd_pcm_t *handle;
  630 +
  631 + req.fmt = aud_to_alsafmt (fmt);
  632 + req.freq = freq;
  633 + req.nchannels = nchannels;
  634 + req.period_size = conf.period_size_out;
  635 + req.buffer_size = conf.buffer_size_out;
  636 +
  637 + if (alsa_open (0, &req, &obt, &handle)) {
  638 + return -1;
  639 + }
  640 +
  641 + err = alsa_to_audfmt (obt.fmt, &effective_fmt, &endianness);
  642 + if (err) {
  643 + alsa_anal_close (&handle);
  644 + return -1;
  645 + }
  646 +
  647 + audio_pcm_init_info (
  648 + &hw->info,
  649 + obt.freq,
  650 + obt.nchannels,
  651 + effective_fmt,
  652 + audio_need_to_swap_endian (endianness)
  653 + );
  654 + alsa->can_pause = obt.can_pause;
  655 + hw->bufsize = obt.buffer_size;
  656 +
  657 + alsa->pcm_buf = qemu_mallocz (hw->bufsize);
  658 + if (!alsa->pcm_buf) {
  659 + alsa_anal_close (&handle);
  660 + return -1;
  661 + }
  662 +
  663 + alsa->handle = handle;
  664 + alsa->was_enabled = 0;
  665 + return 0;
  666 +}
  667 +
  668 +static int alsa_ctl_out (HWVoiceOut *hw, int cmd, ...)
  669 +{
  670 + int err;
  671 + ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
  672 +
  673 + switch (cmd) {
  674 + case VOICE_ENABLE:
  675 + ldebug ("enabling voice\n");
  676 + audio_pcm_info_clear_buf (&hw->info, alsa->pcm_buf, hw->samples);
  677 + if (alsa->can_pause) {
  678 + /* Why this was_enabled madness is needed at all?? */
  679 + if (alsa->was_enabled) {
  680 + err = snd_pcm_pause (alsa->handle, 0);
  681 + if (err < 0) {
  682 + alsa_logerr (err, "Failed to resume playing\n");
  683 + /* not fatal really */
  684 + }
  685 + }
  686 + else {
  687 + alsa->was_enabled = 1;
  688 + }
  689 + }
  690 + break;
  691 +
  692 + case VOICE_DISABLE:
  693 + ldebug ("disabling voice\n");
  694 + if (alsa->can_pause) {
  695 + err = snd_pcm_pause (alsa->handle, 1);
  696 + if (err < 0) {
  697 + alsa_logerr (err, "Failed to stop playing\n");
  698 + /* not fatal really */
  699 + }
  700 + }
  701 + break;
  702 + }
  703 + return 0;
  704 +}
  705 +
  706 +static int alsa_init_in (HWVoiceIn *hw,
  707 + int freq, int nchannels, audfmt_e fmt)
  708 +{
  709 + ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
  710 + struct alsa_params_req req;
  711 + struct alsa_params_obt obt;
  712 + int endianness;
  713 + int err;
  714 + audfmt_e effective_fmt;
  715 + snd_pcm_t *handle;
  716 +
  717 + req.fmt = aud_to_alsafmt (fmt);
  718 + req.freq = freq;
  719 + req.nchannels = nchannels;
  720 + req.period_size = conf.period_size_in;
  721 + req.buffer_size = conf.buffer_size_in;
  722 +
  723 + if (alsa_open (1, &req, &obt, &handle)) {
  724 + return -1;
  725 + }
  726 +
  727 + err = alsa_to_audfmt (obt.fmt, &effective_fmt, &endianness);
  728 + if (err) {
  729 + alsa_anal_close (&handle);
  730 + return -1;
  731 + }
  732 +
  733 + audio_pcm_init_info (
  734 + &hw->info,
  735 + obt.freq,
  736 + obt.nchannels,
  737 + effective_fmt,
  738 + audio_need_to_swap_endian (endianness)
  739 + );
  740 + alsa->can_pause = obt.can_pause;
  741 + hw->bufsize = obt.buffer_size;
  742 + alsa->pcm_buf = qemu_mallocz (hw->bufsize);
  743 + if (!alsa->pcm_buf) {
  744 + alsa_anal_close (&handle);
  745 + return -1;
  746 + }
  747 +
  748 + alsa->handle = handle;
  749 + return 0;
  750 +}
  751 +
  752 +static void alsa_fini_in (HWVoiceIn *hw)
  753 +{
  754 + ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
  755 +
  756 + alsa_anal_close (&alsa->handle);
  757 +
  758 + if (alsa->pcm_buf) {
  759 + qemu_free (alsa->pcm_buf);
  760 + alsa->pcm_buf = NULL;
  761 + }
  762 +}
  763 +
  764 +static int alsa_run_in (HWVoiceIn *hw)
  765 +{
  766 + ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
  767 + int hwshift = hw->info.shift;
  768 + int i;
  769 + int live = audio_pcm_hw_get_live_in (hw);
  770 + int dead = hw->samples - live;
  771 + struct {
  772 + int add;
  773 + int len;
  774 + } bufs[2] = {
  775 + { hw->wpos, 0 },
  776 + { 0, 0 }
  777 + };
  778 +
  779 + snd_pcm_uframes_t read_samples = 0;
  780 +
  781 + if (!dead) {
  782 + return 0;
  783 + }
  784 +
  785 + if (hw->wpos + dead > hw->samples) {
  786 + bufs[0].len = (hw->samples - hw->wpos);
  787 + bufs[1].len = (dead - (hw->samples - hw->wpos));
  788 + }
  789 + else {
  790 + bufs[0].len = dead;
  791 + }
  792 +
  793 +
  794 + for (i = 0; i < 2; ++i) {
  795 + void *src;
  796 + st_sample_t *dst;
  797 + snd_pcm_sframes_t nread;
  798 + snd_pcm_uframes_t len;
  799 +
  800 + len = bufs[i].len;
  801 +
  802 + src = advance (alsa->pcm_buf, bufs[i].add << hwshift);
  803 + dst = hw->conv_buf + bufs[i].add;
  804 +
  805 + while (len) {
  806 + nread = snd_pcm_readi (alsa->handle, src, len);
  807 +
  808 + if (nread < 0) {
  809 + switch (nread) {
  810 + case -EPIPE:
  811 + if (!alsa_recover (alsa->handle)) {
  812 + continue;
  813 + }
  814 + dolog (
  815 + "Failed to read %ld frames from %p, "
  816 + "handle %p not prepared\n",
  817 + len,
  818 + src,
  819 + alsa->handle
  820 + );
  821 + goto exit;
  822 +
  823 + case -EAGAIN:
  824 + continue;
  825 +
  826 + default:
  827 + alsa_logerr (
  828 + nread,
  829 + "Failed to read %ld frames from %p\n",
  830 + len,
  831 + src
  832 + );
  833 + goto exit;
  834 + }
  835 + }
  836 +
  837 + hw->conv (dst, src, nread, &nominal_volume);
  838 +
  839 + src = advance (src, nread << hwshift);
  840 + dst += nread;
  841 +
  842 + read_samples += nread;
  843 + len -= nread;
  844 + }
  845 + }
  846 +
  847 + exit:
  848 + hw->wpos = (hw->wpos + read_samples) % hw->samples;
  849 + return read_samples;
  850 +}
  851 +
  852 +static int alsa_read (SWVoiceIn *sw, void *buf, int size)
  853 +{
  854 + return audio_pcm_sw_read (sw, buf, size);
  855 +}
  856 +
  857 +static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...)
  858 +{
  859 + (void) hw;
  860 + (void) cmd;
  861 + return 0;
  862 +}
  863 +
  864 +static void *alsa_audio_init (void)
  865 +{
  866 + return &conf;
  867 +}
  868 +
  869 +static void alsa_audio_fini (void *opaque)
  870 +{
  871 + (void) opaque;
  872 +}
  873 +
  874 +static struct audio_option alsa_options[] = {
  875 + {"DAC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_out,
  876 + "DAC period/buffer size in microseconds (otherwise in frames)", NULL, 0},
  877 + {"DAC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_out,
  878 + "DAC period size", &conf.period_size_out_overriden, 0},
  879 + {"DAC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_out,
  880 + "DAC buffer size", &conf.buffer_size_out_overriden, 0},
  881 +
  882 + {"ADC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_in,
  883 + "ADC period/buffer size in microseconds (otherwise in frames)", NULL, 0},
  884 + {"ADC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_in,
  885 + "ADC period size", &conf.period_size_in_overriden, 0},
  886 + {"ADC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_in,
  887 + "ADC buffer size", &conf.buffer_size_in_overriden, 0},
  888 +
  889 + {"THRESHOLD", AUD_OPT_INT, &conf.threshold,
  890 + "(undocumented)", NULL, 0},
  891 +
  892 + {"DAC_DEV", AUD_OPT_STR, &conf.pcm_name_out,
  893 + "DAC device name (for instance dmix)", NULL, 0},
  894 +
  895 + {"ADC_DEV", AUD_OPT_STR, &conf.pcm_name_in,
  896 + "ADC device name", NULL, 0},
  897 + {NULL, 0, NULL, NULL, NULL, 0}
  898 +};
  899 +
  900 +static struct audio_pcm_ops alsa_pcm_ops = {
  901 + alsa_init_out,
  902 + alsa_fini_out,
  903 + alsa_run_out,
  904 + alsa_write,
  905 + alsa_ctl_out,
  906 +
  907 + alsa_init_in,
  908 + alsa_fini_in,
  909 + alsa_run_in,
  910 + alsa_read,
  911 + alsa_ctl_in
  912 +};
  913 +
  914 +struct audio_driver alsa_audio_driver = {
  915 + INIT_FIELD (name = ) "alsa",
  916 + INIT_FIELD (descr = ) "ALSA http://www.alsa-project.org",
  917 + INIT_FIELD (options = ) alsa_options,
  918 + INIT_FIELD (init = ) alsa_audio_init,
  919 + INIT_FIELD (fini = ) alsa_audio_fini,
  920 + INIT_FIELD (pcm_ops = ) &alsa_pcm_ops,
  921 + INIT_FIELD (can_be_default = ) 1,
  922 + INIT_FIELD (max_voices_out = ) INT_MAX,
  923 + INIT_FIELD (max_voices_in = ) INT_MAX,
  924 + INIT_FIELD (voice_size_out = ) sizeof (ALSAVoiceOut),
  925 + INIT_FIELD (voice_size_in = ) sizeof (ALSAVoiceIn)
  926 +};
audio/audio.c
1 /* 1 /*
2 * QEMU Audio subsystem 2 * QEMU Audio subsystem
3 - *  
4 - * Copyright (c) 2003-2004 Vassili Karpov (malc)  
5 - * 3 + *
  4 + * Copyright (c) 2003-2005 Vassili Karpov (malc)
  5 + *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy 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 7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights 8 * in the Software without restriction, including without limitation the rights
@@ -21,34 +21,78 @@ @@ -21,34 +21,78 @@
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE. 22 * THE SOFTWARE.
23 */ 23 */
24 -#include <assert.h>  
25 #include "vl.h" 24 #include "vl.h"
26 25
27 -#define USE_WAV_AUDIO 26 +#define AUDIO_CAP "audio"
  27 +#include "audio_int.h"
28 28
29 -#include "audio/audio_int.h" 29 +static void audio_pcm_hw_fini_in (HWVoiceIn *hw);
  30 +static void audio_pcm_hw_fini_out (HWVoiceOut *hw);
30 31
31 -#define dolog(...) AUD_log ("audio", __VA_ARGS__)  
32 -#ifdef DEBUG  
33 -#define ldebug(...) dolog (__VA_ARGS__)  
34 -#else  
35 -#define ldebug(...)  
36 -#endif 32 +static LIST_HEAD (hw_in_listhead, HWVoiceIn) hw_head_in;
  33 +static LIST_HEAD (hw_out_listhead, HWVoiceOut) hw_head_out;
37 34
38 -#define QC_AUDIO_DRV "QEMU_AUDIO_DRV"  
39 -#define QC_VOICES "QEMU_VOICES"  
40 -#define QC_FIXED_FORMAT "QEMU_FIXED_FORMAT"  
41 -#define QC_FIXED_FREQ "QEMU_FIXED_FREQ" 35 +/* #define DEBUG_PLIVE */
  36 +/* #define DEBUG_LIVE */
  37 +/* #define DEBUG_OUT */
42 38
43 -static HWVoice *hw_voices; 39 +static struct audio_driver *drvtab[] = {
  40 +#ifdef CONFIG_OSS
  41 + &oss_audio_driver,
  42 +#endif
  43 +#ifdef CONFIG_ALSA
  44 + &alsa_audio_driver,
  45 +#endif
  46 +#ifdef CONFIG_COREAUDIO
  47 + &coreaudio_audio_driver,
  48 +#endif
  49 +#ifdef CONFIG_DSOUND
  50 + &dsound_audio_driver,
  51 +#endif
  52 +#ifdef CONFIG_FMOD
  53 + &fmod_audio_driver,
  54 +#endif
  55 +#ifdef CONFIG_SDL
  56 + &sdl_audio_driver,
  57 +#endif
  58 + &no_audio_driver,
  59 + &wav_audio_driver
  60 +};
44 61
45 AudioState audio_state = { 62 AudioState audio_state = {
  63 + /* Out */
  64 + 1, /* use fixed settings */
  65 + 44100, /* fixed frequency */
  66 + 2, /* fixed channels */
  67 + AUD_FMT_S16, /* fixed format */
  68 + 1, /* number of hw voices */
  69 + 1, /* greedy */
  70 +
  71 + /* In */
46 1, /* use fixed settings */ 72 1, /* use fixed settings */
47 44100, /* fixed frequency */ 73 44100, /* fixed frequency */
48 2, /* fixed channels */ 74 2, /* fixed channels */
49 AUD_FMT_S16, /* fixed format */ 75 AUD_FMT_S16, /* fixed format */
50 1, /* number of hw voices */ 76 1, /* number of hw voices */
51 - -1 /* voice size */ 77 + 1, /* greedy */
  78 +
  79 + NULL, /* driver opaque */
  80 + NULL, /* driver */
  81 +
  82 + NULL, /* timer handle */
  83 + { 0 }, /* period */
  84 + 0 /* plive */
  85 +};
  86 +
  87 +volume_t nominal_volume = {
  88 + 0,
  89 +#ifdef FLOAT_MIXENG
  90 + 1.0,
  91 + 1.0
  92 +#else
  93 + UINT_MAX,
  94 + UINT_MAX
  95 +#endif
52 }; 96 };
53 97
54 /* http://www.df.lth.se/~john_e/gems/gem002d.html */ 98 /* http://www.df.lth.se/~john_e/gems/gem002d.html */
@@ -68,275 +112,361 @@ inline uint32_t lsbindex (uint32_t u) @@ -68,275 +112,361 @@ inline uint32_t lsbindex (uint32_t u)
68 return popcount ((u&-u)-1); 112 return popcount ((u&-u)-1);
69 } 113 }
70 114
71 -int audio_get_conf_int (const char *key, int defval) 115 +#ifdef AUDIO_IS_FLAWLESS_AND_NO_CHECKS_ARE_REQURIED
  116 +#error No its not
  117 +#else
  118 +int audio_bug (const char *funcname, int cond)
72 { 119 {
73 - int val = defval;  
74 - char *strval;  
75 -  
76 - strval = getenv (key);  
77 - if (strval) {  
78 - val = atoi (strval); 120 + if (cond) {
  121 + static int shown;
  122 +
  123 + AUD_log (NULL, "Error a bug that was just triggered in %s\n", funcname);
  124 + if (!shown) {
  125 + shown = 1;
  126 + AUD_log (NULL, "Save all your work and restart without audio\n");
  127 + AUD_log (NULL, "Please send bug report to malc@pulsesoft.com\n");
  128 + AUD_log (NULL, "I am sorry\n");
  129 + }
  130 + AUD_log (NULL, "Context:\n");
  131 +
  132 +#if defined AUDIO_BREAKPOINT_ON_BUG
  133 +# if defined HOST_I386
  134 +# if defined __GNUC__
  135 + __asm__ ("int3");
  136 +# elif defined _MSC_VER
  137 + _asm _emit 0xcc;
  138 +# else
  139 + abort ();
  140 +# endif
  141 +# else
  142 + abort ();
  143 +# endif
  144 +#endif
79 } 145 }
80 146
81 - return val; 147 + return cond;
82 } 148 }
  149 +#endif
83 150
84 -const char *audio_get_conf_str (const char *key, const char *defval) 151 +static char *audio_alloc_prefix (const char *s)
85 { 152 {
86 - const char *val = getenv (key);  
87 - if (!val)  
88 - return defval;  
89 - else  
90 - return val;  
91 -} 153 + const char qemu_prefix[] = "QEMU_";
  154 + size_t len;
  155 + char *r;
92 156
93 -void AUD_log (const char *cap, const char *fmt, ...)  
94 -{  
95 - va_list ap;  
96 - fprintf (stderr, "%s: ", cap);  
97 - va_start (ap, fmt);  
98 - vfprintf (stderr, fmt, ap);  
99 - va_end (ap);  
100 -} 157 + if (!s) {
  158 + return NULL;
  159 + }
101 160
102 -/*  
103 - * Soft Voice  
104 - */  
105 -void pcm_sw_free_resources (SWVoice *sw)  
106 -{  
107 - if (sw->buf) qemu_free (sw->buf);  
108 - if (sw->rate) st_rate_stop (sw->rate);  
109 - sw->buf = NULL;  
110 - sw->rate = NULL;  
111 -} 161 + len = strlen (s);
  162 + r = qemu_malloc (len + sizeof (qemu_prefix));
112 163
113 -int pcm_sw_alloc_resources (SWVoice *sw)  
114 -{  
115 - sw->buf = qemu_mallocz (sw->hw->samples * sizeof (st_sample_t));  
116 - if (!sw->buf)  
117 - return -1; 164 + if (r) {
  165 + size_t i;
  166 + char *u = r + sizeof (qemu_prefix) - 1;
118 167
119 - sw->rate = st_rate_start (sw->freq, sw->hw->freq);  
120 - if (!sw->rate) {  
121 - qemu_free (sw->buf);  
122 - sw->buf = NULL;  
123 - return -1; 168 + strcpy (r, qemu_prefix);
  169 + strcat (r, s);
  170 +
  171 + for (i = 0; i < len; ++i) {
  172 + u[i] = toupper (u[i]);
  173 + }
124 } 174 }
125 - return 0; 175 + return r;
126 } 176 }
127 177
128 -void pcm_sw_fini (SWVoice *sw) 178 +const char *audio_audfmt_to_string (audfmt_e fmt)
129 { 179 {
130 - pcm_sw_free_resources (sw);  
131 -} 180 + switch (fmt) {
  181 + case AUD_FMT_U8:
  182 + return "U8";
132 183
133 -int pcm_sw_init (SWVoice *sw, HWVoice *hw, int freq,  
134 - int nchannels, audfmt_e fmt)  
135 -{  
136 - int bits = 8, sign = 0; 184 + case AUD_FMT_U16:
  185 + return "U16";
137 186
138 - switch (fmt) {  
139 case AUD_FMT_S8: 187 case AUD_FMT_S8:
140 - sign = 1;  
141 - case AUD_FMT_U8:  
142 - break; 188 + return "S8";
143 189
144 case AUD_FMT_S16: 190 case AUD_FMT_S16:
145 - sign = 1;  
146 - case AUD_FMT_U16:  
147 - bits = 16;  
148 - break; 191 + return "S16";
149 } 192 }
150 193
151 - sw->hw = hw;  
152 - sw->freq = freq;  
153 - sw->fmt = fmt;  
154 - sw->nchannels = nchannels;  
155 - sw->shift = (nchannels == 2) + (bits == 16);  
156 - sw->align = (1 << sw->shift) - 1;  
157 - sw->left = 0;  
158 - sw->pos = 0;  
159 - sw->wpos = 0;  
160 - sw->live = 0;  
161 - sw->ratio = (sw->hw->freq * ((int64_t) INT_MAX)) / sw->freq;  
162 - sw->bytes_per_second = sw->freq << sw->shift;  
163 - sw->conv = mixeng_conv[nchannels == 2][sign][bits == 16];  
164 -  
165 - pcm_sw_free_resources (sw);  
166 - return pcm_sw_alloc_resources (sw);  
167 -}  
168 -  
169 -/* Hard voice */  
170 -void pcm_hw_free_resources (HWVoice *hw)  
171 -{  
172 - if (hw->mix_buf)  
173 - qemu_free (hw->mix_buf);  
174 - hw->mix_buf = NULL; 194 + dolog ("Bogus audfmt %d returning S16\n", fmt);
  195 + return "S16";
175 } 196 }
176 197
177 -int pcm_hw_alloc_resources (HWVoice *hw) 198 +audfmt_e audio_string_to_audfmt (const char *s, audfmt_e defval, int *defaultp)
178 { 199 {
179 - hw->mix_buf = qemu_mallocz (hw->samples * sizeof (st_sample_t));  
180 - if (!hw->mix_buf)  
181 - return -1;  
182 - return 0; 200 + if (!strcasecmp (s, "u8")) {
  201 + *defaultp = 0;
  202 + return AUD_FMT_U8;
  203 + }
  204 + else if (!strcasecmp (s, "u16")) {
  205 + *defaultp = 0;
  206 + return AUD_FMT_U16;
  207 + }
  208 + else if (!strcasecmp (s, "s8")) {
  209 + *defaultp = 0;
  210 + return AUD_FMT_S8;
  211 + }
  212 + else if (!strcasecmp (s, "s16")) {
  213 + *defaultp = 0;
  214 + return AUD_FMT_S16;
  215 + }
  216 + else {
  217 + dolog ("Bogus audio format `%s' using %s\n",
  218 + s, audio_audfmt_to_string (defval));
  219 + *defaultp = 1;
  220 + return defval;
  221 + }
183 } 222 }
184 223
185 -void pcm_hw_fini (HWVoice *hw) 224 +static audfmt_e audio_get_conf_fmt (const char *envname,
  225 + audfmt_e defval,
  226 + int *defaultp)
186 { 227 {
187 - if (hw->active) {  
188 - ldebug ("pcm_hw_fini: %d %d %d\n", hw->freq, hw->nchannels, hw->fmt);  
189 - pcm_hw_free_resources (hw);  
190 - hw->pcm_ops->fini (hw);  
191 - memset (hw, 0, audio_state.drv->voice_size); 228 + const char *var = getenv (envname);
  229 + if (!var) {
  230 + *defaultp = 1;
  231 + return defval;
192 } 232 }
  233 + return audio_string_to_audfmt (var, defval, defaultp);
193 } 234 }
194 235
195 -void pcm_hw_gc (HWVoice *hw) 236 +static int audio_get_conf_int (const char *key, int defval, int *defaultp)
196 { 237 {
197 - if (hw->nb_voices)  
198 - return; 238 + int val;
  239 + char *strval;
199 240
200 - pcm_hw_fini (hw); 241 + strval = getenv (key);
  242 + if (strval) {
  243 + *defaultp = 0;
  244 + val = atoi (strval);
  245 + return val;
  246 + }
  247 + else {
  248 + *defaultp = 1;
  249 + return defval;
  250 + }
201 } 251 }
202 252
203 -int pcm_hw_get_live (HWVoice *hw) 253 +static const char *audio_get_conf_str (const char *key,
  254 + const char *defval,
  255 + int *defaultp)
204 { 256 {
205 - int i, alive = 0, live = hw->samples;  
206 -  
207 - for (i = 0; i < hw->nb_voices; i++) {  
208 - if (hw->pvoice[i]->live) {  
209 - live = audio_MIN (hw->pvoice[i]->live, live);  
210 - alive += 1;  
211 - } 257 + const char *val = getenv (key);
  258 + if (!val) {
  259 + *defaultp = 1;
  260 + return defval;
  261 + }
  262 + else {
  263 + *defaultp = 0;
  264 + return val;
212 } 265 }
213 -  
214 - if (alive)  
215 - return live;  
216 - else  
217 - return -1;  
218 } 266 }
219 267
220 -int pcm_hw_get_live2 (HWVoice *hw, int *nb_active) 268 +void AUD_log (const char *cap, const char *fmt, ...)
221 { 269 {
222 - int i, alive = 0, live = hw->samples;  
223 -  
224 - *nb_active = 0;  
225 - for (i = 0; i < hw->nb_voices; i++) {  
226 - if (hw->pvoice[i]->live) {  
227 - if (hw->pvoice[i]->live < live) {  
228 - *nb_active = hw->pvoice[i]->active != 0;  
229 - live = hw->pvoice[i]->live;  
230 - }  
231 - alive += 1;  
232 - } 270 + va_list ap;
  271 + if (cap) {
  272 + fprintf (stderr, "%s: ", cap);
233 } 273 }
234 -  
235 - if (alive)  
236 - return live;  
237 - else  
238 - return -1; 274 + va_start (ap, fmt);
  275 + vfprintf (stderr, fmt, ap);
  276 + va_end (ap);
239 } 277 }
240 278
241 -void pcm_hw_dec_live (HWVoice *hw, int decr) 279 +void AUD_vlog (const char *cap, const char *fmt, va_list ap)
242 { 280 {
243 - int i;  
244 -  
245 - for (i = 0; i < hw->nb_voices; i++) {  
246 - if (hw->pvoice[i]->live) {  
247 - hw->pvoice[i]->live -= decr;  
248 - } 281 + if (cap) {
  282 + fprintf (stderr, "%s: ", cap);
249 } 283 }
  284 + vfprintf (stderr, fmt, ap);
250 } 285 }
251 286
252 -void pcm_hw_clear (HWVoice *hw, void *buf, int len) 287 +static void audio_print_options (const char *prefix,
  288 + struct audio_option *opt)
253 { 289 {
254 - if (!len) 290 + char *uprefix;
  291 +
  292 + if (!prefix) {
  293 + dolog ("No prefix specified\n");
  294 + return;
  295 + }
  296 +
  297 + if (!opt) {
  298 + dolog ("No options\n");
255 return; 299 return;
  300 + }
256 301
257 - switch (hw->fmt) {  
258 - case AUD_FMT_S16:  
259 - case AUD_FMT_S8:  
260 - memset (buf, len << hw->shift, 0x00);  
261 - break; 302 + uprefix = audio_alloc_prefix (prefix);
262 303
263 - case AUD_FMT_U8:  
264 - memset (buf, len << hw->shift, 0x80);  
265 - break; 304 + for (; opt->name; opt++) {
  305 + const char *state = "default";
  306 + printf (" %s_%s: ", uprefix, opt->name);
266 307
267 - case AUD_FMT_U16:  
268 - {  
269 - unsigned int i;  
270 - uint16_t *p = buf;  
271 - int shift = hw->nchannels - 1; 308 + if (opt->overridenp && *opt->overridenp) {
  309 + state = "current";
  310 + }
272 311
273 - for (i = 0; i < len << shift; i++) {  
274 - p[i] = INT16_MAX; 312 + switch (opt->tag) {
  313 + case AUD_OPT_BOOL:
  314 + {
  315 + int *intp = opt->valp;
  316 + printf ("boolean, %s = %d\n", state, *intp ? 1 : 0);
  317 + }
  318 + break;
  319 +
  320 + case AUD_OPT_INT:
  321 + {
  322 + int *intp = opt->valp;
  323 + printf ("integer, %s = %d\n", state, *intp);
  324 + }
  325 + break;
  326 +
  327 + case AUD_OPT_FMT:
  328 + {
  329 + audfmt_e *fmtp = opt->valp;
  330 + printf (
  331 + "format, %s = %s, (one of: U8 S8 U16 S16)\n",
  332 + state,
  333 + audio_audfmt_to_string (*fmtp)
  334 + );
  335 + }
  336 + break;
  337 +
  338 + case AUD_OPT_STR:
  339 + {
  340 + const char **strp = opt->valp;
  341 + printf ("string, %s = %s\n",
  342 + state,
  343 + *strp ? *strp : "(not set)");
275 } 344 }
  345 + break;
  346 +
  347 + default:
  348 + printf ("???\n");
  349 + dolog ("Bad value tag for option %s_%s %d\n",
  350 + uprefix, opt->name, opt->tag);
  351 + break;
276 } 352 }
277 - break; 353 + printf (" %s\n", opt->descr);
278 } 354 }
  355 +
  356 + qemu_free (uprefix);
279 } 357 }
280 358
281 -int pcm_hw_write (SWVoice *sw, void *buf, int size) 359 +static void audio_process_options (const char *prefix,
  360 + struct audio_option *opt)
282 { 361 {
283 - int hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, blck;  
284 - int ret = 0, pos = 0;  
285 - if (!sw)  
286 - return size; 362 + char *optname;
  363 + const char qemu_prefix[] = "QEMU_";
  364 + size_t preflen;
287 365
288 - hwsamples = sw->hw->samples;  
289 - samples = size >> sw->shift; 366 + if (audio_bug (AUDIO_FUNC, !prefix)) {
  367 + dolog ("prefix = NULL\n");
  368 + return;
  369 + }
290 370
291 - if (!sw->live) {  
292 - sw->wpos = sw->hw->rpos; 371 + if (audio_bug (AUDIO_FUNC, !opt)) {
  372 + dolog ("opt = NULL\n");
  373 + return;
293 } 374 }
294 - wpos = sw->wpos;  
295 - live = sw->live;  
296 - dead = hwsamples - live;  
297 - swlim = (dead * ((int64_t) INT_MAX)) / sw->ratio;  
298 - swlim = audio_MIN (swlim, samples);  
299 375
300 - ldebug ("size=%d live=%d dead=%d swlim=%d wpos=%d\n",  
301 - size, live, dead, swlim, wpos);  
302 - if (swlim)  
303 - sw->conv (sw->buf, buf, swlim); 376 + preflen = strlen (prefix);
304 377
305 - while (swlim) {  
306 - dead = hwsamples - live;  
307 - left = hwsamples - wpos;  
308 - blck = audio_MIN (dead, left);  
309 - if (!blck) {  
310 - /* dolog ("swlim=%d\n", swlim); */ 378 + for (; opt->name; opt++) {
  379 + size_t len, i;
  380 + int def;
  381 +
  382 + if (!opt->valp) {
  383 + dolog ("Option value pointer for `%s' is not set\n",
  384 + opt->name);
  385 + continue;
  386 + }
  387 +
  388 + len = strlen (opt->name);
  389 + optname = qemu_malloc (len + preflen + sizeof (qemu_prefix) + 1);
  390 + if (!optname) {
  391 + dolog ("Can not allocate memory for option name `%s'\n",
  392 + opt->name);
  393 + continue;
  394 + }
  395 +
  396 + strcpy (optname, qemu_prefix);
  397 + for (i = 0; i <= preflen; ++i) {
  398 + optname[i + sizeof (qemu_prefix) - 1] = toupper (prefix[i]);
  399 + }
  400 + strcat (optname, "_");
  401 + strcat (optname, opt->name);
  402 +
  403 + def = 1;
  404 + switch (opt->tag) {
  405 + case AUD_OPT_BOOL:
  406 + case AUD_OPT_INT:
  407 + {
  408 + int *intp = opt->valp;
  409 + *intp = audio_get_conf_int (optname, *intp, &def);
  410 + }
  411 + break;
  412 +
  413 + case AUD_OPT_FMT:
  414 + {
  415 + audfmt_e *fmtp = opt->valp;
  416 + *fmtp = audio_get_conf_fmt (optname, *fmtp, &def);
  417 + }
  418 + break;
  419 +
  420 + case AUD_OPT_STR:
  421 + {
  422 + const char **strp = opt->valp;
  423 + *strp = audio_get_conf_str (optname, *strp, &def);
  424 + }
  425 + break;
  426 +
  427 + default:
  428 + dolog ("Bad value tag for option `%s' - %d\n",
  429 + optname, opt->tag);
311 break; 430 break;
312 } 431 }
313 - isamp = swlim;  
314 - osamp = blck;  
315 - st_rate_flow (sw->rate, sw->buf + pos, sw->hw->mix_buf + wpos, &isamp, &osamp);  
316 - ret += isamp;  
317 - swlim -= isamp;  
318 - pos += isamp;  
319 - live += osamp;  
320 - wpos = (wpos + osamp) % hwsamples;  
321 - }  
322 432
323 - sw->wpos = wpos;  
324 - sw->live = live;  
325 - return ret << sw->shift; 433 + if (!opt->overridenp) {
  434 + opt->overridenp = &opt->overriden;
  435 + }
  436 + *opt->overridenp = !def;
  437 + qemu_free (optname);
  438 + }
326 } 439 }
327 440
328 -int pcm_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt) 441 +static int audio_pcm_info_eq (struct audio_pcm_info *info, int freq,
  442 + int nchannels, audfmt_e fmt)
329 { 443 {
330 - int sign = 0, bits = 8; 444 + int bits = 8, sign = 0;
331 445
332 - pcm_hw_fini (hw);  
333 - ldebug ("pcm_hw_init: %d %d %d\n", freq, nchannels, fmt);  
334 - if (hw->pcm_ops->init (hw, freq, nchannels, fmt)) {  
335 - memset (hw, 0, audio_state.drv->voice_size);  
336 - return -1; 446 + switch (fmt) {
  447 + case AUD_FMT_S8:
  448 + sign = 1;
  449 + case AUD_FMT_U8:
  450 + break;
  451 +
  452 + case AUD_FMT_S16:
  453 + sign = 1;
  454 + case AUD_FMT_U16:
  455 + bits = 16;
  456 + break;
337 } 457 }
  458 + return info->freq == freq
  459 + && info->nchannels == nchannels
  460 + && info->sign == sign
  461 + && info->bits == bits;
  462 +}
338 463
339 - switch (hw->fmt) { 464 +void audio_pcm_init_info (struct audio_pcm_info *info, int freq,
  465 + int nchannels, audfmt_e fmt, int swap_endian)
  466 +{
  467 + int bits = 8, sign = 0;
  468 +
  469 + switch (fmt) {
340 case AUD_FMT_S8: 470 case AUD_FMT_S8:
341 sign = 1; 471 sign = 1;
342 case AUD_FMT_U8: 472 case AUD_FMT_U8:
@@ -349,425 +479,595 @@ int pcm_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt) @@ -349,425 +479,595 @@ int pcm_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
349 break; 479 break;
350 } 480 }
351 481
352 - hw->nb_voices = 0;  
353 - hw->active = 1;  
354 - hw->shift = (hw->nchannels == 2) + (bits == 16);  
355 - hw->bytes_per_second = hw->freq << hw->shift;  
356 - hw->align = (1 << hw->shift) - 1;  
357 - hw->samples = hw->bufsize >> hw->shift;  
358 - hw->clip = mixeng_clip[hw->nchannels == 2][sign][bits == 16];  
359 - if (pcm_hw_alloc_resources (hw)) {  
360 - pcm_hw_fini (hw);  
361 - return -1;  
362 - }  
363 - return 0; 482 + info->freq = freq;
  483 + info->bits = bits;
  484 + info->sign = sign;
  485 + info->nchannels = nchannels;
  486 + info->shift = (nchannels == 2) + (bits == 16);
  487 + info->align = (1 << info->shift) - 1;
  488 + info->bytes_per_second = info->freq << info->shift;
  489 + info->swap_endian = swap_endian;
364 } 490 }
365 491
366 -static int dist (void *hw) 492 +void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
367 { 493 {
368 - if (hw) {  
369 - return (((uint8_t *) hw - (uint8_t *) hw_voices)  
370 - / audio_state.drv->voice_size) + 1; 494 + if (!len) {
  495 + return;
  496 + }
  497 +
  498 + if (info->sign) {
  499 + memset (buf, len << info->shift, 0x00);
371 } 500 }
372 else { 501 else {
373 - return 0; 502 + if (info->bits == 8) {
  503 + memset (buf, len << info->shift, 0x80);
  504 + }
  505 + else {
  506 + int i;
  507 + uint16_t *p = buf;
  508 + int shift = info->nchannels - 1;
  509 + short s = INT16_MAX;
  510 +
  511 + if (info->swap_endian) {
  512 + s = bswap16 (s);
  513 + }
  514 +
  515 + for (i = 0; i < len << shift; i++) {
  516 + p[i] = s;
  517 + }
  518 + }
374 } 519 }
375 } 520 }
376 521
377 -#define ADVANCE(hw) \  
378 - ((hw) ? advance (hw, audio_state.drv->voice_size) : hw_voices)  
379 -  
380 -HWVoice *pcm_hw_find_any (HWVoice *hw) 522 +/*
  523 + * Hard voice (capture)
  524 + */
  525 +static void audio_pcm_hw_free_resources_in (HWVoiceIn *hw)
381 { 526 {
382 - int i = dist (hw);  
383 - for (; i < audio_state.nb_hw_voices; i++) {  
384 - hw = ADVANCE (hw);  
385 - return hw; 527 + if (hw->conv_buf) {
  528 + qemu_free (hw->conv_buf);
386 } 529 }
387 - return NULL; 530 + hw->conv_buf = NULL;
388 } 531 }
389 532
390 -HWVoice *pcm_hw_find_any_active (HWVoice *hw) 533 +static int audio_pcm_hw_alloc_resources_in (HWVoiceIn *hw)
391 { 534 {
392 - int i = dist (hw);  
393 - for (; i < audio_state.nb_hw_voices; i++) {  
394 - hw = ADVANCE (hw);  
395 - if (hw->active)  
396 - return hw; 535 + hw->conv_buf = qemu_mallocz (hw->samples * sizeof (st_sample_t));
  536 + if (!hw->conv_buf) {
  537 + return -1;
397 } 538 }
398 - return NULL; 539 + return 0;
399 } 540 }
400 541
401 -HWVoice *pcm_hw_find_any_active_enabled (HWVoice *hw) 542 +static int audio_pcm_hw_init_in (HWVoiceIn *hw, int freq, int nchannels, audfmt_e fmt)
402 { 543 {
403 - int i = dist (hw);  
404 - for (; i < audio_state.nb_hw_voices; i++) {  
405 - hw = ADVANCE (hw);  
406 - if (hw->active && hw->enabled)  
407 - return hw; 544 + audio_pcm_hw_fini_in (hw);
  545 +
  546 + if (hw->pcm_ops->init_in (hw, freq, nchannels, fmt)) {
  547 + memset (hw, 0, audio_state.drv->voice_size_in);
  548 + return -1;
408 } 549 }
409 - return NULL; 550 + LIST_INIT (&hw->sw_head);
  551 + hw->active = 1;
  552 + hw->samples = hw->bufsize >> hw->info.shift;
  553 + hw->conv =
  554 + mixeng_conv
  555 + [nchannels == 2]
  556 + [hw->info.sign]
  557 + [hw->info.swap_endian]
  558 + [hw->info.bits == 16];
  559 + if (audio_pcm_hw_alloc_resources_in (hw)) {
  560 + audio_pcm_hw_free_resources_in (hw);
  561 + return -1;
  562 + }
  563 + return 0;
410 } 564 }
411 565
412 -HWVoice *pcm_hw_find_any_passive (HWVoice *hw) 566 +static uint64_t audio_pcm_hw_find_min_in (HWVoiceIn *hw)
413 { 567 {
414 - int i = dist (hw);  
415 - for (; i < audio_state.nb_hw_voices; i++) {  
416 - hw = ADVANCE (hw);  
417 - if (!hw->active)  
418 - return hw; 568 + SWVoiceIn *sw;
  569 + int m = hw->total_samples_captured;
  570 +
  571 + for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
  572 + if (sw->active) {
  573 + m = audio_MIN (m, sw->total_hw_samples_acquired);
  574 + }
419 } 575 }
420 - return NULL; 576 + return m;
421 } 577 }
422 578
423 -HWVoice *pcm_hw_find_specific (HWVoice *hw, int freq,  
424 - int nchannels, audfmt_e fmt) 579 +int audio_pcm_hw_get_live_in (HWVoiceIn *hw)
425 { 580 {
426 - while ((hw = pcm_hw_find_any_active (hw))) {  
427 - if (hw->freq == freq &&  
428 - hw->nchannels == nchannels &&  
429 - hw->fmt == fmt)  
430 - return hw; 581 + int live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw);
  582 + if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {
  583 + dolog ("live=%d hw->samples=%d\n", live, hw->samples);
  584 + return 0;
431 } 585 }
432 - return NULL; 586 + return live;
433 } 587 }
434 588
435 -HWVoice *pcm_hw_add (int freq, int nchannels, audfmt_e fmt) 589 +/*
  590 + * Soft voice (capture)
  591 + */
  592 +static void audio_pcm_sw_free_resources_in (SWVoiceIn *sw)
436 { 593 {
437 - HWVoice *hw;  
438 -  
439 - if (audio_state.fixed_format) {  
440 - freq = audio_state.fixed_freq;  
441 - nchannels = audio_state.fixed_channels;  
442 - fmt = audio_state.fixed_fmt; 594 + if (sw->conv_buf) {
  595 + qemu_free (sw->conv_buf);
443 } 596 }
444 597
445 - hw = pcm_hw_find_specific (NULL, freq, nchannels, fmt);  
446 -  
447 - if (hw)  
448 - return hw;  
449 -  
450 - hw = pcm_hw_find_any_passive (NULL);  
451 - if (hw) {  
452 - hw->pcm_ops = audio_state.drv->pcm_ops;  
453 - if (!hw->pcm_ops)  
454 - return NULL;  
455 -  
456 - if (pcm_hw_init (hw, freq, nchannels, fmt)) {  
457 - pcm_hw_gc (hw);  
458 - return NULL;  
459 - }  
460 - else  
461 - return hw; 598 + if (sw->rate) {
  599 + st_rate_stop (sw->rate);
462 } 600 }
463 601
464 - return pcm_hw_find_any (NULL); 602 + sw->conv_buf = NULL;
  603 + sw->rate = NULL;
465 } 604 }
466 605
467 -int pcm_hw_add_sw (HWVoice *hw, SWVoice *sw) 606 +static int audio_pcm_sw_alloc_resources_in (SWVoiceIn *sw)
468 { 607 {
469 - SWVoice **pvoice = qemu_mallocz ((hw->nb_voices + 1) * sizeof (sw));  
470 - if (!pvoice) 608 + int samples = ((int64_t) sw->hw->samples << 32) / sw->ratio;
  609 + sw->conv_buf = qemu_mallocz (samples * sizeof (st_sample_t));
  610 + if (!sw->conv_buf) {
471 return -1; 611 return -1;
  612 + }
472 613
473 - memcpy (pvoice, hw->pvoice, hw->nb_voices * sizeof (sw));  
474 - qemu_free (hw->pvoice);  
475 - hw->pvoice = pvoice;  
476 - hw->pvoice[hw->nb_voices++] = sw; 614 + sw->rate = st_rate_start (sw->hw->info.freq, sw->info.freq);
  615 + if (!sw->rate) {
  616 + qemu_free (sw->conv_buf);
  617 + sw->conv_buf = NULL;
  618 + return -1;
  619 + }
477 return 0; 620 return 0;
478 } 621 }
479 622
480 -int pcm_hw_del_sw (HWVoice *hw, SWVoice *sw) 623 +static int audio_pcm_sw_init_in (SWVoiceIn *sw, HWVoiceIn *hw, const char *name,
  624 + int freq, int nchannels, audfmt_e fmt)
481 { 625 {
482 - int i, j;  
483 - if (hw->nb_voices > 1) {  
484 - SWVoice **pvoice = qemu_mallocz ((hw->nb_voices - 1) * sizeof (sw)); 626 + audio_pcm_init_info (&sw->info, freq, nchannels, fmt,
  627 + /* None of the cards emulated by QEMU are big-endian
  628 + hence following shortcut */
  629 + audio_need_to_swap_endian (0));
  630 + sw->hw = hw;
  631 + sw->ratio = ((int64_t) sw->info.freq << 32) / sw->hw->info.freq;
485 632
486 - if (!pvoice) {  
487 - dolog ("Can not maintain consistent state (not enough memory)\n");  
488 - return -1;  
489 - } 633 + sw->clip =
  634 + mixeng_clip
  635 + [nchannels == 2]
  636 + [sw->info.sign]
  637 + [sw->info.swap_endian]
  638 + [sw->info.bits == 16];
490 639
491 - for (i = 0, j = 0; i < hw->nb_voices; i++) {  
492 - if (j >= hw->nb_voices - 1) {  
493 - dolog ("Can not maintain consistent state "  
494 - "(invariant violated)\n");  
495 - return -1;  
496 - }  
497 - if (hw->pvoice[i] != sw)  
498 - pvoice[j++] = hw->pvoice[i];  
499 - }  
500 - qemu_free (hw->pvoice);  
501 - hw->pvoice = pvoice;  
502 - hw->nb_voices -= 1; 640 + sw->name = qemu_strdup (name);
  641 + audio_pcm_sw_free_resources_in (sw);
  642 + return audio_pcm_sw_alloc_resources_in (sw);
  643 +}
  644 +
  645 +static int audio_pcm_sw_get_rpos_in (SWVoiceIn *sw)
  646 +{
  647 + HWVoiceIn *hw = sw->hw;
  648 + int live = hw->total_samples_captured - sw->total_hw_samples_acquired;
  649 + int rpos;
  650 +
  651 + if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {
  652 + dolog ("live=%d hw->samples=%d\n", live, hw->samples);
  653 + return 0;
  654 + }
  655 +
  656 + rpos = hw->wpos - live;
  657 + if (rpos >= 0) {
  658 + return rpos;
503 } 659 }
504 else { 660 else {
505 - qemu_free (hw->pvoice);  
506 - hw->pvoice = NULL;  
507 - hw->nb_voices = 0; 661 + return hw->samples + rpos;
508 } 662 }
509 - return 0;  
510 } 663 }
511 664
512 -SWVoice *pcm_create_voice_pair (int freq, int nchannels, audfmt_e fmt) 665 +int audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int size)
513 { 666 {
514 - SWVoice *sw;  
515 - HWVoice *hw; 667 + HWVoiceIn *hw = sw->hw;
  668 + int samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0;
  669 + st_sample_t *src, *dst = sw->conv_buf;
  670 +
  671 + rpos = audio_pcm_sw_get_rpos_in (sw) % hw->samples;
  672 +
  673 + live = hw->total_samples_captured - sw->total_hw_samples_acquired;
  674 + if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {
  675 + dolog ("live_in=%d hw->samples=%d\n", live, hw->samples);
  676 + return 0;
  677 + }
  678 +
  679 + samples = size >> sw->info.shift;
  680 + if (!live) {
  681 + return 0;
  682 + }
516 683
517 - sw = qemu_mallocz (sizeof (*sw));  
518 - if (!sw)  
519 - goto err1; 684 + swlim = (live * sw->ratio) >> 32;
  685 + swlim = audio_MIN (swlim, samples);
520 686
521 - hw = pcm_hw_add (freq, nchannels, fmt);  
522 - if (!hw)  
523 - goto err2; 687 + while (swlim) {
  688 + src = hw->conv_buf + rpos;
  689 + isamp = hw->wpos - rpos;
  690 + /* XXX: <= ? */
  691 + if (isamp <= 0) {
  692 + isamp = hw->samples - rpos;
  693 + }
524 694
525 - if (pcm_hw_add_sw (hw, sw))  
526 - goto err3; 695 + if (!isamp) {
  696 + break;
  697 + }
  698 + osamp = swlim;
527 699
528 - if (pcm_sw_init (sw, hw, freq, nchannels, fmt))  
529 - goto err4; 700 + if (audio_bug (AUDIO_FUNC, osamp < 0)) {
  701 + dolog ("osamp=%d\n", osamp);
  702 + }
530 703
531 - return sw; 704 + st_rate_flow (sw->rate, src, dst, &isamp, &osamp);
  705 + swlim -= osamp;
  706 + rpos = (rpos + isamp) % hw->samples;
  707 + dst += osamp;
  708 + ret += osamp;
  709 + total += isamp;
  710 + }
532 711
533 -err4:  
534 - pcm_hw_del_sw (hw, sw);  
535 -err3:  
536 - pcm_hw_gc (hw);  
537 -err2:  
538 - qemu_free (sw);  
539 -err1:  
540 - return NULL; 712 + sw->clip (buf, sw->conv_buf, ret);
  713 + sw->total_hw_samples_acquired += total;
  714 + return ret << sw->info.shift;
541 } 715 }
542 716
543 -SWVoice *AUD_open (SWVoice *sw, const char *name,  
544 - int freq, int nchannels, audfmt_e fmt) 717 +/*
  718 + * Hard voice (playback)
  719 + */
  720 +static int audio_pcm_hw_find_min_out (HWVoiceOut *hw, int *nb_livep)
545 { 721 {
546 - if (!audio_state.drv) {  
547 - return NULL; 722 + SWVoiceOut *sw;
  723 + int m = INT_MAX;
  724 + int nb_live = 0;
  725 +
  726 + for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
  727 + if (sw->active || !sw->empty) {
  728 + m = audio_MIN (m, sw->total_hw_samples_mixed);
  729 + nb_live += 1;
  730 + }
548 } 731 }
549 732
550 - if (sw && freq == sw->freq && sw->nchannels == nchannels && sw->fmt == fmt) {  
551 - return sw; 733 + *nb_livep = nb_live;
  734 + return m;
  735 +}
  736 +
  737 +static void audio_pcm_hw_free_resources_out (HWVoiceOut *hw)
  738 +{
  739 + if (hw->mix_buf) {
  740 + qemu_free (hw->mix_buf);
552 } 741 }
553 742
554 - if (sw) {  
555 - ldebug ("Different format %s %d %d %d\n",  
556 - name,  
557 - sw->freq == freq,  
558 - sw->nchannels == nchannels,  
559 - sw->fmt == fmt); 743 + hw->mix_buf = NULL;
  744 +}
  745 +
  746 +static int audio_pcm_hw_alloc_resources_out (HWVoiceOut *hw)
  747 +{
  748 + hw->mix_buf = qemu_mallocz (hw->samples * sizeof (st_sample_t));
  749 + if (!hw->mix_buf) {
  750 + return -1;
560 } 751 }
561 752
562 - if (nchannels != 1 && nchannels != 2) {  
563 - dolog ("Bogus channel count %d for voice %s\n", nchannels, name);  
564 - return NULL; 753 + return 0;
  754 +}
  755 +
  756 +static int audio_pcm_hw_init_out (HWVoiceOut *hw, int freq,
  757 + int nchannels, audfmt_e fmt)
  758 +{
  759 + audio_pcm_hw_fini_out (hw);
  760 + if (hw->pcm_ops->init_out (hw, freq, nchannels, fmt)) {
  761 + memset (hw, 0, audio_state.drv->voice_size_out);
  762 + return -1;
565 } 763 }
566 764
567 - if (!audio_state.fixed_format && sw) {  
568 - pcm_sw_fini (sw);  
569 - pcm_hw_del_sw (sw->hw, sw);  
570 - pcm_hw_gc (sw->hw);  
571 - if (sw->name) {  
572 - qemu_free (sw->name);  
573 - sw->name = NULL;  
574 - }  
575 - qemu_free (sw);  
576 - sw = NULL; 765 + LIST_INIT (&hw->sw_head);
  766 + hw->active = 1;
  767 + hw->samples = hw->bufsize >> hw->info.shift;
  768 + hw->clip =
  769 + mixeng_clip
  770 + [nchannels == 2]
  771 + [hw->info.sign]
  772 + [hw->info.swap_endian]
  773 + [hw->info.bits == 16];
  774 + if (audio_pcm_hw_alloc_resources_out (hw)) {
  775 + audio_pcm_hw_fini_out (hw);
  776 + return -1;
577 } 777 }
  778 + return 0;
  779 +}
578 780
579 - if (sw) {  
580 - HWVoice *hw = sw->hw;  
581 - if (!hw) {  
582 - dolog ("Internal logic error voice %s has no hardware store\n",  
583 - name);  
584 - return sw;  
585 - } 781 +int audio_pcm_hw_get_live_out2 (HWVoiceOut *hw, int *nb_live)
  782 +{
  783 + int smin;
586 784
587 - if (pcm_sw_init (sw, hw, freq, nchannels, fmt)) {  
588 - pcm_sw_fini (sw);  
589 - pcm_hw_del_sw (hw, sw);  
590 - pcm_hw_gc (hw);  
591 - if (sw->name) {  
592 - qemu_free (sw->name);  
593 - sw->name = NULL;  
594 - }  
595 - qemu_free (sw);  
596 - return NULL;  
597 - } 785 + smin = audio_pcm_hw_find_min_out (hw, nb_live);
  786 +
  787 + if (!*nb_live) {
  788 + return 0;
598 } 789 }
599 else { 790 else {
600 - sw = pcm_create_voice_pair (freq, nchannels, fmt);  
601 - if (!sw) {  
602 - dolog ("Failed to create voice %s\n", name);  
603 - return NULL; 791 + int live = smin;
  792 +
  793 + if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {
  794 + dolog ("live=%d hw->samples=%d\n", live, hw->samples);
  795 + return 0;
604 } 796 }
  797 + return live;
605 } 798 }
  799 +}
  800 +
  801 +int audio_pcm_hw_get_live_out (HWVoiceOut *hw)
  802 +{
  803 + int nb_live;
  804 + int live;
606 805
607 - if (sw->name) {  
608 - qemu_free (sw->name);  
609 - sw->name = NULL; 806 + live = audio_pcm_hw_get_live_out2 (hw, &nb_live);
  807 + if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {
  808 + dolog ("live=%d hw->samples=%d\n", live, hw->samples);
  809 + return 0;
610 } 810 }
611 - sw->name = qemu_strdup (name);  
612 - return sw; 811 + return live;
613 } 812 }
614 813
615 -void AUD_close (SWVoice *sw) 814 +/*
  815 + * Soft voice (playback)
  816 + */
  817 +static void audio_pcm_sw_free_resources_out (SWVoiceOut *sw)
616 { 818 {
617 - if (!sw)  
618 - return; 819 + if (sw->buf) {
  820 + qemu_free (sw->buf);
  821 + }
619 822
620 - pcm_sw_fini (sw);  
621 - pcm_hw_del_sw (sw->hw, sw);  
622 - pcm_hw_gc (sw->hw);  
623 - if (sw->name) {  
624 - qemu_free (sw->name);  
625 - sw->name = NULL; 823 + if (sw->rate) {
  824 + st_rate_stop (sw->rate);
626 } 825 }
627 - qemu_free (sw); 826 +
  827 + sw->buf = NULL;
  828 + sw->rate = NULL;
628 } 829 }
629 830
630 -int AUD_write (SWVoice *sw, void *buf, int size) 831 +static int audio_pcm_sw_alloc_resources_out (SWVoiceOut *sw)
631 { 832 {
632 - int bytes; 833 + sw->buf = qemu_mallocz (sw->hw->samples * sizeof (st_sample_t));
  834 + if (!sw->buf) {
  835 + return -1;
  836 + }
633 837
634 - if (!sw->hw->enabled)  
635 - dolog ("Writing to disabled voice %s\n", sw->name);  
636 - bytes = sw->hw->pcm_ops->write (sw, buf, size);  
637 - return bytes; 838 + sw->rate = st_rate_start (sw->info.freq, sw->hw->info.freq);
  839 + if (!sw->rate) {
  840 + qemu_free (sw->buf);
  841 + sw->buf = NULL;
  842 + return -1;
  843 + }
  844 + return 0;
638 } 845 }
639 846
640 -void AUD_run (void) 847 +static int audio_pcm_sw_init_out (SWVoiceOut *sw, HWVoiceOut *hw,
  848 + const char *name, int freq,
  849 + int nchannels, audfmt_e fmt)
641 { 850 {
642 - HWVoice *hw = NULL;  
643 -  
644 - while ((hw = pcm_hw_find_any_active_enabled (hw))) {  
645 - int i;  
646 - if (hw->pending_disable && pcm_hw_get_live (hw) <= 0) {  
647 - hw->enabled = 0;  
648 - hw->pcm_ops->ctl (hw, VOICE_DISABLE);  
649 - for (i = 0; i < hw->nb_voices; i++) {  
650 - hw->pvoice[i]->live = 0;  
651 - /* hw->pvoice[i]->old_ticks = 0; */  
652 - }  
653 - continue;  
654 - } 851 + audio_pcm_init_info (&sw->info, freq, nchannels, fmt,
  852 + /* None of the cards emulated by QEMU are big-endian
  853 + hence following shortcut */
  854 + audio_need_to_swap_endian (0));
  855 + sw->hw = hw;
  856 + sw->empty = 1;
  857 + sw->active = 0;
  858 + sw->ratio = ((int64_t) sw->hw->info.freq << 32) / sw->info.freq;
  859 + sw->total_hw_samples_mixed = 0;
  860 +
  861 + sw->conv =
  862 + mixeng_conv
  863 + [nchannels == 2]
  864 + [sw->info.sign]
  865 + [sw->info.swap_endian]
  866 + [sw->info.bits == 16];
  867 + sw->name = qemu_strdup (name);
655 868
656 - hw->pcm_ops->run (hw);  
657 - assert (hw->rpos < hw->samples);  
658 - for (i = 0; i < hw->nb_voices; i++) {  
659 - SWVoice *sw = hw->pvoice[i];  
660 - if (!sw->active && !sw->live && sw->old_ticks) {  
661 - int64_t delta = qemu_get_clock (vm_clock) - sw->old_ticks;  
662 - if (delta > audio_state.ticks_threshold) {  
663 - ldebug ("resetting old_ticks for %s\n", sw->name);  
664 - sw->old_ticks = 0;  
665 - }  
666 - }  
667 - }  
668 - } 869 + audio_pcm_sw_free_resources_out (sw);
  870 + return audio_pcm_sw_alloc_resources_out (sw);
669 } 871 }
670 872
671 -int AUD_get_free (SWVoice *sw) 873 +int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int size)
672 { 874 {
673 - int free; 875 + int hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, blck;
  876 + int ret = 0, pos = 0, total = 0;
674 877
675 - if (!sw)  
676 - return 4096; 878 + if (!sw) {
  879 + return size;
  880 + }
677 881
678 - free = ((sw->hw->samples - sw->live) << sw->hw->shift) * sw->ratio  
679 - / INT_MAX; 882 + hwsamples = sw->hw->samples;
680 883
681 - free &= ~sw->hw->align;  
682 - if (!free) return 0; 884 + live = sw->total_hw_samples_mixed;
  885 + if (audio_bug (AUDIO_FUNC, live < 0 || live > hwsamples)){
  886 + dolog ("live=%d hw->samples=%d\n", live, hwsamples);
  887 + return 0;
  888 + }
683 889
684 - return free;  
685 -} 890 + if (live == hwsamples) {
  891 + return 0;
  892 + }
686 893
687 -int AUD_get_buffer_size (SWVoice *sw)  
688 -{  
689 - return sw->hw->bufsize;  
690 -} 894 + wpos = (sw->hw->rpos + live) % hwsamples;
  895 + samples = size >> sw->info.shift;
691 896
692 -void AUD_adjust (SWVoice *sw, int bytes)  
693 -{  
694 - if (!sw)  
695 - return;  
696 - sw->old_ticks += (ticks_per_sec * (int64_t) bytes) / sw->bytes_per_second; 897 + dead = hwsamples - live;
  898 + swlim = ((int64_t) dead << 32) / sw->ratio;
  899 + swlim = audio_MIN (swlim, samples);
  900 + if (swlim) {
  901 + sw->conv (sw->buf, buf, swlim, &sw->vol);
  902 + }
  903 +
  904 + while (swlim) {
  905 + dead = hwsamples - live;
  906 + left = hwsamples - wpos;
  907 + blck = audio_MIN (dead, left);
  908 + if (!blck) {
  909 + break;
  910 + }
  911 + isamp = swlim;
  912 + osamp = blck;
  913 + st_rate_flow_mix (
  914 + sw->rate,
  915 + sw->buf + pos,
  916 + sw->hw->mix_buf + wpos,
  917 + &isamp,
  918 + &osamp
  919 + );
  920 + ret += isamp;
  921 + swlim -= isamp;
  922 + pos += isamp;
  923 + live += osamp;
  924 + wpos = (wpos + osamp) % hwsamples;
  925 + total += osamp;
  926 + }
  927 +
  928 + sw->total_hw_samples_mixed += total;
  929 + sw->empty = sw->total_hw_samples_mixed == 0;
  930 +
  931 +#ifdef DEBUG_OUT
  932 + dolog (
  933 + "%s: write size %d ret %d total sw %d, hw %d\n",
  934 + sw->name,
  935 + size >> sw->info.shift,
  936 + ret,
  937 + sw->total_hw_samples_mixed,
  938 + sw->hw->total_samples_played
  939 + );
  940 +#endif
  941 +
  942 + return ret << sw->info.shift;
697 } 943 }
698 944
699 -void AUD_reset (SWVoice *sw) 945 +#ifdef DEBUG_AUDIO
  946 +static void audio_pcm_print_info (const char *cap, struct audio_pcm_info *info)
700 { 947 {
701 - sw->active = 0;  
702 - sw->old_ticks = 0; 948 + dolog ("%s: bits %d, sign %d, freq %d, nchan %d\n",
  949 + cap, info->bits, info->sign, info->freq, info->nchannels);
703 } 950 }
  951 +#endif
704 952
705 -int AUD_calc_elapsed (SWVoice *sw) 953 +#define DAC
  954 +#include "audio_template.h"
  955 +#undef DAC
  956 +#include "audio_template.h"
  957 +
  958 +int AUD_write (SWVoiceOut *sw, void *buf, int size)
706 { 959 {
707 - int64_t now, delta, bytes;  
708 - int dead, swlim; 960 + int bytes;
709 961
710 - if (!sw)  
711 - return 0; 962 + if (!sw) {
  963 + /* XXX: Consider options */
  964 + return size;
  965 + }
712 966
713 - now = qemu_get_clock (vm_clock);  
714 - delta = now - sw->old_ticks;  
715 - bytes = (delta * sw->bytes_per_second) / ticks_per_sec;  
716 - if (delta < 0) {  
717 - dolog ("whoops delta(<0)=%lld\n", delta); 967 + if (!sw->hw->enabled) {
  968 + dolog ("Writing to disabled voice %s\n", sw->name);
718 return 0; 969 return 0;
719 } 970 }
720 971
721 - dead = sw->hw->samples - sw->live;  
722 - swlim = ((dead * (int64_t) INT_MAX) / sw->ratio); 972 + bytes = sw->hw->pcm_ops->write (sw, buf, size);
  973 + return bytes;
  974 +}
  975 +
  976 +int AUD_read (SWVoiceIn *sw, void *buf, int size)
  977 +{
  978 + int bytes;
723 979
724 - if (bytes > swlim) {  
725 - return swlim; 980 + if (!sw) {
  981 + /* XXX: Consider options */
  982 + return size;
726 } 983 }
727 - else {  
728 - return bytes; 984 +
  985 + if (!sw->hw->enabled) {
  986 + dolog ("Reading from disabled voice %s\n", sw->name);
  987 + return 0;
729 } 988 }
  989 +
  990 + bytes = sw->hw->pcm_ops->read (sw, buf, size);
  991 + return bytes;
730 } 992 }
731 993
732 -void AUD_enable (SWVoice *sw, int on) 994 +int AUD_get_buffer_size_out (SWVoiceOut *sw)
733 { 995 {
734 - int i;  
735 - HWVoice *hw; 996 + return sw->hw->bufsize;
  997 +}
  998 +
  999 +void AUD_set_active_out (SWVoiceOut *sw, int on)
  1000 +{
  1001 + HWVoiceOut *hw;
736 1002
737 - if (!sw) 1003 + if (!sw) {
738 return; 1004 return;
  1005 + }
739 1006
740 hw = sw->hw; 1007 hw = sw->hw;
741 - if (on) {  
742 - if (!sw->live)  
743 - sw->wpos = sw->hw->rpos;  
744 - if (!sw->old_ticks) {  
745 - sw->old_ticks = qemu_get_clock (vm_clock); 1008 + if (sw->active != on) {
  1009 + SWVoiceOut *temp_sw;
  1010 +
  1011 + if (on) {
  1012 + int total;
  1013 +
  1014 + hw->pending_disable = 0;
  1015 + if (!hw->enabled) {
  1016 + hw->enabled = 1;
  1017 + hw->pcm_ops->ctl_out (hw, VOICE_ENABLE);
  1018 + }
  1019 +
  1020 + if (sw->empty) {
  1021 + total = 0;
  1022 + }
  1023 + }
  1024 + else {
  1025 + if (hw->enabled) {
  1026 + int nb_active = 0;
  1027 +
  1028 + for (temp_sw = hw->sw_head.lh_first; temp_sw;
  1029 + temp_sw = temp_sw->entries.le_next) {
  1030 + nb_active += temp_sw->active != 0;
  1031 + }
  1032 +
  1033 + hw->pending_disable = nb_active == 1;
  1034 + }
746 } 1035 }
  1036 + sw->active = on;
  1037 + }
  1038 +}
  1039 +
  1040 +void AUD_set_active_in (SWVoiceIn *sw, int on)
  1041 +{
  1042 + HWVoiceIn *hw;
  1043 +
  1044 + if (!sw) {
  1045 + return;
747 } 1046 }
748 1047
  1048 + hw = sw->hw;
749 if (sw->active != on) { 1049 if (sw->active != on) {
  1050 + SWVoiceIn *temp_sw;
  1051 +
750 if (on) { 1052 if (on) {
751 - hw->pending_disable = 0;  
752 if (!hw->enabled) { 1053 if (!hw->enabled) {
753 hw->enabled = 1; 1054 hw->enabled = 1;
754 - for (i = 0; i < hw->nb_voices; i++) {  
755 - ldebug ("resetting voice\n");  
756 - sw = hw->pvoice[i];  
757 - sw->old_ticks = qemu_get_clock (vm_clock);  
758 - }  
759 - hw->pcm_ops->ctl (hw, VOICE_ENABLE); 1055 + hw->pcm_ops->ctl_in (hw, VOICE_ENABLE);
760 } 1056 }
  1057 + sw->total_hw_samples_acquired = hw->total_samples_captured;
761 } 1058 }
762 else { 1059 else {
763 - if (hw->enabled && !hw->pending_disable) { 1060 + if (hw->enabled) {
764 int nb_active = 0; 1061 int nb_active = 0;
765 - for (i = 0; i < hw->nb_voices; i++) {  
766 - nb_active += hw->pvoice[i]->active != 0; 1062 +
  1063 + for (temp_sw = hw->sw_head.lh_first; temp_sw;
  1064 + temp_sw = temp_sw->entries.le_next) {
  1065 + nb_active += temp_sw->active != 0;
767 } 1066 }
768 1067
769 if (nb_active == 1) { 1068 if (nb_active == 1) {
770 - hw->pending_disable = 1; 1069 + hw->enabled = 0;
  1070 + hw->pcm_ops->ctl_in (hw, VOICE_DISABLE);
771 } 1071 }
772 } 1072 }
773 } 1073 }
@@ -775,118 +1075,547 @@ void AUD_enable (SWVoice *sw, int on) @@ -775,118 +1075,547 @@ void AUD_enable (SWVoice *sw, int on)
775 } 1075 }
776 } 1076 }
777 1077
778 -static struct audio_output_driver *drvtab[] = {  
779 -#ifdef CONFIG_OSS  
780 - &oss_output_driver, 1078 +static int audio_get_avail (SWVoiceIn *sw)
  1079 +{
  1080 + int live;
  1081 +
  1082 + if (!sw) {
  1083 + return 0;
  1084 + }
  1085 +
  1086 + live = sw->hw->total_samples_captured - sw->total_hw_samples_acquired;
  1087 + if (audio_bug (AUDIO_FUNC, live < 0 || live > sw->hw->samples)) {
  1088 + dolog ("live=%d sw->hw->samples=%d\n", live, sw->hw->samples);
  1089 + return 0;
  1090 + }
  1091 +
  1092 + ldebug (
  1093 + "%s: get_avail live %d ret %lld\n",
  1094 + sw->name,
  1095 + live, (((int64_t) live << 32) / sw->ratio) << sw->info.shift
  1096 + );
  1097 +
  1098 + return (((int64_t) live << 32) / sw->ratio) << sw->info.shift;
  1099 +}
  1100 +
  1101 +static int audio_get_free (SWVoiceOut *sw)
  1102 +{
  1103 + int live, dead;
  1104 +
  1105 + if (!sw) {
  1106 + return 0;
  1107 + }
  1108 +
  1109 + live = sw->total_hw_samples_mixed;
  1110 +
  1111 + if (audio_bug (AUDIO_FUNC, live < 0 || live > sw->hw->samples)) {
  1112 + dolog ("live=%d sw->hw->samples=%d\n", live, sw->hw->samples);
  1113 + }
  1114 +
  1115 + dead = sw->hw->samples - live;
  1116 +
  1117 +#ifdef DEBUG_OUT
  1118 + dolog ("%s: get_free live %d dead %d ret %lld\n",
  1119 + sw->name,
  1120 + live, dead, (((int64_t) dead << 32) / sw->ratio) << sw->info.shift);
781 #endif 1121 #endif
782 -#ifdef CONFIG_FMOD  
783 - &fmod_output_driver, 1122 +
  1123 + return (((int64_t) dead << 32) / sw->ratio) << sw->info.shift;
  1124 +}
  1125 +
  1126 +static void audio_run_out (void)
  1127 +{
  1128 + HWVoiceOut *hw = NULL;
  1129 + SWVoiceOut *sw;
  1130 +
  1131 + while ((hw = audio_pcm_hw_find_any_active_enabled_out (hw))) {
  1132 + int played;
  1133 + int live, free, nb_live;
  1134 +
  1135 + live = audio_pcm_hw_get_live_out2 (hw, &nb_live);
  1136 + if (!nb_live) {
  1137 + live = 0;
  1138 + }
  1139 + if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {
  1140 + dolog ("live=%d hw->samples=%d\n", live, hw->samples);
  1141 + }
  1142 +
  1143 + if (hw->pending_disable && !nb_live) {
  1144 +#ifdef DEBUG_OUT
  1145 + dolog ("Disabling voice\n");
784 #endif 1146 #endif
785 -#ifdef CONFIG_SDL  
786 - &sdl_output_driver, 1147 + hw->enabled = 0;
  1148 + hw->pending_disable = 0;
  1149 + hw->pcm_ops->ctl_out (hw, VOICE_DISABLE);
  1150 + continue;
  1151 + }
  1152 +
  1153 + if (!live) {
  1154 + for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
  1155 + if (sw->active) {
  1156 + free = audio_get_free (sw);
  1157 + if (free > 0) {
  1158 + sw->callback.fn (sw->callback.opaque, free);
  1159 + }
  1160 + }
  1161 + }
  1162 + continue;
  1163 + }
  1164 +
  1165 + played = hw->pcm_ops->run_out (hw);
  1166 + if (audio_bug (AUDIO_FUNC, hw->rpos >= hw->samples)) {
  1167 + dolog ("hw->rpos=%d hw->samples=%d played=%d\n",
  1168 + hw->rpos, hw->samples, played);
  1169 + hw->rpos = 0;
  1170 + }
  1171 +
  1172 +#ifdef DEBUG_OUT
  1173 + dolog ("played = %d total %d\n", played, hw->total_samples_played);
787 #endif 1174 #endif
788 - &no_output_driver,  
789 -#ifdef USE_WAV_AUDIO  
790 - &wav_output_driver, 1175 +
  1176 + if (played) {
  1177 + hw->ts_helper += played;
  1178 + }
  1179 +
  1180 + for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
  1181 + again:
  1182 + if (!sw->active && sw->empty) {
  1183 + continue;
  1184 + }
  1185 +
  1186 + if (audio_bug (AUDIO_FUNC, played > sw->total_hw_samples_mixed)) {
  1187 + dolog ("played=%d sw->total_hw_samples_mixed=%d\n",
  1188 + played, sw->total_hw_samples_mixed);
  1189 + played = sw->total_hw_samples_mixed;
  1190 + }
  1191 +
  1192 + sw->total_hw_samples_mixed -= played;
  1193 +
  1194 + if (!sw->total_hw_samples_mixed) {
  1195 + sw->empty = 1;
  1196 +
  1197 + if (!sw->active && !sw->callback.fn) {
  1198 + SWVoiceOut *temp = sw->entries.le_next;
  1199 +
  1200 +#ifdef DEBUG_PLIVE
  1201 + dolog ("Finishing with old voice\n");
791 #endif 1202 #endif
  1203 + AUD_close_out (sw);
  1204 + sw = temp;
  1205 + if (sw) {
  1206 + goto again;
  1207 + }
  1208 + else {
  1209 + break;
  1210 + }
  1211 + }
  1212 + }
  1213 +
  1214 + if (sw->active) {
  1215 + free = audio_get_free (sw);
  1216 + if (free > 0) {
  1217 + sw->callback.fn (sw->callback.opaque, free);
  1218 + }
  1219 + }
  1220 + }
  1221 + }
  1222 +}
  1223 +
  1224 +static void audio_run_in (void)
  1225 +{
  1226 + HWVoiceIn *hw = NULL;
  1227 +
  1228 + while ((hw = audio_pcm_hw_find_any_active_enabled_in (hw))) {
  1229 + SWVoiceIn *sw;
  1230 + int captured, min;
  1231 +
  1232 + captured = hw->pcm_ops->run_in (hw);
  1233 +
  1234 + min = audio_pcm_hw_find_min_in (hw);
  1235 + hw->total_samples_captured += captured - min;
  1236 + hw->ts_helper += captured;
  1237 +
  1238 + for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
  1239 + sw->total_hw_samples_acquired -= min;
  1240 +
  1241 + if (sw->active) {
  1242 + int avail;
  1243 +
  1244 + avail = audio_get_avail (sw);
  1245 + if (avail > 0) {
  1246 + sw->callback.fn (sw->callback.opaque, avail);
  1247 + }
  1248 + }
  1249 + }
  1250 + }
  1251 +}
  1252 +
  1253 +static struct audio_option audio_options[] = {
  1254 + /* DAC */
  1255 + {"DAC_FIXED_SETTINGS", AUD_OPT_BOOL, &audio_state.fixed_settings_out,
  1256 + "Use fixed settings for host DAC", NULL, 0},
  1257 +
  1258 + {"DAC_FIXED_FREQ", AUD_OPT_INT, &audio_state.fixed_freq_out,
  1259 + "Frequency for fixed host DAC", NULL, 0},
  1260 +
  1261 + {"DAC_FIXED_FMT", AUD_OPT_FMT, &audio_state.fixed_fmt_out,
  1262 + "Format for fixed host DAC", NULL, 0},
  1263 +
  1264 + {"DAC_FIXED_CHANNELS", AUD_OPT_INT, &audio_state.fixed_channels_out,
  1265 + "Number of channels for fixed DAC (1 - mono, 2 - stereo)", NULL, 0},
  1266 +
  1267 + {"DAC_VOICES", AUD_OPT_INT, &audio_state.nb_hw_voices_out,
  1268 + "Number of voices for DAC", NULL, 0},
  1269 +
  1270 + /* ADC */
  1271 + {"ADC_FIXED_SETTINGS", AUD_OPT_BOOL, &audio_state.fixed_settings_out,
  1272 + "Use fixed settings for host ADC", NULL, 0},
  1273 +
  1274 + {"ADC_FIXED_FREQ", AUD_OPT_INT, &audio_state.fixed_freq_out,
  1275 + "Frequency for fixed ADC", NULL, 0},
  1276 +
  1277 + {"ADC_FIXED_FMT", AUD_OPT_FMT, &audio_state.fixed_fmt_out,
  1278 + "Format for fixed ADC", NULL, 0},
  1279 +
  1280 + {"ADC_FIXED_CHANNELS", AUD_OPT_INT, &audio_state.fixed_channels_in,
  1281 + "Number of channels for fixed ADC (1 - mono, 2 - stereo)", NULL, 0},
  1282 +
  1283 + {"ADC_VOICES", AUD_OPT_INT, &audio_state.nb_hw_voices_out,
  1284 + "Number of voices for ADC", NULL, 0},
  1285 +
  1286 + /* Misc */
  1287 + {"TIMER_PERIOD", AUD_OPT_INT, &audio_state.period.usec,
  1288 + "Timer period in microseconds (0 - try lowest possible)", NULL, 0},
  1289 +
  1290 + {"PLIVE", AUD_OPT_BOOL, &audio_state.plive,
  1291 + "(undocumented)", NULL, 0},
  1292 +
  1293 + {NULL, 0, NULL, NULL, NULL, 0}
792 }; 1294 };
793 1295
794 -static int voice_init (struct audio_output_driver *drv) 1296 +void AUD_help (void)
  1297 +{
  1298 + size_t i;
  1299 +
  1300 + audio_process_options ("AUDIO", audio_options);
  1301 + for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
  1302 + struct audio_driver *d = drvtab[i];
  1303 + if (d->options) {
  1304 + audio_process_options (d->name, d->options);
  1305 + }
  1306 + }
  1307 +
  1308 + printf ("Audio options:\n");
  1309 + audio_print_options ("AUDIO", audio_options);
  1310 + printf ("\n");
  1311 +
  1312 + printf ("Available drivers:\n");
  1313 +
  1314 + for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
  1315 + struct audio_driver *d = drvtab[i];
  1316 +
  1317 + printf ("Name: %s\n", d->name);
  1318 + printf ("Description: %s\n", d->descr);
  1319 +
  1320 + switch (d->max_voices_out) {
  1321 + case 0:
  1322 + printf ("Does not support DAC\n");
  1323 + break;
  1324 + case 1:
  1325 + printf ("One DAC voice\n");
  1326 + break;
  1327 + case INT_MAX:
  1328 + printf ("Theoretically supports many DAC voices\n");
  1329 + break;
  1330 + default:
  1331 + printf ("Theoretically supports upto %d DAC voices\n",
  1332 + d->max_voices_out);
  1333 + break;
  1334 + }
  1335 +
  1336 + switch (d->max_voices_in) {
  1337 + case 0:
  1338 + printf ("Does not support ADC\n");
  1339 + break;
  1340 + case 1:
  1341 + printf ("One ADC voice\n");
  1342 + break;
  1343 + case INT_MAX:
  1344 + printf ("Theoretically supports many ADC voices\n");
  1345 + break;
  1346 + default:
  1347 + printf ("Theoretically supports upto %d ADC voices\n",
  1348 + d->max_voices_in);
  1349 + break;
  1350 + }
  1351 +
  1352 + if (d->options) {
  1353 + printf ("Options:\n");
  1354 + audio_print_options (d->name, d->options);
  1355 + }
  1356 + else {
  1357 + printf ("No options\n");
  1358 + }
  1359 + printf ("\n");
  1360 + }
  1361 +
  1362 + printf (
  1363 + "Options are settable through environment variables.\n"
  1364 + "Example:\n"
  1365 +#ifdef _WIN32
  1366 + " set QEMU_AUDIO_DRV=wav\n"
  1367 + " set QEMU_WAV_PATH=c:/tune.wav\n"
  1368 +#else
  1369 + " export QEMU_AUDIO_DRV=wav\n"
  1370 + " export QEMU_WAV_PATH=$HOME/tune.wav\n"
  1371 + "(for csh replace export with setenv in the above)\n"
  1372 +#endif
  1373 + " qemu ...\n\n"
  1374 + );
  1375 +}
  1376 +
  1377 +void audio_timer (void *opaque)
  1378 +{
  1379 + AudioState *s = opaque;
  1380 +
  1381 + audio_run_out ();
  1382 + audio_run_in ();
  1383 +
  1384 + qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + s->period.ticks);
  1385 +}
  1386 +
  1387 +static int audio_driver_init (struct audio_driver *drv)
795 { 1388 {
  1389 + if (drv->options) {
  1390 + audio_process_options (drv->name, drv->options);
  1391 + }
796 audio_state.opaque = drv->init (); 1392 audio_state.opaque = drv->init ();
  1393 +
797 if (audio_state.opaque) { 1394 if (audio_state.opaque) {
798 - if (audio_state.nb_hw_voices > drv->max_voices) {  
799 - dolog ("`%s' does not support %d multiple hardware channels\n"  
800 - "Resetting to %d\n",  
801 - drv->name, audio_state.nb_hw_voices, drv->max_voices);  
802 - audio_state.nb_hw_voices = drv->max_voices; 1395 + int i;
  1396 + HWVoiceOut *hwo;
  1397 + HWVoiceIn *hwi;
  1398 +
  1399 + if (audio_state.nb_hw_voices_out > drv->max_voices_out) {
  1400 + if (!drv->max_voices_out) {
  1401 + dolog ("`%s' does not support DAC\n", drv->name);
  1402 + }
  1403 + else {
  1404 + dolog (
  1405 + "`%s' does not support %d multiple DAC voicess\n"
  1406 + "Resetting to %d\n",
  1407 + drv->name,
  1408 + audio_state.nb_hw_voices_out,
  1409 + drv->max_voices_out
  1410 + );
  1411 + }
  1412 + audio_state.nb_hw_voices_out = drv->max_voices_out;
803 } 1413 }
804 - hw_voices = qemu_mallocz (audio_state.nb_hw_voices * drv->voice_size);  
805 - if (hw_voices) {  
806 - audio_state.drv = drv;  
807 - return 1; 1414 +
  1415 + LIST_INIT (&hw_head_out);
  1416 + hwo = qemu_mallocz (audio_state.nb_hw_voices_out * drv->voice_size_out);
  1417 + if (!hwo) {
  1418 + dolog (
  1419 + "Not enough memory for %d `%s' DAC voices (each %d bytes)\n",
  1420 + audio_state.nb_hw_voices_out,
  1421 + drv->name,
  1422 + drv->voice_size_out
  1423 + );
  1424 + drv->fini (audio_state.opaque);
  1425 + return -1;
808 } 1426 }
809 - else {  
810 - dolog ("Not enough memory for %d `%s' voices (each %d bytes)\n",  
811 - audio_state.nb_hw_voices, drv->name, drv->voice_size); 1427 +
  1428 + for (i = 0; i < audio_state.nb_hw_voices_out; ++i) {
  1429 + LIST_INSERT_HEAD (&hw_head_out, hwo, entries);
  1430 + hwo = advance (hwo, drv->voice_size_out);
  1431 + }
  1432 +
  1433 + if (!drv->voice_size_in && drv->max_voices_in) {
  1434 + ldebug ("warning: No ADC voice size defined for `%s'\n",
  1435 + drv->name);
  1436 + drv->max_voices_in = 0;
  1437 + }
  1438 +
  1439 + if (!drv->voice_size_out && drv->max_voices_out) {
  1440 + ldebug ("warning: No DAC voice size defined for `%s'\n",
  1441 + drv->name);
  1442 + }
  1443 +
  1444 + if (drv->voice_size_in && !drv->max_voices_in) {
  1445 + ldebug ("warning: ADC voice size is %d for ADC less driver `%s'\n",
  1446 + drv->voice_size_out, drv->name);
  1447 + }
  1448 +
  1449 + if (drv->voice_size_out && !drv->max_voices_out) {
  1450 + ldebug ("warning: DAC voice size is %d for DAC less driver `%s'\n",
  1451 + drv->voice_size_in, drv->name);
  1452 + }
  1453 +
  1454 + if (audio_state.nb_hw_voices_in > drv->max_voices_in) {
  1455 + if (!drv->max_voices_in) {
  1456 + ldebug ("`%s' does not support ADC\n", drv->name);
  1457 + }
  1458 + else {
  1459 + dolog (
  1460 + "`%s' does not support %d multiple ADC voices\n"
  1461 + "Resetting to %d\n",
  1462 + drv->name,
  1463 + audio_state.nb_hw_voices_in,
  1464 + drv->max_voices_in
  1465 + );
  1466 + }
  1467 + audio_state.nb_hw_voices_in = drv->max_voices_in;
  1468 + }
  1469 +
  1470 + LIST_INIT (&hw_head_in);
  1471 + hwi = qemu_mallocz (audio_state.nb_hw_voices_in * drv->voice_size_in);
  1472 + if (!hwi) {
  1473 + dolog (
  1474 + "Not enough memory for %d `%s' ADC voices (each %d bytes)\n",
  1475 + audio_state.nb_hw_voices_in,
  1476 + drv->name,
  1477 + drv->voice_size_in
  1478 + );
  1479 + qemu_free (hwo);
812 drv->fini (audio_state.opaque); 1480 drv->fini (audio_state.opaque);
813 - return 0; 1481 + return -1;
  1482 + }
  1483 +
  1484 + for (i = 0; i < audio_state.nb_hw_voices_in; ++i) {
  1485 + LIST_INSERT_HEAD (&hw_head_in, hwi, entries);
  1486 + hwi = advance (hwi, drv->voice_size_in);
814 } 1487 }
  1488 +
  1489 + audio_state.drv = drv;
  1490 + return 0;
815 } 1491 }
816 else { 1492 else {
817 - dolog ("Could not init `%s' audio\n", drv->name);  
818 - return 0; 1493 + dolog ("Could not init `%s' audio driver\n", drv->name);
  1494 + return -1;
819 } 1495 }
820 } 1496 }
821 1497
822 static void audio_vm_stop_handler (void *opaque, int reason) 1498 static void audio_vm_stop_handler (void *opaque, int reason)
823 { 1499 {
824 - HWVoice *hw = NULL; 1500 + HWVoiceOut *hwo = NULL;
  1501 + HWVoiceIn *hwi = NULL;
  1502 + int op = reason ? VOICE_ENABLE : VOICE_DISABLE;
  1503 +
  1504 + (void) opaque;
  1505 + while ((hwo = audio_pcm_hw_find_any_out (hwo))) {
  1506 + if (!hwo->pcm_ops) {
  1507 + continue;
  1508 + }
  1509 +
  1510 + if (hwo->enabled != reason) {
  1511 + hwo->pcm_ops->ctl_out (hwo, op);
  1512 + }
  1513 + }
825 1514
826 - while ((hw = pcm_hw_find_any (hw))) {  
827 - if (!hw->pcm_ops) 1515 + while ((hwi = audio_pcm_hw_find_any_in (hwi))) {
  1516 + if (!hwi->pcm_ops) {
828 continue; 1517 continue;
  1518 + }
829 1519
830 - hw->pcm_ops->ctl (hw, reason ? VOICE_ENABLE : VOICE_DISABLE); 1520 + if (hwi->enabled != reason) {
  1521 + hwi->pcm_ops->ctl_in (hwi, op);
  1522 + }
831 } 1523 }
832 } 1524 }
833 1525
834 static void audio_atexit (void) 1526 static void audio_atexit (void)
835 { 1527 {
836 - HWVoice *hw = NULL; 1528 + HWVoiceOut *hwo = NULL;
  1529 + HWVoiceIn *hwi = NULL;
  1530 +
  1531 + while ((hwo = audio_pcm_hw_find_any_out (hwo))) {
  1532 + if (!hwo->pcm_ops) {
  1533 + continue;
  1534 + }
  1535 +
  1536 + if (hwo->enabled) {
  1537 + hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE);
  1538 + }
  1539 + hwo->pcm_ops->fini_out (hwo);
  1540 + }
837 1541
838 - while ((hw = pcm_hw_find_any (hw))) {  
839 - if (!hw->pcm_ops) 1542 + while ((hwi = audio_pcm_hw_find_any_in (hwi))) {
  1543 + if (!hwi->pcm_ops) {
840 continue; 1544 continue;
  1545 + }
841 1546
842 - hw->pcm_ops->ctl (hw, VOICE_DISABLE);  
843 - hw->pcm_ops->fini (hw); 1547 + if (hwi->enabled) {
  1548 + hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE);
  1549 + }
  1550 + hwi->pcm_ops->fini_in (hwi);
844 } 1551 }
845 audio_state.drv->fini (audio_state.opaque); 1552 audio_state.drv->fini (audio_state.opaque);
846 } 1553 }
847 1554
848 static void audio_save (QEMUFile *f, void *opaque) 1555 static void audio_save (QEMUFile *f, void *opaque)
849 { 1556 {
  1557 + (void) f;
  1558 + (void) opaque;
850 } 1559 }
851 1560
852 static int audio_load (QEMUFile *f, void *opaque, int version_id) 1561 static int audio_load (QEMUFile *f, void *opaque, int version_id)
853 { 1562 {
854 - if (version_id != 1) 1563 + (void) f;
  1564 + (void) opaque;
  1565 +
  1566 + if (version_id != 1) {
855 return -EINVAL; 1567 return -EINVAL;
  1568 + }
856 1569
857 return 0; 1570 return 0;
858 } 1571 }
859 1572
860 void AUD_init (void) 1573 void AUD_init (void)
861 { 1574 {
862 - int i; 1575 + size_t i;
863 int done = 0; 1576 int done = 0;
864 const char *drvname; 1577 const char *drvname;
  1578 + AudioState *s = &audio_state;
  1579 +
  1580 + audio_process_options ("AUDIO", audio_options);
  1581 +
  1582 + if (s->nb_hw_voices_out <= 0) {
  1583 + dolog ("Bogus number of DAC voices %d\n",
  1584 + s->nb_hw_voices_out);
  1585 + s->nb_hw_voices_out = 1;
  1586 + }
  1587 +
  1588 + if (s->nb_hw_voices_in <= 0) {
  1589 + dolog ("Bogus number of ADC voices %d\n",
  1590 + s->nb_hw_voices_in);
  1591 + s->nb_hw_voices_in = 1;
  1592 + }
865 1593
866 - audio_state.fixed_format =  
867 - !!audio_get_conf_int (QC_FIXED_FORMAT, audio_state.fixed_format);  
868 - audio_state.fixed_freq =  
869 - audio_get_conf_int (QC_FIXED_FREQ, audio_state.fixed_freq);  
870 - audio_state.nb_hw_voices =  
871 - audio_get_conf_int (QC_VOICES, audio_state.nb_hw_voices); 1594 + {
  1595 + int def;
  1596 + drvname = audio_get_conf_str ("QEMU_AUDIO_DRV", NULL, &def);
  1597 + }
872 1598
873 - if (audio_state.nb_hw_voices <= 0) {  
874 - dolog ("Bogus number of voices %d, resetting to 1\n",  
875 - audio_state.nb_hw_voices); 1599 + s->ts = qemu_new_timer (vm_clock, audio_timer, s);
  1600 + if (!s->ts) {
  1601 + dolog ("Can not create audio timer\n");
  1602 + return;
876 } 1603 }
877 1604
878 - drvname = audio_get_conf_str (QC_AUDIO_DRV, NULL);  
879 if (drvname) { 1605 if (drvname) {
880 int found = 0; 1606 int found = 0;
  1607 +
881 for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) { 1608 for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
882 if (!strcmp (drvname, drvtab[i]->name)) { 1609 if (!strcmp (drvname, drvtab[i]->name)) {
883 - done = voice_init (drvtab[i]); 1610 + done = !audio_driver_init (drvtab[i]);
884 found = 1; 1611 found = 1;
885 break; 1612 break;
886 } 1613 }
887 } 1614 }
  1615 +
888 if (!found) { 1616 if (!found) {
889 dolog ("Unknown audio driver `%s'\n", drvname); 1617 dolog ("Unknown audio driver `%s'\n", drvname);
  1618 + dolog ("Run with -audio-help to list available drivers\n");
890 } 1619 }
891 } 1620 }
892 1621
@@ -895,17 +1624,32 @@ void AUD_init (void) @@ -895,17 +1624,32 @@ void AUD_init (void)
895 1624
896 if (!done) { 1625 if (!done) {
897 for (i = 0; !done && i < sizeof (drvtab) / sizeof (drvtab[0]); i++) { 1626 for (i = 0; !done && i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
898 - if (drvtab[i]->can_be_default)  
899 - done = voice_init (drvtab[i]); 1627 + if (drvtab[i]->can_be_default) {
  1628 + done = !audio_driver_init (drvtab[i]);
  1629 + }
900 } 1630 }
901 } 1631 }
902 1632
903 - audio_state.ticks_threshold = ticks_per_sec / 50;  
904 - audio_state.freq_threshold = 100;  
905 -  
906 register_savevm ("audio", 0, 1, audio_save, audio_load, NULL); 1633 register_savevm ("audio", 0, 1, audio_save, audio_load, NULL);
907 if (!done) { 1634 if (!done) {
908 - dolog ("Can not initialize audio subsystem\n");  
909 - voice_init (&no_output_driver); 1635 + if (audio_driver_init (&no_audio_driver)) {
  1636 + dolog ("Can not initialize audio subsystem\n");
  1637 + }
  1638 + else {
  1639 + dolog ("warning: using timer based audio emulation\n");
  1640 + }
910 } 1641 }
  1642 +
  1643 + if (s->period.usec <= 0) {
  1644 + if (s->period.usec < 0) {
  1645 + dolog ("warning: timer period is negative - %d treating as zero\n",
  1646 + s->period.usec);
  1647 + }
  1648 + s->period.ticks = 1;
  1649 + }
  1650 + else {
  1651 + s->period.ticks = (ticks_per_sec * s->period.usec) / 1000000;
  1652 + }
  1653 +
  1654 + qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + s->period.ticks);
911 } 1655 }
audio/audio.h
1 /* 1 /*
2 * QEMU Audio subsystem header 2 * QEMU Audio subsystem header
3 - *  
4 - * Copyright (c) 2003-2004 Vassili Karpov (malc)  
5 - * 3 + *
  4 + * Copyright (c) 2003-2005 Vassili Karpov (malc)
  5 + *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy 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 7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights 8 * in the Software without restriction, including without limitation the rights
@@ -24,7 +24,7 @@ @@ -24,7 +24,7 @@
24 #ifndef QEMU_AUDIO_H 24 #ifndef QEMU_AUDIO_H
25 #define QEMU_AUDIO_H 25 #define QEMU_AUDIO_H
26 26
27 -#include "mixeng.h" 27 +typedef void (*audio_callback_fn_t) (void *opaque, int avail);
28 28
29 typedef enum { 29 typedef enum {
30 AUD_FMT_U8, 30 AUD_FMT_U8,
@@ -33,22 +33,60 @@ typedef enum { @@ -33,22 +33,60 @@ typedef enum {
33 AUD_FMT_S16 33 AUD_FMT_S16
34 } audfmt_e; 34 } audfmt_e;
35 35
36 -typedef struct SWVoice SWVoice; 36 +typedef struct SWVoiceOut SWVoiceOut;
  37 +typedef struct SWVoiceIn SWVoiceIn;
  38 +
  39 +typedef struct QEMUAudioTimeStamp {
  40 + uint64_t old_ts;
  41 +} QEMUAudioTimeStamp;
  42 +
  43 +void AUD_vlog (const char *cap, const char *fmt, va_list ap);
  44 +void AUD_log (const char *cap, const char *fmt, ...)
  45 +#ifdef __GNUC__
  46 + __attribute__ ((__format__ (__printf__, 2, 3)))
  47 +#endif
  48 + ;
37 49
38 -SWVoice * AUD_open (SWVoice *sw, const char *name, int freq,  
39 - int nchannels, audfmt_e fmt);  
40 -void AUD_init (void);  
41 -void AUD_log (const char *cap, const char *fmt, ...)  
42 - __attribute__ ((__format__ (__printf__, 2, 3)));;  
43 -void AUD_close (SWVoice *sw);  
44 -int AUD_write (SWVoice *sw, void *pcm_buf, int size);  
45 -void AUD_adjust (SWVoice *sw, int leftover);  
46 -void AUD_reset (SWVoice *sw);  
47 -int AUD_get_free (SWVoice *sw);  
48 -int AUD_get_buffer_size (SWVoice *sw);  
49 -void AUD_run (void);  
50 -void AUD_enable (SWVoice *sw, int on);  
51 -int AUD_calc_elapsed (SWVoice *sw); 50 +void AUD_init (void);
  51 +void AUD_help (void);
  52 +
  53 +SWVoiceOut *AUD_open_out (
  54 + SWVoiceOut *sw,
  55 + const char *name,
  56 + void *callback_opaque,
  57 + audio_callback_fn_t callback_fn,
  58 + int freq,
  59 + int nchannels,
  60 + audfmt_e fmt
  61 + );
  62 +void AUD_close_out (SWVoiceOut *sw);
  63 +int AUD_write (SWVoiceOut *sw, void *pcm_buf, int size);
  64 +int AUD_get_buffer_size_out (SWVoiceOut *sw);
  65 +void AUD_set_active_out (SWVoiceOut *sw, int on);
  66 +int AUD_is_active_out (SWVoiceOut *sw);
  67 +void AUD_init_time_stamp_out (SWVoiceOut *sw,
  68 + QEMUAudioTimeStamp *ts);
  69 +uint64_t AUD_time_stamp_get_elapsed_usec_out (SWVoiceOut *sw,
  70 + QEMUAudioTimeStamp *ts);
  71 +
  72 +SWVoiceIn *AUD_open_in (
  73 + SWVoiceIn *sw,
  74 + const char *name,
  75 + void *callback_opaque,
  76 + audio_callback_fn_t callback_fn,
  77 + int freq,
  78 + int nchannels,
  79 + audfmt_e fmt
  80 + );
  81 +void AUD_close_in (SWVoiceIn *sw);
  82 +int AUD_read (SWVoiceIn *sw, void *pcm_buf, int size);
  83 +void AUD_adjust_in (SWVoiceIn *sw, int leftover);
  84 +void AUD_set_active_in (SWVoiceIn *sw, int on);
  85 +int AUD_is_active_in (SWVoiceIn *sw);
  86 +void AUD_init_time_stamp_in (SWVoiceIn *sw,
  87 + QEMUAudioTimeStamp *ts);
  88 +uint64_t AUD_time_stamp_get_elapsed_usec_in (SWVoiceIn *sw,
  89 + QEMUAudioTimeStamp *ts);
52 90
53 static inline void *advance (void *p, int incr) 91 static inline void *advance (void *p, int incr)
54 { 92 {
@@ -59,7 +97,21 @@ static inline void *advance (void *p, int incr) @@ -59,7 +97,21 @@ static inline void *advance (void *p, int incr)
59 uint32_t popcount (uint32_t u); 97 uint32_t popcount (uint32_t u);
60 inline uint32_t lsbindex (uint32_t u); 98 inline uint32_t lsbindex (uint32_t u);
61 99
  100 +#ifdef __GNUC__
  101 +#define audio_MIN(a, b) ( __extension__ ({ \
  102 + __typeof (a) ta = a; \
  103 + __typeof (b) tb = b; \
  104 + ((ta)>(tb)?(tb):(ta)); \
  105 +}))
  106 +
  107 +#define audio_MAX(a, b) ( __extension__ ({ \
  108 + __typeof (a) ta = a; \
  109 + __typeof (b) tb = b; \
  110 + ((ta)<(tb)?(tb):(ta)); \
  111 +}))
  112 +#else
62 #define audio_MIN(a, b) ((a)>(b)?(b):(a)) 113 #define audio_MIN(a, b) ((a)>(b)?(b):(a))
63 #define audio_MAX(a, b) ((a)<(b)?(b):(a)) 114 #define audio_MAX(a, b) ((a)<(b)?(b):(a))
  115 +#endif
64 116
65 #endif /* audio.h */ 117 #endif /* audio.h */
audio/audio_int.h
1 /* 1 /*
2 * QEMU Audio subsystem header 2 * QEMU Audio subsystem header
3 - *  
4 - * Copyright (c) 2003-2004 Vassili Karpov (malc)  
5 - * 3 + *
  4 + * Copyright (c) 2003-2005 Vassili Karpov (malc)
  5 + *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy 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 7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights 8 * in the Software without restriction, including without limitation the rights
@@ -24,140 +24,266 @@ @@ -24,140 +24,266 @@
24 #ifndef QEMU_AUDIO_INT_H 24 #ifndef QEMU_AUDIO_INT_H
25 #define QEMU_AUDIO_INT_H 25 #define QEMU_AUDIO_INT_H
26 26
27 -#include "vl.h" 27 +#include "sys-queue.h"
  28 +
  29 +#ifdef CONFIG_COREAUDIO
  30 +#define FLOAT_MIXENG
  31 +/* #define RECIPROCAL */
  32 +#endif
  33 +#include "mixeng.h"
  34 +
  35 +int audio_bug (const char *funcname, int cond);
  36 +
  37 +struct audio_pcm_ops;
  38 +
  39 +typedef enum {
  40 + AUD_OPT_INT,
  41 + AUD_OPT_FMT,
  42 + AUD_OPT_STR,
  43 + AUD_OPT_BOOL
  44 +} audio_option_tag_e;
  45 +
  46 +struct audio_option {
  47 + const char *name;
  48 + audio_option_tag_e tag;
  49 + void *valp;
  50 + const char *descr;
  51 + int *overridenp;
  52 + int overriden;
  53 +};
  54 +
  55 +struct audio_callback {
  56 + void *opaque;
  57 + audio_callback_fn_t fn;
  58 +};
28 59
29 -struct pcm_ops; 60 +struct audio_pcm_info {
  61 + int bits;
  62 + int sign;
  63 + int freq;
  64 + int nchannels;
  65 + int align;
  66 + int shift;
  67 + int bytes_per_second;
  68 + int swap_endian;
  69 +};
30 70
31 -typedef struct HWVoice { 71 +typedef struct HWVoiceOut {
32 int active; 72 int active;
33 int enabled; 73 int enabled;
34 int pending_disable; 74 int pending_disable;
35 int valid; 75 int valid;
36 - int freq; 76 + struct audio_pcm_info info;
37 77
38 f_sample *clip; 78 f_sample *clip;
39 - audfmt_e fmt;  
40 - int nchannels;  
41 -  
42 - int align;  
43 - int shift;  
44 79
45 int rpos; 80 int rpos;
46 int bufsize; 81 int bufsize;
  82 + uint64_t ts_helper;
47 83
48 - int bytes_per_second;  
49 st_sample_t *mix_buf; 84 st_sample_t *mix_buf;
50 85
51 int samples; 86 int samples;
52 - int64_t old_ticks;  
53 - int nb_voices;  
54 - struct SWVoice **pvoice;  
55 - struct pcm_ops *pcm_ops;  
56 -} HWVoice; 87 + LIST_HEAD (sw_out_listhead, SWVoiceOut) sw_head;
  88 + struct audio_pcm_ops *pcm_ops;
  89 + LIST_ENTRY (HWVoiceOut) entries;
  90 +} HWVoiceOut;
57 91
58 -extern struct pcm_ops no_pcm_ops;  
59 -extern struct audio_output_driver no_output_driver; 92 +typedef struct HWVoiceIn {
  93 + int enabled;
  94 + int active;
  95 + struct audio_pcm_info info;
  96 +
  97 + t_sample *conv;
60 98
61 -extern struct pcm_ops oss_pcm_ops;  
62 -extern struct audio_output_driver oss_output_driver; 99 + int wpos;
  100 + int bufsize;
  101 + int total_samples_captured;
  102 + uint64_t ts_helper;
63 103
64 -extern struct pcm_ops sdl_pcm_ops;  
65 -extern struct audio_output_driver sdl_output_driver; 104 + st_sample_t *conv_buf;
66 105
67 -extern struct pcm_ops wav_pcm_ops;  
68 -extern struct audio_output_driver wav_output_driver; 106 + int samples;
  107 + LIST_HEAD (sw_in_listhead, SWVoiceIn) sw_head;
  108 + struct audio_pcm_ops *pcm_ops;
  109 + LIST_ENTRY (HWVoiceIn) entries;
  110 +} HWVoiceIn;
69 111
70 -extern struct pcm_ops fmod_pcm_ops;  
71 -extern struct audio_output_driver fmod_output_driver; 112 +extern struct audio_driver no_audio_driver;
  113 +extern struct audio_driver oss_audio_driver;
  114 +extern struct audio_driver sdl_audio_driver;
  115 +extern struct audio_driver wav_audio_driver;
  116 +extern struct audio_driver fmod_audio_driver;
  117 +extern struct audio_driver alsa_audio_driver;
  118 +extern struct audio_driver coreaudio_audio_driver;
  119 +extern struct audio_driver dsound_audio_driver;
  120 +extern volume_t nominal_volume;
72 121
73 -struct audio_output_driver { 122 +struct audio_driver {
74 const char *name; 123 const char *name;
  124 + const char *descr;
  125 + struct audio_option *options;
75 void *(*init) (void); 126 void *(*init) (void);
76 void (*fini) (void *); 127 void (*fini) (void *);
77 - struct pcm_ops *pcm_ops; 128 + struct audio_pcm_ops *pcm_ops;
78 int can_be_default; 129 int can_be_default;
79 - int max_voices;  
80 - int voice_size; 130 + int max_voices_out;
  131 + int max_voices_in;
  132 + int voice_size_out;
  133 + int voice_size_in;
81 }; 134 };
82 135
83 typedef struct AudioState { 136 typedef struct AudioState {
84 - int fixed_format;  
85 - int fixed_freq;  
86 - int fixed_channels;  
87 - int fixed_fmt;  
88 - int nb_hw_voices;  
89 - int64_t ticks_threshold;  
90 - int freq_threshold; 137 + int fixed_settings_out;
  138 + int fixed_freq_out;
  139 + int fixed_channels_out;
  140 + int fixed_fmt_out;
  141 + int nb_hw_voices_out;
  142 + int greedy_out;
  143 +
  144 + int fixed_settings_in;
  145 + int fixed_freq_in;
  146 + int fixed_channels_in;
  147 + int fixed_fmt_in;
  148 + int nb_hw_voices_in;
  149 + int greedy_in;
  150 +
91 void *opaque; 151 void *opaque;
92 - struct audio_output_driver *drv;  
93 -} AudioState;  
94 -extern AudioState audio_state; 152 + struct audio_driver *drv;
95 153
96 -struct SWVoice {  
97 - int freq;  
98 - audfmt_e fmt;  
99 - int nchannels; 154 + QEMUTimer *ts;
  155 + union {
  156 + int usec;
  157 + int64_t ticks;
  158 + } period;
100 159
101 - int shift;  
102 - int align; 160 + int plive;
  161 +} AudioState;
  162 +extern AudioState audio_state;
103 163
  164 +struct SWVoiceOut {
  165 + struct audio_pcm_info info;
104 t_sample *conv; 166 t_sample *conv;
105 -  
106 - int left;  
107 - int pos;  
108 - int bytes_per_second;  
109 int64_t ratio; 167 int64_t ratio;
110 st_sample_t *buf; 168 st_sample_t *buf;
111 void *rate; 169 void *rate;
  170 + int total_hw_samples_mixed;
  171 + int active;
  172 + int empty;
  173 + HWVoiceOut *hw;
  174 + char *name;
  175 + volume_t vol;
  176 + struct audio_callback callback;
  177 + LIST_ENTRY (SWVoiceOut) entries;
  178 +};
112 179
113 - int wpos;  
114 - int live; 180 +struct SWVoiceIn {
115 int active; 181 int active;
116 - int64_t old_ticks;  
117 - HWVoice *hw; 182 + struct audio_pcm_info info;
  183 + int64_t ratio;
  184 + void *rate;
  185 + int total_hw_samples_acquired;
  186 + st_sample_t *conv_buf;
  187 + f_sample *clip;
  188 + HWVoiceIn *hw;
118 char *name; 189 char *name;
  190 + volume_t vol;
  191 + struct audio_callback callback;
  192 + LIST_ENTRY (SWVoiceIn) entries;
119 }; 193 };
120 194
121 -struct pcm_ops {  
122 - int (*init) (HWVoice *hw, int freq, int nchannels, audfmt_e fmt);  
123 - void (*fini) (HWVoice *hw);  
124 - void (*run) (HWVoice *hw);  
125 - int (*write) (SWVoice *sw, void *buf, int size);  
126 - int (*ctl) (HWVoice *hw, int cmd, ...); 195 +struct audio_pcm_ops {
  196 + int (*init_out)(HWVoiceOut *hw, int freq, int nchannels, audfmt_e fmt);
  197 + void (*fini_out)(HWVoiceOut *hw);
  198 + int (*run_out) (HWVoiceOut *hw);
  199 + int (*write) (SWVoiceOut *sw, void *buf, int size);
  200 + int (*ctl_out) (HWVoiceOut *hw, int cmd, ...);
  201 +
  202 + int (*init_in) (HWVoiceIn *hw, int freq, int nchannels, audfmt_e fmt);
  203 + void (*fini_in) (HWVoiceIn *hw);
  204 + int (*run_in) (HWVoiceIn *hw);
  205 + int (*read) (SWVoiceIn *sw, void *buf, int size);
  206 + int (*ctl_in) (HWVoiceIn *hw, int cmd, ...);
127 }; 207 };
128 208
129 -void pcm_sw_free_resources (SWVoice *sw);  
130 -int pcm_sw_alloc_resources (SWVoice *sw);  
131 -void pcm_sw_fini (SWVoice *sw);  
132 -int pcm_sw_init (SWVoice *sw, HWVoice *hw, int freq,  
133 - int nchannels, audfmt_e fmt);  
134 -  
135 -void pcm_hw_clear (HWVoice *hw, void *buf, int len);  
136 -HWVoice * pcm_hw_find_any (HWVoice *hw);  
137 -HWVoice * pcm_hw_find_any_active (HWVoice *hw);  
138 -HWVoice * pcm_hw_find_any_passive (HWVoice *hw);  
139 -HWVoice * pcm_hw_find_specific (HWVoice *hw, int freq,  
140 - int nchannels, audfmt_e fmt);  
141 -HWVoice * pcm_hw_add (int freq, int nchannels, audfmt_e fmt);  
142 -int pcm_hw_add_sw (HWVoice *hw, SWVoice *sw);  
143 -int pcm_hw_del_sw (HWVoice *hw, SWVoice *sw);  
144 -SWVoice * pcm_create_voice_pair (int freq, int nchannels, audfmt_e fmt);  
145 -  
146 -void pcm_hw_free_resources (HWVoice *hw);  
147 -int pcm_hw_alloc_resources (HWVoice *hw);  
148 -void pcm_hw_fini (HWVoice *hw);  
149 -void pcm_hw_gc (HWVoice *hw);  
150 -int pcm_hw_get_live (HWVoice *hw);  
151 -int pcm_hw_get_live2 (HWVoice *hw, int *nb_active);  
152 -void pcm_hw_dec_live (HWVoice *hw, int decr);  
153 -int pcm_hw_write (SWVoice *sw, void *buf, int len);  
154 -  
155 -int audio_get_conf_int (const char *key, int defval);  
156 -const char *audio_get_conf_str (const char *key, const char *defval);  
157 -  
158 -struct audio_output_driver; 209 +void audio_pcm_init_info (struct audio_pcm_info *info, int freq,
  210 + int nchannels, audfmt_e fmt, int swap_endian);
  211 +void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len);
  212 +
  213 +int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int len);
  214 +int audio_pcm_hw_get_live_in (HWVoiceIn *hw);
  215 +
  216 +int audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int len);
  217 +int audio_pcm_hw_get_live_out (HWVoiceOut *hw);
  218 +int audio_pcm_hw_get_live_out2 (HWVoiceOut *hw, int *nb_live);
159 219
160 #define VOICE_ENABLE 1 220 #define VOICE_ENABLE 1
161 #define VOICE_DISABLE 2 221 #define VOICE_DISABLE 2
162 222
  223 +static inline int audio_ring_dist (int dst, int src, int len)
  224 +{
  225 + return (dst >= src) ? (dst - src) : (len - src + dst);
  226 +}
  227 +
  228 +static inline int audio_need_to_swap_endian (int endianness)
  229 +{
  230 +#ifdef WORDS_BIGENDIAN
  231 + return endianness != 1;
  232 +#else
  233 + return endianness != 0;
  234 +#endif
  235 +}
  236 +
  237 +#if defined __GNUC__
  238 +#define GCC_ATTR __attribute__ ((__unused__, __format__ (__printf__, 1, 2)))
  239 +#define INIT_FIELD(f) . f
  240 +#define GCC_FMT_ATTR(n, m) __attribute__ ((__format__ (printf, n, m)))
  241 +#else
  242 +#define GCC_ATTR /**/
  243 +#define INIT_FIELD(f) /**/
  244 +#define GCC_FMT_ATTR(n, m)
  245 +#endif
  246 +
  247 +static void GCC_ATTR dolog (const char *fmt, ...)
  248 +{
  249 + va_list ap;
  250 +
  251 + va_start (ap, fmt);
  252 + AUD_vlog (AUDIO_CAP, fmt, ap);
  253 + va_end (ap);
  254 +}
  255 +
  256 +#ifdef DEBUG
  257 +static void GCC_ATTR ldebug (const char *fmt, ...)
  258 +{
  259 + va_list ap;
  260 +
  261 + va_start (ap, fmt);
  262 + AUD_vlog (AUDIO_CAP, fmt, ap);
  263 + va_end (ap);
  264 +}
  265 +#else
  266 +#if defined NDEBUG && defined __GNUC__
  267 +#define ldebug(...)
  268 +#elif defined NDEBUG && defined _MSC_VER
  269 +#define ldebug __noop
  270 +#else
  271 +static void GCC_ATTR ldebug (const char *fmt, ...)
  272 +{
  273 + (void) fmt;
  274 +}
  275 +#endif
  276 +#endif
  277 +
  278 +#undef GCC_ATTR
  279 +
  280 +#define AUDIO_STRINGIFY_(n) #n
  281 +#define AUDIO_STRINGIFY(n) AUDIO_STRINGIFY_(n)
  282 +
  283 +#if defined _MSC_VER || defined __GNUC__
  284 +#define AUDIO_FUNC __FUNCTION__
  285 +#else
  286 +#define AUDIO_FUNC __FILE__ ":" AUDIO_STRINGIFY (__LINE__)
  287 +#endif
  288 +
163 #endif /* audio_int.h */ 289 #endif /* audio_int.h */
audio/audio_template.h 0 โ†’ 100644
  1 +/*
  2 + * QEMU Audio subsystem header
  3 + *
  4 + * Copyright (c) 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 +#ifdef DAC
  26 +#define TYPE out
  27 +#define HW glue (HWVoice, Out)
  28 +#define SW glue (SWVoice, Out)
  29 +#else
  30 +#define TYPE in
  31 +#define HW glue (HWVoice, In)
  32 +#define SW glue (SWVoice, In)
  33 +#endif
  34 +
  35 +static void glue (audio_pcm_sw_fini_, TYPE) (SW *sw)
  36 +{
  37 + glue (audio_pcm_sw_free_resources_, TYPE) (sw);
  38 + if (sw->name) {
  39 + qemu_free (sw->name);
  40 + sw->name = NULL;
  41 + }
  42 +}
  43 +
  44 +static void glue (audio_pcm_hw_add_sw_, TYPE) (HW *hw, SW *sw)
  45 +{
  46 + LIST_INSERT_HEAD (&hw->sw_head, sw, entries);
  47 +}
  48 +
  49 +static void glue (audio_pcm_hw_del_sw_, TYPE) (SW *sw)
  50 +{
  51 + LIST_REMOVE (sw, entries);
  52 +}
  53 +
  54 +static void glue (audio_pcm_hw_fini_, TYPE) (HW *hw)
  55 +{
  56 + if (hw->active) {
  57 + glue (audio_pcm_hw_free_resources_ ,TYPE) (hw);
  58 + glue (hw->pcm_ops->fini_, TYPE) (hw);
  59 + memset (hw, 0, glue (audio_state.drv->voice_size_, TYPE));
  60 + }
  61 +}
  62 +
  63 +static void glue (audio_pcm_hw_gc_, TYPE) (HW *hw)
  64 +{
  65 + if (!hw->sw_head.lh_first) {
  66 + glue (audio_pcm_hw_fini_, TYPE) (hw);
  67 + }
  68 +}
  69 +
  70 +static HW *glue (audio_pcm_hw_find_any_, TYPE) (HW *hw)
  71 +{
  72 + return hw ? hw->entries.le_next : glue (hw_head_, TYPE).lh_first;
  73 +}
  74 +
  75 +static HW *glue (audio_pcm_hw_find_any_active_, TYPE) (HW *hw)
  76 +{
  77 + while ((hw = glue (audio_pcm_hw_find_any_, TYPE) (hw))) {
  78 + if (hw->active) {
  79 + return hw;
  80 + }
  81 + }
  82 + return NULL;
  83 +}
  84 +
  85 +static HW *glue (audio_pcm_hw_find_any_active_enabled_, TYPE) (HW *hw)
  86 +{
  87 + while ((hw = glue (audio_pcm_hw_find_any_, TYPE) (hw))) {
  88 + if (hw->active && hw->enabled) {
  89 + return hw;
  90 + }
  91 + }
  92 + return NULL;
  93 +}
  94 +
  95 +static HW *glue (audio_pcm_hw_find_any_passive_, TYPE) (HW *hw)
  96 +{
  97 + while ((hw = glue (audio_pcm_hw_find_any_, TYPE) (hw))) {
  98 + if (!hw->active) {
  99 + return hw;
  100 + }
  101 + }
  102 + return NULL;
  103 +}
  104 +
  105 +static HW *glue (audio_pcm_hw_find_specific_, TYPE) (
  106 + HW *hw,
  107 + int freq,
  108 + int nchannels,
  109 + audfmt_e fmt
  110 + )
  111 +{
  112 + while ((hw = glue (audio_pcm_hw_find_any_active_, TYPE) (hw))) {
  113 + if (audio_pcm_info_eq (&hw->info, freq, nchannels, fmt)) {
  114 + return hw;
  115 + }
  116 + }
  117 + return NULL;
  118 +}
  119 +
  120 +static HW *glue (audio_pcm_hw_add_new_, TYPE) (
  121 + int freq,
  122 + int nchannels,
  123 + audfmt_e fmt
  124 + )
  125 +{
  126 + HW *hw;
  127 +
  128 + hw = glue (audio_pcm_hw_find_any_passive_, TYPE) (NULL);
  129 + if (hw) {
  130 + hw->pcm_ops = audio_state.drv->pcm_ops;
  131 + if (!hw->pcm_ops) {
  132 + return NULL;
  133 + }
  134 +
  135 + if (glue (audio_pcm_hw_init_, TYPE) (hw, freq, nchannels, fmt)) {
  136 + glue (audio_pcm_hw_gc_, TYPE) (hw);
  137 + return NULL;
  138 + }
  139 + else {
  140 + return hw;
  141 + }
  142 + }
  143 +
  144 + return NULL;
  145 +}
  146 +
  147 +static HW *glue (audio_pcm_hw_add_, TYPE) (
  148 + int freq,
  149 + int nchannels,
  150 + audfmt_e fmt
  151 + )
  152 +{
  153 + HW *hw;
  154 +
  155 + if (glue (audio_state.greedy_, TYPE)) {
  156 + hw = glue (audio_pcm_hw_add_new_, TYPE) (freq, nchannels, fmt);
  157 + if (hw) {
  158 + return hw;
  159 + }
  160 + }
  161 +
  162 + hw = glue (audio_pcm_hw_find_specific_, TYPE) (NULL, freq, nchannels, fmt);
  163 + if (hw) {
  164 + return hw;
  165 + }
  166 +
  167 + hw = glue (audio_pcm_hw_add_new_, TYPE) (freq, nchannels, fmt);
  168 + if (hw) {
  169 + return hw;
  170 + }
  171 +
  172 + return glue (audio_pcm_hw_find_any_active_, TYPE) (NULL);
  173 +}
  174 +
  175 +static SW *glue (audio_pcm_create_voice_pair_, TYPE) (
  176 + const char *name,
  177 + int freq,
  178 + int nchannels,
  179 + audfmt_e fmt
  180 + )
  181 +{
  182 + SW *sw;
  183 + HW *hw;
  184 + int hw_freq = freq;
  185 + int hw_nchannels = nchannels;
  186 + int hw_fmt = fmt;
  187 +
  188 + if (glue (audio_state.fixed_settings_, TYPE)) {
  189 + hw_freq = glue (audio_state.fixed_freq_, TYPE);
  190 + hw_nchannels = glue (audio_state.fixed_channels_, TYPE);
  191 + hw_fmt = glue (audio_state.fixed_fmt_, TYPE);
  192 + }
  193 +
  194 + sw = qemu_mallocz (sizeof (*sw));
  195 + if (!sw) {
  196 + goto err1;
  197 + }
  198 +
  199 + hw = glue (audio_pcm_hw_add_, TYPE) (hw_freq, hw_nchannels, hw_fmt);
  200 + if (!hw) {
  201 + goto err2;
  202 + }
  203 +
  204 + glue (audio_pcm_hw_add_sw_, TYPE) (hw, sw);
  205 +
  206 + if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, freq, nchannels, fmt)) {
  207 + goto err3;
  208 + }
  209 +
  210 + return sw;
  211 +
  212 +err3:
  213 + glue (audio_pcm_hw_del_sw_, TYPE) (sw);
  214 + glue (audio_pcm_hw_gc_, TYPE) (hw);
  215 +err2:
  216 + qemu_free (sw);
  217 +err1:
  218 + return NULL;
  219 +}
  220 +
  221 +void glue (AUD_close_, TYPE) (SW *sw)
  222 +{
  223 + if (sw) {
  224 + glue (audio_pcm_sw_fini_, TYPE) (sw);
  225 + glue (audio_pcm_hw_del_sw_, TYPE) (sw);
  226 + glue (audio_pcm_hw_gc_, TYPE) (sw->hw);
  227 + qemu_free (sw);
  228 + }
  229 +}
  230 +
  231 +SW *glue (AUD_open_, TYPE) (
  232 + SW *sw,
  233 + const char *name,
  234 + void *callback_opaque ,
  235 + audio_callback_fn_t callback_fn,
  236 + int freq,
  237 + int nchannels,
  238 + audfmt_e fmt
  239 + )
  240 +{
  241 +#ifdef DAC
  242 + int live = 0;
  243 + SW *old_sw = NULL;
  244 +#endif
  245 +
  246 + if (!callback_fn) {
  247 + dolog ("No callback specifed for voice `%s'\n", name);
  248 + goto fail;
  249 + }
  250 +
  251 + if (nchannels != 1 && nchannels != 2) {
  252 + dolog ("Bogus channel count %d for voice `%s'\n", nchannels, name);
  253 + goto fail;
  254 + }
  255 +
  256 + if (!audio_state.drv) {
  257 + dolog ("No audio driver defined\n");
  258 + goto fail;
  259 + }
  260 +
  261 + if (sw && audio_pcm_info_eq (&sw->info, freq, nchannels, fmt)) {
  262 + return sw;
  263 + }
  264 +
  265 +#ifdef DAC
  266 + if (audio_state.plive && sw && (!sw->active && !sw->empty)) {
  267 + live = sw->total_hw_samples_mixed;
  268 +
  269 +#ifdef DEBUG_PLIVE
  270 + dolog ("Replacing voice %s with %d live samples\n", sw->name, live);
  271 + dolog ("Old %s freq %d, bits %d, channels %d\n",
  272 + sw->name, sw->info.freq, sw->info.bits, sw->info.nchannels);
  273 + dolog ("New %s freq %d, bits %d, channels %d\n",
  274 + name, freq, (fmt == AUD_FMT_S16 || fmt == AUD_FMT_U16) ? 16 : 8,
  275 + nchannels);
  276 +#endif
  277 +
  278 + if (live) {
  279 + old_sw = sw;
  280 + old_sw->callback.fn = NULL;
  281 + sw = NULL;
  282 + }
  283 + }
  284 +#endif
  285 +
  286 + if (!glue (audio_state.fixed_settings_, TYPE) && sw) {
  287 + glue (AUD_close_, TYPE) (sw);
  288 + sw = NULL;
  289 + }
  290 +
  291 + if (sw) {
  292 + HW *hw = sw->hw;
  293 +
  294 + if (!hw) {
  295 + dolog ("Internal logic error voice %s has no hardware store\n",
  296 + name);
  297 + goto fail;
  298 + }
  299 +
  300 + if (glue (audio_pcm_sw_init_, TYPE) (
  301 + sw,
  302 + hw,
  303 + name,
  304 + freq,
  305 + nchannels,
  306 + fmt
  307 + )) {
  308 + goto fail;
  309 + }
  310 + }
  311 + else {
  312 + sw = glue (audio_pcm_create_voice_pair_, TYPE) (
  313 + name,
  314 + freq,
  315 + nchannels,
  316 + fmt);
  317 + if (!sw) {
  318 + dolog ("Failed to create voice %s\n", name);
  319 + goto fail;
  320 + }
  321 + }
  322 +
  323 + if (sw) {
  324 + sw->vol = nominal_volume;
  325 + sw->callback.fn = callback_fn;
  326 + sw->callback.opaque = callback_opaque;
  327 +
  328 +#ifdef DAC
  329 + if (live) {
  330 + int mixed =
  331 + (live << old_sw->info.shift)
  332 + * old_sw->info.bytes_per_second
  333 + / sw->info.bytes_per_second;
  334 +
  335 +#ifdef DEBUG_PLIVE
  336 + dolog ("Silence will be mixed %d\n", mixed);
  337 +#endif
  338 + sw->total_hw_samples_mixed += mixed;
  339 + }
  340 +#endif
  341 +
  342 +#ifdef DEBUG_AUDIO
  343 + dolog ("%s\n", name);
  344 + audio_pcm_print_info ("hw", &sw->hw->info);
  345 + audio_pcm_print_info ("sw", &sw->info);
  346 +#endif
  347 + }
  348 +
  349 + return sw;
  350 +
  351 + fail:
  352 + glue (AUD_close_, TYPE) (sw);
  353 + return NULL;
  354 +}
  355 +
  356 +int glue (AUD_is_active_, TYPE) (SW *sw)
  357 +{
  358 + return sw ? sw->active : 0;
  359 +}
  360 +
  361 +void glue (AUD_init_time_stamp_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts)
  362 +{
  363 + if (!sw) {
  364 + return;
  365 + }
  366 +
  367 + ts->old_ts = sw->hw->ts_helper;
  368 +}
  369 +
  370 +uint64_t glue (AUD_time_stamp_get_elapsed_usec_, TYPE) (
  371 + SW *sw,
  372 + QEMUAudioTimeStamp *ts
  373 + )
  374 +{
  375 + uint64_t delta, cur_ts, old_ts;
  376 +
  377 + if (!sw) {
  378 + return 0;
  379 + }
  380 +
  381 + cur_ts = sw->hw->ts_helper;
  382 + old_ts = ts->old_ts;
  383 + /* dolog ("cur %lld old %lld\n", cur_ts, old_ts); */
  384 +
  385 + if (cur_ts >= old_ts) {
  386 + delta = cur_ts - old_ts;
  387 + }
  388 + else {
  389 + delta = UINT64_MAX - old_ts + cur_ts;
  390 + }
  391 +
  392 + if (!delta) {
  393 + return 0;
  394 + }
  395 +
  396 + return (delta * sw->hw->info.freq) / 1000000;
  397 +}
  398 +
  399 +#undef TYPE
  400 +#undef HW
  401 +#undef SW
audio/coreaudio.c 0 โ†’ 100644
  1 +/*
  2 + * QEMU OS X CoreAudio audio driver
  3 + *
  4 + * Copyright (c) 2005 Mike Kronenberg
  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 <CoreAudio/CoreAudio.h>
  26 +#include <string.h> /* strerror */
  27 +#include <pthread.h> /* pthread_X */
  28 +
  29 +#include "vl.h"
  30 +
  31 +#define AUDIO_CAP "coreaudio"
  32 +#include "audio_int.h"
  33 +
  34 +#define DEVICE_BUFFER_FRAMES (512)
  35 +
  36 +struct {
  37 + int buffer_frames;
  38 +} conf = {
  39 + .buffer_frames = 512
  40 +};
  41 +
  42 +typedef struct coreaudioVoiceOut {
  43 + HWVoiceOut hw;
  44 + pthread_mutex_t mutex;
  45 + AudioDeviceID outputDeviceID;
  46 + UInt32 audioDevicePropertyBufferSize;
  47 + AudioStreamBasicDescription outputStreamBasicDescription;
  48 + int isPlaying;
  49 + int live;
  50 + int decr;
  51 + int rpos;
  52 +} coreaudioVoiceOut;
  53 +
  54 +static void coreaudio_logstatus (OSStatus status)
  55 +{
  56 + char *str = "BUG";
  57 +
  58 + switch(status) {
  59 + case kAudioHardwareNoError:
  60 + str = "kAudioHardwareNoError";
  61 + break;
  62 +
  63 + case kAudioHardwareNotRunningError:
  64 + str = "kAudioHardwareNotRunningError";
  65 + break;
  66 +
  67 + case kAudioHardwareUnspecifiedError:
  68 + str = "kAudioHardwareUnspecifiedError";
  69 + break;
  70 +
  71 + case kAudioHardwareUnknownPropertyError:
  72 + str = "kAudioHardwareUnknownPropertyError";
  73 + break;
  74 +
  75 + case kAudioHardwareBadPropertySizeError:
  76 + str = "kAudioHardwareBadPropertySizeError";
  77 + break;
  78 +
  79 + case kAudioHardwareIllegalOperationError:
  80 + str = "kAudioHardwareIllegalOperationError";
  81 + break;
  82 +
  83 + case kAudioHardwareBadDeviceError:
  84 + str = "kAudioHardwareBadDeviceError";
  85 + break;
  86 +
  87 + case kAudioHardwareBadStreamError:
  88 + str = "kAudioHardwareBadStreamError";
  89 + break;
  90 +
  91 + case kAudioHardwareUnsupportedOperationError:
  92 + str = "kAudioHardwareUnsupportedOperationError";
  93 + break;
  94 +
  95 + case kAudioDeviceUnsupportedFormatError:
  96 + str = "kAudioDeviceUnsupportedFormatError";
  97 + break;
  98 +
  99 + case kAudioDevicePermissionsError:
  100 + str = "kAudioDevicePermissionsError";
  101 + break;
  102 +
  103 + default:
  104 + AUD_log (AUDIO_CAP, "Reason: status code %ld\n", status);
  105 + return;
  106 + }
  107 +
  108 + AUD_log (AUDIO_CAP, "Reason: %s\n", str);
  109 +}
  110 +
  111 +static void GCC_FMT_ATTR (2, 3) coreaudio_logerr (
  112 + OSStatus status,
  113 + const char *fmt,
  114 + ...
  115 + )
  116 +{
  117 + va_list ap;
  118 +
  119 + va_start (ap, fmt);
  120 + AUD_log (AUDIO_CAP, fmt, ap);
  121 + va_end (ap);
  122 +
  123 + coreaudio_logstatus (status);
  124 +}
  125 +
  126 +static void GCC_FMT_ATTR (3, 4) coreaudio_logerr2 (
  127 + OSStatus status,
  128 + const char *typ,
  129 + const char *fmt,
  130 + ...
  131 + )
  132 +{
  133 + va_list ap;
  134 +
  135 + AUD_log (AUDIO_CAP, "Can not initialize %s\n", typ);
  136 +
  137 + va_start (ap, fmt);
  138 + AUD_vlog (AUDIO_CAP, fmt, ap);
  139 + va_end (ap);
  140 +
  141 + coreaudio_logstatus (status);
  142 +}
  143 +
  144 +static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name)
  145 +{
  146 + int err;
  147 +
  148 + err = pthread_mutex_lock (&core->mutex);
  149 + if (err) {
  150 + dolog ("Can not lock voice for %s\nReason: %s\n",
  151 + fn_name, strerror (err));
  152 + return -1;
  153 + }
  154 + return 0;
  155 +}
  156 +
  157 +static int coreaudio_unlock (coreaudioVoiceOut *core, const char *fn_name)
  158 +{
  159 + int err;
  160 +
  161 + err = pthread_mutex_unlock (&core->mutex);
  162 + if (err) {
  163 + dolog ("Can not unlock voice for %s\nReason: %s\n",
  164 + fn_name, strerror (err));
  165 + return -1;
  166 + }
  167 + return 0;
  168 +}
  169 +
  170 +static int coreaudio_run_out (HWVoiceOut *hw)
  171 +{
  172 + int live, decr;
  173 + coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
  174 +
  175 + if (coreaudio_lock (core, "coreaudio_run_out")) {
  176 + return 0;
  177 + }
  178 +
  179 + live = audio_pcm_hw_get_live_out (hw);
  180 +
  181 + if (core->decr > live) {
  182 + ldebug ("core->decr %d live %d core->live %d\n",
  183 + core->decr,
  184 + live,
  185 + core->live);
  186 + }
  187 +
  188 + decr = audio_MIN (core->decr, live);
  189 + core->decr -= decr;
  190 +
  191 + core->live = live - decr;
  192 + hw->rpos = core->rpos;
  193 +
  194 + coreaudio_unlock (core, "coreaudio_run_out");
  195 + return decr;
  196 +}
  197 +
  198 +/* callback to feed audiooutput buffer */
  199 +static OSStatus audioDeviceIOProc(
  200 + AudioDeviceID inDevice,
  201 + const AudioTimeStamp* inNow,
  202 + const AudioBufferList* inInputData,
  203 + const AudioTimeStamp* inInputTime,
  204 + AudioBufferList* outOutputData,
  205 + const AudioTimeStamp* inOutputTime,
  206 + void* hwptr)
  207 +{
  208 + unsigned int frame, frameCount;
  209 + float *out = outOutputData->mBuffers[0].mData;
  210 + HWVoiceOut *hw = hwptr;
  211 + coreaudioVoiceOut *core = (coreaudioVoiceOut *) hwptr;
  212 + int rpos, live;
  213 + st_sample_t *src;
  214 +#ifndef FLOAT_MIXENG
  215 +#ifdef RECIPROCAL
  216 + const float scale = 1.f / UINT_MAX;
  217 +#else
  218 + const float scale = UINT_MAX;
  219 +#endif
  220 +#endif
  221 +
  222 + if (coreaudio_lock (core, "audioDeviceIOProc")) {
  223 + inInputTime = 0;
  224 + return 0;
  225 + }
  226 +
  227 + frameCount = conf.buffer_frames;
  228 + live = core->live;
  229 +
  230 + /* if there are not enough samples, set signal and return */
  231 + if (live < frameCount) {
  232 + inInputTime = 0;
  233 + coreaudio_unlock (core, "audioDeviceIOProc(empty)");
  234 + return 0;
  235 + }
  236 +
  237 + rpos = core->rpos;
  238 + src = hw->mix_buf + rpos;
  239 +
  240 + /* fill buffer */
  241 + for (frame = 0; frame < frameCount; frame++) {
  242 +#ifdef FLOAT_MIXENG
  243 + *out++ = src[frame].l; /* left channel */
  244 + *out++ = src[frame].r; /* right channel */
  245 +#else
  246 +#ifdef RECIPROCAL
  247 + *out++ = src[frame].l * scale; /* left channel */
  248 + *out++ = src[frame].r * scale; /* right channel */
  249 +#else
  250 + *out++ = src[frame].l / scale; /* left channel */
  251 + *out++ = src[frame].r / scale; /* right channel */
  252 +#endif
  253 +#endif
  254 + }
  255 +
  256 + /* cleanup */
  257 + mixeng_clear (src, frameCount);
  258 + rpos = (rpos + frameCount) % hw->samples;
  259 + core->decr = frameCount;
  260 + core->rpos = rpos;
  261 +
  262 + coreaudio_unlock (core, "audioDeviceIOProc");
  263 + return 0;
  264 +}
  265 +
  266 +static int coreaudio_write (SWVoiceOut *sw, void *buf, int len)
  267 +{
  268 + return audio_pcm_sw_write (sw, buf, len);
  269 +}
  270 +
  271 +static int coreaudio_init_out (HWVoiceOut *hw, int freq,
  272 + int nchannels, audfmt_e fmt)
  273 +{
  274 + OSStatus status;
  275 + coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
  276 + UInt32 propertySize;
  277 + int err;
  278 + int bits = 8;
  279 + int endianess = 0;
  280 + const char *typ = "DAC";
  281 +
  282 + /* create mutex */
  283 + err = pthread_mutex_init(&core->mutex, NULL);
  284 + if (err) {
  285 + dolog("Can not create mutex\nReason: %s\n", strerror (err));
  286 + return -1;
  287 + }
  288 +
  289 + if (fmt == AUD_FMT_S16 || fmt == AUD_FMT_U16) {
  290 + bits = 16;
  291 + endianess = 1;
  292 + }
  293 +
  294 + audio_pcm_init_info (
  295 + &hw->info,
  296 + freq,
  297 + nchannels,
  298 + fmt,
  299 + /* Following is irrelevant actually since we do not use
  300 + mixengs clipping routines */
  301 + audio_need_to_swap_endian (endianess)
  302 + );
  303 + hw->bufsize = 4 * conf.buffer_frames * nchannels * bits;
  304 +
  305 + /* open default output device */
  306 + propertySize = sizeof(core->outputDeviceID);
  307 + status = AudioHardwareGetProperty(
  308 + kAudioHardwarePropertyDefaultOutputDevice,
  309 + &propertySize,
  310 + &core->outputDeviceID);
  311 + if (status != kAudioHardwareNoError) {
  312 + coreaudio_logerr2 (status, typ,
  313 + "Can not get default output Device\n");
  314 + return -1;
  315 + }
  316 + if (core->outputDeviceID == kAudioDeviceUnknown) {
  317 + dolog ("Can not initialize %s - Unknown Audiodevice\n", typ);
  318 + return -1;
  319 + }
  320 +
  321 + /* set Buffersize to conf.buffer_frames frames */
  322 + propertySize = sizeof(core->audioDevicePropertyBufferSize);
  323 + core->audioDevicePropertyBufferSize =
  324 + conf.buffer_frames * sizeof(float) * 2;
  325 + status = AudioDeviceSetProperty(
  326 + core->outputDeviceID,
  327 + NULL,
  328 + 0,
  329 + false,
  330 + kAudioDevicePropertyBufferSize,
  331 + propertySize,
  332 + &core->audioDevicePropertyBufferSize);
  333 + if (status != kAudioHardwareNoError) {
  334 + coreaudio_logerr2 (status, typ,
  335 + "Can not set device buffer size %d\n",
  336 + kAudioDevicePropertyBufferSize);
  337 + return -1;
  338 + }
  339 +
  340 + /* get Buffersize */
  341 + propertySize = sizeof(core->audioDevicePropertyBufferSize);
  342 + status = AudioDeviceGetProperty(
  343 + core->outputDeviceID,
  344 + 0,
  345 + false,
  346 + kAudioDevicePropertyBufferSize,
  347 + &propertySize,
  348 + &core->audioDevicePropertyBufferSize);
  349 + if (status != kAudioHardwareNoError) {
  350 + coreaudio_logerr2 (status, typ, "Can not get device buffer size\n");
  351 + return -1;
  352 + }
  353 +
  354 + /* get StreamFormat */
  355 + propertySize = sizeof(core->outputStreamBasicDescription);
  356 + status = AudioDeviceGetProperty(
  357 + core->outputDeviceID,
  358 + 0,
  359 + false,
  360 + kAudioDevicePropertyStreamFormat,
  361 + &propertySize,
  362 + &core->outputStreamBasicDescription);
  363 + if (status != kAudioHardwareNoError) {
  364 + coreaudio_logerr2 (status, typ,
  365 + "Can not get Device Stream properties\n");
  366 + core->outputDeviceID = kAudioDeviceUnknown;
  367 + return -1;
  368 + }
  369 +
  370 + /* set Samplerate */
  371 + core->outputStreamBasicDescription.mSampleRate = (Float64)freq;
  372 + propertySize = sizeof(core->outputStreamBasicDescription);
  373 + status = AudioDeviceSetProperty(
  374 + core->outputDeviceID,
  375 + 0,
  376 + 0,
  377 + 0,
  378 + kAudioDevicePropertyStreamFormat,
  379 + propertySize,
  380 + &core->outputStreamBasicDescription);
  381 + if (status != kAudioHardwareNoError) {
  382 + coreaudio_logerr2 (status, typ, "Can not set samplerate %d\n", freq);
  383 + core->outputDeviceID = kAudioDeviceUnknown;
  384 + return -1;
  385 + }
  386 +
  387 + /* set Callback */
  388 + status = AudioDeviceAddIOProc(core->outputDeviceID, audioDeviceIOProc, hw);
  389 + if (status != kAudioHardwareNoError) {
  390 + coreaudio_logerr2 (status, typ, "Can not set IOProc\n");
  391 + core->outputDeviceID = kAudioDeviceUnknown;
  392 + return -1;
  393 + }
  394 +
  395 + /* start Playback */
  396 + if (!core->isPlaying) {
  397 + status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc);
  398 + if (status != kAudioHardwareNoError) {
  399 + coreaudio_logerr2 (status, typ, "Can not start playback\n");
  400 + AudioDeviceRemoveIOProc(core->outputDeviceID, audioDeviceIOProc);
  401 + core->outputDeviceID = kAudioDeviceUnknown;
  402 + return -1;
  403 + }
  404 + core->isPlaying = 1;
  405 + }
  406 +
  407 + return 0;
  408 +}
  409 +
  410 +static void coreaudio_fini_out (HWVoiceOut *hw)
  411 +{
  412 + OSStatus status;
  413 + int err;
  414 + coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
  415 +
  416 + /* stop playback */
  417 + if (core->isPlaying) {
  418 + status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc);
  419 + if (status != kAudioHardwareNoError) {
  420 + coreaudio_logerr (status, "Can not stop playback\n");
  421 + }
  422 + core->isPlaying = 0;
  423 + }
  424 +
  425 + /* remove callback */
  426 + status = AudioDeviceRemoveIOProc(core->outputDeviceID, audioDeviceIOProc);
  427 + if (status != kAudioHardwareNoError) {
  428 + coreaudio_logerr (status, "Can not remove IOProc\n");
  429 + }
  430 + core->outputDeviceID = kAudioDeviceUnknown;
  431 +
  432 + /* destroy mutex */
  433 + err = pthread_mutex_destroy(&core->mutex);
  434 + if (err) {
  435 + dolog("Can not destroy mutex\nReason: %s\n", strerror (err));
  436 + }
  437 +}
  438 +
  439 +static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...)
  440 +{
  441 + OSStatus status;
  442 + coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
  443 +
  444 + switch (cmd) {
  445 + case VOICE_ENABLE:
  446 + /* start playback */
  447 + if (!core->isPlaying) {
  448 + status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc);
  449 + if (status != kAudioHardwareNoError) {
  450 + coreaudio_logerr (status, "Can not unpause playback\n");
  451 + }
  452 + core->isPlaying = 1;
  453 + }
  454 + break;
  455 +
  456 + case VOICE_DISABLE:
  457 + /* stop playback */
  458 + if (core->isPlaying) {
  459 + status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc);
  460 + if (status != kAudioHardwareNoError) {
  461 + coreaudio_logerr (status, "Can not pause playback\n");
  462 + }
  463 + core->isPlaying = 0;
  464 + }
  465 + break;
  466 + }
  467 + return 0;
  468 +}
  469 +
  470 +static void *coreaudio_audio_init (void)
  471 +{
  472 + return &coreaudio_audio_init;
  473 +}
  474 +
  475 +static void coreaudio_audio_fini (void *opaque)
  476 +{
  477 + (void) opaque;
  478 +}
  479 +
  480 +static struct audio_option coreaudio_options[] = {
  481 + {"BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_frames,
  482 + "Size of the buffer in frames", NULL, 0},
  483 + {NULL, 0, NULL, NULL, NULL, 0}
  484 +};
  485 +
  486 +static struct audio_pcm_ops coreaudio_pcm_ops = {
  487 + coreaudio_init_out,
  488 + coreaudio_fini_out,
  489 + coreaudio_run_out,
  490 + coreaudio_write,
  491 + coreaudio_ctl_out,
  492 +
  493 + NULL,
  494 + NULL,
  495 + NULL,
  496 + NULL,
  497 + NULL
  498 +};
  499 +
  500 +struct audio_driver coreaudio_audio_driver = {
  501 + INIT_FIELD (name = ) "coreaudio",
  502 + INIT_FIELD (descr = )
  503 + "CoreAudio http://developer.apple.com/audio/coreaudio.html",
  504 + INIT_FIELD (options = ) coreaudio_options,
  505 + INIT_FIELD (init = ) coreaudio_audio_init,
  506 + INIT_FIELD (fini = ) coreaudio_audio_fini,
  507 + INIT_FIELD (pcm_ops = ) &coreaudio_pcm_ops,
  508 + INIT_FIELD (can_be_default = ) 1,
  509 + INIT_FIELD (max_voices_out = ) 1,
  510 + INIT_FIELD (max_voices_in = ) 0,
  511 + INIT_FIELD (voice_size_out = ) sizeof (coreaudioVoiceOut),
  512 + INIT_FIELD (voice_size_in = ) 0
  513 +};
audio/dsound_template.h 0 โ†’ 100644
  1 +/*
  2 + * QEMU DirectSound audio driver header
  3 + *
  4 + * Copyright (c) 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 +#ifdef DSBTYPE_IN
  25 +#define NAME "capture buffer"
  26 +#define TYPE in
  27 +#define IFACE IDirectSoundCaptureBuffer
  28 +#define BUFPTR LPDIRECTSOUNDCAPTUREBUFFER
  29 +#define FIELD dsound_capture_buffer
  30 +#else
  31 +#define NAME "playback buffer"
  32 +#define TYPE out
  33 +#define IFACE IDirectSoundBuffer
  34 +#define BUFPTR LPDIRECTSOUNDBUFFER
  35 +#define FIELD dsound_buffer
  36 +#endif
  37 +
  38 +static int glue (dsound_unlock_, TYPE) (
  39 + BUFPTR buf,
  40 + LPVOID p1,
  41 + LPVOID p2,
  42 + DWORD blen1,
  43 + DWORD blen2
  44 + )
  45 +{
  46 + HRESULT hr;
  47 +
  48 + hr = glue (IFACE, _Unlock) (buf, p1, blen1, p2, blen2);
  49 + if (FAILED (hr)) {
  50 + dsound_logerr (hr, "Can not unlock " NAME "\n");
  51 + return -1;
  52 + }
  53 +
  54 + return 0;
  55 +}
  56 +
  57 +static int glue (dsound_lock_, TYPE) (
  58 + BUFPTR buf,
  59 + struct audio_pcm_info *info,
  60 + DWORD pos,
  61 + DWORD len,
  62 + LPVOID *p1p,
  63 + LPVOID *p2p,
  64 + DWORD *blen1p,
  65 + DWORD *blen2p,
  66 + int entire
  67 + )
  68 +{
  69 + HRESULT hr;
  70 + int i;
  71 + LPVOID p1 = NULL, p2 = NULL;
  72 + DWORD blen1 = 0, blen2 = 0;
  73 +
  74 + for (i = 0; i < conf.lock_retries; ++i) {
  75 + hr = glue (IFACE, _Lock) (
  76 + buf,
  77 + pos,
  78 + len,
  79 + &p1,
  80 + &blen1,
  81 + &p2,
  82 + &blen2,
  83 + (entire
  84 +#ifdef DSBTYPE_IN
  85 + ? DSCBLOCK_ENTIREBUFFER
  86 +#else
  87 + ? DSBLOCK_ENTIREBUFFER
  88 +#endif
  89 + : 0)
  90 + );
  91 +
  92 + if (FAILED (hr)) {
  93 +#ifndef DSBTYPE_IN
  94 + if (hr == DSERR_BUFFERLOST) {
  95 + if (glue (dsound_restore_, TYPE) (buf)) {
  96 + dsound_logerr (hr, "Can not lock " NAME "\n");
  97 + goto fail;
  98 + }
  99 + continue;
  100 + }
  101 +#endif
  102 + dsound_logerr (hr, "Can not lock " NAME "\n");
  103 + goto fail;
  104 + }
  105 +
  106 + break;
  107 + }
  108 +
  109 + if (i == conf.lock_retries) {
  110 + dolog ("%d attempts to lock " NAME " failed\n", i);
  111 + goto fail;
  112 + }
  113 +
  114 + if ((p1 && (blen1 & info->align)) || (p2 && (blen2 & info->align))) {
  115 + dolog ("DirectSound returned misaligned buffer %ld %ld\n",
  116 + blen1, blen2);
  117 + glue (dsound_unlock_, TYPE) (buf, p1, p2, blen1, blen2);
  118 + goto fail;
  119 + }
  120 +
  121 + if (!p1 && blen1) {
  122 + dolog ("warning: !p1 && blen1=%ld\n", blen1);
  123 + blen1 = 0;
  124 + }
  125 +
  126 + if (!p2 && blen2) {
  127 + dolog ("warning: !p2 && blen2=%ld\n", blen2);
  128 + blen2 = 0;
  129 + }
  130 +
  131 + *p1p = p1;
  132 + *p2p = p2;
  133 + *blen1p = blen1;
  134 + *blen2p = blen2;
  135 + return 0;
  136 +
  137 + fail:
  138 + *p1p = NULL - 1;
  139 + *p2p = NULL - 1;
  140 + *blen1p = -1;
  141 + *blen2p = -1;
  142 + return -1;
  143 +}
  144 +
  145 +#ifdef DSBTYPE_IN
  146 +static void dsound_fini_in (HWVoiceIn *hw)
  147 +#else
  148 +static void dsound_fini_out (HWVoiceOut *hw)
  149 +#endif
  150 +{
  151 + HRESULT hr;
  152 +#ifdef DSBTYPE_IN
  153 + DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
  154 +#else
  155 + DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
  156 +#endif
  157 +
  158 + if (ds->FIELD) {
  159 + hr = glue (IFACE, _Stop) (ds->FIELD);
  160 + if (FAILED (hr)) {
  161 + dsound_logerr (hr, "Can not stop " NAME "\n");
  162 + }
  163 +
  164 + hr = glue (IFACE, _Release) (ds->FIELD);
  165 + if (FAILED (hr)) {
  166 + dsound_logerr (hr, "Can not release " NAME "\n");
  167 + }
  168 + ds->FIELD = NULL;
  169 + }
  170 +}
  171 +
  172 +#ifdef DSBTYPE_IN
  173 +static int dsound_init_in (
  174 + HWVoiceIn *hw,
  175 + int freq,
  176 + int nchannels,
  177 + audfmt_e fmt
  178 + )
  179 +#else
  180 +static int dsound_init_out (
  181 + HWVoiceOut *hw,
  182 + int freq,
  183 + int nchannels,
  184 + audfmt_e fmt
  185 + )
  186 +#endif
  187 +{
  188 + int err;
  189 + HRESULT hr;
  190 + dsound *s = &glob_dsound;
  191 + WAVEFORMATEX wfx;
  192 + struct full_fmt full_fmt;
  193 +#ifdef DSBTYPE_IN
  194 + const char *typ = "ADC";
  195 + DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
  196 + DSCBUFFERDESC bd;
  197 + DSCBCAPS bc;
  198 +#else
  199 + const char *typ = "DAC";
  200 + DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
  201 + DSBUFFERDESC bd;
  202 + DSBCAPS bc;
  203 +#endif
  204 +
  205 + full_fmt.freq = freq;
  206 + full_fmt.nchannels = nchannels;
  207 + full_fmt.fmt = fmt;
  208 + err = waveformat_from_full_fmt (&wfx, &full_fmt);
  209 + if (err) {
  210 + return -1;
  211 + }
  212 +
  213 + memset (&bd, 0, sizeof (bd));
  214 + bd.dwSize = sizeof (bd);
  215 + bd.lpwfxFormat = &wfx;
  216 +#ifdef DSBTYPE_IN
  217 + bd.dwBufferBytes = conf.bufsize_in;
  218 + hr = IDirectSoundCapture_CreateCaptureBuffer (
  219 + s->dsound_capture,
  220 + &bd,
  221 + &ds->dsound_capture_buffer,
  222 + NULL
  223 + );
  224 +#else
  225 + bd.dwFlags = DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2;
  226 + bd.dwBufferBytes = conf.bufsize_out;
  227 + hr = IDirectSound_CreateSoundBuffer (
  228 + s->dsound,
  229 + &bd,
  230 + &ds->dsound_buffer,
  231 + NULL
  232 + );
  233 +#endif
  234 +
  235 + if (FAILED (hr)) {
  236 + dsound_logerr2 (hr, typ, "Can not create " NAME "\n");
  237 + return -1;
  238 + }
  239 +
  240 + hr = glue (IFACE, _GetFormat) (
  241 + ds->FIELD,
  242 + &wfx,
  243 + sizeof (wfx),
  244 + NULL
  245 + );
  246 + if (FAILED (hr)) {
  247 + dsound_logerr2 (hr, typ, "Can not get " NAME " format\n");
  248 + goto fail0;
  249 + }
  250 +
  251 +#ifdef DEBUG_DSOUND
  252 + dolog (NAME "\n");
  253 + print_wave_format (&wfx);
  254 +#endif
  255 +
  256 + memset (&bc, 0, sizeof (bc));
  257 + bc.dwSize = sizeof (bc);
  258 +
  259 + hr = glue (IFACE, _GetCaps) (ds->FIELD, &bc);
  260 + if (FAILED (hr)) {
  261 + dsound_logerr2 (hr, typ, "Can not get " NAME " format\n");
  262 + goto fail0;
  263 + }
  264 +
  265 + err = waveformat_to_full_fmt (&wfx, &full_fmt);
  266 + if (err) {
  267 + goto fail0;
  268 + }
  269 +
  270 + ds->first_time = 1;
  271 + hw->bufsize = bc.dwBufferBytes;
  272 + audio_pcm_init_info (
  273 + &hw->info,
  274 + full_fmt.freq,
  275 + full_fmt.nchannels,
  276 + full_fmt.fmt,
  277 + audio_need_to_swap_endian (0)
  278 + );
  279 +
  280 +#ifdef DEBUG_DSOUND
  281 + dolog ("caps %ld, desc %ld\n",
  282 + bc.dwBufferBytes, bd.dwBufferBytes);
  283 +
  284 + dolog ("bufsize %d, freq %d, chan %d, fmt %d\n",
  285 + hw->bufsize, full_fmt.freq, full_fmt.nchannels, full_fmt.fmt);
  286 +#endif
  287 + return 0;
  288 +
  289 + fail0:
  290 + glue (dsound_fini_, TYPE) (hw);
  291 + return -1;
  292 +}
  293 +
  294 +#undef NAME
  295 +#undef TYPE
  296 +#undef IFACE
  297 +#undef BUFPTR
  298 +#undef FIELD