- Timestamp:
- Nov 24, 2014 7:35:57 PM (10 years ago)
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/dsound_template.h
r32936 r53392 1 /* $Id$ */ 2 1 3 /* 4 * Copyright (C) 2014 Oracle Corporation 5 * 6 * This file is part of VirtualBox Open Source Edition (OSE), as 7 * available from http://www.virtualbox.org. This file is free software; 8 * you can redistribute it and/or modify it under the terms of the GNU 9 * General Public License (GPL) as published by the Free Software 10 * Foundation, in version 2 as it comes in the "COPYING" file of the 11 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 12 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 13 * -------------------------------------------------------------------- 14 * 15 * This code is based on: audio.h 16 * 2 17 * QEMU DirectSound audio driver header 3 18 * … … 146 161 #ifdef DSBTYPE_IN 147 162 static void dsound_fini_in (HWVoiceIn *hw) 163 { 164 DSoundVoiceIn *ds = (DSoundVoiceIn *) hw; 165 dsoundCaptureClose (ds); 166 ds->last_read_pos = 0; 167 ds->capture_buffer_size = 0; 168 memset (&ds->as, 0, sizeof(ds->as)); 169 } 148 170 #else 149 171 static void dsound_fini_out (HWVoiceOut *hw) 150 #endif151 172 { 152 173 HRESULT hr; 153 #ifdef DSBTYPE_IN154 DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;155 #else156 174 DSoundVoiceOut *ds = (DSoundVoiceOut *) hw; 157 #endif158 175 159 176 if (ds->FIELD) { … … 170 187 } 171 188 } 189 #endif 172 190 173 191 #ifdef DSBTYPE_IN 174 192 static int dsound_init_in (HWVoiceIn *hw, audsettings_t *as) 193 { 194 DSoundVoiceIn *ds = (DSoundVoiceIn *) hw; 195 196 ds->last_read_pos = 0; 197 ds->capture_buffer_size = 0; 198 ds->dsound_capture_buffer = NULL; 199 ds->as = *as; 200 201 /* Init default settings. */ 202 audio_pcm_init_info (&hw->info, &ds->as); 203 hw->samples = conf.bufsize_in >> hw->info.shift; 204 205 /* Try to open capture in case the device is already there. */ 206 dsoundCaptureOpen (ds); 207 208 return 0; 209 } 175 210 #else 176 211 static int dsound_init_out (HWVoiceOut *hw, audsettings_t *as) 177 #endif178 212 { 179 213 int err; … … 182 216 WAVEFORMATEX wfx; 183 217 audsettings_t obt_as; 184 #ifdef DSBTYPE_IN185 const char *typ = "ADC";186 DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;187 DSCBUFFERDESC bd;188 DSCBCAPS bc;189 #else190 218 const char *typ = "DAC"; 191 219 DSoundVoiceOut *ds = (DSoundVoiceOut *) hw; 192 220 DSBUFFERDESC bd; 193 221 DSBCAPS bc; 194 #endif195 222 196 223 err = waveformat_from_audio_settings (&wfx, as); … … 199 226 } 200 227 201 #ifdef DSBTYPE_IN202 if (!s->dsound_capture)203 return -1;204 #endif205 206 228 memset (&bd, 0, sizeof (bd)); 207 229 bd.dwSize = sizeof (bd); 208 230 bd.lpwfxFormat = &wfx; 209 #ifdef DSBTYPE_IN210 bd.dwBufferBytes = conf.bufsize_in;211 hr = IDirectSoundCapture_CreateCaptureBuffer (212 s->dsound_capture,213 &bd,214 &ds->dsound_capture_buffer,215 NULL216 );217 #else218 231 bd.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2; 219 232 bd.dwBufferBytes = conf.bufsize_out; … … 224 237 NULL 225 238 ); 226 #endif227 239 228 240 if (FAILED (hr)) { … … 285 297 return -1; 286 298 } 299 #endif 287 300 288 301 #undef NAME -
trunk/src/VBox/Devices/Audio/dsoundaudio.c
r53361 r53392 1 /* $Id$ */ 2 /** @file 3 * DirectSound Windows Host Audio Backend. 4 */ 5 1 6 /* 7 * Copyright (C) 2014 Oracle Corporation 8 * 9 * This file is part of VirtualBox Open Source Edition (OSE), as 10 * available from http://www.virtualbox.org. This file is free software; 11 * you can redistribute it and/or modify it under the terms of the GNU 12 * General Public License (GPL) as published by the Free Software 13 * Foundation, in version 2 as it comes in the "COPYING" file of the 14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 16 * -------------------------------------------------------------------- 17 * 18 * This code is based on: dsoundaudio.c 19 * 2 20 * QEMU DirectSound audio driver 3 21 * … … 45 63 46 64 /* #define DEBUG_DSOUND */ 65 66 #define DSLOGF(a) do { LogRel2(a); } while(0) 67 #define DSLOGREL(a) \ 68 do { \ 69 static int8_t scLogged = 0; \ 70 if (scLogged < 8) { \ 71 ++scLogged; \ 72 LogRel(a); \ 73 } \ 74 else { \ 75 DSLOGF(a); \ 76 } \ 77 } while (0) 47 78 48 79 static struct { … … 79 110 LPDIRECTSOUNDBUFFER dsound_primary_buffer; 80 111 audsettings_t settings; 112 LPCGUID devguidp; 113 LPCGUID devguidp_capture; 81 114 } dsound; 82 115 … … 97 130 typedef struct { 98 131 HWVoiceIn hw; 99 int first_time; 132 int last_read_pos; 133 int capture_buffer_size; 100 134 LPDIRECTSOUNDCAPTUREBUFFER dsound_capture_buffer; 135 audsettings_t as; 136 HRESULT hr_last_run_in; 101 137 } DSoundVoiceIn; 102 138 … … 408 444 409 445 return 0; 446 } 447 448 static void dsoundCaptureInterfaceRelease (dsound *s) 449 { 450 if (s->dsound_capture) { 451 HRESULT hr = IDirectSoundCapture_Release (s->dsound_capture); 452 if (FAILED (hr)) { 453 DSLOGF(("DSound: DirectSoundCapture release %Rhrc\n", hr)); 454 } 455 s->dsound_capture = NULL; 456 } 457 } 458 459 static int dsoundCaptureInterfaceCreate (dsound *s) 460 { 461 HRESULT hr; 462 463 if (s->dsound_capture != NULL) { 464 DSLOGF(("DSound: DirectSoundCapture instance already exists\n")); 465 return -1; 466 } 467 468 hr = CoCreateInstance (&CLSID_DirectSoundCapture, NULL, CLSCTX_ALL, 469 &IID_IDirectSoundCapture, (void **) &s->dsound_capture); 470 if (FAILED (hr)) { 471 DSLOGREL(("DSound: DirectSoundCapture create instance %Rhrc\n", hr)); 472 } 473 else { 474 hr = IDirectSoundCapture_Initialize (s->dsound_capture, s->devguidp_capture); 475 if (FAILED (hr)) { 476 DSLOGREL(("DSound: DirectSoundCapture initialize %Rhrc\n", hr)); 477 dsoundCaptureInterfaceRelease (s); 478 } 479 } 480 481 return SUCCEEDED (hr)? 0: -1; 482 } 483 484 static void dsoundCaptureClose (DSoundVoiceIn *ds) 485 { 486 dsound *s = &glob_dsound; 487 488 DSLOGF(("DSound: capture close %p buffer %p\n", ds, ds->dsound_capture_buffer)); 489 490 if (ds->dsound_capture_buffer) { 491 HRESULT hr = IDirectSoundCaptureBuffer_Stop (ds->dsound_capture_buffer); 492 if (FAILED (hr)) { 493 DSLOGF(("DSound: close capture buffer stop %Rhrc\n", hr)); 494 } 495 496 hr = IDirectSoundCaptureBuffer_Release (ds->dsound_capture_buffer); 497 if (FAILED (hr)) { 498 DSLOGF(("DSound: close capture buffer release %Rhrc\n", hr)); 499 } 500 ds->dsound_capture_buffer = NULL; 501 } 502 503 dsoundCaptureInterfaceRelease (s); 504 } 505 506 static int dsoundCaptureOpen (DSoundVoiceIn *ds) 507 { 508 dsound *s = &glob_dsound; 509 510 int err; 511 HRESULT hr; 512 WAVEFORMATEX wfx; 513 DSCBUFFERDESC bd; 514 DSCBCAPS bc; 515 DWORD cpos; 516 517 DSLOGF(("DSound: capture open %p size %d samples, freq %d, chan %d, bits %d, sign %d\n", 518 ds, 519 ds->hw.samples, 520 ds->hw.info.freq, 521 ds->hw.info.nchannels, 522 ds->hw.info.bits, 523 ds->hw.info.sign)); 524 525 if (ds->dsound_capture_buffer != NULL) { 526 /* Should not happen but be forgiving. */ 527 DSLOGREL(("DSound: DirectSoundCaptureBuffer already exists\n")); 528 dsoundCaptureClose (ds); 529 } 530 531 err = waveformat_from_audio_settings (&wfx, &ds->as); 532 if (err) { 533 return err; 534 } 535 536 err = dsoundCaptureInterfaceCreate (s); 537 if (err) { 538 return err; 539 } 540 541 memset (&bd, 0, sizeof (bd)); 542 bd.dwSize = sizeof (bd); 543 bd.lpwfxFormat = &wfx; 544 bd.dwBufferBytes = ds->hw.samples << ds->hw.info.shift; 545 hr = IDirectSoundCapture_CreateCaptureBuffer (s->dsound_capture, 546 &bd, &ds->dsound_capture_buffer, NULL); 547 548 if (FAILED (hr)) { 549 DSLOGREL(("DSound: create capture buffer %Rhrc\n", hr)); 550 ds->dsound_capture_buffer = NULL; 551 goto fail0; 552 } 553 554 /* Query the actual parameters. */ 555 556 hr = IDirectSoundCaptureBuffer_GetCurrentPosition (ds->dsound_capture_buffer, &cpos, NULL); 557 if (FAILED (hr)) { 558 cpos = 0; 559 DSLOGF(("DSound: open GetCurrentPosition %Rhrc\n", hr)); 560 } 561 562 memset (&wfx, 0, sizeof (wfx)); 563 hr = IDirectSoundCaptureBuffer_GetFormat (ds->dsound_capture_buffer, &wfx, sizeof (wfx), NULL); 564 if (FAILED (hr)) { 565 DSLOGREL(("DSound: capture buffer GetFormat %Rhrc\n", hr)); 566 goto fail0; 567 } 568 569 memset (&bc, 0, sizeof (bc)); 570 bc.dwSize = sizeof (bc); 571 hr = IDirectSoundCaptureBuffer_GetCaps (ds->dsound_capture_buffer, &bc); 572 if (FAILED (hr)) { 573 DSLOGREL(("DSound: capture buffer GetCaps %Rhrc\n", hr)); 574 goto fail0; 575 } 576 577 DSLOGF(("DSound: capture buffer format: size %d bytes\n" 578 " tag = %d\n" 579 " nChannels = %d\n" 580 " nSamplesPerSec = %d\n" 581 " nAvgBytesPerSec = %d\n" 582 " nBlockAlign = %d\n" 583 " wBitsPerSample = %d\n" 584 " cbSize = %d\n", 585 bc.dwBufferBytes, 586 wfx.wFormatTag, 587 wfx.nChannels, 588 wfx.nSamplesPerSec, 589 wfx.nAvgBytesPerSec, 590 wfx.nBlockAlign, 591 wfx.wBitsPerSample, 592 wfx.cbSize)); 593 594 if (bc.dwBufferBytes & ds->hw.info.align) { 595 DSLOGREL(("DSound: GetCaps returned misaligned buffer size %ld, alignment %d\n", 596 bc.dwBufferBytes, ds->hw.info.align + 1)); 597 } 598 599 if (ds->hw.samples != 0 && ds->hw.samples != (bc.dwBufferBytes >> ds->hw.info.shift)) { 600 DSLOGREL(("DSound: buffer size mismatch dsound %d, hw %d bytes\n", 601 bc.dwBufferBytes, ds->hw.samples << ds->hw.info.shift)); 602 } 603 604 /* Initial state: reading at the initial capture position. */ 605 ds->hw.wpos = 0; 606 ds->last_read_pos = cpos >> ds->hw.info.shift; 607 ds->capture_buffer_size = bc.dwBufferBytes >> ds->hw.info.shift; 608 DSLOGF(("DSound: open last_read_pos %d, capture_buffer_size %d\n", ds->last_read_pos, ds->capture_buffer_size)); 609 610 ds->hr_last_run_in = S_OK; 611 612 return 0; 613 614 fail0: 615 dsoundCaptureClose (ds); 616 return -1; 617 } 618 619 static void dsoundCaptureStop (DSoundVoiceIn *ds) 620 { 621 if (ds->dsound_capture_buffer) { 622 HRESULT hr = IDirectSoundCaptureBuffer_Stop (ds->dsound_capture_buffer); 623 if (FAILED (hr)) { 624 DSLOGF(("DSound: stop capture buffer %Rhrc\n", hr)); 625 } 626 } 627 } 628 629 static int dsoundCaptureStart (DSoundVoiceIn *ds) 630 { 631 HRESULT hr; 632 DWORD status; 633 634 if (ds->dsound_capture_buffer != NULL) { 635 hr = IDirectSoundCaptureBuffer_GetStatus (ds->dsound_capture_buffer, &status); 636 if (FAILED (hr)) { 637 DSLOGF(("DSound: start GetStatus %Rhrc\n", hr)); 638 } 639 else { 640 if (status & DSCBSTATUS_CAPTURING) { 641 DSLOGF(("DSound: already capturing\n")); 642 } 643 else { 644 hr = IDirectSoundCaptureBuffer_Start (ds->dsound_capture_buffer, DSCBSTART_LOOPING); 645 if (FAILED (hr)) { 646 DSLOGREL(("DSound: start %Rhrc\n", hr)); 647 } 648 } 649 } 650 } 651 else { 652 hr = E_FAIL; 653 } 654 655 return SUCCEEDED (hr)? 0: -1; 410 656 } 411 657 … … 833 1079 static int dsound_ctl_in (HWVoiceIn *hw, int cmd, ...) 834 1080 { 835 HRESULT hr;836 DWORD status;837 1081 DSoundVoiceIn *ds = (DSoundVoiceIn *) hw; 838 LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer;839 840 if (!dscb) {841 dolog ("Attempt to control capture voice without a buffer\n");842 return -1;843 }844 1082 845 1083 switch (cmd) { 846 1084 case VOICE_ENABLE: 847 if (dsound_get_status_in (dscb, &status)) { 848 return -1; 849 } 850 851 if (status & DSCBSTATUS_CAPTURING) { 852 dolog ("warning: Voice is already capturing\n"); 853 return 0; 854 } 855 856 /* clear ?? */ 857 858 hr = IDirectSoundCaptureBuffer_Start (dscb, DSCBSTART_LOOPING); 859 if (FAILED (hr)) { 860 dsound_logerr (hr, "Could not start capturing\n"); 861 return -1; 862 } 863 break; 864 865 case VOICE_DISABLE: 866 if (dsound_get_status_in (dscb, &status)) { 867 return -1; 868 } 869 870 if (status & DSCBSTATUS_CAPTURING) { 871 hr = IDirectSoundCaptureBuffer_Stop (dscb); 872 if (FAILED (hr)) { 873 dsound_logerr (hr, "Could not stop capturing\n"); 1085 /* Try to start capture. If it fails, then reopen and try again. */ 1086 if (dsoundCaptureStart (ds)) { 1087 dsoundCaptureClose (ds); 1088 dsoundCaptureOpen (ds); 1089 1090 if (dsoundCaptureStart (ds)) { 874 1091 return -1; 875 1092 } 876 1093 } 877 else { 878 dolog ("warning: Voice is not capturing\n"); 879 } 1094 break; 1095 1096 case VOICE_DISABLE: 1097 dsoundCaptureStop (ds); 880 1098 break; 881 1099 } … … 895 1113 LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer; 896 1114 int live, len, dead; 1115 int ltmp; 897 1116 DWORD blen1, blen2; 898 DWORDlen1, len2;899 DWORDdecr;900 DWORD cpos , rpos;1117 int len1, len2; 1118 int decr; 1119 DWORD cpos; 901 1120 LPVOID p1, p2; 902 1121 int hwshift; 903 1122 904 1123 if (!dscb) { 905 dolog ("Attempt to run without capture buffer\n");1124 DSLOGF(("DSound: run_in no capture buffer\n")); 906 1125 return 0; 907 1126 } … … 918 1137 dscb, 919 1138 &cpos, 920 ds->first_time ? &rpos :NULL1139 NULL 921 1140 ); 922 1141 if (FAILED (hr)) { 923 dsound_logerr (hr, "Could not get capture buffer position\n"); 1142 if (hr != ds->hr_last_run_in) { 1143 DSLOGREL(("DSound: run_in GetCurrentPosition %Rhrc\n", hr)); 1144 } 1145 ds->hr_last_run_in = hr; 924 1146 return 0; 925 1147 } 926 927 if (ds->first_time) { 928 ds->first_time = 0; 929 if (rpos & hw->info.align) { 930 ldebug ("warning: Misaligned capture read position %ld(%d)\n", 931 rpos, hw->info.align); 932 } 933 hw->wpos = rpos >> hwshift; 934 } 1148 ds->hr_last_run_in = hr; 935 1149 936 1150 if (cpos & hw->info.align) { 937 ldebug ("warning: Misaligned capture position %ld(%d)\n",938 cpos, hw->info.align);939 } 1151 DSLOGF(("DSound: run_in misaligned capture position %ld(%d)\n", cpos, hw->info.align)); 1152 } 1153 940 1154 cpos >>= hwshift; 941 1155 942 len = audio_ring_dist (cpos, hw->wpos, hw->samples); 1156 /* Number of samples available in the capture buffer. */ 1157 len = audio_ring_dist (cpos, ds->last_read_pos, ds->capture_buffer_size); 943 1158 if (!len) { 944 1159 return 0; … … 949 1164 dscb, 950 1165 &hw->info, 951 hw->wpos << hwshift,1166 ds->last_read_pos << hwshift, 952 1167 len << hwshift, 953 1168 &p1, … … 965 1180 decr = len1 + len2; 966 1181 967 #ifndef VBOX968 1182 if (p1 && len1) { 969 hw->conv (hw->conv_buf + hw->wpos, p1, len1, &nominal_volume); 1183 ltmp = audio_MIN(len1, hw->samples - hw->wpos); 1184 hw->conv (hw->conv_buf + hw->wpos, p1, ltmp, &pcm_in_volume); 1185 if (len1 > ltmp) { 1186 hw->conv (hw->conv_buf, (void *)((uintptr_t)p1 + (ltmp << hwshift)), len1 - ltmp, &pcm_in_volume); 1187 } 1188 hw->wpos = (hw->wpos + len1) % hw->samples; 970 1189 } 971 1190 972 1191 if (p2 && len2) { 973 hw->conv (hw->conv_buf, p2, len2, &nominal_volume); 974 } 975 #else 976 if (p1 && len1) { 977 hw->conv (hw->conv_buf + hw->wpos, p1, len1, &pcm_in_volume); 978 } 979 980 if (p2 && len2) { 981 hw->conv (hw->conv_buf, p2, len2, &pcm_in_volume); 982 } 983 #endif 1192 ltmp = audio_MIN(len2, hw->samples - hw->wpos); 1193 hw->conv (hw->conv_buf + hw->wpos, p2, ltmp, &pcm_in_volume); 1194 if (len2 > ltmp) { 1195 hw->conv (hw->conv_buf, (void *)((uintptr_t)p2 + (ltmp << hwshift)), len2 - ltmp, &pcm_in_volume); 1196 } 1197 hw->wpos = (hw->wpos + len2) % hw->samples; 1198 } 984 1199 985 1200 dsound_unlock_in (dscb, p1, p2, blen1, blen2); 986 hw->wpos = (hw->wpos + decr) % hw->samples;1201 ds->last_read_pos = (ds->last_read_pos + decr) % ds->capture_buffer_size; 987 1202 return decr; 988 1203 } … … 1081 1296 } 1082 1297 1083 hr = CoCreateInstance ( 1084 &CLSID_DirectSoundCapture, 1085 NULL, 1086 CLSCTX_ALL, 1087 &IID_IDirectSoundCapture, 1088 (void **) &s->dsound_capture 1089 ); 1090 if (FAILED (hr)) { 1091 #ifndef VBOX 1092 dsound_logerr (hr, "Could not create DirectSoundCapture instance\n"); 1093 #else 1094 LogRel(("DSound: Could not create DirectSoundCapture instance\n")); 1095 dsound_log_hresult(hr); 1096 #endif 1097 } 1098 else { 1099 if (conf.device_guid_in) { 1100 hr = RTUuidFromStr(&devguid, conf.device_guid_in); 1101 if (FAILED (hr)) { 1102 LogRel(("DSound: Could not parse DirectSound input device GUID\n")); 1103 } 1104 devguidp = (LPCGUID)&devguid; 1105 } else { 1106 devguidp = NULL; 1107 } 1108 hr = IDirectSoundCapture_Initialize (s->dsound_capture, devguidp); 1109 if (FAILED (hr)) { 1110 #ifndef VBOX 1111 dsound_logerr (hr, "Could not initialize DirectSoundCapture\n"); 1112 #else 1113 LogRel(("DSound: Could not initialize DirectSoundCapture\n")); 1114 dsound_log_hresult(hr); 1115 #endif 1116 1117 hr = IDirectSoundCapture_Release (s->dsound_capture); 1118 if (FAILED (hr)) { 1119 dsound_logerr (hr, 1120 "Could not release DirectSoundCapture\n"); 1121 } 1122 s->dsound_capture = NULL; 1123 } 1298 if (conf.device_guid_in) { 1299 int rc = RTUuidFromStr(&devguid, conf.device_guid_in); 1300 if (RT_FAILURE(rc)) { 1301 LogRel(("DSound: Could not parse DirectSound input device GUID\n")); 1302 } 1303 s->devguidp = (LPCGUID)&devguid; 1304 } else { 1305 s->devguidp = NULL; 1124 1306 } 1125 1307
Note:
See TracChangeset
for help on using the changeset viewer.