dsoundaudio.c (33f18cf7dca7741d3647d514040904ce83edd73d) dsoundaudio.c (7fa9754ac888d571000110504a3a7950f1404212)
1/*
2 * QEMU DirectSound 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

--- 39 unchanged lines hidden (view full) ---

48 LPDIRECTSOUNDCAPTURE dsound_capture;
49 struct audsettings settings;
50 Audiodev *dev;
51} dsound;
52
53typedef struct {
54 HWVoiceOut hw;
55 LPDIRECTSOUNDBUFFER dsound_buffer;
1/*
2 * QEMU DirectSound 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

--- 39 unchanged lines hidden (view full) ---

48 LPDIRECTSOUNDCAPTURE dsound_capture;
49 struct audsettings settings;
50 Audiodev *dev;
51} dsound;
52
53typedef struct {
54 HWVoiceOut hw;
55 LPDIRECTSOUNDBUFFER dsound_buffer;
56 DWORD old_pos;
57 int first_time;
58 dsound *s;
56 dsound *s;
59#ifdef DEBUG_DSOUND
60 DWORD old_ppos;
61 DWORD played;
62 DWORD mixed;
63#endif
64} DSoundVoiceOut;
65
66typedef struct {
67 HWVoiceIn hw;
57} DSoundVoiceOut;
58
59typedef struct {
60 HWVoiceIn hw;
68 int first_time;
69 LPDIRECTSOUNDCAPTUREBUFFER dsound_capture_buffer;
70 dsound *s;
71} DSoundVoiceIn;
72
73static void dsound_log_hresult (HRESULT hr)
74{
75 const char *str = "BUG";
76

--- 161 unchanged lines hidden (view full) ---

238 AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
239 va_start (ap, fmt);
240 AUD_vlog (AUDIO_CAP, fmt, ap);
241 va_end (ap);
242
243 dsound_log_hresult (hr);
244}
245
61 LPDIRECTSOUNDCAPTUREBUFFER dsound_capture_buffer;
62 dsound *s;
63} DSoundVoiceIn;
64
65static void dsound_log_hresult (HRESULT hr)
66{
67 const char *str = "BUG";
68

--- 161 unchanged lines hidden (view full) ---

230 AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
231 va_start (ap, fmt);
232 AUD_vlog (AUDIO_CAP, fmt, ap);
233 va_end (ap);
234
235 dsound_log_hresult (hr);
236}
237
246static uint64_t usecs_to_bytes(struct audio_pcm_info *info, uint32_t usecs)
247{
248 return muldiv64(usecs, info->bytes_per_second, 1000000);
249}
250
251#ifdef DEBUG_DSOUND
252static void print_wave_format (WAVEFORMATEX *wfx)
253{
254 dolog ("tag = %d\n", wfx->wFormatTag);
255 dolog ("nChannels = %d\n", wfx->nChannels);
256 dolog ("nSamplesPerSec = %ld\n", wfx->nSamplesPerSec);
257 dolog ("nAvgBytesPerSec = %ld\n", wfx->nAvgBytesPerSec);
258 dolog ("nBlockAlign = %d\n", wfx->nBlockAlign);

--- 48 unchanged lines hidden (view full) ---

307 if (FAILED (hr)) {
308 dsound_logerr (hr, "Could not get capture buffer status\n");
309 return -1;
310 }
311
312 return 0;
313}
314
238#ifdef DEBUG_DSOUND
239static void print_wave_format (WAVEFORMATEX *wfx)
240{
241 dolog ("tag = %d\n", wfx->wFormatTag);
242 dolog ("nChannels = %d\n", wfx->nChannels);
243 dolog ("nSamplesPerSec = %ld\n", wfx->nSamplesPerSec);
244 dolog ("nAvgBytesPerSec = %ld\n", wfx->nAvgBytesPerSec);
245 dolog ("nBlockAlign = %d\n", wfx->nBlockAlign);

--- 48 unchanged lines hidden (view full) ---

294 if (FAILED (hr)) {
295 dsound_logerr (hr, "Could not get capture buffer status\n");
296 return -1;
297 }
298
299 return 0;
300}
301
315static void dsound_write_sample (HWVoiceOut *hw, uint8_t *dst, int dst_len)
316{
317 int src_len1 = dst_len;
318 int src_len2 = 0;
319 int pos = hw->rpos + dst_len;
320 struct st_sample *src1 = hw->mix_buf + hw->rpos;
321 struct st_sample *src2 = NULL;
322
323 if (pos > hw->samples) {
324 src_len1 = hw->samples - hw->rpos;
325 src2 = hw->mix_buf;
326 src_len2 = dst_len - src_len1;
327 pos = src_len2;
328 }
329
330 if (src_len1) {
331 hw->clip (dst, src1, src_len1);
332 }
333
334 if (src_len2) {
335 dst = advance (dst, src_len1 << hw->info.shift);
336 hw->clip (dst, src2, src_len2);
337 }
338
339 hw->rpos = pos % hw->samples;
340}
341
342static void dsound_clear_sample (HWVoiceOut *hw, LPDIRECTSOUNDBUFFER dsb,
343 dsound *s)
344{
345 int err;
346 LPVOID p1, p2;
347 DWORD blen1, blen2, len1, len2;
348
349 err = dsound_lock_out (
350 dsb,
351 &hw->info,
352 0,
302static void dsound_clear_sample (HWVoiceOut *hw, LPDIRECTSOUNDBUFFER dsb,
303 dsound *s)
304{
305 int err;
306 LPVOID p1, p2;
307 DWORD blen1, blen2, len1, len2;
308
309 err = dsound_lock_out (
310 dsb,
311 &hw->info,
312 0,
353 hw->samples << hw->info.shift,
313 hw->size_emul,
354 &p1, &p2,
355 &blen1, &blen2,
356 1,
357 s
358 );
359 if (err) {
360 return;
361 }

--- 87 unchanged lines hidden (view full) ---

449 else {
450 dolog ("warning: Voice is not playing\n");
451 }
452 break;
453 }
454 return 0;
455}
456
314 &p1, &p2,
315 &blen1, &blen2,
316 1,
317 s
318 );
319 if (err) {
320 return;
321 }

--- 87 unchanged lines hidden (view full) ---

409 else {
410 dolog ("warning: Voice is not playing\n");
411 }
412 break;
413 }
414 return 0;
415}
416
457static size_t dsound_run_out(HWVoiceOut *hw, size_t live)
417static void *dsound_get_buffer_out(HWVoiceOut *hw, size_t *size)
458{
418{
459 int err;
460 HRESULT hr;
461 DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
462 LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
419 DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
420 LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
463 size_t len;
464 int hwshift;
465 DWORD blen1, blen2;
466 DWORD len1, len2;
467 DWORD decr;
468 DWORD wpos, ppos, old_pos;
469 LPVOID p1, p2;
470 size_t bufsize;
471 dsound *s = ds->s;
472 AudiodevDsoundOptions *dso = &s->dev->u.dsound;
421 HRESULT hr;
422 DWORD ppos, act_size;
423 size_t req_size;
424 int err;
425 void *ret;
473
426
474 if (!dsb) {
475 dolog ("Attempt to run empty with playback buffer\n");
476 return 0;
427 hr = IDirectSoundBuffer_GetCurrentPosition(dsb, &ppos, NULL);
428 if (FAILED(hr)) {
429 dsound_logerr(hr, "Could not get playback buffer position\n");
430 *size = 0;
431 return NULL;
477 }
478
432 }
433
479 hwshift = hw->info.shift;
480 bufsize = hw->samples << hwshift;
434 req_size = audio_ring_dist(ppos, hw->pos_emul, hw->size_emul);
435 req_size = MIN(req_size, hw->size_emul - hw->pos_emul);
481
436
482 hr = IDirectSoundBuffer_GetCurrentPosition (
483 dsb,
484 &ppos,
485 ds->first_time ? &wpos : NULL
486 );
487 if (FAILED (hr)) {
488 dsound_logerr (hr, "Could not get playback buffer position\n");
489 return 0;
437 err = dsound_lock_out(dsb, &hw->info, hw->pos_emul, req_size, &ret, NULL,
438 &act_size, NULL, false, ds->s);
439 if (err) {
440 dolog("Failed to lock buffer\n");
441 *size = 0;
442 return NULL;
490 }
491
443 }
444
492 len = live << hwshift;
445 *size = act_size;
446 return ret;
447}
493
448
494 if (ds->first_time) {
495 if (dso->latency) {
496 DWORD cur_blat;
449static size_t dsound_put_buffer_out(HWVoiceOut *hw, void *buf, size_t len)
450{
451 DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
452 LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
453 int err = dsound_unlock_out(dsb, buf, NULL, len, 0);
497
454
498 cur_blat = audio_ring_dist (wpos, ppos, bufsize);
499 ds->first_time = 0;
500 old_pos = wpos;
501 old_pos +=
502 usecs_to_bytes(&hw->info, dso->latency) - cur_blat;
503 old_pos %= bufsize;
504 old_pos &= ~hw->info.align;
505 }
506 else {
507 old_pos = wpos;
508 }
509#ifdef DEBUG_DSOUND
510 ds->played = 0;
511 ds->mixed = 0;
512#endif
513 }
514 else {
515 if (ds->old_pos == ppos) {
516#ifdef DEBUG_DSOUND
517 dolog ("old_pos == ppos\n");
518#endif
519 return 0;
520 }
521
522#ifdef DEBUG_DSOUND
523 ds->played += audio_ring_dist (ds->old_pos, ppos, hw->bufsize);
524#endif
525 old_pos = ds->old_pos;
526 }
527
528 if ((old_pos < ppos) && ((old_pos + len) > ppos)) {
529 len = ppos - old_pos;
530 }
531 else {
532 if ((old_pos > ppos) && ((old_pos + len) > (ppos + bufsize))) {
533 len = bufsize - old_pos + ppos;
534 }
535 }
536
537 if (audio_bug(__func__, len > bufsize)) {
538 dolog("len=%zu bufsize=%zu old_pos=%ld ppos=%ld\n",
539 len, bufsize, old_pos, ppos);
540 return 0;
541 }
542
543 len &= ~hw->info.align;
544 if (!len) {
545 return 0;
546 }
547
548#ifdef DEBUG_DSOUND
549 ds->old_ppos = ppos;
550#endif
551 err = dsound_lock_out (
552 dsb,
553 &hw->info,
554 old_pos,
555 len,
556 &p1, &p2,
557 &blen1, &blen2,
558 0,
559 s
560 );
561 if (err) {
455 if (err) {
456 dolog("Failed to unlock buffer!!\n");
562 return 0;
563 }
457 return 0;
458 }
459 hw->pos_emul = (hw->pos_emul + len) % hw->size_emul;
564
460
565 len1 = blen1 >> hwshift;
566 len2 = blen2 >> hwshift;
567 decr = len1 + len2;
568
569 if (p1 && len1) {
570 dsound_write_sample (hw, p1, len1);
571 }
572
573 if (p2 && len2) {
574 dsound_write_sample (hw, p2, len2);
575 }
576
577 dsound_unlock_out (dsb, p1, p2, blen1, blen2);
578 ds->old_pos = (old_pos + (decr << hwshift)) % bufsize;
579
580#ifdef DEBUG_DSOUND
581 ds->mixed += decr << hwshift;
582
583 dolog ("played %lu mixed %lu diff %ld sec %f\n",
584 ds->played,
585 ds->mixed,
586 ds->mixed - ds->played,
587 abs (ds->mixed - ds->played) / (double) hw->info.bytes_per_second);
588#endif
589 return decr;
461 return len;
590}
591
592static int dsound_ctl_in (HWVoiceIn *hw, int cmd, ...)
593{
594 HRESULT hr;
595 DWORD status;
596 DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
597 LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer;

--- 38 unchanged lines hidden (view full) ---

636 else {
637 dolog ("warning: Voice is not capturing\n");
638 }
639 break;
640 }
641 return 0;
642}
643
462}
463
464static int dsound_ctl_in (HWVoiceIn *hw, int cmd, ...)
465{
466 HRESULT hr;
467 DWORD status;
468 DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
469 LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer;

--- 38 unchanged lines hidden (view full) ---

508 else {
509 dolog ("warning: Voice is not capturing\n");
510 }
511 break;
512 }
513 return 0;
514}
515
644static size_t dsound_run_in(HWVoiceIn *hw)
516static void *dsound_get_buffer_in(HWVoiceIn *hw, size_t *size)
645{
517{
646 int err;
647 HRESULT hr;
648 DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
649 LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer;
518 DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
519 LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer;
650 size_t live, len, dead;
651 DWORD blen1, blen2;
652 DWORD len1, len2;
653 DWORD decr;
654 DWORD cpos, rpos;
655 LPVOID p1, p2;
656 int hwshift;
657 dsound *s = ds->s;
520 HRESULT hr;
521 DWORD cpos, act_size;
522 size_t req_size;
523 int err;
524 void *ret;
658
525
659 if (!dscb) {
660 dolog ("Attempt to run without capture buffer\n");
661 return 0;
526 hr = IDirectSoundCaptureBuffer_GetCurrentPosition(dscb, &cpos, NULL);
527 if (FAILED(hr)) {
528 dsound_logerr(hr, "Could not get capture buffer position\n");
529 *size = 0;
530 return NULL;
662 }
663
531 }
532
664 hwshift = hw->info.shift;
533 req_size = audio_ring_dist(cpos, hw->pos_emul, hw->size_emul);
534 req_size = MIN(req_size, hw->size_emul - hw->pos_emul);
665
535
666 live = audio_pcm_hw_get_live_in (hw);
667 dead = hw->samples - live;
668 if (!dead) {
669 return 0;
536 err = dsound_lock_in(dscb, &hw->info, hw->pos_emul, req_size, &ret, NULL,
537 &act_size, NULL, false, ds->s);
538 if (err) {
539 dolog("Failed to lock buffer\n");
540 *size = 0;
541 return NULL;
670 }
671
542 }
543
672 hr = IDirectSoundCaptureBuffer_GetCurrentPosition (
673 dscb,
674 &cpos,
675 ds->first_time ? &rpos : NULL
676 );
677 if (FAILED (hr)) {
678 dsound_logerr (hr, "Could not get capture buffer position\n");
679 return 0;
680 }
544 *size = act_size;
545 return ret;
546}
681
547
682 if (ds->first_time) {
683 ds->first_time = 0;
684 if (rpos & hw->info.align) {
685 ldebug ("warning: Misaligned capture read position %ld(%d)\n",
686 rpos, hw->info.align);
687 }
688 hw->wpos = rpos >> hwshift;
689 }
548static void dsound_put_buffer_in(HWVoiceIn *hw, void *buf, size_t len)
549{
550 DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
551 LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer;
552 int err = dsound_unlock_in(dscb, buf, NULL, len, 0);
690
553
691 if (cpos & hw->info.align) {
692 ldebug ("warning: Misaligned capture position %ld(%d)\n",
693 cpos, hw->info.align);
694 }
695 cpos >>= hwshift;
696
697 len = audio_ring_dist (cpos, hw->wpos, hw->samples);
698 if (!len) {
699 return 0;
700 }
701 len = MIN (len, dead);
702
703 err = dsound_lock_in (
704 dscb,
705 &hw->info,
706 hw->wpos << hwshift,
707 len << hwshift,
708 &p1,
709 &p2,
710 &blen1,
711 &blen2,
712 0,
713 s
714 );
715 if (err) {
554 if (err) {
716 return 0;
555 dolog("Failed to unlock buffer!!\n");
556 return;
717 }
557 }
718
719 len1 = blen1 >> hwshift;
720 len2 = blen2 >> hwshift;
721 decr = len1 + len2;
722
723 if (p1 && len1) {
724 hw->conv (hw->conv_buf + hw->wpos, p1, len1);
725 }
726
727 if (p2 && len2) {
728 hw->conv (hw->conv_buf, p2, len2);
729 }
730
731 dsound_unlock_in (dscb, p1, p2, blen1, blen2);
732 hw->wpos = (hw->wpos + decr) % hw->samples;
733 return decr;
558 hw->pos_emul = (hw->pos_emul + len) % hw->size_emul;
734}
735
736static void dsound_audio_fini (void *opaque)
737{
738 HRESULT hr;
739 dsound *s = opaque;
740
741 if (!s->dsound) {

--- 99 unchanged lines hidden (view full) ---

841 }
842
843 return s;
844}
845
846static struct audio_pcm_ops dsound_pcm_ops = {
847 .init_out = dsound_init_out,
848 .fini_out = dsound_fini_out,
559}
560
561static void dsound_audio_fini (void *opaque)
562{
563 HRESULT hr;
564 dsound *s = opaque;
565
566 if (!s->dsound) {

--- 99 unchanged lines hidden (view full) ---

666 }
667
668 return s;
669}
670
671static struct audio_pcm_ops dsound_pcm_ops = {
672 .init_out = dsound_init_out,
673 .fini_out = dsound_fini_out,
849 .run_out = dsound_run_out,
674 .write = audio_generic_write,
675 .get_buffer_out = dsound_get_buffer_out,
676 .put_buffer_out = dsound_put_buffer_out,
850 .ctl_out = dsound_ctl_out,
851
852 .init_in = dsound_init_in,
853 .fini_in = dsound_fini_in,
677 .ctl_out = dsound_ctl_out,
678
679 .init_in = dsound_init_in,
680 .fini_in = dsound_fini_in,
854 .run_in = dsound_run_in,
681 .read = audio_generic_read,
682 .get_buffer_in = dsound_get_buffer_in,
683 .put_buffer_in = dsound_put_buffer_in,
855 .ctl_in = dsound_ctl_in
856};
857
858static struct audio_driver dsound_audio_driver = {
859 .name = "dsound",
860 .descr = "DirectSound http://wikipedia.org/wiki/DirectSound",
861 .init = dsound_audio_init,
862 .fini = dsound_audio_fini,

--- 13 unchanged lines hidden ---
684 .ctl_in = dsound_ctl_in
685};
686
687static struct audio_driver dsound_audio_driver = {
688 .name = "dsound",
689 .descr = "DirectSound http://wikipedia.org/wiki/DirectSound",
690 .init = dsound_audio_init,
691 .fini = dsound_audio_fini,

--- 13 unchanged lines hidden ---