- Timestamp:
- Jun 27, 2016 8:26:56 AM (8 years ago)
- Location:
- trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/pdmaudioifs.h
r61764 r61887 323 323 { 324 324 /** Set to @c true if this stream is muted, @c false if not. */ 325 bool fMuted; 326 /** Left channel volume. */ 327 uint32_t uLeft; 328 /** Right channel volume. */ 329 uint32_t uRight; 325 bool fMuted; 326 /** Left channel volume. 327 * Range is from [0 ... 255], whereas 0 specifies 328 * the most silent and 255 the loudest value. */ 329 uint8_t uLeft; 330 /** Right channel volume. 331 * Range is from [0 ... 255], whereas 0 specifies 332 * the most silent and 255 the loudest value. */ 333 uint8_t uRight; 330 334 } PDMAUDIOVOLUME, *PPDMAUDIOVOLUME; 335 336 /** Defines the minimum volume allowed. */ 337 #define PDMAUDIO_VOLUME_MIN (0) 338 /** Defines the maximum volume allowed. */ 339 #define PDMAUDIO_VOLUME_MAX (255) 331 340 332 341 /** … … 354 363 355 364 /** 365 * Structure for holding mixing buffer volume parameters. 366 * The volume values are in fixed point style and must 367 * be converted to/from before using with e.g. PDMAUDIOVOLUME. 368 */ 369 typedef struct PDMAUDMIXBUFVOL 370 { 371 /** Set to @c true if this stream is muted, @c false if not. */ 372 bool fMuted; 373 /** Left volume to apply during conversion. Pass 0 374 * to convert the original values. May not apply to 375 * all conversion functions. */ 376 uint32_t uLeft; 377 /** Right volume to apply during conversion. Pass 0 378 * to convert the original values. May not apply to 379 * all conversion functions. */ 380 uint32_t uRight; 381 } PDMAUDMIXBUFVOL, *PPDMAUDMIXBUFVOL; 382 383 /** 356 384 * Structure for holding sample conversion parameters for 357 385 * the audioMixBufConvFromXXX / audioMixBufConvToXXX macros. … … 360 388 { 361 389 /** Number of audio samples to convert. */ 362 uint32_t cSamples; 363 /** Volume to apply during conversion. Pass 0 364 * to convert the original values. May not apply to 365 * all conversion functions. */ 366 PDMAUDIOVOLUME Volume; 390 uint32_t cSamples; 391 union 392 { 393 struct 394 { 395 /** Volume to use for conversion. */ 396 PDMAUDMIXBUFVOL Volume; 397 } From; 398 }; 367 399 } PDMAUDMIXBUFCONVOPTS; 368 400 /** Pointer to conversion parameters for the audio mixer. */ … … 435 467 /** Intermediate structure for buffer conversion tasks. */ 436 468 PPDMAUDIOSTRMRATE pRate; 437 /** Current volume used for mixing. */438 PDMAUD IOVOLUMEVolume;469 /** Internal representation of current volume used for mixing. */ 470 PDMAUDMIXBUFVOL Volume; 439 471 /** This buffer's audio format. */ 440 472 PDMAUDIOMIXBUFFMT AudioFmt; -
trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp
r61609 r61887 70 70 * value of 0 corresponds to -96dB and 255 corresponds to 0dB (unchanged). 71 71 * 72 * Each step thus correspon s to 96 / 256 or 0.375dB. Every 6dB (16 steps)72 * Each step thus corresponds to 96 / 256 or 0.375dB. Every 6dB (16 steps) 73 73 * represents doubling the sample value. 74 74 * … … 408 408 uint32_t cSamples = RT_MIN(pOpts->cSamples, cbSrc / sizeof(_aType)); \ 409 409 AUDMIXBUF_MACRO_LOG(("cSamples=%RU32, BpS=%zu, lVol=%RU32, rVol=%RU32\n", \ 410 pOpts->cSamples, sizeof(_aType), pOpts-> Volume.uLeft, pOpts->Volume.uRight)); \410 pOpts->cSamples, sizeof(_aType), pOpts->From.Volume.uLeft, pOpts->From.Volume.uRight)); \ 411 411 for (uint32_t i = 0; i < cSamples; i++) \ 412 412 { \ 413 AUDMIXBUF_MACRO_LOG(("l=%#5RI16 (0x%x), r=%#5RI16 (0x%x)", paDst, *pSrc, *pSrc, *(pSrc + 1), *(pSrc + 1))); \ 414 paDst->i64LSample = ASMMult2xS32RetS64((int32_t)audioMixBufClipFrom##_aName(*pSrc++), pOpts->Volume.uLeft ) >> AUDIOMIXBUF_VOL_SHIFT; \ 415 paDst->i64RSample = ASMMult2xS32RetS64((int32_t)audioMixBufClipFrom##_aName(*pSrc++), pOpts->Volume.uRight) >> AUDIOMIXBUF_VOL_SHIFT; \ 416 AUDMIXBUF_MACRO_LOG((" -> l=%#10RI64, r=%#10RI64\n", paDst->i64LSample, paDst->i64RSample)); \ 413 paDst->i64LSample = ASMMult2xS32RetS64((int32_t)audioMixBufClipFrom##_aName(*pSrc++), pOpts->From.Volume.uLeft ) >> AUDIOMIXBUF_VOL_SHIFT; \ 414 paDst->i64RSample = ASMMult2xS32RetS64((int32_t)audioMixBufClipFrom##_aName(*pSrc++), pOpts->From.Volume.uRight) >> AUDIOMIXBUF_VOL_SHIFT; \ 417 415 paDst++; \ 418 416 } \ … … 427 425 const uint32_t cSamples = RT_MIN(pOpts->cSamples, cbSrc / sizeof(_aType)); \ 428 426 AUDMIXBUF_MACRO_LOG(("cSamples=%RU32, BpS=%zu, lVol=%RU32, rVol=%RU32\n", \ 429 cSamples, sizeof(_aType), pOpts-> Volume.uLeft >> 14, pOpts->Volume.uRight)); \427 cSamples, sizeof(_aType), pOpts->From.Volume.uLeft, pOpts->From.Volume.uRight)); \ 430 428 for (uint32_t i = 0; i < cSamples; i++) \ 431 429 { \ 432 paDst->i64LSample = ASMMult2xS32RetS64((int32_t)audioMixBufClipFrom##_aName(*pSrc), pOpts->Volume.uLeft) >> AUDIOMIXBUF_VOL_SHIFT; \ 433 paDst->i64RSample = ASMMult2xS32RetS64((int32_t)audioMixBufClipFrom##_aName(*pSrc), pOpts->Volume.uRight) >> AUDIOMIXBUF_VOL_SHIFT; \ 434 AUDMIXBUF_MACRO_LOG(("%#5RI16 (0x%x) -> l=%#10RI64, r=%#10RI64\n", *pSrc, *pSrc, paDst->i64LSample, paDst->i64RSample)); \ 430 paDst->i64LSample = ASMMult2xS32RetS64((int32_t)audioMixBufClipFrom##_aName(*pSrc), pOpts->From.Volume.uLeft) >> AUDIOMIXBUF_VOL_SHIFT; \ 431 paDst->i64RSample = ASMMult2xS32RetS64((int32_t)audioMixBufClipFrom##_aName(*pSrc), pOpts->From.Volume.uRight) >> AUDIOMIXBUF_VOL_SHIFT; \ 435 432 pSrc++; \ 436 433 paDst++; \ … … 717 714 718 715 /** 716 * Converts a PDM audio volume to an internal mixing buffer volume. 717 * 718 * @returns IPRT status code. 719 * @param pVolDst Where to store the converted mixing buffer volume. 720 * @param pVolSrc Volume to convert. 721 */ 722 static int audioMixBufConvVol(PPDMAUDMIXBUFVOL pVolDst, PPDMAUDIOVOLUME pVolSrc) 723 { 724 if (!pVolSrc->fMuted) /* Only change/convert the volume value if we're not muted. */ 725 { 726 uint8_t uVolL = pVolSrc->uLeft & 0xFF; 727 uint8_t uVolR = pVolSrc->uRight & 0xFF; 728 729 /** @todo Ensure that the input is in the correct range/initialized! */ 730 pVolDst->uLeft = s_aVolumeConv[uVolL] * (AUDIOMIXBUF_VOL_0DB >> 16); 731 pVolDst->uRight = s_aVolumeConv[uVolR] * (AUDIOMIXBUF_VOL_0DB >> 16); 732 } 733 734 pVolDst->fMuted = pVolSrc->fMuted; 735 736 return VINF_SUCCESS; 737 } 738 739 /** 719 740 * Initializes a mixing buffer. 720 741 * … … 1278 1299 if (cToProcess) 1279 1300 { 1280 PFNPDMAUDIOMIXBUFCONVTO pfnConv ;1301 PFNPDMAUDIOMIXBUFCONVTO pfnConvTo = NULL; 1281 1302 if (pMixBuf->AudioFmt != enmFmt) 1282 pfnConv = audioMixBufConvToLookup(enmFmt);1303 pfnConvTo = audioMixBufConvToLookup(enmFmt); 1283 1304 else 1284 pfnConv = pMixBuf->pfnConvTo;1285 1286 if (pfnConv )1305 pfnConvTo = pMixBuf->pfnConvTo; 1306 1307 if (pfnConvTo) 1287 1308 { 1288 PDMAUDMIXBUFCONVOPTS convOpts = { cToProcess, pMixBuf->Volume }; 1289 1290 AssertPtr(pfnConv); 1291 pfnConv(pvBuf, pMixBuf->pSamples + offSamples, &convOpts); 1309 PDMAUDMIXBUFCONVOPTS convOpts; 1310 RT_ZERO(convOpts); 1311 /* Note: No volume handling/conversion done in the conversion-to macros (yet). */ 1312 1313 convOpts.cSamples = cToProcess; 1314 1315 pfnConvTo(pvBuf, pMixBuf->pSamples + offSamples, &convOpts); 1292 1316 1293 1317 #ifdef DEBUG … … 1297 1321 } 1298 1322 else 1323 { 1324 AssertFailed(); 1299 1325 rc = VERR_NOT_SUPPORTED; 1326 } 1300 1327 } 1301 1328 else … … 1348 1375 1349 1376 if (!cbBuf) 1350 return VINF_SUCCESS; 1351 1352 uint32_t cToRead = RT_MIN(AUDIOMIXBUF_B2S(pMixBuf, cbBuf), pMixBuf->cUsed); 1353 1354 AUDMIXBUF_LOG(("%s: pvBuf=%p, cbBuf=%zu (%RU32 samples), cToRead=%RU32\n", 1355 pMixBuf->pszName, pvBuf, cbBuf, AUDIOMIXBUF_B2S(pMixBuf, cbBuf), cToRead)); 1356 1357 if (!cToRead) 1358 { 1359 #ifdef DEBUG 1360 audioMixBufDbgPrintInternal(pMixBuf); 1361 #endif 1377 { 1362 1378 if (pcRead) 1363 1379 *pcRead = 0; … … 1365 1381 } 1366 1382 1367 PFNPDMAUDIOMIXBUFCONVTO pfnConv = audioMixBufConvToLookup(enmFmt); 1368 if (!pfnConv) /* Audio format not supported. */ 1383 uint32_t cToRead = RT_MIN(AUDIOMIXBUF_B2S(pMixBuf, cbBuf), pMixBuf->cUsed); 1384 1385 AUDMIXBUF_LOG(("%s: pvBuf=%p, cbBuf=%zu (%RU32 samples), cToRead=%RU32\n", 1386 pMixBuf->pszName, pvBuf, cbBuf, AUDIOMIXBUF_B2S(pMixBuf, cbBuf), cToRead)); 1387 1388 if (!cToRead) 1389 { 1390 #ifdef DEBUG 1391 audioMixBufDbgPrintInternal(pMixBuf); 1392 #endif 1393 if (pcRead) 1394 *pcRead = 0; 1395 return VINF_SUCCESS; 1396 } 1397 1398 PFNPDMAUDIOMIXBUFCONVTO pfnConvTo = NULL; 1399 if (pMixBuf->AudioFmt != enmFmt) 1400 pfnConvTo = audioMixBufConvToLookup(enmFmt); 1401 else 1402 pfnConvTo = pMixBuf->pfnConvTo; 1403 1404 if (!pfnConvTo) /* Audio format not supported. */ 1405 { 1406 AssertFailed(); 1369 1407 return VERR_NOT_SUPPORTED; 1408 } 1370 1409 1371 1410 PPDMAUDIOSAMPLE pSamplesSrc1 = pMixBuf->pSamples + pMixBuf->offRead; … … 1391 1430 1392 1431 PDMAUDMIXBUFCONVOPTS convOpts; 1393 convOpts.Volume = pMixBuf->Volume; 1432 RT_ZERO(convOpts); 1433 /* Note: No volume handling/conversion done in the conversion-to macros (yet). */ 1394 1434 1395 1435 /* Anything to do at all? */ … … 1397 1437 if (cLenSrc1) 1398 1438 { 1439 AssertPtr(pSamplesSrc1); 1440 1399 1441 convOpts.cSamples = cLenSrc1; 1400 1442 1401 1443 AUDMIXBUF_LOG(("P1: offRead=%RU32, cToRead=%RU32\n", pMixBuf->offRead, cLenSrc1)); 1402 pfnConv (pvBuf, pSamplesSrc1, &convOpts);1444 pfnConvTo(pvBuf, pSamplesSrc1, &convOpts); 1403 1445 } 1404 1446 … … 1413 1455 AUDMIXBUF_LOG(("P2: cToRead=%RU32, offWrite=%RU32 (%zu bytes)\n", cLenSrc2, cLenSrc1, 1414 1456 AUDIOMIXBUF_S2B(pMixBuf, cLenSrc1))); 1415 pfnConv ((uint8_t *)pvBuf + AUDIOMIXBUF_S2B(pMixBuf, cLenSrc1), pSamplesSrc2, &convOpts);1457 pfnConvTo((uint8_t *)pvBuf + AUDIOMIXBUF_S2B(pMixBuf, cLenSrc1), pSamplesSrc2, &convOpts); 1416 1458 } 1417 1459 … … 1474 1516 AssertPtrReturnVoid(pVol); 1475 1517 1476 LogFlowFunc(("%s: lVol=%RU32, rVol=%RU32\n", pMixBuf->pszName, pVol->uLeft, pVol->uRight)); 1477 1478 pMixBuf->Volume.fMuted = pVol->fMuted; 1479 /** @todo Ensure that the input is in the correct range/initialized! */ 1480 pMixBuf->Volume.uLeft = s_aVolumeConv[pVol->uLeft & 0xFF] * (AUDIOMIXBUF_VOL_0DB >> 16); 1481 pMixBuf->Volume.uRight = s_aVolumeConv[pVol->uRight & 0xFF] * (AUDIOMIXBUF_VOL_0DB >> 16); 1482 1483 LogFlowFunc(("\t-> lVol=%#RX32, rVol=%#RX32\n", pMixBuf->Volume.uLeft, pMixBuf->Volume.uRight)); 1518 LogFlowFunc(("%s: lVol=%RU8, rVol=%RU8, fMuted=%RTbool\n", pMixBuf->pszName, pVol->uLeft, pVol->uRight, pVol->fMuted)); 1519 1520 int rc2 = audioMixBufConvVol(&pMixBuf->Volume /* Dest */, pVol /* Source */); 1521 AssertRC(rc2); 1484 1522 } 1485 1523 … … 1637 1675 * Pick the conversion function and do the conversion. 1638 1676 */ 1639 PFNPDMAUDIOMIXBUFCONVFROM pfnConv; 1640 if (pMixBuf->AudioFmt != enmFmt) 1641 pfnConv = audioMixBufConvFromLookup(enmFmt); 1677 PFNPDMAUDIOMIXBUFCONVFROM pfnConvFrom = NULL; 1678 if (!pMixBuf->Volume.fMuted) 1679 { 1680 if (pMixBuf->AudioFmt != enmFmt) 1681 pfnConvFrom = audioMixBufConvFromLookup(enmFmt); 1682 else 1683 pfnConvFrom = pMixBuf->pfnConvFrom; 1684 } 1642 1685 else 1643 pfnConv = pMixBuf->Volume.fMuted ? &audioMixBufConvFromSilence : pMixBuf->pfnConvFrom;1686 pfnConvFrom = &audioMixBufConvFromSilence; 1644 1687 1645 1688 uint32_t cWritten; 1646 if ( pfnConv 1689 if ( pfnConvFrom 1647 1690 && cToWrite) 1648 1691 { 1649 PDMAUDMIXBUFCONVOPTS convOpts = { cToWrite, pMixBuf->Volume }; 1650 cWritten = pfnConv(pMixBuf->pSamples + offSamples, pvBuf, AUDIOMIXBUF_S2B(pMixBuf, cToWrite), &convOpts); 1692 PDMAUDMIXBUFCONVOPTS convOpts; 1693 1694 convOpts.cSamples = cToWrite; 1695 convOpts.From.Volume.fMuted = pMixBuf->Volume.fMuted; 1696 convOpts.From.Volume.uLeft = pMixBuf->Volume.uLeft; 1697 convOpts.From.Volume.uRight = pMixBuf->Volume.uRight; 1698 1699 cWritten = pfnConvFrom(pMixBuf->pSamples + offSamples, pvBuf, AUDIOMIXBUF_S2B(pMixBuf, cToWrite), &convOpts); 1651 1700 } 1652 1701 else 1653 1702 { 1654 1703 cWritten = 0; 1655 if (!pfnConv) 1704 if (!pfnConvFrom) 1705 { 1706 AssertFailed(); 1656 1707 rc = VERR_NOT_SUPPORTED; 1708 } 1657 1709 } 1658 1710 … … 1733 1785 } 1734 1786 1735 PFNPDMAUDIOMIXBUFCONVFROM pfnCnvFrm; 1736 if (pMixBuf->AudioFmt != enmFmt) 1737 pfnCnvFrm = audioMixBufConvFromLookup(enmFmt); 1787 PFNPDMAUDIOMIXBUFCONVFROM pfnConvFrom = NULL; 1788 if (!pMixBuf->Volume.fMuted) 1789 { 1790 if (pMixBuf->AudioFmt != enmFmt) 1791 pfnConvFrom = audioMixBufConvFromLookup(enmFmt); 1792 else 1793 pfnConvFrom = pMixBuf->pfnConvFrom; 1794 } 1738 1795 else 1739 pfnCnvFrm = pMixBuf->Volume.fMuted ? &audioMixBufConvFromSilence : pMixBuf->pfnConvFrom; 1740 1741 if (!pfnCnvFrm) 1796 pfnConvFrom = &audioMixBufConvFromSilence; 1797 1798 if (!pfnConvFrom) 1799 { 1800 AssertFailed(); 1742 1801 return VERR_NOT_SUPPORTED; 1743 1744 int rc = VINF_SUCCESS; /** @todo Move this down to where you actually need it and you'll get somewhat nice code! */ 1802 } 1745 1803 1746 1804 uint32_t cToWrite = AUDIOMIXBUF_B2S(pMixBuf, cbBuf); … … 1782 1840 1783 1841 PDMAUDMIXBUFCONVOPTS convOpts; 1784 convOpts.Volume = pMixBuf->Volume; 1842 convOpts.From.Volume.fMuted = pMixBuf->Volume.fMuted; 1843 convOpts.From.Volume.uLeft = pMixBuf->Volume.uLeft; 1844 convOpts.From.Volume.uRight = pMixBuf->Volume.uRight; 1845 1846 LogFlowFunc(("ASDF %RU32 %RU32\n", pMixBuf->Volume.uLeft, pMixBuf->Volume.uRight)); 1785 1847 1786 1848 /* Anything to do at all? */ … … 1788 1850 { 1789 1851 convOpts.cSamples = cLenDst1; 1790 cWrittenTotal = pfnC nvFrm(pSamplesDst1, pvBuf, AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), &convOpts);1852 cWrittenTotal = pfnConvFrom(pSamplesDst1, pvBuf, AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), &convOpts); 1791 1853 Assert(cWrittenTotal == cLenDst1); 1792 1854 … … 1797 1859 1798 1860 /* Second part present? */ 1799 if ( RT_LIKELY(RT_SUCCESS(rc)) /** @todo r=bird: RT_SUCCESS implies RT_LIKELY for at least 10 years now. besides, it's actually always VINF_SUCCESS at this point. */ 1800 && cLenDst2) 1861 if (cLenDst2) 1801 1862 { 1802 1863 AssertPtr(pSamplesDst2); 1803 1864 1804 1865 convOpts.cSamples = cLenDst2; 1805 cWrittenTotal += pfnC nvFrm(pSamplesDst2,1806 (uint8_t *)pvBuf + AUDIOMIXBUF_S2B(pMixBuf, cLenDst1),1807 cbBuf - AUDIOMIXBUF_S2B(pMixBuf, cLenDst1),1808 &convOpts);1866 cWrittenTotal += pfnConvFrom(pSamplesDst2, 1867 (uint8_t *)pvBuf + AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), 1868 cbBuf - AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), 1869 &convOpts); 1809 1870 Assert(cWrittenTotal == cLenDst1 + cLenDst2); 1810 1871 … … 1819 1880 #endif 1820 1881 1821 if (RT_SUCCESS(rc)) 1822 { 1823 pMixBuf->offWrite = (pMixBuf->offWrite + cWrittenTotal) % pMixBuf->cSamples; 1824 pMixBuf->cUsed += cWrittenTotal; 1825 1826 if (pMixBuf->cUsed > pMixBuf->cSamples) 1827 { 1828 AUDMIXBUF_LOG(("Warning: %RU32 unprocessed samples overwritten\n", pMixBuf->cUsed - pMixBuf->cSamples)); 1829 pMixBuf->cUsed = pMixBuf->cSamples; 1830 1831 rc = VINF_BUFFER_OVERFLOW; 1832 } 1833 1834 if (pcWritten) 1835 *pcWritten = cWrittenTotal; 1836 } 1882 pMixBuf->offWrite = (pMixBuf->offWrite + cWrittenTotal) % pMixBuf->cSamples; 1883 pMixBuf->cUsed += cWrittenTotal; 1884 1885 int rc = VINF_SUCCESS; 1886 1887 if (pMixBuf->cUsed > pMixBuf->cSamples) 1888 { 1889 AUDMIXBUF_LOG(("Warning: %RU32 unprocessed samples overwritten\n", pMixBuf->cUsed - pMixBuf->cSamples)); 1890 pMixBuf->cUsed = pMixBuf->cSamples; 1891 1892 rc = VINF_BUFFER_OVERFLOW; 1893 } 1894 1895 if (pcWritten) 1896 *pcWritten = cWrittenTotal; 1837 1897 1838 1898 #ifdef DEBUG … … 1843 1903 pMixBuf->offWrite, cLenDst1, cLenDst2, cLenDst1 + cLenDst2, 1844 1904 AUDIOMIXBUF_S2B(pMixBuf, cLenDst1 + cLenDst2), rc)); 1845 1846 1905 return rc; 1847 1906 } -
trunk/src/VBox/Devices/Audio/AudioMixer.cpp
r61764 r61887 84 84 /* Set initial volume to max. */ 85 85 pSink->Volume.fMuted = false; 86 pSink->Volume.uLeft = 0x7F; 87 pSink->Volume.uRight = 0x7F; 86 pSink->Volume.uLeft = PDMAUDIO_VOLUME_MAX; 87 pSink->Volume.uRight = PDMAUDIO_VOLUME_MAX; 88 89 /* Ditto for the combined volume. */ 90 pSink->VolumeCombined.fMuted = false; 91 pSink->VolumeCombined.uLeft = PDMAUDIO_VOLUME_MAX; 92 pSink->VolumeCombined.uRight = PDMAUDIO_VOLUME_MAX; 88 93 89 94 RTListAppend(&pMixer->lstSinks, &pSink->Node); … … 125 130 RTListInit(&pMixer->lstSinks); 126 131 132 /* Set master volume to the max. */ 127 133 pMixer->VolMaster.fMuted = false; 128 pMixer->VolMaster.uLeft = UINT32_MAX;129 pMixer->VolMaster.uRight = UINT32_MAX;134 pMixer->VolMaster.uLeft = PDMAUDIO_VOLUME_MAX; 135 pMixer->VolMaster.uRight = PDMAUDIO_VOLUME_MAX; 130 136 131 137 LogFlowFunc(("Created mixer '%s'\n", pMixer->pszName)); … … 200 206 } 201 207 202 void AudioMixerInvalidate(PAUDIOMIXER pMixer)203 { 204 AssertPtrReturn Void(pMixer);205 206 LogFlowFunc(("[%s] : Invalidating ...\n", pMixer->pszName));208 int audioMixerInvalidateInternal(PAUDIOMIXER pMixer) 209 { 210 AssertPtrReturn(pMixer, VERR_INVALID_POINTER); 211 212 LogFlowFunc(("[%s]\n", pMixer->pszName)); 207 213 208 214 /* Propagate new master volume to all connected sinks. */ … … 213 219 AssertRC(rc2); 214 220 } 221 222 return VINF_SUCCESS; 223 } 224 225 void AudioMixerInvalidate(PAUDIOMIXER pMixer) 226 { 227 AssertPtrReturnVoid(pMixer); 228 229 LogFlowFunc(("[%s]\n", pMixer->pszName)); 230 231 int rc2 = audioMixerInvalidateInternal(pMixer); 232 AssertRC(rc2); 215 233 } 216 234 217 235 static int audioMixerRemoveSinkInternal(PAUDIOMIXER pMixer, PAUDMIXSINK pSink) 218 236 { 219 AssertPtrReturn(pMixer, VERR_INVALID_P ARAMETER);237 AssertPtrReturn(pMixer, VERR_INVALID_POINTER); 220 238 if (!pSink) 221 239 return VERR_NOT_FOUND; … … 267 285 AssertPtrReturn(pVol, VERR_INVALID_POINTER); 268 286 269 pMixer->VolMaster = *pVol;287 memcpy(&pMixer->VolMaster, pVol, sizeof(PDMAUDIOVOLUME)); 270 288 271 289 LogFlowFunc(("[%s]: lVol=%RU32, rVol=%RU32 => fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n", … … 273 291 pMixer->VolMaster.fMuted, pMixer->VolMaster.uLeft, pMixer->VolMaster.uRight)); 274 292 275 AudioMixerInvalidate(pMixer); 276 return VINF_SUCCESS; 293 return audioMixerInvalidateInternal(pMixer); 277 294 } 278 295 … … 350 367 /** @todo Check if stream already is assigned to (another) sink. */ 351 368 369 /* Apply the sink's combined volume to the stream. */ 370 AssertPtr(pStream->pConn); 371 int rc2 = pStream->pConn->pfnStreamSetVolume(pStream->pConn, pStream->pStream, &pSink->VolumeCombined); 372 AssertRC(rc2); 373 352 374 /* Save pointer to sink the stream is attached to. */ 353 375 pStream->pSink = pSink; … … 874 896 AssertPtrReturn(pSink, VERR_INVALID_POINTER); 875 897 AssertPtrReturn(pVol, VERR_INVALID_POINTER); 898 899 memcpy(&pSink->Volume, pVol, sizeof(PDMAUDIOVOLUME)); 900 901 LogFlowFunc(("[%s]: fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n", 902 pSink->pszName, pSink->Volume.fMuted, pSink->Volume.uLeft, pSink->Volume.uRight)); 903 876 904 AssertPtr(pSink->pParent); 877 878 LogFlowFunc(("[%s]: fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n", pSink->pszName, pVol->fMuted, pVol->uLeft, pVol->uRight));879 880 pSink->Volume = *pVol;881 882 905 return audioMixerSinkUpdateVolume(pSink, &pSink->pParent->VolMaster); 883 906 } … … 1022 1045 AssertPtrReturn(pVolMaster, VERR_INVALID_POINTER); 1023 1046 1024 LogFlowFunc((" Master fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n",1025 p VolMaster->fMuted, pVolMaster->uLeft, pVolMaster->uRight));1026 LogFlowFunc(("[%s]: fMuted=%RTbool, lVol=%RU32, rVol=%RU32 \n",1047 LogFlowFunc(("[%s]: Master fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n", 1048 pSink->pszName, pVolMaster->fMuted, pVolMaster->uLeft, pVolMaster->uRight)); 1049 LogFlowFunc(("[%s]: fMuted=%RTbool, lVol=%RU32, rVol=%RU32 ", 1027 1050 pSink->pszName, pSink->Volume.fMuted, pSink->Volume.uLeft, pSink->Volume.uRight)); 1028 1051 1029 1052 /** @todo Very crude implementation for now -- needs more work! */ 1030 1053 1031 PDMAUDIOVOLUME volSink; 1032 volSink.fMuted = pVolMaster->fMuted || pSink->Volume.fMuted; 1033 volSink.uLeft = (pSink->Volume.uLeft * pVolMaster->uLeft) / UINT8_MAX; 1034 volSink.uRight = (pSink->Volume.uRight * pVolMaster->uRight) / UINT8_MAX; 1035 1036 LogFlowFunc(("\t-> fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n", 1037 volSink.fMuted, volSink.uLeft, volSink.uRight)); 1038 1039 bool fOut = pSink->enmDir == AUDMIXSINKDIR_OUTPUT; 1054 pSink->VolumeCombined.fMuted = pVolMaster->fMuted || pSink->Volume.fMuted; 1055 1056 pSink->VolumeCombined.uLeft = ( (pSink->Volume.uLeft ? pSink->Volume.uLeft : 1) 1057 * (pVolMaster->uLeft ? pVolMaster->uLeft : 1)) / PDMAUDIO_VOLUME_MAX; 1058 1059 pSink->VolumeCombined.uRight = ( (pSink->Volume.uRight ? pSink->Volume.uRight : 1) 1060 * (pVolMaster->uRight ? pVolMaster->uRight : 1)) / PDMAUDIO_VOLUME_MAX; 1061 1062 LogFlow(("-> fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n", 1063 pSink->VolumeCombined.fMuted, pSink->VolumeCombined.uLeft, pSink->VolumeCombined.uRight)); 1040 1064 1041 1065 /* Propagate new sink volume to all streams in the sink. */ … … 1043 1067 RTListForEach(&pSink->lstStreams, pMixStream, AUDMIXSTREAM, Node) 1044 1068 { 1045 int rc2 = pMixStream->pConn->pfnStreamSetVolume(pMixStream->pConn, pMixStream->pStream, & volSink);1069 int rc2 = pMixStream->pConn->pfnStreamSetVolume(pMixStream->pConn, pMixStream->pStream, &pSink->VolumeCombined); 1046 1070 AssertRC(rc2); 1047 1071 } -
trunk/src/VBox/Devices/Audio/AudioMixer.h
r61668 r61887 181 181 * be combined with the mixer's master volume. */ 182 182 PDMAUDIOVOLUME Volume; 183 /** The volume of this sink, combined with the last set master volume. */ 184 PDMAUDIOVOLUME VolumeCombined; 183 185 /** Timestamp (in ns) since last update. */ 184 186 uint64_t tsLastUpdatedNS; -
trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
r61668 r61887 120 120 #define GS_WCLEAR_MASK (GS_RCS|GS_S1R1|GS_S0R1|GS_GSCI) 121 121 122 /** @name Buffer Descriptor 122 /** @name Buffer Descriptor (BD). 123 123 * @{ */ 124 124 #define BD_IOC RT_BIT(31) /**< Interrupt on Completion. */ … … 128 128 /** @} */ 129 129 130 /** @name Extended Audio Status and Control Register 130 /** @name Extended Audio Status and Control Register (EACS). 131 131 * @{ */ 132 132 #define EACS_VRA 1 /**< Variable Rate Audio (4.2.1.1). */ … … 134 134 /** @} */ 135 135 136 #define VOL_MASK 0x1f 137 #define MUTE_SHIFT 15 136 /** @name Baseline Audio Register Set (BARS). 137 * @{ */ 138 #define AC97_BARS_VOL_MASK 0x1f /**< Volume mask for the Baseline Audio Register Set (5.7.2). */ 139 #define AC97_BARS_VOL_STEPS 31 /**< Volume steps for the Baseline Audio Register Set (5.7.2). */ 140 #define AC97_BARS_VOL_MUTE_SHIFT 15 /**< Mute bit shift for the Baseline Audio Register Set (5.7.2). */ 141 142 #define AC97_BARS_VOL_MASTER_MASK 0x3f /**< Master volume mask for the Baseline Audio Register Set (5.7.2). */ 143 #define AC97_BARS_VOL_MASTER_STEPS 63 /**< Master volume steps for the Baseline Audio Register Set (5.7.2). */ 144 #define AC97_BARS_VOL_MASTER_MUTE_SHIFT 15 /**< Master Mute bit shift for the Baseline Audio Register Set (5.7.2). */ 145 146 #define AC97_VOL_MAX_STEPS 63 147 /** @} */ 138 148 139 149 #define REC_MASK 7 … … 637 647 } 638 648 639 static void ichac97MixerSet(PAC97STATE pThis, uint 32_t u8Idx, uint16_t v)640 { 641 if ( u8Idx + 2> sizeof(pThis->mixer_data))642 { 643 AssertMsgFailed(("Index %RU8 out of bounds(%zu)\n", u 8Idx, sizeof(pThis->mixer_data)));649 static void ichac97MixerSet(PAC97STATE pThis, uint8_t uMixerIdx, uint16_t uVal) 650 { 651 if (size_t(uMixerIdx + 2) > sizeof(pThis->mixer_data)) 652 { 653 AssertMsgFailed(("Index %RU8 out of bounds(%zu)\n", uMixerIdx, sizeof(pThis->mixer_data))); 644 654 return; 645 655 } 646 656 647 pThis->mixer_data[u 8Idx + 0] = RT_LO_U8(v);648 pThis->mixer_data[u 8Idx + 1] = RT_HI_U8(v);649 } 650 651 static uint16_t ichac97MixerGet(PAC97STATE pThis, uint32_t u 8Idx)657 pThis->mixer_data[uMixerIdx + 0] = RT_LO_U8(uVal); 658 pThis->mixer_data[uMixerIdx + 1] = RT_HI_U8(uVal); 659 } 660 661 static uint16_t ichac97MixerGet(PAC97STATE pThis, uint32_t uMixerIdx) 652 662 { 653 663 uint16_t uVal; 654 664 655 if ( u8Idx + 2> sizeof(pThis->mixer_data))656 { 657 AssertMsgFailed(("Index %RU8 out of bounds (%zu)\n", u 8Idx, sizeof(pThis->mixer_data)));665 if (size_t(uMixerIdx + 2) > sizeof(pThis->mixer_data)) 666 { 667 AssertMsgFailed(("Index %RU8 out of bounds (%zu)\n", uMixerIdx, sizeof(pThis->mixer_data))); 658 668 uVal = UINT16_MAX; 659 669 } 660 670 else 661 uVal = RT_MAKE_U16(pThis->mixer_data[u 8Idx + 0], pThis->mixer_data[u8Idx + 1]);671 uVal = RT_MAKE_U16(pThis->mixer_data[uMixerIdx + 0], pThis->mixer_data[uMixerIdx + 1]); 662 672 663 673 return uVal; … … 953 963 } 954 964 955 static int ichac97MixerSetVolume(PAC97STATE pThis, int index, PDMAUDIOMIXERCTL mt, uint32_t val) 956 { 957 int mute = (val >> MUTE_SHIFT) & 1; 958 uint8_t rvol = val & VOL_MASK; 959 uint8_t lvol = (val >> 8) & VOL_MASK; 960 961 /* For the master volume, 0 corresponds to 0dB gain. But for the other 962 * volume controls, 0 corresponds to +12dB and 8 to 0dB. */ 963 if (mt != PDMAUDIOMIXERCTL_VOLUME) 964 { 965 static int ichac97MixerSetVolume(PAC97STATE pThis, int index, PDMAUDIOMIXERCTL enmMixerCtl, uint32_t uVal) 966 { 967 #ifdef DEBUG 968 uint32_t uValMaster = ichac97MixerGet(pThis, AC97_Master_Volume_Mute); 969 970 bool fMasterMuted = (uValMaster >> AC97_BARS_VOL_MASTER_MUTE_SHIFT) & 1; 971 uint8_t lMasterAtt = (uValMaster >> 8) & AC97_BARS_VOL_MASTER_MASK; 972 uint8_t rMasterAtt = uValMaster & AC97_BARS_VOL_MASTER_MASK; 973 974 Assert(lMasterAtt <= AC97_VOL_MAX_STEPS); 975 Assert(rMasterAtt <= AC97_VOL_MAX_STEPS); 976 977 LogFlowFunc(("lMasterAtt=%RU8, rMasterAtt=%RU8, fMasterMuted=%RTbool\n", lMasterAtt, rMasterAtt, fMasterMuted)); 978 #endif 979 980 bool fCntlMuted; 981 uint8_t lCntlAtt, rCntlAtt; 982 983 uint8_t uSteps; 984 985 /* 986 * From AC'97 SoundMax Codec AD1981A/AD1981B: 987 * "Because AC '97 defines 6-bit volume registers, to maintain compatibility whenever the 988 * D5 or D13 bits are set to 1, their respective lower five volume bits are automatically 989 * set to 1 by the Codec logic. On readback, all lower 5 bits will read ones whenever 990 * these bits are set to 1." 991 * 992 * Linux ALSA depends on this behavior. 993 */ 994 if (uVal & RT_BIT(5)) 995 uVal |= RT_BIT(4) | RT_BIT(3) | RT_BIT(2) | RT_BIT(1) | RT_BIT(0); 996 if (uVal & RT_BIT(13)) 997 uVal |= RT_BIT(12) | RT_BIT(11) | RT_BIT(10) | RT_BIT(9) | RT_BIT(8); 998 999 /* For the master volume, 0 corresponds to 0dB attenuation, each step 1000 * corresponds to -1.5dB. */ 1001 if (index == AC97_Master_Volume_Mute) 1002 { 1003 fCntlMuted = (uVal >> AC97_BARS_VOL_MASTER_MUTE_SHIFT) & 1; 1004 lCntlAtt = (uVal >> 8) & AC97_BARS_VOL_MASTER_MASK; 1005 rCntlAtt = uVal & AC97_BARS_VOL_MASTER_MASK; 1006 1007 uSteps = PDMAUDIO_VOLUME_MAX / AC97_BARS_VOL_MASTER_STEPS; 1008 } 1009 /* For other volume controls: 1010 * - 0 - 7 corresponds to +12dB, in 1.5dB steps. 1011 * - 8 corresponds to 0dB gain (unchanged). 1012 * - 9 - X corresponds to -1.5dB steps. */ 1013 else 1014 { 1015 fCntlMuted = (uVal >> AC97_BARS_VOL_MUTE_SHIFT) & 1; 1016 lCntlAtt = (uVal >> 8) & AC97_BARS_VOL_MASK; 1017 rCntlAtt = uVal & AC97_BARS_VOL_MASK; 1018 1019 Assert(lCntlAtt <= AC97_VOL_MAX_STEPS); 1020 Assert(rCntlAtt <= AC97_VOL_MAX_STEPS); 1021 1022 #ifndef VBOX_WITH_AC97_GAIN_SUPPORT 965 1023 /* NB: Currently there is no gain support, only attenuation. */ 966 lvol = lvol < 8 ? 0 : lvol - 8; 967 rvol = rvol < 8 ? 0 : rvol - 8; 968 } 969 970 /* AC'97 has 1.5dB steps; we use 0.375dB steps. */ 971 rvol = 255 - rvol * 4; 972 lvol = 255 - lvol * 4; 973 974 LogFunc(("mt=%ld, val=%RX32, mute=%RTbool\n", mt, val, RT_BOOL(mute))); 1024 lCntlAtt = lCntlAtt <= 8 ? 0 : lCntlAtt - 8; 1025 rCntlAtt = rCntlAtt <= 8 ? 0 : rCntlAtt - 8; 1026 #endif 1027 uSteps = PDMAUDIO_VOLUME_MAX / AC97_BARS_VOL_STEPS; 1028 } 1029 1030 LogFunc(("index=0x%x, uVal=%RU32, enmMixerCtl=%RU32\n", index, uVal, enmMixerCtl)); 1031 1032 LogFunc(("lAtt=%RU8, rAtt=%RU8 ", lCntlAtt, rCntlAtt)); 1033 1034 /* 1035 * AC'97 volume controls have 31 steps, each -1.5dB => -40,5dB attenuation total. 1036 * 1037 * In contrast, we're internally using 255 (PDMAUDIO_VOLUME_MAX) steps, each -0.375dB, 1038 * where 0 corresponds to -96dB and 255 corresponds to 0dB (unchanged). 1039 */ 1040 uint8_t lVol = PDMAUDIO_VOLUME_MAX - RT_MIN((lCntlAtt * 4 /* dB resolution */ * uSteps /* steps */), PDMAUDIO_VOLUME_MAX); 1041 uint8_t rVol = PDMAUDIO_VOLUME_MAX - RT_MIN((rCntlAtt * 4 /* dB resolution */ * uSteps /* steps */), PDMAUDIO_VOLUME_MAX); 1042 1043 Log(("-> fMuted=%RTbool, lVol=%RU8, rVol=%RU8\n", fCntlMuted, lVol, rVol)); 975 1044 976 1045 int rc; … … 978 1047 if (pThis->pMixer) /* Device can be in reset state, so no mixer available. */ 979 1048 { 980 PDMAUDIOVOLUME vol = { RT_BOOL(mute), lvol, rvol };981 switch ( mt)1049 PDMAUDIOVOLUME Vol = { fCntlMuted, lVol, rVol }; 1050 switch (enmMixerCtl) 982 1051 { 983 1052 case PDMAUDIOMIXERCTL_VOLUME: 984 rc = AudioMixerSetMasterVolume(pThis->pMixer, &vol);1053 rc = AudioMixerSetMasterVolume(pThis->pMixer, &Vol); 985 1054 break; 986 987 1055 case PDMAUDIOMIXERCTL_FRONT: 988 rc = AudioMixerSinkSetVolume(pThis->pSinkOutput, & vol);1056 rc = AudioMixerSinkSetVolume(pThis->pSinkOutput, &Vol); 989 1057 break; 990 1058 991 1059 case PDMAUDIOMIXERCTL_MIC_IN: 992 rc = AudioMixerSinkSetVolume(pThis->pSinkMicIn, &vol);1060 rc = AudioMixerSinkSetVolume(pThis->pSinkMicIn, &Vol); 993 1061 break; 994 1062 995 1063 case PDMAUDIOMIXERCTL_LINE_IN: 996 rc = AudioMixerSinkSetVolume(pThis->pSinkLineIn, & vol);1064 rc = AudioMixerSinkSetVolume(pThis->pSinkLineIn, &Vol); 997 1065 break; 998 1066 999 1067 default: 1068 AssertFailed(); 1000 1069 rc = VERR_NOT_SUPPORTED; 1001 1070 break; … … 1005 1074 rc = VINF_SUCCESS; 1006 1075 1007 rvol = VOL_MASK - ((VOL_MASK * rvol) / 255); 1008 lvol = VOL_MASK - ((VOL_MASK * lvol) / 255); 1009 1010 /* 1011 * From AC'97 SoundMax Codec AD1981A: "Because AC '97 defines 6-bit volume registers, to 1012 * maintain compatibility whenever the D5 or D13 bits are set to `1,' their respective 1013 * lower five volume bits are automatically set to `1' by the Codec logic. On readback, 1014 * all lower 5 bits will read ones whenever these bits are set to `1.'" 1015 * 1016 * Linux ALSA depends on this behavior. 1017 */ 1018 if (val & RT_BIT(5)) 1019 val |= RT_BIT(4) | RT_BIT(3) | RT_BIT(2) | RT_BIT(1) | RT_BIT(0); 1020 if (val & RT_BIT(13)) 1021 val |= RT_BIT(12) | RT_BIT(11) | RT_BIT(10) | RT_BIT(9) | RT_BIT(8); 1022 1023 ichac97MixerSet(pThis, index, val); 1076 ichac97MixerSet(pThis, index, uVal); 1024 1077 1025 1078 if (RT_FAILURE(rc)) … … 1110 1163 { 1111 1164 /* Analog Devices 1980 (AD1980) */ 1112 ichac97MixerSet(pThis, AC97_Reset , 0x0010); 1165 ichac97MixerSet(pThis, AC97_Reset , 0x0010); /* Headphones. */ 1113 1166 ichac97MixerSet(pThis, AC97_Vendor_ID1 , 0x4144); 1114 1167 ichac97MixerSet(pThis, AC97_Vendor_ID2 , 0x5370); … … 1129 1182 ichac97RecordSelect(pThis, 0); 1130 1183 1131 ichac97MixerSetVolume(pThis, AC97_Master_Volume_Mute, PDMAUDIOMIXERCTL_VOLUME, 0x8000); 1132 ichac97MixerSetVolume(pThis, AC97_PCM_Out_Volume_Mute, PDMAUDIOMIXERCTL_FRONT, 0x8808); 1133 ichac97MixerSetVolume(pThis, AC97_Line_In_Volume_Mute, PDMAUDIOMIXERCTL_LINE_IN, 0x8808); 1184 ichac97MixerSetVolume(pThis, AC97_Master_Volume_Mute, PDMAUDIOMIXERCTL_VOLUME, 0x8000); 1185 ichac97MixerSetVolume(pThis, AC97_PCM_Out_Volume_Mute, PDMAUDIOMIXERCTL_FRONT, 0x8808); 1186 ichac97MixerSetVolume(pThis, AC97_Line_In_Volume_Mute, PDMAUDIOMIXERCTL_LINE_IN, 0x8808); 1187 ichac97MixerSetVolume(pThis, AC97_Mic_Volume_Mute, PDMAUDIOMIXERCTL_MIC_IN, 0x8808); 1134 1188 1135 1189 return VINF_SUCCESS; … … 1964 2018 case AC97_Master_Volume_Mute: 1965 2019 if (pThis->uCodecModel == Codec_AD1980) 2020 { 1966 2021 if (ichac97MixerGet(pThis, AC97_AD_Misc) & AD_MISC_LOSEL) 1967 break; /* Register controls surround (rear), do nothing. */ 2022 break; /* Register controls surround (rear), do nothing. */ 2023 } 1968 2024 ichac97MixerSetVolume(pThis, index, PDMAUDIOMIXERCTL_VOLUME, u32Val); 1969 2025 break; 1970 2026 case AC97_Headphone_Volume_Mute: 1971 2027 if (pThis->uCodecModel == Codec_AD1980) 2028 { 1972 2029 if (ichac97MixerGet(pThis, AC97_AD_Misc) & AD_MISC_HPSEL) 2030 { 1973 2031 /* Register controls PCM (front) outputs. */ 1974 2032 ichac97MixerSetVolume(pThis, index, PDMAUDIOMIXERCTL_VOLUME, u32Val); 2033 } 2034 } 1975 2035 break; 1976 2036 case AC97_PCM_Out_Volume_Mute: … … 2215 2275 V_(AC97_PCM_Out_Volume_Mute, PDMAUDIOMIXERCTL_FRONT); 2216 2276 V_(AC97_Line_In_Volume_Mute, PDMAUDIOMIXERCTL_LINE_IN); 2277 V_(AC97_Mic_Volume_Mute, PDMAUDIOMIXERCTL_MIC_IN); 2217 2278 # undef V_ 2218 2279 if (pThis->uCodecModel == Codec_AD1980) -
trunk/src/VBox/Devices/Audio/DrvAudio.cpp
r61764 r61887 1607 1607 LogFlowFunc(("%s: volL=%RU32, volR=%RU32, fMute=%RTbool\n", pStream->szName, pVol->uLeft, pVol->uRight, pVol->fMuted)); 1608 1608 1609 AudioMixBufSetVolume(&pStream->MixBuf, pVol); 1610 1609 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); 1610 PPDMAUDIOSTREAM pGstStream = pHstStream ? pHstStream->pPair : pStream; 1611 1612 AudioMixBufSetVolume(&pHstStream->MixBuf, pVol); 1613 AudioMixBufSetVolume(&pGstStream->MixBuf, pVol); 1611 1614 return VINF_SUCCESS; 1612 1615 }
Note:
See TracChangeset
for help on using the changeset viewer.