Revision c0fe3827 audio/dsoundaudio.c
b/audio/dsoundaudio.c | ||
---|---|---|
37 | 37 |
|
38 | 38 |
/* #define DEBUG_DSOUND */ |
39 | 39 |
|
40 |
struct full_fmt { |
|
41 |
int freq; |
|
42 |
int nchannels; |
|
43 |
audfmt_e fmt; |
|
44 |
}; |
|
45 |
|
|
46 | 40 |
static struct { |
47 | 41 |
int lock_retries; |
48 | 42 |
int restore_retries; |
... | ... | |
50 | 44 |
int set_primary; |
51 | 45 |
int bufsize_in; |
52 | 46 |
int bufsize_out; |
53 |
struct full_fmt full_fmt;
|
|
47 |
audsettings_t settings;
|
|
54 | 48 |
int latency_millis; |
55 | 49 |
} conf = { |
56 | 50 |
1, |
... | ... | |
71 | 65 |
LPDIRECTSOUND dsound; |
72 | 66 |
LPDIRECTSOUNDCAPTURE dsound_capture; |
73 | 67 |
LPDIRECTSOUNDBUFFER dsound_primary_buffer; |
74 |
struct full_fmt fmt;
|
|
68 |
audsettings_t settings;
|
|
75 | 69 |
} dsound; |
76 | 70 |
|
77 | 71 |
static dsound glob_dsound; |
... | ... | |
259 | 253 |
{ |
260 | 254 |
va_list ap; |
261 | 255 |
|
262 |
AUD_log (AUDIO_CAP, "Can not initialize %s\n", typ);
|
|
256 |
AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
|
|
263 | 257 |
va_start (ap, fmt); |
264 | 258 |
AUD_vlog (AUDIO_CAP, fmt, ap); |
265 | 259 |
va_end (ap); |
... | ... | |
301 | 295 |
continue; |
302 | 296 |
|
303 | 297 |
default: |
304 |
dsound_logerr (hr, "Can not restore playback buffer\n");
|
|
298 |
dsound_logerr (hr, "Could not restore playback buffer\n");
|
|
305 | 299 |
return -1; |
306 | 300 |
} |
307 | 301 |
} |
... | ... | |
310 | 304 |
return -1; |
311 | 305 |
} |
312 | 306 |
|
313 |
static int waveformat_from_full_fmt (WAVEFORMATEX *wfx, |
|
314 |
struct full_fmt *full_fmt) |
|
307 |
static int waveformat_from_audio_settings (WAVEFORMATEX *wfx, audsettings_t *as) |
|
315 | 308 |
{ |
316 | 309 |
memset (wfx, 0, sizeof (*wfx)); |
317 | 310 |
|
318 | 311 |
wfx->wFormatTag = WAVE_FORMAT_PCM; |
319 |
wfx->nChannels = full_fmt->nchannels;
|
|
320 |
wfx->nSamplesPerSec = full_fmt->freq;
|
|
321 |
wfx->nAvgBytesPerSec = full_fmt->freq << (full_fmt->nchannels == 2);
|
|
322 |
wfx->nBlockAlign = 1 << (full_fmt->nchannels == 2);
|
|
312 |
wfx->nChannels = as->nchannels;
|
|
313 |
wfx->nSamplesPerSec = as->freq;
|
|
314 |
wfx->nAvgBytesPerSec = as->freq << (as->nchannels == 2);
|
|
315 |
wfx->nBlockAlign = 1 << (as->nchannels == 2);
|
|
323 | 316 |
wfx->cbSize = 0; |
324 | 317 |
|
325 |
switch (full_fmt->fmt) {
|
|
318 |
switch (as->fmt) {
|
|
326 | 319 |
case AUD_FMT_S8: |
327 | 320 |
wfx->wBitsPerSample = 8; |
328 | 321 |
break; |
... | ... | |
344 | 337 |
break; |
345 | 338 |
|
346 | 339 |
default: |
347 |
dolog ("Internal logic error: Bad audio format %d\n", |
|
348 |
full_fmt->freq); |
|
340 |
dolog ("Internal logic error: Bad audio format %d\n", as->freq); |
|
349 | 341 |
return -1; |
350 | 342 |
} |
351 | 343 |
|
352 | 344 |
return 0; |
353 | 345 |
} |
354 | 346 |
|
355 |
static int waveformat_to_full_fmt (WAVEFORMATEX *wfx, |
|
356 |
struct full_fmt *full_fmt) |
|
347 |
static int waveformat_to_audio_settings (WAVEFORMATEX *wfx, audsettings_t *as) |
|
357 | 348 |
{ |
358 | 349 |
if (wfx->wFormatTag != WAVE_FORMAT_PCM) { |
359 | 350 |
dolog ("Invalid wave format, tag is not PCM, but %d\n", |
... | ... | |
365 | 356 |
dolog ("Invalid wave format, frequency is zero\n"); |
366 | 357 |
return -1; |
367 | 358 |
} |
368 |
full_fmt->freq = wfx->nSamplesPerSec;
|
|
359 |
as->freq = wfx->nSamplesPerSec;
|
|
369 | 360 |
|
370 | 361 |
switch (wfx->nChannels) { |
371 | 362 |
case 1: |
372 |
full_fmt->nchannels = 1;
|
|
363 |
as->nchannels = 1;
|
|
373 | 364 |
break; |
374 | 365 |
|
375 | 366 |
case 2: |
376 |
full_fmt->nchannels = 2;
|
|
367 |
as->nchannels = 2;
|
|
377 | 368 |
break; |
378 | 369 |
|
379 | 370 |
default: |
... | ... | |
386 | 377 |
|
387 | 378 |
switch (wfx->wBitsPerSample) { |
388 | 379 |
case 8: |
389 |
full_fmt->fmt = AUD_FMT_U8;
|
|
380 |
as->fmt = AUD_FMT_U8;
|
|
390 | 381 |
break; |
391 | 382 |
|
392 | 383 |
case 16: |
393 |
full_fmt->fmt = AUD_FMT_S16;
|
|
384 |
as->fmt = AUD_FMT_S16;
|
|
394 | 385 |
break; |
395 | 386 |
|
396 | 387 |
default: |
... | ... | |
415 | 406 |
for (i = 0; i < conf.getstatus_retries; ++i) { |
416 | 407 |
hr = IDirectSoundBuffer_GetStatus (dsb, statusp); |
417 | 408 |
if (FAILED (hr)) { |
418 |
dsound_logerr (hr, "Can not get playback buffer status\n");
|
|
409 |
dsound_logerr (hr, "Could not get playback buffer status\n");
|
|
419 | 410 |
return -1; |
420 | 411 |
} |
421 | 412 |
|
... | ... | |
438 | 429 |
|
439 | 430 |
hr = IDirectSoundCaptureBuffer_GetStatus (dscb, statusp); |
440 | 431 |
if (FAILED (hr)) { |
441 |
dsound_logerr (hr, "Can not get capture buffer status\n");
|
|
432 |
dsound_logerr (hr, "Could not get capture buffer status\n");
|
|
442 | 433 |
return -1; |
443 | 434 |
} |
444 | 435 |
|
... | ... | |
520 | 511 |
if (s->dsound_primary_buffer) { |
521 | 512 |
hr = IDirectSoundBuffer_Release (s->dsound_primary_buffer); |
522 | 513 |
if (FAILED (hr)) { |
523 |
dsound_logerr (hr, "Can not release primary buffer\n");
|
|
514 |
dsound_logerr (hr, "Could not release primary buffer\n");
|
|
524 | 515 |
} |
525 | 516 |
s->dsound_primary_buffer = NULL; |
526 | 517 |
} |
... | ... | |
542 | 533 |
); |
543 | 534 |
|
544 | 535 |
if (FAILED (hr)) { |
545 |
dsound_logerr (hr, "Can not set cooperative level for window %p\n",
|
|
536 |
dsound_logerr (hr, "Could not set cooperative level for window %p\n",
|
|
546 | 537 |
hwnd); |
547 | 538 |
return -1; |
548 | 539 |
} |
... | ... | |
551 | 542 |
return 0; |
552 | 543 |
} |
553 | 544 |
|
554 |
err = waveformat_from_full_fmt (&wfx, &conf.full_fmt);
|
|
545 |
err = waveformat_from_audio_settings (&wfx, &conf.settings);
|
|
555 | 546 |
if (err) { |
556 | 547 |
return -1; |
557 | 548 |
} |
... | ... | |
569 | 560 |
NULL |
570 | 561 |
); |
571 | 562 |
if (FAILED (hr)) { |
572 |
dsound_logerr (hr, "Can not create primary playback buffer\n");
|
|
563 |
dsound_logerr (hr, "Could not create primary playback buffer\n");
|
|
573 | 564 |
return -1; |
574 | 565 |
} |
575 | 566 |
|
576 | 567 |
hr = IDirectSoundBuffer_SetFormat (s->dsound_primary_buffer, &wfx); |
577 | 568 |
if (FAILED (hr)) { |
578 |
dsound_logerr (hr, "Can not set primary playback buffer format\n");
|
|
569 |
dsound_logerr (hr, "Could not set primary playback buffer format\n");
|
|
579 | 570 |
} |
580 | 571 |
|
581 | 572 |
hr = IDirectSoundBuffer_GetFormat ( |
... | ... | |
585 | 576 |
NULL |
586 | 577 |
); |
587 | 578 |
if (FAILED (hr)) { |
588 |
dsound_logerr (hr, "Can not get primary playback buffer format\n");
|
|
579 |
dsound_logerr (hr, "Could not get primary playback buffer format\n");
|
|
589 | 580 |
goto fail0; |
590 | 581 |
} |
591 | 582 |
|
... | ... | |
594 | 585 |
print_wave_format (&wfx); |
595 | 586 |
#endif |
596 | 587 |
|
597 |
err = waveformat_to_full_fmt (&wfx, &s->fmt);
|
|
588 |
err = waveformat_to_audio_settings (&wfx, &s->settings);
|
|
598 | 589 |
if (err) { |
599 | 590 |
goto fail0; |
600 | 591 |
} |
... | ... | |
625 | 616 |
} |
626 | 617 |
|
627 | 618 |
if (status & DSBSTATUS_PLAYING) { |
628 |
dolog ("warning: voice is already playing\n");
|
|
619 |
dolog ("warning: Voice is already playing\n");
|
|
629 | 620 |
return 0; |
630 | 621 |
} |
631 | 622 |
|
... | ... | |
633 | 624 |
|
634 | 625 |
hr = IDirectSoundBuffer_Play (dsb, 0, 0, DSBPLAY_LOOPING); |
635 | 626 |
if (FAILED (hr)) { |
636 |
dsound_logerr (hr, "Can not start playing buffer\n");
|
|
627 |
dsound_logerr (hr, "Could not start playing buffer\n");
|
|
637 | 628 |
return -1; |
638 | 629 |
} |
639 | 630 |
break; |
... | ... | |
646 | 637 |
if (status & DSBSTATUS_PLAYING) { |
647 | 638 |
hr = IDirectSoundBuffer_Stop (dsb); |
648 | 639 |
if (FAILED (hr)) { |
649 |
dsound_logerr (hr, "Can not stop playing buffer\n");
|
|
640 |
dsound_logerr (hr, "Could not stop playing buffer\n");
|
|
650 | 641 |
return -1; |
651 | 642 |
} |
652 | 643 |
} |
653 | 644 |
else { |
654 |
dolog ("warning: voice is not playing\n");
|
|
645 |
dolog ("warning: Voice is not playing\n");
|
|
655 | 646 |
} |
656 | 647 |
break; |
657 | 648 |
} |
... | ... | |
675 | 666 |
DWORD decr; |
676 | 667 |
DWORD wpos, ppos, old_pos; |
677 | 668 |
LPVOID p1, p2; |
669 |
int bufsize; |
|
678 | 670 |
|
679 | 671 |
if (!dsb) { |
680 | 672 |
dolog ("Attempt to run empty with playback buffer\n"); |
... | ... | |
682 | 674 |
} |
683 | 675 |
|
684 | 676 |
hwshift = hw->info.shift; |
677 |
bufsize = hw->samples << hwshift; |
|
685 | 678 |
|
686 | 679 |
live = audio_pcm_hw_get_live_out (hw); |
687 | 680 |
|
... | ... | |
691 | 684 |
ds->first_time ? &wpos : NULL |
692 | 685 |
); |
693 | 686 |
if (FAILED (hr)) { |
694 |
dsound_logerr (hr, "Can not get playback buffer position\n");
|
|
687 |
dsound_logerr (hr, "Could not get playback buffer position\n");
|
|
695 | 688 |
return 0; |
696 | 689 |
} |
697 | 690 |
|
... | ... | |
699 | 692 |
|
700 | 693 |
if (ds->first_time) { |
701 | 694 |
if (conf.latency_millis) { |
702 |
DWORD cur_blat = audio_ring_dist (wpos, ppos, hw->bufsize);
|
|
695 |
DWORD cur_blat; |
|
703 | 696 |
|
697 |
cur_blat = audio_ring_dist (wpos, ppos, bufsize); |
|
704 | 698 |
ds->first_time = 0; |
705 | 699 |
old_pos = wpos; |
706 | 700 |
old_pos += |
707 | 701 |
millis_to_bytes (&hw->info, conf.latency_millis) - cur_blat; |
708 |
old_pos %= hw->bufsize;
|
|
702 |
old_pos %= bufsize; |
|
709 | 703 |
old_pos &= ~hw->info.align; |
710 | 704 |
} |
711 | 705 |
else { |
... | ... | |
734 | 728 |
len = ppos - old_pos; |
735 | 729 |
} |
736 | 730 |
else { |
737 |
if ((old_pos > ppos) && ((old_pos + len) > (ppos + hw->bufsize))) {
|
|
738 |
len = hw->bufsize - old_pos + ppos;
|
|
731 |
if ((old_pos > ppos) && ((old_pos + len) > (ppos + bufsize))) { |
|
732 |
len = bufsize - old_pos + ppos; |
|
739 | 733 |
} |
740 | 734 |
} |
741 | 735 |
|
742 |
if (audio_bug (AUDIO_FUNC, len < 0 || len > hw->bufsize)) {
|
|
743 |
dolog ("len=%d hw->bufsize=%d old_pos=%ld ppos=%ld\n",
|
|
744 |
len, hw->bufsize, old_pos, ppos);
|
|
736 |
if (audio_bug (AUDIO_FUNC, len < 0 || len > bufsize)) { |
|
737 |
dolog ("len=%d bufsize=%d old_pos=%ld ppos=%ld\n", |
|
738 |
len, bufsize, old_pos, ppos); |
|
745 | 739 |
return 0; |
746 | 740 |
} |
747 | 741 |
|
... | ... | |
779 | 773 |
} |
780 | 774 |
|
781 | 775 |
dsound_unlock_out (dsb, p1, p2, blen1, blen2); |
782 |
ds->old_pos = (old_pos + (decr << hwshift)) % hw->bufsize;
|
|
776 |
ds->old_pos = (old_pos + (decr << hwshift)) % bufsize; |
|
783 | 777 |
|
784 | 778 |
#ifdef DEBUG_DSOUND |
785 | 779 |
ds->mixed += decr << hwshift; |
... | ... | |
812 | 806 |
} |
813 | 807 |
|
814 | 808 |
if (status & DSCBSTATUS_CAPTURING) { |
815 |
dolog ("warning: voice is already capturing\n");
|
|
809 |
dolog ("warning: Voice is already capturing\n");
|
|
816 | 810 |
return 0; |
817 | 811 |
} |
818 | 812 |
|
... | ... | |
820 | 814 |
|
821 | 815 |
hr = IDirectSoundCaptureBuffer_Start (dscb, DSCBSTART_LOOPING); |
822 | 816 |
if (FAILED (hr)) { |
823 |
dsound_logerr (hr, "Can not start capturing\n");
|
|
817 |
dsound_logerr (hr, "Could not start capturing\n");
|
|
824 | 818 |
return -1; |
825 | 819 |
} |
826 | 820 |
break; |
... | ... | |
833 | 827 |
if (status & DSCBSTATUS_CAPTURING) { |
834 | 828 |
hr = IDirectSoundCaptureBuffer_Stop (dscb); |
835 | 829 |
if (FAILED (hr)) { |
836 |
dsound_logerr (hr, "Can not stop capturing\n");
|
|
830 |
dsound_logerr (hr, "Could not stop capturing\n");
|
|
837 | 831 |
return -1; |
838 | 832 |
} |
839 | 833 |
} |
840 | 834 |
else { |
841 |
dolog ("warning: voice is not capturing\n");
|
|
835 |
dolog ("warning: Voice is not capturing\n");
|
|
842 | 836 |
} |
843 | 837 |
break; |
844 | 838 |
} |
... | ... | |
883 | 877 |
ds->first_time ? &rpos : NULL |
884 | 878 |
); |
885 | 879 |
if (FAILED (hr)) { |
886 |
dsound_logerr (hr, "Can not get capture buffer position\n");
|
|
880 |
dsound_logerr (hr, "Could not get capture buffer position\n");
|
|
887 | 881 |
return 0; |
888 | 882 |
} |
889 | 883 |
|
890 | 884 |
if (ds->first_time) { |
891 | 885 |
ds->first_time = 0; |
892 | 886 |
if (rpos & hw->info.align) { |
893 |
ldebug ("warning: misaligned capture read position %ld(%d)\n",
|
|
887 |
ldebug ("warning: Misaligned capture read position %ld(%d)\n",
|
|
894 | 888 |
rpos, hw->info.align); |
895 | 889 |
} |
896 | 890 |
hw->wpos = rpos >> hwshift; |
897 | 891 |
} |
898 | 892 |
|
899 | 893 |
if (cpos & hw->info.align) { |
900 |
ldebug ("warning: misaligned capture position %ld(%d)\n",
|
|
894 |
ldebug ("warning: Misaligned capture position %ld(%d)\n",
|
|
901 | 895 |
cpos, hw->info.align); |
902 | 896 |
} |
903 | 897 |
cpos >>= hwshift; |
... | ... | |
951 | 945 |
|
952 | 946 |
hr = IDirectSound_Release (s->dsound); |
953 | 947 |
if (FAILED (hr)) { |
954 |
dsound_logerr (hr, "Can not release DirectSound\n");
|
|
948 |
dsound_logerr (hr, "Could not release DirectSound\n");
|
|
955 | 949 |
} |
956 | 950 |
s->dsound = NULL; |
957 | 951 |
|
... | ... | |
961 | 955 |
|
962 | 956 |
hr = IDirectSoundCapture_Release (s->dsound_capture); |
963 | 957 |
if (FAILED (hr)) { |
964 |
dsound_logerr (hr, "Can not release DirectSoundCapture\n");
|
|
958 |
dsound_logerr (hr, "Could not release DirectSoundCapture\n");
|
|
965 | 959 |
} |
966 | 960 |
s->dsound_capture = NULL; |
967 | 961 |
} |
... | ... | |
974 | 968 |
|
975 | 969 |
hr = CoInitialize (NULL); |
976 | 970 |
if (FAILED (hr)) { |
977 |
dsound_logerr (hr, "Can not initialize COM\n");
|
|
971 |
dsound_logerr (hr, "Could not initialize COM\n");
|
|
978 | 972 |
return NULL; |
979 | 973 |
} |
980 | 974 |
|
... | ... | |
986 | 980 |
(void **) &s->dsound |
987 | 981 |
); |
988 | 982 |
if (FAILED (hr)) { |
989 |
dsound_logerr (hr, "Can not create DirectSound instance\n");
|
|
983 |
dsound_logerr (hr, "Could not create DirectSound instance\n");
|
|
990 | 984 |
return NULL; |
991 | 985 |
} |
992 | 986 |
|
993 | 987 |
hr = IDirectSound_Initialize (s->dsound, NULL); |
994 | 988 |
if (FAILED (hr)) { |
995 |
dsound_logerr (hr, "Can not initialize DirectSound\n");
|
|
989 |
dsound_logerr (hr, "Could not initialize DirectSound\n");
|
|
996 | 990 |
return NULL; |
997 | 991 |
} |
998 | 992 |
|
... | ... | |
1004 | 998 |
(void **) &s->dsound_capture |
1005 | 999 |
); |
1006 | 1000 |
if (FAILED (hr)) { |
1007 |
dsound_logerr (hr, "Can not create DirectSoundCapture instance\n");
|
|
1001 |
dsound_logerr (hr, "Could not create DirectSoundCapture instance\n");
|
|
1008 | 1002 |
} |
1009 | 1003 |
else { |
1010 | 1004 |
hr = IDirectSoundCapture_Initialize (s->dsound_capture, NULL); |
1011 | 1005 |
if (FAILED (hr)) { |
1012 |
dsound_logerr (hr, "Can not initialize DirectSoundCapture\n");
|
|
1006 |
dsound_logerr (hr, "Could not initialize DirectSoundCapture\n");
|
|
1013 | 1007 |
|
1014 | 1008 |
hr = IDirectSoundCapture_Release (s->dsound_capture); |
1015 | 1009 |
if (FAILED (hr)) { |
1016 |
dsound_logerr (hr, "Can not release DirectSoundCapture\n");
|
|
1010 |
dsound_logerr (hr, "Could not release DirectSoundCapture\n");
|
|
1017 | 1011 |
} |
1018 | 1012 |
s->dsound_capture = NULL; |
1019 | 1013 |
} |
... | ... | |
1039 | 1033 |
"Set the parameters of primary buffer", NULL, 0}, |
1040 | 1034 |
{"LATENCY_MILLIS", AUD_OPT_INT, &conf.latency_millis, |
1041 | 1035 |
"(undocumented)", NULL, 0}, |
1042 |
{"PRIMARY_FREQ", AUD_OPT_INT, &conf.full_fmt.freq,
|
|
1036 |
{"PRIMARY_FREQ", AUD_OPT_INT, &conf.settings.freq,
|
|
1043 | 1037 |
"Primary buffer frequency", NULL, 0}, |
1044 |
{"PRIMARY_CHANNELS", AUD_OPT_INT, &conf.full_fmt.nchannels,
|
|
1038 |
{"PRIMARY_CHANNELS", AUD_OPT_INT, &conf.settings.nchannels,
|
|
1045 | 1039 |
"Primary buffer number of channels (1 - mono, 2 - stereo)", NULL, 0}, |
1046 |
{"PRIMARY_FMT", AUD_OPT_FMT, &conf.full_fmt.fmt,
|
|
1040 |
{"PRIMARY_FMT", AUD_OPT_FMT, &conf.settings.fmt,
|
|
1047 | 1041 |
"Primary buffer format", NULL, 0}, |
1048 | 1042 |
{"BUFSIZE_OUT", AUD_OPT_INT, &conf.bufsize_out, |
1049 | 1043 |
"(undocumented)", NULL, 0}, |
Also available in: Unified diff