Changeset 60934 in vbox for trunk/src/VBox/Devices/Audio
- Timestamp:
- May 11, 2016 9:13:40 AM (9 years ago)
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/AudioMixer.cpp
r60925 r60934 51 51 static int audioMixerSinkUpdateVolume(PAUDMIXSINK pSink, const PPDMAUDIOVOLUME pVolMaster); 52 52 static void audioMixerSinkRemoveStreamInternal(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream); 53 static int audioMixerSinkUpdateInternal(PAUDMIXSINK pSink); 53 54 54 55 static void audioMixerStreamDestroyInternal(PAUDMIXSTREAM pStream); … … 516 517 } 517 518 518 int AudioMixerSinkUpdate(PAUDMIXSINK pSink) 519 void AudioMixerSinkTimerUpdate(PAUDMIXSINK pSink, uint64_t cTicksPerSec, uint64_t cTicksElapsed, uint32_t *pcbData) 520 { 521 uint32_t cSamplesMin = (uint32_t)((2 * cTicksElapsed * pSink->PCMProps.uHz + cTicksPerSec) / cTicksPerSec / 2); 522 uint32_t cbSamplesMin = cSamplesMin << pSink->PCMProps.cShift; 523 524 LogFlowFunc(("%s: cbSamplesMin=%RU32\n", pSink->pszName, cbSamplesMin)); 525 526 audioMixerSinkUpdateInternal(pSink); 527 528 if (pcbData) 529 *pcbData = cbSamplesMin; 530 } 531 532 static int audioMixerSinkUpdateInternal(PAUDMIXSINK pSink) 519 533 { 520 534 AssertPtrReturn(pSink, VERR_INVALID_POINTER); … … 532 546 || cSamplesLive) 533 547 { 534 Log3Func(("cbIn=%RU32, cbOut=%RU32, cSamplesLive=%RU32, rc2=%Rrc\n", cbIn, cbOut, cSamplesLive, rc2)); 548 Log3Func(("%s: cbIn=%RU32, cbOut=%RU32, cSamplesLive=%RU32, rc2=%Rrc\n", 549 pSink->pszName, cbIn, cbOut, cSamplesLive, rc2)); 535 550 } 536 551 #endif … … 551 566 552 567 return VINF_SUCCESS; 568 } 569 570 int AudioMixerSinkUpdate(PAUDMIXSINK pSink) 571 { 572 return audioMixerSinkUpdateInternal(pSink); 553 573 } 554 574 -
trunk/src/VBox/Devices/Audio/AudioMixer.h
r60925 r60934 163 163 int AudioMixerSinkSetFormat(PAUDMIXSINK pSink, PPDMPCMPROPS pPCMProps); 164 164 int AudioMixerSinkSetVolume(PAUDMIXSINK pSink, PPDMAUDIOVOLUME pVol); 165 void AudioMixerSinkTimerUpdate(PAUDMIXSINK pSink, uint64_t cTicksPerSec, uint64_t cTicksElapsed, uint32_t *pcbData); 165 166 int AudioMixerSinkWrite(PAUDMIXSINK pSink, AUDMIXOP enmOp, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten); 166 167 int AudioMixerSinkUpdate(PAUDMIXSINK pSink); -
trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
r60931 r60934 52 52 #define AC97_SSM_VERSION 1 53 53 54 #define AC97_TIMER_HZ 20054 #define AC97_TIMER_HZ 100 55 55 56 56 #ifdef VBOX … … 363 363 /** Stream state for output. */ 364 364 AC97STREAM StrmStOut; 365 /** Number of active (running) SDn streams. */ 366 uint8_t cStreamsActive; 365 367 #ifndef VBOX_WITH_AUDIO_CALLBACKS 366 368 /** The timer for pumping data thru the attached LUN drivers. */ 367 369 PTMTIMERR3 pTimer; 368 370 # if HC_ARCH_BITS == 32 369 uint32_t Alignment1;371 uint32_t Padding0; 370 372 # endif 371 373 /** The timer interval for pumping data thru the LUN drivers in timer ticks. */ … … 376 378 #endif 377 379 #ifdef VBOX_WITH_STATISTICS 380 uint8_t Padding1; 378 381 STAMPROFILE StatTimer; 379 382 STAMCOUNTER StatBytesRead; … … 382 385 /** List of associated LUN drivers (AC97DRIVER). */ 383 386 RTLISTANCHOR lstDrv; 384 /** The device' software mixer. */387 /** The device's software mixer. */ 385 388 R3PTRTYPE(PAUDIOMIXER) pMixer; 386 389 /** Audio sink for PCM output. */ … … 401 404 402 405 #ifdef VBOX_WITH_STATISTICS 403 AssertCompileMemberAlignment(AC97STATE, StatTimer, 8); 406 AssertCompileMemberAlignment(AC97STATE, StatTimer, 8); 407 AssertCompileMemberAlignment(AC97STATE, StatBytesRead, 8); 408 AssertCompileMemberAlignment(AC97STATE, StatBytesWritten, 8); 404 409 #endif 405 410 … … 412 417 static DECLCALLBACK(void) ichac97Reset(PPDMDEVINS pDevIns); 413 418 #ifndef VBOX_WITH_AUDIO_CALLBACKS 419 static void ichac97TimerMaybeStart(PAC97STATE pThis); 420 static void ichac97TimerMaybeStop(PAC97STATE pThis); 414 421 static DECLCALLBACK(void) ichac97Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser); 415 422 #endif … … 523 530 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 524 531 525 LogFlowFunc(("u8Strm=%RU8, fActive=%RTbool\n", pStream->u8Strm, fActive)); 532 if (!fActive) 533 { 534 if (pThis->cStreamsActive) /* Disable can be called mupltiple times. */ 535 pThis->cStreamsActive--; 536 537 #ifndef VBOX_WITH_AUDIO_CALLBACKS 538 ichac97TimerMaybeStop(pThis); 539 #endif 540 } 541 else 542 { 543 pThis->cStreamsActive++; 544 #ifndef VBOX_WITH_AUDIO_CALLBACKS 545 ichac97TimerMaybeStart(pThis); 546 #endif 547 } 548 549 LogFlowFunc(("u8Strm=%RU8, fActive=%RTbool, cStreamsActive=%RU8\n", pStream->u8Strm, fActive, pThis->cStreamsActive)); 526 550 527 551 return AudioMixerSinkCtl(ichac97IndexToSink(pThis, pStream->u8Strm), … … 1023 1047 PDMAUDIORECSOURCE ars = ichac97IndextoRecSource(rs); 1024 1048 PDMAUDIORECSOURCE als = ichac97IndextoRecSource(ls); 1025 //AUD_set_record_source(&als, &ars);1026 1049 rs = ichac97RecSourceToIndex(ars); 1027 1050 ls = ichac97RecSourceToIndex(als); … … 1280 1303 #ifndef VBOX_WITH_AUDIO_CALLBACKS 1281 1304 1305 static void ichac97TimerMaybeStart(PAC97STATE pThis) 1306 { 1307 LogFlowFunc(("cStreamsActive=%RU8\n", pThis->cStreamsActive)); 1308 1309 if (pThis->cStreamsActive == 0) /* Only start the timer if there are no active streams. */ 1310 return; 1311 1312 if (!pThis->pTimer) 1313 return; 1314 1315 /* Fire off timer. */ 1316 TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->cTimerTicks); 1317 } 1318 1319 static void ichac97TimerMaybeStop(PAC97STATE pThis) 1320 { 1321 LogFlowFunc(("cStreamsActive=%RU8\n", pThis->cStreamsActive)); 1322 1323 if (pThis->cStreamsActive) /* Some streams still active? Bail out. */ 1324 return; 1325 1326 if (!pThis->pTimer) 1327 return; 1328 1329 int rc2 = TMTimerStop(pThis->pTimer); 1330 AssertRC(rc2); 1331 } 1332 1282 1333 static DECLCALLBACK(void) ichac97Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) 1283 1334 { … … 1288 1339 STAM_PROFILE_START(&pThis->StatTimer, a); 1289 1340 1290 uint32_t cbInMax = 0;1291 uint32_t cbOutMin = UINT32_MAX;1292 1293 // PAC97DRIVER pDrv;1294 1295 1341 uint64_t cTicksNow = TMTimerGet(pTimer); 1296 1342 uint64_t cTicksElapsed = cTicksNow - pThis->uTimerTS; … … 1299 1345 pThis->uTimerTS = cTicksNow; 1300 1346 1301 #if 0 1302 /* 1303 * Calculate the mixer's (fixed) sampling rate. 1304 */ 1305 AssertPtr(pThis->pMixer); 1306 1307 PDMAUDIOSTREAMCFG mixerStrmCfg; 1308 int rc = AudioMixerGetDeviceFormat(pThis->pMixer, &mixerStrmCfg); 1309 AssertRC(rc); 1310 1311 PDMPCMPROPS mixerStrmProps; 1312 rc = DrvAudioStreamCfgToProps(&mixerStrmCfg, &mixerStrmProps); 1313 AssertRC(rc); 1314 1315 uint32_t cMixerSamplesMin = (int)((2 * cTicksElapsed * mixerStrmCfg.uHz + cTicksPerSec) / cTicksPerSec / 2); 1316 uint32_t cbMixerSamplesMin = cMixerSamplesMin << mixerStrmProps.cShift; 1317 1318 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 1319 { 1320 uint32_t cbIn = 0; 1321 uint32_t cbOut = 0; 1322 1323 rc = pDrv->pConnector->pfnQueryStatus(pDrv->pConnector, 1324 &cbIn, &cbOut, NULL /* cSamplesLive */); 1325 if (RT_SUCCESS(rc)) 1326 rc = pDrv->pConnector->pfnPlayOut(pDrv->pConnector, NULL /* cSamplesPlayed */); 1327 1328 #ifdef DEBUG_TIMER 1329 LogFlowFunc(("LUN#%RU8: rc=%Rrc, cbIn=%RU32, cbOut=%RU32\n", pDrv->uLUN, rc, cbIn, cbOut)); 1330 #endif 1331 /* If we there was an error handling (available) output or there simply is no output available, 1332 * then calculate the minimum data rate which must be processed by the device emulation in order 1333 * to function correctly. 1334 * 1335 * This is not the optimal solution, but as we have to deal with this on a timer-based approach 1336 * (until we have the audio callbacks) we need to have device' DMA engines running. */ 1337 if (!pDrv->pConnector->pfnIsValidOut(pDrv->pConnector, pDrv->Out.pStrmOut)) 1338 { 1339 /* Use the mixer's (fixed) sampling rate. */ 1340 cbOut = RT_MAX(cbOut, cbMixerSamplesMin); 1341 continue; 1342 } 1343 1344 const bool fIsActiveOut = pDrv->pConnector->pfnIsActiveOut(pDrv->pConnector, pDrv->Out.pStrmOut); 1345 if ( RT_FAILURE(rc) 1346 || !fIsActiveOut) 1347 { 1348 uint32_t cSamplesMin = (int)((2 * cTicksElapsed * pDrv->Out.pStrmOut->Props.uHz + cTicksPerSec) / cTicksPerSec / 2); 1349 uint32_t cbSamplesMin = AUDIOMIXBUF_S2B(&pDrv->Out.pStrmOut->MixBuf, cSamplesMin); 1350 1351 #ifdef DEBUG_TIMER 1352 LogFlowFunc(("\trc=%Rrc, cSamplesMin=%RU32, cbSamplesMin=%RU32\n", rc, cSamplesMin, cbSamplesMin)); 1353 #endif 1354 cbOut = RT_MAX(cbOut, cbSamplesMin); 1355 } 1356 1357 cbOutMin = RT_MIN(cbOutMin, cbOut); 1358 cbInMax = RT_MAX(cbInMax, cbIn); 1359 } 1360 1361 #ifdef DEBUG_TIMER 1362 LogFlowFunc(("cbInMax=%RU32, cbOutMin=%RU32\n", cbInMax, cbOutMin)); 1363 #endif 1364 1365 if (cbOutMin == UINT32_MAX) 1366 cbOutMin = 0; 1367 1368 /* 1369 * Playback. 1370 */ 1371 if (cbOutMin) 1372 { 1373 Assert(cbOutMin != UINT32_MAX); 1374 ichac97TransferAudio(pThis, PO_INDEX, cbOutMin); /** @todo Add rc! */ 1375 } 1376 1377 /* 1378 * Recording. 1379 */ 1380 if (cbInMax) 1381 ichac97TransferAudio(pThis, PI_INDEX, cbInMax); /** @todo Add rc! */ 1382 #else 1383 AudioMixerSinkUpdate(pThis->pSinkLineIn); 1384 AudioMixerSinkUpdate(pThis->pSinkMicIn); 1385 AudioMixerSinkUpdate(pThis->pSinkOutput); 1386 1387 uint32_t cMixerSamplesMin = (int)((2 * cTicksElapsed * pThis->pSinkOutput->PCMProps.uHz + cTicksPerSec) / cTicksPerSec / 2); 1388 uint32_t cbMixerSamplesMin = cMixerSamplesMin << pThis->pSinkOutput->PCMProps.cShift; 1389 1390 Log3Func(("cMixerSamplesMin=%RU32, cbMixerSamplesMin=%RU32, mixerHz=%RU32\n", 1391 cMixerSamplesMin, cbMixerSamplesMin, pThis->pSinkOutput->PCMProps.uHz)); 1392 1393 //uint32_t cbSamplesElapsed = 5120; //((48000 / AC97_TIMER_HZ) * 20) / 8; 1394 1395 uint32_t cMixerSamplesMinIn = (int)((2 * cTicksElapsed * pThis->pSinkLineIn->PCMProps.uHz + cTicksPerSec) / cTicksPerSec / 2); 1396 uint32_t cbMixerSamplesMinIn = cMixerSamplesMinIn << pThis->pSinkLineIn->PCMProps.cShift; 1397 1398 ichac97TransferAudio(pThis, &pThis->StrmStLineIn, cMixerSamplesMinIn); /** @todo Add rc! */ 1399 ichac97TransferAudio(pThis, &pThis->StrmStOut, cbMixerSamplesMin); /** @todo Add rc! */ 1400 #endif 1347 uint32_t cbLineIn; 1348 AudioMixerSinkTimerUpdate(pThis->pSinkLineIn, cTicksPerSec, cTicksElapsed, &cbLineIn); 1349 if (cbLineIn) 1350 ichac97TransferAudio(pThis, &pThis->StrmStLineIn, cbLineIn); /** @todo Add rc! */ 1351 1352 uint32_t cbMicIn; 1353 AudioMixerSinkTimerUpdate(pThis->pSinkMicIn , cTicksPerSec, cTicksElapsed, &cbMicIn); 1354 1355 uint32_t cbOut; 1356 AudioMixerSinkTimerUpdate(pThis->pSinkOutput, cTicksPerSec, cTicksElapsed, &cbOut); 1357 if (cbOut) 1358 ichac97TransferAudio(pThis, &pThis->StrmStOut, cbOut); /** @todo Add rc! */ 1401 1359 1402 1360 /* Kick the timer again. */ … … 1408 1366 } 1409 1367 1410 #endif 1368 #endif /* !VBOX_WITH_AUDIO_CALLBACKS */ 1411 1369 1412 1370 static int ichac97TransferAudio(PAC97STATE pThis, PAC97STREAM pStream, uint32_t cbElapsed) … … 1523 1481 if (pRegs->civ == pRegs->lvi) 1524 1482 { 1525 Log3Func(("Underrun civ (%RU8) == lvi (%RU8)\n", pRegs->civ, pRegs->lvi)); 1483 /* Did we run out of data? */ 1484 LogFunc(("Underrun CIV (%RU8) == LVI (%RU8)\n", pRegs->civ, pRegs->lvi)); 1485 1526 1486 new_sr |= SR_LVBCI | SR_DCH | SR_CELV; 1527 1487 pThis->bup_flag = (pRegs->bd.ctl_len & BD_BUP) ? BUP_LAST : 0; … … 2260 2220 2261 2221 /* 2262 * Stop any audio currently playing.2263 */2264 /*2265 2222 * Stop any audio currently playing and/or recording. 2266 2223 */ … … 2755 2712 LogFunc(("Timer ticks=%RU64 (%RU16 Hz)\n", pThis->cTimerTicks, uTimerHz)); 2756 2713 2757 /* Fire off timer. */ 2758 TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->cTimerTicks); 2714 ichac97TimerMaybeStart(pThis); 2759 2715 } 2760 2716 }
Note:
See TracChangeset
for help on using the changeset viewer.