audio_template.h 13.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/*
 * QEMU Audio subsystem header
 *
 * Copyright (c) 2005 Vassili Karpov (malc)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#ifdef DAC
B
bellard 已提交
26 27
#define NAME "playback"
#define HWBUF hw->mix_buf
28
#define TYPE out
B
bellard 已提交
29 30
#define HW HWVoiceOut
#define SW SWVoiceOut
31
#else
B
bellard 已提交
32
#define NAME "capture"
33
#define TYPE in
B
bellard 已提交
34 35 36
#define HW HWVoiceIn
#define SW SWVoiceIn
#define HWBUF hw->conv_buf
37 38
#endif

39
static void glue (audio_init_nb_voices_, TYPE) (struct audio_driver *drv)
B
bellard 已提交
40
{
41
    AudioState *s = &glob_audio_state;
B
bellard 已提交
42 43
    int max_voices = glue (drv->max_voices_, TYPE);
    int voice_size = glue (drv->voice_size_, TYPE);
B
bellard 已提交
44

B
bellard 已提交
45 46 47 48 49 50 51 52 53 54 55 56 57
    if (glue (s->nb_hw_voices_, TYPE) > max_voices) {
        if (!max_voices) {
#ifdef DAC
            dolog ("Driver `%s' does not support " NAME "\n", drv->name);
#endif
        }
        else {
            dolog ("Driver `%s' does not support %d " NAME " voices, max %d\n",
                   drv->name,
                   glue (s->nb_hw_voices_, TYPE),
                   max_voices);
        }
        glue (s->nb_hw_voices_, TYPE) = max_voices;
B
bellard 已提交
58 59
    }

B
bellard 已提交
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
    if (audio_bug (AUDIO_FUNC, !voice_size && max_voices)) {
        dolog ("drv=`%s' voice_size=0 max_voices=%d\n",
               drv->name, max_voices);
        glue (s->nb_hw_voices_, TYPE) = 0;
    }

    if (audio_bug (AUDIO_FUNC, voice_size && !max_voices)) {
        dolog ("drv=`%s' voice_size=%d max_voices=0\n",
               drv->name, voice_size);
    }
}

static void glue (audio_pcm_hw_free_resources_, TYPE) (HW *hw)
{
    if (HWBUF) {
        qemu_free (HWBUF);
    }

    HWBUF = NULL;
}

static int glue (audio_pcm_hw_alloc_resources_, TYPE) (HW *hw)
{
M
malc 已提交
83
    HWBUF = audio_calloc (AUDIO_FUNC, hw->samples, sizeof (struct st_sample));
B
bellard 已提交
84 85 86
    if (!HWBUF) {
        dolog ("Could not allocate " NAME " buffer (%d samples)\n",
               hw->samples);
B
bellard 已提交
87 88 89
        return -1;
    }

B
bellard 已提交
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
    return 0;
}

static void glue (audio_pcm_sw_free_resources_, TYPE) (SW *sw)
{
    if (sw->buf) {
        qemu_free (sw->buf);
    }

    if (sw->rate) {
        st_rate_stop (sw->rate);
    }

    sw->buf = NULL;
    sw->rate = NULL;
}

static int glue (audio_pcm_sw_alloc_resources_, TYPE) (SW *sw)
{
    int samples;

B
bellard 已提交
111
#ifdef DAC
B
bellard 已提交
112
    samples = sw->hw->samples;
B
bellard 已提交
113
#else
B
bellard 已提交
114
    samples = ((int64_t) sw->hw->samples << 32) / sw->ratio;
B
bellard 已提交
115 116
#endif

M
malc 已提交
117
    sw->buf = audio_calloc (AUDIO_FUNC, samples, sizeof (struct st_sample));
B
bellard 已提交
118 119 120
    if (!sw->buf) {
        dolog ("Could not allocate buffer for `%s' (%d samples)\n",
               SW_NAME (sw), samples);
B
bellard 已提交
121 122 123
        return -1;
    }

B
bellard 已提交
124 125 126 127 128 129 130 131 132 133
#ifdef DAC
    sw->rate = st_rate_start (sw->info.freq, sw->hw->info.freq);
#else
    sw->rate = st_rate_start (sw->hw->info.freq, sw->info.freq);
#endif
    if (!sw->rate) {
        qemu_free (sw->buf);
        sw->buf = NULL;
        return -1;
    }
B
bellard 已提交
134 135 136
    return 0;
}

B
bellard 已提交
137 138 139 140
static int glue (audio_pcm_sw_init_, TYPE) (
    SW *sw,
    HW *hw,
    const char *name,
M
malc 已提交
141
    struct audsettings *as
B
bellard 已提交
142 143 144 145
    )
{
    int err;

B
bellard 已提交
146
    audio_pcm_init_info (&sw->info, as);
B
bellard 已提交
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
    sw->hw = hw;
    sw->active = 0;
#ifdef DAC
    sw->ratio = ((int64_t) sw->hw->info.freq << 32) / sw->info.freq;
    sw->total_hw_samples_mixed = 0;
    sw->empty = 1;
#else
    sw->ratio = ((int64_t) sw->info.freq << 32) / sw->hw->info.freq;
#endif

#ifdef DAC
    sw->conv = mixeng_conv
#else
    sw->clip = mixeng_clip
#endif
        [sw->info.nchannels == 2]
        [sw->info.sign]
B
bellard 已提交
164
        [sw->info.swap_endianness]
165
        [audio_bits_to_index (sw->info.bits)];
B
bellard 已提交
166 167 168 169 170 171 172 173 174 175

    sw->name = qemu_strdup (name);
    err = glue (audio_pcm_sw_alloc_resources_, TYPE) (sw);
    if (err) {
        qemu_free (sw->name);
        sw->name = NULL;
    }
    return err;
}

176 177 178 179 180 181 182 183 184 185 186
static void glue (audio_pcm_sw_fini_, TYPE) (SW *sw)
{
    glue (audio_pcm_sw_free_resources_, TYPE) (sw);
    if (sw->name) {
        qemu_free (sw->name);
        sw->name = NULL;
    }
}

static void glue (audio_pcm_hw_add_sw_, TYPE) (HW *hw, SW *sw)
{
B
Blue Swirl 已提交
187
    QLIST_INSERT_HEAD (&hw->sw_head, sw, entries);
188 189 190 191
}

static void glue (audio_pcm_hw_del_sw_, TYPE) (SW *sw)
{
B
Blue Swirl 已提交
192
    QLIST_REMOVE (sw, entries);
193 194
}

195
static void glue (audio_pcm_hw_gc_, TYPE) (HW **hwp)
196
{
197
    AudioState *s = &glob_audio_state;
B
bellard 已提交
198
    HW *hw = *hwp;
199 200

    if (!hw->sw_head.lh_first) {
201 202 203
#ifdef DAC
        audio_detach_capture (hw);
#endif
B
Blue Swirl 已提交
204
        QLIST_REMOVE (hw, entries);
B
bellard 已提交
205 206 207 208 209
        glue (s->nb_hw_voices_, TYPE) += 1;
        glue (audio_pcm_hw_free_resources_ ,TYPE) (hw);
        glue (hw->pcm_ops->fini_, TYPE) (hw);
        qemu_free (hw);
        *hwp = NULL;
210 211 212
    }
}

213
static HW *glue (audio_pcm_hw_find_any_, TYPE) (HW *hw)
214
{
215 216
    AudioState *s = &glob_audio_state;
    return hw ? hw->entries.le_next : glue (s->hw_head_, TYPE).lh_first;
217 218
}

219
static HW *glue (audio_pcm_hw_find_any_enabled_, TYPE) (HW *hw)
220
{
221
    while ((hw = glue (audio_pcm_hw_find_any_, TYPE) (hw))) {
B
bellard 已提交
222
        if (hw->enabled) {
223 224 225 226 227 228 229 230
            return hw;
        }
    }
    return NULL;
}

static HW *glue (audio_pcm_hw_find_specific_, TYPE) (
    HW *hw,
M
malc 已提交
231
    struct audsettings *as
232 233
    )
{
234
    while ((hw = glue (audio_pcm_hw_find_any_, TYPE) (hw))) {
B
bellard 已提交
235
        if (audio_pcm_info_eq (&hw->info, as)) {
236 237 238 239 240 241
            return hw;
        }
    }
    return NULL;
}

242
static HW *glue (audio_pcm_hw_add_new_, TYPE) (struct audsettings *as)
243 244
{
    HW *hw;
245
    AudioState *s = &glob_audio_state;
B
bellard 已提交
246
    struct audio_driver *drv = s->drv;
247

B
bellard 已提交
248 249 250
    if (!glue (s->nb_hw_voices_, TYPE)) {
        return NULL;
    }
251

B
bellard 已提交
252 253 254
    if (audio_bug (AUDIO_FUNC, !drv)) {
        dolog ("No host audio driver\n");
        return NULL;
255 256
    }

B
bellard 已提交
257 258 259 260 261 262 263 264 265 266 267 268 269
    if (audio_bug (AUDIO_FUNC, !drv->pcm_ops)) {
        dolog ("Host audio driver without pcm_ops\n");
        return NULL;
    }

    hw = audio_calloc (AUDIO_FUNC, 1, glue (drv->voice_size_, TYPE));
    if (!hw) {
        dolog ("Can not allocate voice `%s' size %d\n",
               drv->name, glue (drv->voice_size_, TYPE));
        return NULL;
    }

    hw->pcm_ops = drv->pcm_ops;
B
Blue Swirl 已提交
270
    QLIST_INIT (&hw->sw_head);
271
#ifdef DAC
B
Blue Swirl 已提交
272
    QLIST_INIT (&hw->cap_head);
273
#endif
B
bellard 已提交
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
    if (glue (hw->pcm_ops->init_, TYPE) (hw, as)) {
        goto err0;
    }

    if (audio_bug (AUDIO_FUNC, hw->samples <= 0)) {
        dolog ("hw->samples=%d\n", hw->samples);
        goto err1;
    }

#ifdef DAC
    hw->clip = mixeng_clip
#else
    hw->conv = mixeng_conv
#endif
        [hw->info.nchannels == 2]
        [hw->info.sign]
B
bellard 已提交
290
        [hw->info.swap_endianness]
291
        [audio_bits_to_index (hw->info.bits)];
B
bellard 已提交
292 293 294 295 296

    if (glue (audio_pcm_hw_alloc_resources_, TYPE) (hw)) {
        goto err1;
    }

B
Blue Swirl 已提交
297
    QLIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries);
B
bellard 已提交
298
    glue (s->nb_hw_voices_, TYPE) -= 1;
299
#ifdef DAC
300
    audio_attach_capture (hw);
301
#endif
B
bellard 已提交
302 303 304 305 306 307
    return hw;

 err1:
    glue (hw->pcm_ops->fini_, TYPE) (hw);
 err0:
    qemu_free (hw);
308 309 310
    return NULL;
}

311
static HW *glue (audio_pcm_hw_add_, TYPE) (struct audsettings *as)
312 313 314
{
    HW *hw;

B
bellard 已提交
315
    if (glue (conf.fixed_, TYPE).enabled && glue (conf.fixed_, TYPE).greedy) {
316
        hw = glue (audio_pcm_hw_add_new_, TYPE) (as);
317 318 319 320 321
        if (hw) {
            return hw;
        }
    }

322
    hw = glue (audio_pcm_hw_find_specific_, TYPE) (NULL, as);
323 324 325 326
    if (hw) {
        return hw;
    }

327
    hw = glue (audio_pcm_hw_add_new_, TYPE) (as);
328 329 330 331
    if (hw) {
        return hw;
    }

332
    return glue (audio_pcm_hw_find_any_, TYPE) (NULL);
333 334 335
}

static SW *glue (audio_pcm_create_voice_pair_, TYPE) (
B
bellard 已提交
336
    const char *sw_name,
M
malc 已提交
337
    struct audsettings *as
338 339 340 341
    )
{
    SW *sw;
    HW *hw;
M
malc 已提交
342
    struct audsettings hw_as;
343

B
bellard 已提交
344 345 346 347 348
    if (glue (conf.fixed_, TYPE).enabled) {
        hw_as = glue (conf.fixed_, TYPE).settings;
    }
    else {
        hw_as = *as;
349 350
    }

B
bellard 已提交
351
    sw = audio_calloc (AUDIO_FUNC, 1, sizeof (*sw));
352
    if (!sw) {
B
bellard 已提交
353
        dolog ("Could not allocate soft voice `%s' (%zu bytes)\n",
B
bellard 已提交
354
               sw_name ? sw_name : "unknown", sizeof (*sw));
355 356 357
        goto err1;
    }

358
    hw = glue (audio_pcm_hw_add_, TYPE) (&hw_as);
359 360 361 362 363 364
    if (!hw) {
        goto err2;
    }

    glue (audio_pcm_hw_add_sw_, TYPE) (hw, sw);

B
bellard 已提交
365
    if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as)) {
366 367 368 369 370 371 372
        goto err3;
    }

    return sw;

err3:
    glue (audio_pcm_hw_del_sw_, TYPE) (sw);
373
    glue (audio_pcm_hw_gc_, TYPE) (&hw);
374 375 376 377 378 379
err2:
    qemu_free (sw);
err1:
    return NULL;
}

380
static void glue (audio_close_, TYPE) (SW *sw)
B
bellard 已提交
381 382 383
{
    glue (audio_pcm_sw_fini_, TYPE) (sw);
    glue (audio_pcm_hw_del_sw_, TYPE) (sw);
384
    glue (audio_pcm_hw_gc_, TYPE) (&sw->hw);
B
bellard 已提交
385 386
    qemu_free (sw);
}
B
bellard 已提交
387

B
bellard 已提交
388
void glue (AUD_close_, TYPE) (QEMUSoundCard *card, SW *sw)
389 390
{
    if (sw) {
391 392
        if (audio_bug (AUDIO_FUNC, !card)) {
            dolog ("card=%p\n", card);
B
bellard 已提交
393 394 395
            return;
        }

396
        glue (audio_close_, TYPE) (sw);
397 398 399 400
    }
}

SW *glue (AUD_open_, TYPE) (
B
bellard 已提交
401
    QEMUSoundCard *card,
402 403 404
    SW *sw,
    const char *name,
    void *callback_opaque ,
M
malc 已提交
405
    audio_callback_fn callback_fn,
M
malc 已提交
406
    struct audsettings *as
407 408
    )
{
409
    AudioState *s = &glob_audio_state;
410 411 412 413 414
#ifdef DAC
    int live = 0;
    SW *old_sw = NULL;
#endif

B
bellard 已提交
415 416 417
    ldebug ("open %s, freq %d, nchannels %d, fmt %d\n",
            name, as->freq, as->nchannels, as->fmt);

418 419 420
    if (audio_bug (AUDIO_FUNC, !card || !name || !callback_fn || !as)) {
        dolog ("card=%p name=%p callback_fn=%p as=%p\n",
               card, name, callback_fn, as);
421 422 423
        goto fail;
    }

B
bellard 已提交
424
    if (audio_bug (AUDIO_FUNC, audio_validate_settings (as))) {
B
bellard 已提交
425
        audio_print_settings (as);
426 427 428
        goto fail;
    }

B
bellard 已提交
429 430
    if (audio_bug (AUDIO_FUNC, !s->drv)) {
        dolog ("Can not open `%s' (no host audio driver)\n", name);
431 432 433
        goto fail;
    }

B
bellard 已提交
434
    if (sw && audio_pcm_info_eq (&sw->info, as)) {
435 436 437 438
        return sw;
    }

#ifdef DAC
B
bellard 已提交
439
    if (conf.plive && sw && (!sw->active && !sw->empty)) {
440 441 442
        live = sw->total_hw_samples_mixed;

#ifdef DEBUG_PLIVE
B
bellard 已提交
443
        dolog ("Replacing voice %s with %d live samples\n", SW_NAME (sw), live);
444
        dolog ("Old %s freq %d, bits %d, channels %d\n",
B
bellard 已提交
445
               SW_NAME (sw), sw->info.freq, sw->info.bits, sw->info.nchannels);
446
        dolog ("New %s freq %d, bits %d, channels %d\n",
B
bellard 已提交
447 448 449
               name,
               freq,
               (fmt == AUD_FMT_S16 || fmt == AUD_FMT_U16) ? 16 : 8,
450 451 452 453 454 455 456 457 458 459 460
               nchannels);
#endif

        if (live) {
            old_sw = sw;
            old_sw->callback.fn = NULL;
            sw = NULL;
        }
    }
#endif

B
bellard 已提交
461 462
    if (!glue (conf.fixed_, TYPE).enabled && sw) {
        glue (AUD_close_, TYPE) (card, sw);
463 464 465 466 467 468 469
        sw = NULL;
    }

    if (sw) {
        HW *hw = sw->hw;

        if (!hw) {
B
bellard 已提交
470 471
            dolog ("Internal logic error voice `%s' has no hardware store\n",
                   SW_NAME (sw));
472 473 474
            goto fail;
        }

B
bellard 已提交
475
        glue (audio_pcm_sw_fini_, TYPE) (sw);
B
bellard 已提交
476
        if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, as)) {
477 478 479 480
            goto fail;
        }
    }
    else {
481
        sw = glue (audio_pcm_create_voice_pair_, TYPE) (name, as);
482
        if (!sw) {
B
bellard 已提交
483
            dolog ("Failed to create voice `%s'\n", name);
B
bellard 已提交
484
            return NULL;
485 486 487
        }
    }

488 489 490 491
    sw->card = card;
    sw->vol = nominal_volume;
    sw->callback.fn = callback_fn;
    sw->callback.opaque = callback_opaque;
492 493

#ifdef DAC
494 495 496 497 498
    if (live) {
        int mixed =
            (live << old_sw->info.shift)
            * old_sw->info.bytes_per_second
            / sw->info.bytes_per_second;
499 500

#ifdef DEBUG_PLIVE
501
        dolog ("Silence will be mixed %d\n", mixed);
502
#endif
503 504
        sw->total_hw_samples_mixed += mixed;
    }
505 506 507
#endif

#ifdef DEBUG_AUDIO
508 509 510
    dolog ("%s\n", name);
    audio_pcm_print_info ("hw", &sw->hw->info);
    audio_pcm_print_info ("sw", &sw->info);
511 512 513 514 515
#endif

    return sw;

 fail:
B
bellard 已提交
516
    glue (AUD_close_, TYPE) (card, sw);
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533
    return NULL;
}

int glue (AUD_is_active_, TYPE) (SW *sw)
{
    return sw ? sw->active : 0;
}

void glue (AUD_init_time_stamp_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts)
{
    if (!sw) {
        return;
    }

    ts->old_ts = sw->hw->ts_helper;
}

B
bellard 已提交
534
uint64_t glue (AUD_get_elapsed_usec_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts)
535 536 537 538 539 540 541 542 543
{
    uint64_t delta, cur_ts, old_ts;

    if (!sw) {
        return 0;
    }

    cur_ts = sw->hw->ts_helper;
    old_ts = ts->old_ts;
544
    /* dolog ("cur %lld old %lld\n", cur_ts, old_ts); */
545 546 547 548 549 550 551 552 553 554 555 556

    if (cur_ts >= old_ts) {
        delta = cur_ts - old_ts;
    }
    else {
        delta = UINT64_MAX - old_ts + cur_ts;
    }

    if (!delta) {
        return 0;
    }

M
malc 已提交
557
    return muldiv64 (delta, sw->hw->info.freq, 1000000);
558 559 560 561 562
}

#undef TYPE
#undef HW
#undef SW
B
bellard 已提交
563 564
#undef HWBUF
#undef NAME