Changeset 58983 in vbox for trunk/src/VBox/Devices/Audio
- Timestamp:
- Dec 4, 2015 2:15:30 PM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 104507
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
r58600 r58983 33 33 34 34 #include "VBoxDD.h" 35 36 #include "AudioMixBuffer.h" 35 37 #include "AudioMixer.h" 36 38 … … 276 278 AC97BusMasterRegs bm_regs[3]; 277 279 uint8_t mixer_data[256]; 280 #ifndef VBOX_WITH_AUDIO_CALLBACKS 278 281 /** The emulation timer for handling the attached 279 282 * LUN drivers. */ 280 283 PTMTIMERR3 pTimer; 281 284 /** Timer ticks for handling the LUN drivers. */ 282 uint64_t uTicks; 285 uint64_t uTimerTicks; 286 /** Timestamp (delta) since last timer call. */ 287 uint64_t uTimerTS; 288 #endif 283 289 #ifdef VBOX_WITH_STATISTICS 284 290 # if HC_ARCH_BITS == 32 … … 365 371 #define GET_BM(a_idx) ( ((a_idx) >> 4) & 3 ) 366 372 373 #ifndef VBOX_WITH_AUDIO_CALLBACKS 367 374 static DECLCALLBACK(void) ichac97Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser); 375 #endif 368 376 static int ichac97TransferAudio(PAC97STATE pThis, int index, uint32_t cbElapsed); 369 377 … … 1005 1013 while (cbToWrite) 1006 1014 { 1007 uint32_t cbWrittenMin = UINT32_MAX;1008 1009 1015 cbToRead = RT_MIN(cbToWrite, pThis->cbReadWriteBuf); 1010 1016 PDMDevHlpPhysRead(pDevIns, addr, pThis->pvReadWriteBuf, cbToRead); /** @todo Check rc? */ … … 1019 1025 int rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut, 1020 1026 pThis->pvReadWriteBuf, cbToRead, &cbWritten); 1021 AssertRCBreak(rc); 1022 if (RT_FAILURE(rc2)) 1023 continue; 1024 1025 cbWrittenMin = RT_MIN(cbWrittenMin, cbWritten); 1026 LogFlowFunc(("\tLUN#%RU8: cbWritten=%RU32, cWrittenMin=%RU32\n", pDrv->uLUN, cbWritten, cbWrittenMin)); 1027 } 1028 1029 LogFlowFunc(("\tcbToRead=%RU32, cbWrittenMin=%RU32, cbToWrite=%RU32, cbLeft=%RU32\n", 1030 cbToRead, cbWrittenMin, cbToWrite, cbToWrite - cbWrittenMin)); 1031 1032 if (!cbWrittenMin) 1033 { 1034 rc = VINF_EOF; 1035 break; 1036 } 1037 1038 Assert(cbWrittenMin != UINT32_MAX); 1039 Assert(cbToWrite >= cbWrittenMin); 1040 cbToWrite -= cbWrittenMin; 1041 addr += cbWrittenMin; 1042 cbWrittenTotal += cbWrittenMin; 1027 LogFlowFunc(("\tLUN#%RU8: rc=%Rrc, cbWritten=%RU32\n", pDrv->uLUN, rc2, cbWritten)); 1028 } 1029 1030 LogFlowFunc(("\tcbToRead=%RU32, cbToWrite=%RU32, cbLeft=%RU32\n", 1031 cbToRead, cbToWrite, cbToWrite - cbWrittenTotal)); 1032 1033 Assert(cbToWrite >= cbToRead); 1034 cbToWrite -= cbToRead; 1035 addr += cbToRead; 1036 cbWrittenTotal += cbToRead; 1043 1037 } 1044 1038 … … 1163 1157 } 1164 1158 1159 #ifndef VBOX_WITH_AUDIO_CALLBACKS 1160 1165 1161 static DECLCALLBACK(void) ichac97Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) 1166 1162 { … … 1178 1174 1179 1175 uint32_t cbIn, cbOut, cSamplesLive; 1176 1177 uint64_t uTicksNow = PDMDevHlpTMTimeVirtGet(pDevIns); 1178 uint64_t uTicksElapsed = uTicksNow - pThis->uTimerTS; 1179 uint64_t uTicksPerSec = PDMDevHlpTMTimeVirtGetFreq(pDevIns); 1180 1181 pThis->uTimerTS = uTicksNow; 1182 1180 1183 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 1181 1184 { 1185 cbIn = cbOut = 0; 1182 1186 rc = pDrv->pConnector->pfnQueryStatus(pDrv->pConnector, 1183 &cbIn, &cbOut, &cSamplesLive);1187 &cbIn, &cbOut, NULL /* cSamplesLive */); 1184 1188 if (RT_SUCCESS(rc)) 1185 { 1186 #ifdef DEBUG_TIMER 1187 LogFlowFunc(("\tLUN#%RU8: [1] cbIn=%RU32, cbOut=%RU32\n", pDrv->uLUN, cbIn, cbOut)); 1188 #endif 1189 if (cSamplesLive) 1190 { 1191 uint32_t cSamplesPlayed; 1192 int rc2 = pDrv->pConnector->pfnPlayOut(pDrv->pConnector, &cSamplesPlayed); 1193 #ifdef DEBUG_TIMER 1194 if (RT_SUCCESS(rc2)) 1195 LogFlowFunc(("LUN#%RU8: cSamplesLive=%RU32, cSamplesPlayed=%RU32\n", 1196 pDrv->uLUN, cSamplesLive, cSamplesPlayed)); 1197 #endif 1198 if (cSamplesPlayed) 1199 { 1200 rc = pDrv->pConnector->pfnQueryStatus(pDrv->pConnector, 1201 &cbIn, &cbOut, &cSamplesLive); 1202 #ifdef DEBUG_TIMER 1203 if (RT_SUCCESS(rc)) 1204 LogFlowFunc(("\tLUN#%RU8: [2] cbIn=%RU32, cbOut=%RU32\n", pDrv->uLUN, cbIn, cbOut)); 1205 #endif 1206 } 1207 } 1208 1209 cbInMax = RT_MAX(cbInMax, cbIn); 1210 cbOutMin = RT_MIN(cbOutMin, cbOut); 1211 } 1189 rc = pDrv->pConnector->pfnPlayOut(pDrv->pConnector, NULL /* cSamplesPlayed */); 1190 1191 uint32_t cSamplesMin = (int)((2 * uTicksElapsed * pDrv->Out.pStrmOut->Props.uHz + uTicksPerSec) / uTicksPerSec / 2); 1192 uint32_t cbSamplesMin = AUDIOMIXBUF_S2B(&pDrv->Out.pStrmOut->MixBuf, cSamplesMin); 1193 1194 LogFlowFunc(("LUN#%RU8: rc=%Rrc, cbOut=%RU32, cSamplesMin=%RU32, cbSamplesMin=%RU32\n", 1195 pDrv->uLUN, rc, cbOut, cSamplesMin, cbSamplesMin)); 1196 1197 if ( RT_FAILURE(rc) 1198 && cbSamplesMin > cbOut) 1199 { 1200 LogFlowFunc(("LUN#%RU8: Adj: %RU32 -> %RU32\n", pDrv->uLUN, cbOut, cbSamplesMin)); 1201 cbOut = cbSamplesMin; 1202 } 1203 1204 cbOutMin = RT_MIN(cbOutMin, cbOut); 1205 cbInMax = RT_MAX(cbInMax, cbIn); 1212 1206 } 1213 1207 … … 1234 1228 ichac97TransferAudio(pThis, PI_INDEX, cbInMax); /** @todo Add rc! */ 1235 1229 1236 TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTi cks);1230 TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTimerTicks); 1237 1231 1238 1232 STAM_PROFILE_STOP(&pThis->StatTimer, a); 1239 1233 } 1234 1235 #endif 1240 1236 1241 1237 static int ichac97TransferAudio(PAC97STATE pThis, int index, uint32_t cbElapsed) … … 2325 2321 } 2326 2322 2323 # ifndef VBOX_WITH_AUDIO_CALLBACKS 2327 2324 if (RT_SUCCESS(rc)) 2328 2325 { … … 2334 2331 if (RT_SUCCESS(rc)) 2335 2332 { 2336 pThis->uTicks = PDMDevHlpTMTimeVirtGetFreq(pDevIns) / 200; /** Hz. @todo Make this configurable! */ 2337 if (pThis->uTicks < 100) 2338 pThis->uTicks = 100; 2339 LogFunc(("Timer ticks=%RU64\n", pThis->uTicks)); 2333 pThis->uTimerTicks = PDMDevHlpTMTimeVirtGetFreq(pDevIns) / 200; /** Hz. @todo Make this configurable! */ 2334 pThis->uTimerTS = PDMDevHlpTMTimeVirtGet(pDevIns); 2335 if (pThis->uTimerTicks < 100) 2336 pThis->uTimerTicks = 100; 2337 LogFunc(("Timer ticks=%RU64\n", pThis->uTimerTicks)); 2340 2338 2341 2339 /* Fire off timer. */ 2342 TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTicks); 2343 } 2344 } 2340 TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTimerTicks); 2341 } 2342 } 2343 # else 2344 if (RT_SUCCESS(rc)) 2345 { 2346 PAC97DRIVER pDrv; 2347 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 2348 { 2349 /* Only register primary driver. 2350 * The device emulation does the output multiplexing then. */ 2351 if (pDrv->Flags != PDMAUDIODRVFLAG_PRIMARY) 2352 continue; 2353 2354 PDMAUDIOCALLBACK AudioCallbacks[2]; 2355 2356 AC97CALLBACKCTX Ctx = { pThis, pDrv }; 2357 2358 AudioCallbacks[0].enmType = PDMAUDIOCALLBACKTYPE_INPUT; 2359 AudioCallbacks[0].pfnCallback = ac97CallbackInput; 2360 AudioCallbacks[0].pvCtx = &Ctx; 2361 AudioCallbacks[0].cbCtx = sizeof(AC97CALLBACKCTX); 2362 2363 AudioCallbacks[1].enmType = PDMAUDIOCALLBACKTYPE_OUTPUT; 2364 AudioCallbacks[1].pfnCallback = ac97CallbackOutput; 2365 AudioCallbacks[1].pvCtx = &Ctx; 2366 AudioCallbacks[1].cbCtx = sizeof(AC97CALLBACKCTX); 2367 2368 rc = pDrv->pConnector->pfnRegisterCallbacks(pDrv->pConnector, AudioCallbacks, RT_ELEMENTS(AudioCallbacks)); 2369 if (RT_FAILURE(rc)) 2370 break; 2371 } 2372 } 2373 # endif 2345 2374 2346 2375 # ifdef VBOX_WITH_STATISTICS -
trunk/src/VBox/Devices/Audio/DevIchHda.cpp
r58954 r58983 42 42 #include "VBoxDD.h" 43 43 44 #include "AudioMixBuffer.h" 44 45 #include "AudioMixer.h" 45 46 #include "DevIchHdaCodec.h" … … 723 724 /** Flag whether the RC part is enabled. */ 724 725 bool fRCEnabled; 726 #ifndef VBOX_WITH_AUDIO_CALLBACKS 725 727 /** The emulation timer for handling the attached 726 728 * LUN drivers. */ 727 729 PTMTIMERR3 pTimer; 728 730 /** Timer ticks for handling the LUN drivers. */ 729 uint64_t uTicks; 731 uint64_t uTimerTicks; 732 /** Timestamp (delta) since last timer call. */ 733 uint64_t uTimerTS; 734 #endif 730 735 #ifdef VBOX_WITH_STATISTICS 731 736 # ifndef VBOX_WITH_AUDIO_CALLBACKS … … 1716 1721 *pu32Value = (uint32_t)ASMMultU64ByU32DivByU32(PDMDevHlpTMTimeVirtGetNano(pThis->CTX_SUFF(pDevIns)) 1717 1722 - pThis->u64BaseTS, 24, 1000); 1723 LogFlowFunc(("%RU32\n", *pu32Value)); 1718 1724 return VINF_SUCCESS; 1719 1725 } … … 2088 2094 #ifdef IN_RING3 2089 2095 # ifdef VBOX_WITH_HDA_CODEC_EMU 2090 /* No reason to re open voicewith same settings. */2096 /* No reason to re-open stream with same settings. */ 2091 2097 if (u32Value == HDA_REG_IND(pThis, iReg)) 2092 2098 return VINF_SUCCESS; … … 2111 2117 # endif 2112 2118 default: 2113 LogFunc(("Warning: Attempt to change format on register % d\n", iReg));2119 LogFunc(("Warning: Attempt to change format on register %RU32\n", iReg)); 2114 2120 break; 2115 2121 } … … 2395 2401 } 2396 2402 } 2397 2398 Log(("HDADEBUG: cb2Copy=%RU32, CVI(len:%RU32, pos:%RU32), CBLL=%RU32, FIFOS=%RU32, Avail=%RU32\n",2399 cbFree, pBDLE->u32BufSize, pBDLE->State.u32BufOff, pStrmSt->u32CBL - HDA_STREAM_REG(pThis, LPIB, pStrmSt->u8Strm), pStrmSt->u16FIFOS, 0));2400 2403 } 2401 2404 … … 2815 2818 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 2816 2819 { 2817 if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] %s", pDrv->uLUN, pszName) <= 0) 2820 if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] %s (%RU32Hz, %RU8 %s)", 2821 pDrv->uLUN, pszName, pCfg->uHz, pCfg->cChannels, pCfg->cChannels > 1 ? "Channels" : "Channel") <= 0) 2818 2822 { 2819 2823 rc = VERR_NO_MEMORY; … … 2874 2878 { 2875 2879 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE); 2876 AssertPtr (pThis);2880 AssertPtrReturnVoid(pThis); 2877 2881 2878 2882 STAM_PROFILE_START(&pThis->StatTimer, a); … … 2886 2890 2887 2891 uint32_t cbIn, cbOut, cSamplesLive; 2892 2893 uint64_t uTicksNow = PDMDevHlpTMTimeVirtGet(pDevIns); 2894 uint64_t uTicksElapsed = uTicksNow - pThis->uTimerTS; 2895 uint64_t uTicksPerSec = PDMDevHlpTMTimeVirtGetFreq(pDevIns); 2896 2897 pThis->uTimerTS = uTicksNow; 2898 2888 2899 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 2889 2900 { 2901 cbIn = cbOut = 0; 2890 2902 rc = pDrv->pConnector->pfnQueryStatus(pDrv->pConnector, 2891 &cbIn, &cbOut, &cSamplesLive);2903 &cbIn, &cbOut, NULL /* cSamplesLive */); 2892 2904 if (RT_SUCCESS(rc)) 2893 { 2894 #ifdef DEBUG_TIMER 2895 LogFlowFunc(("\tLUN#%RU8: [1] cbIn=%RU32, cbOut=%RU32\n", pDrv->uLUN, cbIn, cbOut)); 2896 #endif 2897 if (cSamplesLive) 2898 { 2899 uint32_t cSamplesPlayed; 2900 int rc2 = pDrv->pConnector->pfnPlayOut(pDrv->pConnector, &cSamplesPlayed); 2901 if (RT_SUCCESS(rc2)) 2902 LogFlowFunc(("LUN#%RU8: cSamplesLive=%RU32, cSamplesPlayed=%RU32\n", 2903 pDrv->uLUN, cSamplesLive, cSamplesPlayed)); 2904 2905 rc = pDrv->pConnector->pfnQueryStatus(pDrv->pConnector, 2906 &cbIn, &cbOut, &cSamplesLive); 2907 #ifdef DEBUG_TIMER 2908 if (RT_SUCCESS(rc)) 2909 LogFlowFunc(("\tLUN#%RU8: [2] cbIn=%RU32, cbOut=%RU32\n", pDrv->uLUN, cbIn, cbOut)); 2910 #endif 2911 } 2912 2913 cbInMax = RT_MAX(cbInMax, cbIn); 2914 cbOutMin = RT_MIN(cbOutMin, cbOut); 2915 } 2905 rc = pDrv->pConnector->pfnPlayOut(pDrv->pConnector, NULL /* cSamplesPlayed */); 2906 2907 uint32_t cSamplesMin = (int)((2 * uTicksElapsed * pDrv->Out.pStrmOut->Props.uHz + uTicksPerSec) / uTicksPerSec / 2); 2908 uint32_t cbSamplesMin = AUDIOMIXBUF_S2B(&pDrv->Out.pStrmOut->MixBuf, cSamplesMin); 2909 2910 LogFlowFunc(("LUN#%RU8: rc=%Rrc, cbOut=%RU32, cSamplesMin=%RU32, cbSamplesMin=%RU32\n", 2911 pDrv->uLUN, rc, cbOut, cSamplesMin, cbSamplesMin)); 2912 2913 if ( RT_FAILURE(rc) 2914 && cbSamplesMin > cbOut) 2915 { 2916 LogFlowFunc(("LUN#%RU8: Adj: %RU32 -> %RU32\n", pDrv->uLUN, cbOut, cbSamplesMin)); 2917 cbOut = cbSamplesMin; 2918 } 2919 2920 cbOutMin = RT_MIN(cbOutMin, cbOut); 2921 cbInMax = RT_MAX(cbInMax, cbIn); 2916 2922 } 2917 2923 … … 2938 2944 hdaTransfer(pThis, PI_INDEX, cbInMax /* cbMax */, NULL /* pcbProcessed */); /** @todo Add rc! */ 2939 2945 2940 TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTi cks);2946 TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTimerTicks); 2941 2947 2942 2948 STAM_PROFILE_STOP(&pThis->StatTimer, a); … … 4424 4430 /** @todo Investigate why sounds is getting corrupted if the "ticks" value is too 4425 4431 * low, e.g. "PDMDevHlpTMTimeVirtGetFreq / 200". */ 4426 pThis->uTicks = PDMDevHlpTMTimeVirtGetFreq(pDevIns) / 500; /** @todo Make this configurable! */ 4427 if (pThis->uTicks < 100) 4428 pThis->uTicks = 100; 4429 LogFunc(("Timer ticks=%RU64\n", pThis->uTicks)); 4432 pThis->uTimerTicks = PDMDevHlpTMTimeVirtGetFreq(pDevIns) / 500; /** @todo Make this configurable! */ 4433 pThis->uTimerTS = PDMDevHlpTMTimeVirtGet(pDevIns); 4434 if (pThis->uTimerTicks < 100) 4435 pThis->uTimerTicks = 100; 4436 LogFunc(("Timer ticks=%RU64\n", pThis->uTimerTicks)); 4430 4437 4431 4438 /* Fire off timer. */ 4432 TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTi cks);4439 TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTimerTicks); 4433 4440 } 4434 4441 } -
trunk/src/VBox/Devices/Audio/DevSB16.cpp
r58600 r58983 55 55 #include "VBoxDD.h" 56 56 57 #include "AudioMixBuffer.h" 57 58 #include "AudioMixer.h" 58 59 … … 178 179 /** Audio sink for PCM output. */ 179 180 R3PTRTYPE(PAUDMIXSINK) pSinkOutput; 181 #ifndef VBOX_WITH_AUDIO_CALLBACKS 180 182 /** The emulation timer for handling I/O of the attached LUN drivers. */ 181 183 PTMTIMERR3 pTimerIO; 182 184 /** Timer ticks for handling the LUN drivers. */ 183 uint64_t uTicksIO; 184 185 uint64_t uTimerTicksIO; 186 /** Timestamp (delta) since last timer call. */ 187 uint64_t uTimerTSIO; 188 #endif 185 189 PTMTIMER pTimerIRQ; 186 190 PPDMIBASE pDrvBase; … … 1520 1524 uint32_t dma_len, int len) 1521 1525 { 1522 uint8_t 1523 uint32_t 1524 uint32_t 1526 uint8_t tmpbuf[_4K]; /** @todo Have a buffer on the heap. */ 1527 uint32_t cbToWrite = len; 1528 uint32_t cbWrittenTotal = 0; 1525 1529 1526 1530 while (cbToWrite) 1527 1531 { 1528 uint32_t cbWrittenMin = UINT32_MAX;1529 1532 uint32_t cbToRead; 1530 1533 uint32_t cbRead; … … 1546 1549 int rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut, 1547 1550 tmpbuf, cbToRead, &cbWritten); 1548 AssertRCBreak(rc); 1549 if (RT_FAILURE(rc2)) 1550 continue; 1551 1552 cbWrittenMin = RT_MIN(cbWrittenMin, cbWritten); 1553 LogFlowFunc(("\tLUN#%RU8: cbWritten=%RU32, cWrittenMin=%RU32\n", pDrv->uLUN, cbWritten, cbWrittenMin)); 1551 LogFlowFunc(("\tLUN#%RU8: rc=%Rrc, cbWritten=%RU32, cWrittenMin=%RU32\n", pDrv->uLUN, rc2, cbWritten)); 1554 1552 } 1555 1553 1556 Assert(cbToWrite >= cb WrittenMin);1557 cbToWrite -= cb WrittenMin;1558 dma_pos = (dma_pos + cb WrittenMin) % dma_len;1559 cbWrittenTotal += cb WrittenMin;1560 1561 if (!cbRead || !cbWrittenMin)1554 Assert(cbToWrite >= cbToRead); 1555 cbToWrite -= cbToRead; 1556 dma_pos = (dma_pos + cbToRead) % dma_len; 1557 cbWrittenTotal += cbToRead; 1558 1559 if (!cbRead) 1562 1560 break; 1563 1561 } … … 1664 1662 PSB16DRIVER pDrv; 1665 1663 1666 uint32_t cbIn, cbOut, cSamplesLive; 1664 uint32_t cbIn, cbOut; 1665 1666 uint64_t uTicksNow = PDMDevHlpTMTimeVirtGet(pDevIns); 1667 uint64_t uTicksElapsed = uTicksNow - pThis->uTimerTSIO; 1668 uint64_t uTicksPerSec = PDMDevHlpTMTimeVirtGetFreq(pDevIns); 1669 1670 pThis->uTimerTSIO = uTicksNow; 1671 1667 1672 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 1668 1673 { 1674 cbIn = cbOut = 0; 1669 1675 rc = pDrv->pConnector->pfnQueryStatus(pDrv->pConnector, 1670 &cbIn, &cbOut, &cSamplesLive);1676 &cbIn, &cbOut, NULL /* cSamplesLive */); 1671 1677 if (RT_SUCCESS(rc)) 1672 { 1673 LogFlowFunc(("\tLUN#%RU8: [1] cbIn=%RU32, cbOut=%RU32\n", pDrv->uLUN, cbIn, cbOut)); 1674 1675 if (cSamplesLive) 1676 { 1677 uint32_t cSamplesPlayed; 1678 int rc2 = pDrv->pConnector->pfnPlayOut(pDrv->pConnector, &cSamplesPlayed); 1679 if (RT_SUCCESS(rc2)) 1680 LogFlowFunc(("LUN#%RU8: cSamplesLive=%RU32, cSamplesPlayed=%RU32\n", 1681 pDrv->uLUN, cSamplesLive, cSamplesPlayed)); 1682 1683 if (cSamplesPlayed) 1684 { 1685 rc = pDrv->pConnector->pfnQueryStatus(pDrv->pConnector, 1686 &cbIn, &cbOut, &cSamplesLive); 1687 if (RT_SUCCESS(rc)) 1688 LogFlowFunc(("\tLUN#%RU8: [2] cbIn=%RU32, cbOut=%RU32\n", pDrv->uLUN, cbIn, cbOut)); 1689 } 1690 } 1691 1692 cbInMax = RT_MAX(cbInMax, cbIn); 1693 cbOutMin = RT_MIN(cbOutMin, cbOut); 1678 rc = pDrv->pConnector->pfnPlayOut(pDrv->pConnector, NULL /* cSamplesPlayed */); 1679 1680 uint32_t cSamplesMin = (int)((2 * uTicksElapsed * pDrv->Out.pStrmOut->Props.uHz + uTicksPerSec) / uTicksPerSec / 2); 1681 uint32_t cbSamplesMin = AUDIOMIXBUF_S2B(&pDrv->Out.pStrmOut->MixBuf, cSamplesMin); 1682 1683 LogFlowFunc(("LUN#%RU8: rc=%Rrc, cbOut=%RU32, cSamplesMin=%RU32, cbSamplesMin=%RU32\n", 1684 pDrv->uLUN, rc, cbOut, cSamplesMin, cbSamplesMin)); 1685 1686 if ( RT_FAILURE(rc) 1687 && cbSamplesMin > cbOut) 1688 { 1689 LogFlowFunc(("LUN#%RU8: Adj: %RU32 -> %RU32\n", pDrv->uLUN, cbOut, cbSamplesMin)); 1690 cbOut = cbSamplesMin; 1694 1691 } 1695 } 1696 1692 1693 cbOutMin = RT_MIN(cbOutMin, cbOut); 1694 cbInMax = RT_MAX(cbInMax, cbIn); 1695 } 1696 1697 #ifdef DEBUG_TIMER 1697 1698 LogFlowFunc(("cbInMax=%RU32, cbOutMin=%RU32\n", cbInMax, cbOutMin)); 1699 #endif 1698 1700 1699 1701 if (cbOutMin == UINT32_MAX) … … 1716 1718 /** @todo Implement recording. */ 1717 1719 1718 TMTimerSet(pThis->pTimerIO, TMTimerGet(pThis->pTimerIO) + pThis->uTi cksIO);1720 TMTimerSet(pThis->pTimerIO, TMTimerGet(pThis->pTimerIO) + pThis->uTimerTicksIO); 1719 1721 } 1720 1722 … … 2168 2170 sb16ResetLegacy(pThis); 2169 2171 2170 PSB16DRIVER pDrv; 2171 uLUN = 0; 2172 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 2173 { 2174 PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector; 2175 AssertPtr(pCon); 2176 2177 bool fIsOK = pCon->pfnIsOutputOK(pCon, pDrv->Out.pStrmOut); 2178 if (fIsOK) 2179 { 2180 rc = pCon->pfnEnableOut(pCon, pDrv->Out.pStrmOut, true /* fEnable */); 2181 fIsOK = RT_SUCCESS(rc); 2182 } 2183 2184 if (!fIsOK) 2185 { 2186 /* 2187 * Only primary drivers are critical for the VM to run. Everything else 2188 * might not worth showing an own error message box in the GUI. 2189 */ 2190 if (!(pDrv->Flags & PDMAUDIODRVFLAG_PRIMARY)) 2191 continue; 2192 2193 LogRel(("SB16: Warning: Unable to enable/use output for LUN#%RU8\n", uLUN)); 2194 2195 pCon->pfnDestroyOut(pCon, pDrv->Out.pStrmOut); 2196 pDrv->Out.pStrmOut = NULL; 2197 2198 pThis->pDrv->pfnInitNull(pThis->pDrv); 2199 2200 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding", 2201 N_("No audio devices could be opened. Selecting the NULL audio backend " 2202 "with the consequence that no sound is audible")); 2203 } 2204 2205 uLUN++; 2206 } 2207 2172 #ifndef VBOX_WITH_AUDIO_CALLBACKS 2208 2173 if (RT_SUCCESS(rc)) 2209 2174 { … … 2214 2179 else 2215 2180 { 2216 pThis->uTicksIO = PDMDevHlpTMTimeVirtGetFreq(pDevIns) / 200; /** Hz. @todo Make this configurable! */ 2217 if (pThis->uTicksIO < 100) 2218 pThis->uTicksIO = 100; 2219 LogFunc(("I/O timer ticks=%RU64\n", pThis->uTicksIO)); 2181 pThis->uTimerTicksIO = PDMDevHlpTMTimeVirtGetFreq(pDevIns) / 200; /** Hz. @todo Make this configurable! */ 2182 pThis->uTimerTSIO = PDMDevHlpTMTimeVirtGet(pDevIns); 2183 if (pThis->uTimerTicksIO < 100) 2184 pThis->uTimerTicksIO = 100; 2185 LogFunc(("I/O timer ticks=%RU64\n", pThis->uTimerTicksIO)); 2220 2186 2221 2187 /* Fire off timer. */ 2222 TMTimerSet(pThis->pTimerIO, TMTimerGet(pThis->pTimerIO) + pThis->uTi cksIO);2188 TMTimerSet(pThis->pTimerIO, TMTimerGet(pThis->pTimerIO) + pThis->uTimerTicksIO); 2223 2189 } 2224 2190 } 2191 #else 2192 if (RT_SUCCESS(rc)) 2193 { 2194 PSB16DRIVER pDrv; 2195 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 2196 { 2197 /* Only register primary driver. 2198 * The device emulation does the output multiplexing then. */ 2199 if (pDrv->Flags != PDMAUDIODRVFLAG_PRIMARY) 2200 continue; 2201 2202 PDMAUDIOCALLBACK AudioCallbacks[2]; 2203 2204 SB16CALLBACKCTX Ctx = { pThis, pDrv }; 2205 2206 AudioCallbacks[0].enmType = PDMAUDIOCALLBACKTYPE_INPUT; 2207 AudioCallbacks[0].pfnCallback = sb16CallbackInput; 2208 AudioCallbacks[0].pvCtx = &Ctx; 2209 AudioCallbacks[0].cbCtx = sizeof(SB16CALLBACKCTX); 2210 2211 AudioCallbacks[1].enmType = PDMAUDIOCALLBACKTYPE_OUTPUT; 2212 AudioCallbacks[1].pfnCallback = sb16CallbackOutput; 2213 AudioCallbacks[1].pvCtx = &Ctx; 2214 AudioCallbacks[1].cbCtx = sizeof(SB16CALLBACKCTX); 2215 2216 rc = pDrv->pConnector->pfnRegisterCallbacks(pDrv->pConnector, AudioCallbacks, RT_ELEMENTS(AudioCallbacks)); 2217 if (RT_FAILURE(rc)) 2218 break; 2219 } 2220 } 2221 #endif 2225 2222 2226 2223 return VINF_SUCCESS; -
trunk/src/VBox/Devices/Audio/DrvAudio.cpp
r58744 r58983 1053 1053 pHstStrmOut->MixBuf.pszName)); 1054 1054 1055 if (!AudioMixBufFreeBytes(&pGstStrmOut->MixBuf)) 1056 { 1057 if (pcbWritten) 1058 *pcbWritten = 0; 1059 return VINF_SUCCESS; 1060 } 1061 1055 1062 /* 1056 1063 * First, write data from the device emulation into our … … 1752 1759 AssertPtr(pHstStrmOut); 1753 1760 1754 if (pGstStrmOut->State.fActive != fEnable) /* Only process real state changes. */ 1755 { 1756 if (fEnable) 1761 if (fEnable) 1762 { 1763 /* Is a pending disable outstanding? Then disable first. */ 1764 if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE) 1757 1765 { 1758 pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE;1759 if ( !(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED))1760 rc = drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_ENABLE);1766 rc = drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_DISABLE); 1767 if (RT_SUCCESS(rc)) 1768 pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE; 1761 1769 } 1762 else /* Disable */ 1770 1771 if (RT_SUCCESS(rc)) 1772 rc = drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_ENABLE); 1773 } 1774 else /* Disable */ 1775 { 1776 if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED) 1763 1777 { 1764 if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED) 1778 uint32_t cGstStrmsActive = 0; 1779 1780 /* 1781 * Check if there are any active guest streams assigned 1782 * to this host stream which still are being marked as active. 1783 * 1784 * In that case we have to defer closing the host stream and 1785 * wait until all guest streams have been finished. 1786 */ 1787 PPDMAUDIOGSTSTRMOUT pIter; 1788 RTListForEach(&pHstStrmOut->lstGstStrmOut, pIter, PDMAUDIOGSTSTRMOUT, Node) 1765 1789 { 1766 uint32_t cGstStrmsActive = 0; 1767 1768 /* 1769 * Check if there are any active guest streams assigned 1770 * to this host stream which still are being marked as active. 1771 * 1772 * In that case we have to defer closing the host stream and 1773 * wait until all guest streams have been finished. 1774 */ 1775 PPDMAUDIOGSTSTRMOUT pIter; 1776 RTListForEach(&pHstStrmOut->lstGstStrmOut, pIter, PDMAUDIOGSTSTRMOUT, Node) 1790 if (pIter->State.fActive) 1777 1791 { 1778 if (pIter->State.fActive) 1779 { 1780 cGstStrmsActive++; 1781 break; /* At least one assigned & active guest stream is enough. */ 1782 } 1792 cGstStrmsActive++; 1793 break; /* At least one assigned & active guest stream is enough. */ 1783 1794 } 1784 1785 /* Do we need to defer closing the host stream? */1786 if (cGstStrmsActive >= 1)1787 pHstStrmOut->fStatus |= PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE;1788 1789 /* Can we close the host stream now instead of deferring it? */1790 if (!(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE))1791 rc = drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_DISABLE);1792 1795 } 1796 1797 /* Do we need to defer closing the host stream? */ 1798 if (cGstStrmsActive >= 1) 1799 pHstStrmOut->fStatus |= PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE; 1800 1801 /* Can we close the host stream now instead of deferring it? */ 1802 if (!(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE)) 1803 rc = drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_DISABLE); 1793 1804 } 1794 1795 if (RT_SUCCESS(rc)) 1796 pGstStrmOut->State.fActive = fEnable;1797 1798 LogFlowFunc(("%s: fEnable=%RTbool, fStatus=0x%x, rc=%Rrc\n", 1799 pGstStrmOut->MixBuf.pszName, fEnable, pHstStrmOut->fStatus, rc));1800 }1805 } 1806 1807 if (RT_SUCCESS(rc)) 1808 pGstStrmOut->State.fActive = fEnable; 1809 1810 LogFlowFunc(("%s: fEnable=%RTbool, fStatus=0x%x, rc=%Rrc\n", 1811 pGstStrmOut->MixBuf.pszName, fEnable, pHstStrmOut->fStatus, rc)); 1801 1812 } 1802 1813 -
trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp
r58744 r58983 123 123 /** DirectSound configuration options. */ 124 124 DSOUNDHOSTCFG cfg; 125 /** Whether the input currently is in an enabled (working) 126 * state or not. */ 127 bool fEnabledIn; 128 /** Whether the output currently is in an enabled (working) 129 * state or not. */ 130 bool fEnabledOut; 125 131 #ifdef VBOX_WITH_AUDIO_CALLBACKS 126 132 /** Pointer to the audio connector interface of the driver/device above us. */ … … 137 143 * Must not exceed VBOX_DSOUND_MAX_EVENTS. */ 138 144 uint8_t cEvents; 139 PDSOUNDSTREAMIN pStrmIn; 140 PDSOUNDSTREAMOUT pStrmOut; 145 /** Pointer to the input stream. */ 146 PDSOUNDSTREAMIN pDSStrmIn; 147 /** Pointer to the output stream. */ 148 PDSOUNDSTREAMOUT pDSStrmOut; 141 149 #endif 142 150 } DRVHOSTDSOUND, *PDRVHOSTDSOUND; … … 162 170 ( (PDRVHOSTDSOUND)((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTDSOUND, IHostAudio)) ) 163 171 172 static HRESULT directSoundPlayRestore(LPDIRECTSOUNDBUFFER8 pDSB); 173 164 174 static void dsoundDevRemove(PDSOUNDDEV pDev); 165 175 #ifdef VBOX_WITH_AUDIO_CALLBACKS … … 174 184 static int dsoundWaveFmtFromCfg(PPDMAUDIOSTREAMCFG pCfg, PWAVEFORMATEX pFmt) 175 185 { 186 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 187 AssertPtrReturn(pFmt, VERR_INVALID_POINTER); 188 176 189 RT_BZERO(pFmt, sizeof(WAVEFORMATEX)); 190 177 191 pFmt->wFormatTag = WAVE_FORMAT_PCM; 178 192 pFmt->nChannels = pCfg->cChannels; … … 211 225 } 212 226 227 static int dsoundGetStatusOut(PDSOUNDSTREAMOUT pDSoundStrmOut, DWORD *pdwBuffer, DWORD *pdwFree, DWORD *pdwPlayPos) 228 { 229 AssertPtrReturn(pDSoundStrmOut, VERR_INVALID_POINTER); 230 231 LPDIRECTSOUNDBUFFER8 pDSB = pDSoundStrmOut->pDSB; 232 if (!pDSB) 233 return VERR_INVALID_POINTER; 234 235 DWORD cbBuffer = AUDIOMIXBUF_S2B(&pDSoundStrmOut->strmOut.MixBuf, pDSoundStrmOut->csPlaybackBufferSize); 236 237 /* Get the current play position which is used for calculating the free space in the buffer. */ 238 DWORD cbPlayPos; 239 HRESULT hr = IDirectSoundBuffer8_GetCurrentPosition(pDSB, &cbPlayPos, NULL); 240 if (hr == DSERR_BUFFERLOST) 241 { 242 hr = directSoundPlayRestore(pDSB); 243 if (SUCCEEDED(hr)) 244 hr = IDirectSoundBuffer8_GetCurrentPosition(pDSB, &cbPlayPos, NULL); 245 } 246 247 if (FAILED(hr)) 248 { 249 if (hr != DSERR_BUFFERLOST) /* Avoid log flooding if the error is still there. */ 250 DSLOGREL(("DSound: Playback: GetCurrentPosition failed with %Rhrc\n", hr)); 251 LogFlowFunc(("Failed with %Rhrc\n", hr)); 252 return VERR_NOT_AVAILABLE; 253 } 254 255 if (pdwBuffer) 256 *pdwBuffer = cbBuffer; 257 258 if (pdwFree) 259 *pdwFree = cbBuffer - dsoundRingDistance(pDSoundStrmOut->cbPlayWritePos, cbPlayPos, cbBuffer); 260 261 if (pdwPlayPos) 262 *pdwPlayPos = cbPlayPos; 263 264 return VINF_SUCCESS; 265 } 266 213 267 static char *dsoundGUIDToUtf8StrA(LPCGUID lpGUID) 214 268 { … … 429 483 pThis->cEvents--; 430 484 431 pThis->p StrmOut = NULL;485 pThis->pDSStrmOut = NULL; 432 486 } 433 487 … … 590 644 break; 591 645 592 pThis->p StrmOut = pDSoundStrmOut;646 pThis->pDSStrmOut = pDSoundStrmOut; 593 647 594 648 Assert(pThis->cEvents < VBOX_DSOUND_MAX_EVENTS); … … 995 1049 else 996 1050 { 1051 DWORD fFlags = 0; 1052 #ifndef VBOX_WITH_AUDIO_CALLBACKS 1053 fFlags |= DSCBSTART_LOOPING; 1054 #endif 997 1055 DSLOG(("DSound: Capture start\n")); 998 hr = IDirectSoundCaptureBuffer8_Start(pDSoundStrmIn->pDSCB, DSCBSTART_LOOPING);1056 hr = IDirectSoundCaptureBuffer8_Start(pDSoundStrmIn->pDSCB, fFlags); 999 1057 if (FAILED(hr)) 1000 1058 DSLOGREL(("DSound: Capture started %Rhrc\n", hr)); … … 1181 1239 rc = VERR_NOT_SUPPORTED; 1182 1240 1241 pThis->fEnabledOut = RT_SUCCESS(rc); 1183 1242 break; 1184 1243 } … … 1218 1277 do /* to use 'break' */ 1219 1278 { 1220 LPDIRECTSOUNDBUFFER8 pDSB = pDSoundStrmOut->pDSB; 1221 if (!pDSB) 1222 break; 1223 1224 int cShift = pHstStrmOut->Props.cShift; 1225 DWORD cbBuffer = AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, pDSoundStrmOut->csPlaybackBufferSize); 1226 1227 /* Get the current play position which is used for calculating the free space in the buffer. */ 1228 DWORD cbPlayPos; 1229 HRESULT hr = IDirectSoundBuffer8_GetCurrentPosition(pDSB, &cbPlayPos, NULL); 1230 if (hr == DSERR_BUFFERLOST) 1231 { 1232 hr = directSoundPlayRestore(pDSB); 1233 if (SUCCEEDED(hr)) 1234 hr = IDirectSoundBuffer8_GetCurrentPosition(pDSB, &cbPlayPos, NULL); 1235 } 1236 1237 if (FAILED(hr)) 1238 { 1239 if (hr != DSERR_BUFFERLOST) /* Avoid log flooding if the error is still there. */ 1240 DSLOGREL(("DSound: Playback GetCurrentPosition %Rhrc\n", hr)); 1241 break; 1242 } 1243 1244 DWORD cbFree = cbBuffer - dsoundRingDistance(pDSoundStrmOut->cbPlayWritePos, cbPlayPos, cbBuffer); 1279 DWORD cbBuffer, cbFree, cbPlayPos; 1280 rc = dsoundGetStatusOut(pDSoundStrmOut, &cbBuffer, &cbFree, &cbPlayPos); 1281 if (RT_FAILURE(rc)) 1282 { 1283 /* Set the output status to disabled, as we are not able to retrieve the current 1284 * status (anymore). */ 1285 pThis->fEnabledOut = false; 1286 break; 1287 } 1288 1245 1289 /* 1246 1290 * Check for full buffer, do not allow the cbPlayWritePos to catch cbPlayPos during playback, … … 1266 1310 } 1267 1311 1312 LPDIRECTSOUNDBUFFER8 pDSB = pDSoundStrmOut->pDSB; 1313 AssertPtr(pDSB); 1314 1268 1315 LPVOID pv1, pv2; 1269 1316 DWORD cb1, cb2; 1270 hr = directSoundPlayLock(pDSB, &pHstStrmOut->Props, pDSoundStrmOut->cbPlayWritePos, cbLive,1271 &pv1, &pv2, &cb1, &cb2, 0 /* dwFlags */);1317 HRESULT hr = directSoundPlayLock(pDSB, &pHstStrmOut->Props, pDSoundStrmOut->cbPlayWritePos, cbLive, 1318 &pv1, &pv2, &cb1, &cb2, 0 /* dwFlags */); 1272 1319 if (FAILED(hr)) 1273 break; 1320 { 1321 rc = VERR_ACCESS_DENIED; 1322 break; 1323 } 1274 1324 1275 1325 DWORD len1 = AUDIOMIXBUF_B2S(&pHstStrmOut->MixBuf, cb1); … … 1315 1365 if (pDSoundStrmOut->fRestartPlayback) 1316 1366 { 1317 /* The playback has been just started. 1367 /* 1368 * The playback has been just started. 1318 1369 * Some samples of the new sound have been copied to the buffer 1319 1370 * and it can start playing. 1320 1371 */ 1321 1372 pDSoundStrmOut->fRestartPlayback = false; 1322 hr = IDirectSoundBuffer8_Play(pDSoundStrmOut->pDSB, 0, 0, DSBPLAY_LOOPING); 1373 1374 DWORD fFlags = 0; 1375 #ifndef VBOX_WITH_AUDIO_CALLBACKS 1376 fFlags |= DSCBSTART_LOOPING; 1377 #endif 1378 hr = IDirectSoundBuffer8_Play(pDSoundStrmOut->pDSB, 0, 0, fFlags); 1323 1379 if (FAILED(hr)) 1324 1380 { 1325 DSLOGREL(("DSound: Playback start%Rhrc\n", hr));1381 DSLOGREL(("DSound: Playback: Unable to start playing, hr=%Rhrc\n", hr)); 1326 1382 rc = VERR_NOT_SUPPORTED; 1383 break; 1327 1384 } 1328 1385 } 1386 1329 1387 } while (0); 1330 1388 1331 if (pcSamplesPlayed) 1332 *pcSamplesPlayed = cReadTotal; 1389 if (RT_SUCCESS(rc)) 1390 { 1391 if (pcSamplesPlayed) 1392 *pcSamplesPlayed = cReadTotal; 1393 } 1333 1394 1334 1395 return rc; … … 1421 1482 if (FAILED(hr)) 1422 1483 rc = VERR_NOT_SUPPORTED; 1423 } break; 1484 1485 pThis->fEnabledIn = RT_SUCCESS(rc); 1486 break; 1487 } 1424 1488 1425 1489 case PDMAUDIOSTREAMCMD_DISABLE: 1426 1490 { 1427 1491 directSoundCaptureStop(pDSoundStrmIn); 1428 } break; 1492 break; 1493 } 1429 1494 1430 1495 default: … … 1432 1497 AssertMsgFailed(("Invalid command %ld\n", enmStreamCmd)); 1433 1498 rc = VERR_INVALID_PARAMETER; 1434 } break; 1499 break; 1500 } 1435 1501 } 1436 1502 … … 1447 1513 int rc = VINF_SUCCESS; 1448 1514 1449 if (pDSCB == NULL) 1450 { 1451 if (pcSamplesCaptured) /** @todo single point of return */ 1452 *pcSamplesCaptured = 0; 1453 return VINF_SUCCESS; 1454 } 1455 1456 /* Get DirectSound capture position in bytes. */ 1457 DWORD cbReadPos; 1458 HRESULT hr = IDirectSoundCaptureBuffer_GetCurrentPosition(pDSCB, NULL, &cbReadPos); 1459 if (FAILED(hr)) 1460 { 1461 if (hr != pDSoundStrmIn->hrLastCaptureIn) 1462 { 1463 DSLOGREL(("DSound: Capture GetCurrentPosition %Rhrc\n", hr)); 1464 pDSoundStrmIn->hrLastCaptureIn = hr; 1465 } 1466 1467 if (pcSamplesCaptured) 1468 *pcSamplesCaptured = 0; 1469 return VINF_SUCCESS; 1470 } 1471 pDSoundStrmIn->hrLastCaptureIn = hr; 1472 1473 if (cbReadPos & pHstStrmIn->Props.uAlign) 1474 DSLOGF(("DSound: Misaligned capture read position %ld (alignment: %RU32)\n", cbReadPos, pHstStrmIn->Props.uAlign)); 1475 1476 /* Capture position in samples. */ 1477 DWORD csReadPos = cbReadPos >> pHstStrmIn->Props.cShift; 1478 1479 /* Number of samples available in the DirectSound capture buffer. */ 1480 DWORD csCaptured = dsoundRingDistance(csReadPos, pDSoundStrmIn->csCaptureReadPos, pDSoundStrmIn->csCaptureBufferSize); 1481 if (csCaptured == 0) 1482 { 1483 if (pcSamplesCaptured) 1484 *pcSamplesCaptured = 0; 1485 return VINF_SUCCESS; 1486 } 1487 1488 /* Using as an intermediate not circular buffer. */ 1489 AudioMixBufReset(&pHstStrmIn->MixBuf); 1490 1491 /* Get number of free samples in the mix buffer and check that is has free space */ 1492 uint32_t csMixFree = AudioMixBufFree(&pHstStrmIn->MixBuf); 1493 if (csMixFree == 0) 1494 { 1495 DSLOGF(("DSound: Capture buffer full\n")); 1496 if (pcSamplesCaptured) 1497 *pcSamplesCaptured = 0; 1498 return VINF_SUCCESS; 1499 } 1500 1501 DSLOGF(("DSound: Capture csMixFree=%RU32, csReadPos=%ld, csCaptureReadPos=%ld, csCaptured=%ld\n", 1502 csMixFree, csReadPos, pDSoundStrmIn->csCaptureReadPos, csCaptured)); 1503 1504 /* No need to fetch more samples than mix buffer can receive. */ 1505 csCaptured = RT_MIN(csCaptured, csMixFree); 1506 1507 /* Lock relevant range in the DirectSound capture buffer. */ 1508 LPVOID pv1, pv2; 1509 DWORD cb1, cb2; 1510 hr = directSoundCaptureLock(pDSCB, &pHstStrmIn->Props, 1511 AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, pDSoundStrmIn->csCaptureReadPos), /* dwOffset */ 1512 AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, csCaptured), /* dwBytes */ 1513 &pv1, &pv2, &cb1, &cb2, 1514 0 /* dwFlags */); 1515 if (FAILED(hr)) 1516 { 1517 if (pcSamplesCaptured) 1518 *pcSamplesCaptured = 0; 1519 return VINF_SUCCESS; 1520 } 1521 1522 DWORD len1 = AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, cb1); 1523 DWORD len2 = AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, cb2); 1524 1525 uint32_t csWrittenTotal = 0; 1526 uint32_t csWritten; 1527 if (pv1 && len1) 1528 { 1529 rc = AudioMixBufWriteAt(&pHstStrmIn->MixBuf, 0 /* offWrite */, 1530 pv1, cb1, &csWritten); 1515 uint32_t cCaptured = 0; 1516 1517 do 1518 { 1519 if (pDSCB == NULL) 1520 { 1521 pThis->fEnabledIn = false; 1522 1523 rc = VERR_NOT_AVAILABLE; 1524 break; 1525 } 1526 1527 /* Get DirectSound capture position in bytes. */ 1528 DWORD cbReadPos; 1529 HRESULT hr = IDirectSoundCaptureBuffer_GetCurrentPosition(pDSCB, NULL, &cbReadPos); 1530 if (FAILED(hr)) 1531 { 1532 if (hr != pDSoundStrmIn->hrLastCaptureIn) 1533 { 1534 DSLOGREL(("DSound: Capture GetCurrentPosition %Rhrc\n", hr)); 1535 pDSoundStrmIn->hrLastCaptureIn = hr; 1536 } 1537 1538 rc = VERR_NOT_AVAILABLE; 1539 break; 1540 } 1541 1542 pDSoundStrmIn->hrLastCaptureIn = hr; 1543 1544 if (cbReadPos & pHstStrmIn->Props.uAlign) 1545 DSLOGF(("DSound: Misaligned capture read position %ld (alignment: %RU32)\n", cbReadPos, pHstStrmIn->Props.uAlign)); 1546 1547 /* Capture position in samples. */ 1548 DWORD csReadPos = cbReadPos >> pHstStrmIn->Props.cShift; 1549 1550 /* Number of samples available in the DirectSound capture buffer. */ 1551 DWORD csCaptured = dsoundRingDistance(csReadPos, pDSoundStrmIn->csCaptureReadPos, pDSoundStrmIn->csCaptureBufferSize); 1552 if (csCaptured == 0) 1553 break; 1554 1555 /* Using as an intermediate not circular buffer. */ 1556 AudioMixBufReset(&pHstStrmIn->MixBuf); 1557 1558 /* Get number of free samples in the mix buffer and check that is has free space */ 1559 uint32_t csMixFree = AudioMixBufFree(&pHstStrmIn->MixBuf); 1560 if (csMixFree == 0) 1561 { 1562 DSLOGF(("DSound: Capture buffer full\n")); 1563 break; 1564 } 1565 1566 DSLOGF(("DSound: Capture csMixFree=%RU32, csReadPos=%ld, csCaptureReadPos=%ld, csCaptured=%ld\n", 1567 csMixFree, csReadPos, pDSoundStrmIn->csCaptureReadPos, csCaptured)); 1568 1569 /* No need to fetch more samples than mix buffer can receive. */ 1570 csCaptured = RT_MIN(csCaptured, csMixFree); 1571 1572 /* Lock relevant range in the DirectSound capture buffer. */ 1573 LPVOID pv1, pv2; 1574 DWORD cb1, cb2; 1575 hr = directSoundCaptureLock(pDSCB, &pHstStrmIn->Props, 1576 AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, pDSoundStrmIn->csCaptureReadPos), /* dwOffset */ 1577 AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, csCaptured), /* dwBytes */ 1578 &pv1, &pv2, &cb1, &cb2, 1579 0 /* dwFlags */); 1580 if (FAILED(hr)) 1581 { 1582 rc = VERR_ACCESS_DENIED; 1583 break; 1584 } 1585 1586 DWORD len1 = AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, cb1); 1587 DWORD len2 = AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, cb2); 1588 1589 uint32_t csWrittenTotal = 0; 1590 uint32_t csWritten; 1591 if (pv1 && len1) 1592 { 1593 rc = AudioMixBufWriteAt(&pHstStrmIn->MixBuf, 0 /* offWrite */, 1594 pv1, cb1, &csWritten); 1595 if (RT_SUCCESS(rc)) 1596 csWrittenTotal += csWritten; 1597 } 1598 1599 if ( RT_SUCCESS(rc) 1600 && csWrittenTotal == len1 1601 && pv2 && len2) 1602 { 1603 rc = AudioMixBufWriteAt(&pHstStrmIn->MixBuf, csWrittenTotal, 1604 pv2, cb2, &csWritten); 1605 if (RT_SUCCESS(rc)) 1606 csWrittenTotal += csWritten; 1607 } 1608 1609 directSoundCaptureUnlock(pDSCB, pv1, pv2, cb1, cb2); 1610 1611 if (csWrittenTotal) /* Captured something? */ 1612 rc = AudioMixBufMixToParent(&pHstStrmIn->MixBuf, csWrittenTotal, &cCaptured); 1613 1531 1614 if (RT_SUCCESS(rc)) 1532 csWrittenTotal += csWritten; 1533 } 1534 1535 if ( RT_SUCCESS(rc) 1536 && csWrittenTotal == len1 1537 && pv2 && len2) 1538 { 1539 rc = AudioMixBufWriteAt(&pHstStrmIn->MixBuf, csWrittenTotal, 1540 pv2, cb2, &csWritten); 1541 if (RT_SUCCESS(rc)) 1542 csWrittenTotal += csWritten; 1543 } 1544 1545 directSoundCaptureUnlock(pDSCB, pv1, pv2, cb1, cb2); 1546 1547 uint32_t csProcessed = 0; 1548 if (csWrittenTotal != 0) 1549 { 1550 /* Captured something. */ 1551 rc = AudioMixBufMixToParent(&pHstStrmIn->MixBuf, csWrittenTotal, 1552 &csProcessed); 1553 } 1554 1555 if (RT_SUCCESS(rc)) 1556 { 1557 pDSoundStrmIn->csCaptureReadPos = (pDSoundStrmIn->csCaptureReadPos + csProcessed) % pDSoundStrmIn->csCaptureBufferSize; 1558 DSLOGF(("DSound: Capture %ld (%ld+%ld), processed %RU32/%RU32\n", 1559 csCaptured, len1, len2, csProcessed, csWrittenTotal)); 1560 } 1615 { 1616 pDSoundStrmIn->csCaptureReadPos = (pDSoundStrmIn->csCaptureReadPos + cCaptured) % pDSoundStrmIn->csCaptureBufferSize; 1617 DSLOGF(("DSound: Capture %ld (%ld+%ld), processed %RU32/%RU32\n", 1618 csCaptured, len1, len2, cCaptured, csWrittenTotal)); 1619 } 1620 1621 } while (0); 1561 1622 1562 1623 if (pcSamplesCaptured) 1563 *pcSamplesCaptured = c sProcessed;1624 *pcSamplesCaptured = cCaptured; 1564 1625 1565 1626 return rc; … … 1580 1641 } 1581 1642 1643 /** @todo Replace PDMAUDIODIR with a (registered? unique) channel ID to provide multi-channel input/output. */ 1582 1644 static DECLCALLBACK(bool) drvHostDSoundIsEnabled(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir) 1583 1645 { 1584 NOREF(pInterface); 1585 NOREF(enmDir); 1586 return true; /* Always all enabled. */ 1646 AssertPtrReturn(pInterface, false); 1647 1648 PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface); 1649 1650 if (enmDir == PDMAUDIODIR_IN) 1651 return pThis->fEnabledIn; 1652 1653 return pThis->fEnabledOut; 1587 1654 } 1588 1655 1589 1656 static DECLCALLBACK(int) drvHostDSoundGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg) 1590 1657 { 1658 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1659 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 1660 1591 1661 PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface); 1592 1593 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);1594 1662 1595 1663 dsoundFreeDeviceLists(pThis); … … 1683 1751 int rc = RTThreadUserSignal(hThreadSelf); 1684 1752 AssertRC(rc); 1685 1686 HRESULT hr;1687 1753 1688 1754 do … … 1727 1793 else if (aEvents[dwObj] == pThis->aEvents[DSOUNDEVENT_OUTPUT]) 1728 1794 { 1729 DWORD cbPlayPos; 1730 hr = IDirectSoundCaptureBuffer8_GetCurrentPosition(pThis->pStrmOut->pDSB, NULL, &cbPlayPos); 1731 if (SUCCEEDED(hr)) 1795 DWORD cbBuffer, cbFree, cbPlayPos; 1796 rc = dsoundGetStatusOut(pThis->pDSStrmOut, &cbBuffer, &cbFree, &cbPlayPos); 1797 if ( RT_SUCCESS(rc) 1798 && cbFree) 1732 1799 { 1733 LogFlowFunc(("Output: hr=%Rhrc, dwPlayPos=%ld\n", hr, cbPlayPos)); 1734 1735 uint32_t cbFree = pThis->pStrmOut->csPlaybackBufferSize - pThis->pStrmOut->cbPlayWritePos; 1736 1737 AssertPtr(pThis->pUpIAudioConnector); 1738 pThis->pUpIAudioConnector->pfnCallback(pThis->pUpIAudioConnector, PDMAUDIOCALLBACKTYPE_OUTPUT, &cbFree, sizeof(cbFree)); 1800 PDMAUDIOCALLBACKDATAOUT Out; 1801 Out.cbInFree = cbFree; 1802 Out.cbOutWritten = 0; 1803 1804 while (!Out.cbOutWritten) 1805 { 1806 rc = pThis->pUpIAudioConnector->pfnCallback(pThis->pUpIAudioConnector, 1807 PDMAUDIOCALLBACKTYPE_OUTPUT, &Out, sizeof(Out)); 1808 if (RT_FAILURE(rc)) 1809 break; 1810 RTThreadSleep(100); 1811 } 1812 1813 LogFlowFunc(("Output: cbBuffer=%ld, cbFree=%ld, cbPlayPos=%ld, cbWritten=%RU32, rc=%Rrc\n", 1814 cbBuffer, cbFree, cbPlayPos, Out.cbOutWritten, rc)); 1739 1815 } 1740 1816 } … … 1939 2015 RTListInit(&pThis->lstDevOutput); 1940 2016 2017 pThis->fEnabledIn = false; 2018 pThis->fEnabledOut = false; 1941 2019 #ifdef VBOX_WITH_AUDIO_CALLBACKS 1942 pThis->fStopped = false;1943 pThis->fShutdown = false;2020 pThis->fStopped = false; 2021 pThis->fShutdown = false; 1944 2022 1945 2023 RT_ZERO(pThis->aEvents); -
trunk/src/VBox/Devices/Audio/DrvHostNullAudio.cpp
r58378 r58983 164 164 165 165 /* Consume as many samples as would be played at the current frequency since last call. */ 166 uint32_t csLive = AudioMixBufAvail(&pHstStrmOut->MixBuf); ;166 uint32_t csLive = AudioMixBufAvail(&pHstStrmOut->MixBuf); 167 167 uint64_t u64TicksNow = PDMDrvHlpTMGetVirtualTime(pDrv->pDrvIns); 168 168 uint64_t u64TicksElapsed = u64TicksNow - pNullStrmOut->u64TicksLast;
Note:
See TracChangeset
for help on using the changeset viewer.