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 8 version 0.7.2:
2 9  
3 10 - x86_64 fixes (Win2000 and Linux 2.6 boot in 32 bit)
... ...
Makefile.target
... ... @@ -262,7 +262,7 @@ endif
262 262 VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o
263 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 266 AUDIODRV = audio.o noaudio.o wavaudio.o
267 267 ifdef CONFIG_SDL
268 268 AUDIODRV += sdlaudio.o
... ... @@ -270,29 +270,38 @@ endif
270 270 ifdef CONFIG_OSS
271 271 AUDIODRV += ossaudio.o
272 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 283 endif
279   -
280 284 ifdef CONFIG_FMOD
281 285 AUDIODRV += fmodaudio.o
282 286 audio.o fmodaudio.o: DEFINES := -I$(CONFIG_FMOD_INC) $(DEFINES)
283 287 LIBS += $(CONFIG_FMOD_LIB)
284 288 endif
  289 +ifdef CONFIG_ADLIB
  290 +SOUND_HW += fmopl.o adlib.o
  291 +endif
285 292  
286 293 ifeq ($(TARGET_BASE_ARCH), i386)
287 294 # Hardware support
288 295 VL_OBJS+= ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
289 296 VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o
290 297 VL_OBJS+= cirrus_vga.o mixeng.o apic.o parallel.o
  298 +DEFINES += -DHAS_AUDIO
291 299 endif
292 300 ifeq ($(TARGET_BASE_ARCH), ppc)
293 301 VL_OBJS+= ppc.o ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
294 302 VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
295 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 305 endif
297 306 ifeq ($(TARGET_ARCH), mips)
298 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 326 endif
318 327 ifdef CONFIG_COCOA
319 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 333 endif
322 334 ifdef CONFIG_SLIRP
323 335 DEFINES+=-I$(SRC_PATH)/slirp
... ... @@ -349,6 +361,10 @@ ifeq ($(ARCH),ia64)
349 361 VL_LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/ia64.ld
350 362 endif
351 363  
  364 +ifdef CONFIG_WIN32
  365 +SDL_LIBS := $(filter-out -mwindows, $(SDL_LIBS)) -mconsole
  366 +endif
  367 +
352 368 $(QEMU_SYSTEM): $(VL_OBJS) libqemu.a
353 369 $(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS)
354 370  
... ... @@ -364,6 +380,9 @@ sdlaudio.o: sdlaudio.c
364 380 depend: $(SRCS)
365 381 $(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend
366 382  
  383 +vldepend: $(VL_OBJS:.o=.c)
  384 + $(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend
  385 +
367 386 # libqemu
368 387  
369 388 libqemu.a: $(LIBOBJS)
... ... @@ -415,8 +434,6 @@ op.o: op.c op_template.c op_mem.c
415 434 op_helper.o: op_helper_mem.c
416 435 endif
417 436  
418   -mixeng.o: mixeng.c mixeng.h mixeng_template.h
419   -
420 437 %.o: %.c
421 438 $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
422 439  
... ... @@ -434,3 +451,9 @@ endif
434 451 ifneq ($(wildcard .depend),)
435 452 include .depend
436 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 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 6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 7 * of this software and associated documentation files (the "Software"), to deal
8 8 * in the Software without restriction, including without limitation the rights
... ... @@ -21,34 +21,78 @@
21 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 22 * THE SOFTWARE.
23 23 */
24   -#include <assert.h>
25 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 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 72 1, /* use fixed settings */
47 73 44100, /* fixed frequency */
48 74 2, /* fixed channels */
49 75 AUD_FMT_S16, /* fixed format */
50 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 98 /* http://www.df.lth.se/~john_e/gems/gem002d.html */
... ... @@ -68,275 +112,361 @@ inline uint32_t lsbindex (uint32_t u)
68 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 187 case AUD_FMT_S8:
140   - sign = 1;
141   - case AUD_FMT_U8:
142   - break;
  188 + return "S8";
143 189  
144 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 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 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 470 case AUD_FMT_S8:
341 471 sign = 1;
342 472 case AUD_FMT_U8:
... ... @@ -349,425 +479,595 @@ int pcm_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
349 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 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 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 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 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 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 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 1004 return;
  1005 + }
739 1006  
740 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 1049 if (sw->active != on) {
  1050 + SWVoiceIn *temp_sw;
  1051 +
750 1052 if (on) {
751   - hw->pending_disable = 0;
752 1053 if (!hw->enabled) {
753 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 1059 else {
763   - if (hw->enabled && !hw->pending_disable) {
  1060 + if (hw->enabled) {
764 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 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 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 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 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 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 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 1392 audio_state.opaque = drv->init ();
  1393 +
797 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 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 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 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 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 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 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 1552 audio_state.drv->fini (audio_state.opaque);
846 1553 }
847 1554  
848 1555 static void audio_save (QEMUFile *f, void *opaque)
849 1556 {
  1557 + (void) f;
  1558 + (void) opaque;
850 1559 }
851 1560  
852 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 1567 return -EINVAL;
  1568 + }
856 1569  
857 1570 return 0;
858 1571 }
859 1572  
860 1573 void AUD_init (void)
861 1574 {
862   - int i;
  1575 + size_t i;
863 1576 int done = 0;
864 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 1605 if (drvname) {
880 1606 int found = 0;
  1607 +
881 1608 for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
882 1609 if (!strcmp (drvname, drvtab[i]->name)) {
883   - done = voice_init (drvtab[i]);
  1610 + done = !audio_driver_init (drvtab[i]);
884 1611 found = 1;
885 1612 break;
886 1613 }
887 1614 }
  1615 +
888 1616 if (!found) {
889 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 1624  
896 1625 if (!done) {
897 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 1633 register_savevm ("audio", 0, 1, audio_save, audio_load, NULL);
907 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 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 6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 7 * of this software and associated documentation files (the "Software"), to deal
8 8 * in the Software without restriction, including without limitation the rights
... ... @@ -24,7 +24,7 @@
24 24 #ifndef QEMU_AUDIO_H
25 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 29 typedef enum {
30 30 AUD_FMT_U8,
... ... @@ -33,22 +33,60 @@ typedef enum {
33 33 AUD_FMT_S16
34 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 91 static inline void *advance (void *p, int incr)
54 92 {
... ... @@ -59,7 +97,21 @@ static inline void *advance (void *p, int incr)
59 97 uint32_t popcount (uint32_t u);
60 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 113 #define audio_MIN(a, b) ((a)>(b)?(b):(a))
63 114 #define audio_MAX(a, b) ((a)<(b)?(b):(a))
  115 +#endif
64 116  
65 117 #endif /* audio.h */
... ...
audio/audio_int.h
1 1 /*
2 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 6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 7 * of this software and associated documentation files (the "Software"), to deal
8 8 * in the Software without restriction, including without limitation the rights
... ... @@ -24,140 +24,266 @@
24 24 #ifndef QEMU_AUDIO_INT_H
25 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 72 int active;
33 73 int enabled;
34 74 int pending_disable;
35 75 int valid;
36   - int freq;
  76 + struct audio_pcm_info info;
37 77  
38 78 f_sample *clip;
39   - audfmt_e fmt;
40   - int nchannels;
41   -
42   - int align;
43   - int shift;
44 79  
45 80 int rpos;
46 81 int bufsize;
  82 + uint64_t ts_helper;
47 83  
48   - int bytes_per_second;
49 84 st_sample_t *mix_buf;
50 85  
51 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 123 const char *name;
  124 + const char *descr;
  125 + struct audio_option *options;
75 126 void *(*init) (void);
76 127 void (*fini) (void *);
77   - struct pcm_ops *pcm_ops;
  128 + struct audio_pcm_ops *pcm_ops;
78 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 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 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 166 t_sample *conv;
105   -
106   - int left;
107   - int pos;
108   - int bytes_per_second;
109 167 int64_t ratio;
110 168 st_sample_t *buf;
111 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 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 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 220 #define VOICE_ENABLE 1
161 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 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
... ...