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 --- |