Changeset 89640 in vbox for trunk/src/VBox/Devices/Audio
- Timestamp:
- Jun 11, 2021 11:04:20 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 145085
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
r89639 r89640 309 309 /** Location of data buffer (bits 31:1). */ 310 310 uint32_t addr; 311 /** Flags (bits 31 + 30) and length (bits 15:0) of data buffer (in audio samples). */ 311 /** Flags (bits 31 + 30) and length (bits 15:0) of data buffer (in audio samples). 312 * @todo split up into two 16-bit fields. */ 312 313 uint32_t ctl_len; 313 314 } AC97BDLE; … … 1810 1811 1811 1812 /* 1813 * Read the buffer descriptors and check what the max distance between 1814 * interrupts are, so we can more correctly size the internal DMA buffer. 1815 * 1816 * Note! The buffer list are not fixed once the stream starts running as 1817 * with HDA, so this is just a general idea of what the guest is 1818 * up to and we cannot really make much of a plan out of it. 1819 */ 1820 AC97BDLE aBdl[AC97_MAX_BDLE]; 1821 RT_ZERO(aBdl); 1822 unsigned const cBuffers = pStream->Regs.lvi + 1; 1823 PDMDevHlpPCIPhysRead(pDevIns, pStream->Regs.bdbar, aBdl, sizeof(aBdl[0]) * cBuffers); 1824 1825 uint32_t cSamplesMax = 0; 1826 uint32_t cSamplesMin = UINT32_MAX; 1827 uint32_t cSamplesCur = 0; 1828 uint32_t cSamplesTotal = 0; 1829 for (unsigned i = 0; i < cBuffers; i++) 1830 { 1831 cSamplesCur += aBdl[0].ctl_len & AC97_BD_LEN_MASK; 1832 cSamplesTotal += aBdl[0].ctl_len & AC97_BD_LEN_MASK; 1833 if (aBdl[0].ctl_len & AC97_BD_IOC) 1834 { 1835 if (cSamplesCur > cSamplesMax) 1836 cSamplesMax = cSamplesCur; 1837 if (cSamplesCur < cSamplesMin) 1838 cSamplesMin = cSamplesCur; 1839 cSamplesCur = 0; 1840 } 1841 } 1842 1843 if (cSamplesCur && cSamplesMax != 0) 1844 { 1845 LogFlowFunc(("Tail buffer w/o IOC, loops.\n")); 1846 for (unsigned i = 0; i < cBuffers; i++) 1847 { 1848 cSamplesCur += aBdl[0].ctl_len & AC97_BD_LEN_MASK; 1849 if (aBdl[0].ctl_len & AC97_BD_IOC) 1850 { 1851 if (cSamplesCur > cSamplesMax) 1852 cSamplesMax = cSamplesCur; 1853 if (cSamplesCur < cSamplesMin) 1854 cSamplesMin = cSamplesCur; 1855 cSamplesCur = 0; 1856 break; 1857 } 1858 } 1859 } 1860 1861 uint32_t const cbDmaMinBuf = cSamplesMax * PDMAudioPropsSampleSize(&Cfg.Props) * 3; /* see further down */ 1862 uint32_t const cMsDmaMinBuf = PDMAudioPropsBytesToMilli(&Cfg.Props, cbDmaMinBuf); 1863 LogRel3(("AC97: [SD%RU8] buffer length stats: total=%#x in %u buffers, min=%#x, max=%#x => min DMA buffer %u ms / %#x bytes\n", 1864 pStream->u8SD, cSamplesTotal, cBuffers, cSamplesMin, cSamplesMax, cMsDmaMinBuf, cbDmaMinBuf)); 1865 1866 /* 1812 1867 * Only (re-)create the stream (and driver chain) if we really have to. 1813 1868 * Otherwise avoid this and just reuse it, as this costs performance. 1814 1869 */ 1815 1870 int rc = VINF_SUCCESS; 1816 if ( !PDMAudioStrmCfgMatchesProps(&Cfg, &pStreamCC->State.Cfg.Props) 1817 || fForce) 1871 if ( fForce 1872 || !PDMAudioStrmCfgMatchesProps(&Cfg, &pStreamCC->State.Cfg.Props) 1873 || !pStreamCC->State.pCircBuf 1874 || cbDmaMinBuf > RTCircBufSize(pStreamCC->State.pCircBuf)) 1818 1875 { 1819 1876 LogRel2(("AC97: (Re-)Opening stream '%s' (%RU32Hz, %RU8 channels, %s%RU8)\n", Cfg.szName, Cfg.Props.uHz, … … 1862 1919 * the minimums here. The less buffer the less possible delay can build when 1863 1920 * TM is doing catch up. 1864 *1865 * Unlike the HDA code, we currently do not have any knowledge of the buffer1866 * timinings, so we only have the scheduling hint to work with.1867 1921 */ 1868 uint32_t const cMsCircBuf = RT_MAX(Cfg.enmDir == PDMAUDIODIR_IN ? pThis->cMsCircBufIn : pThis->cMsCircBufOut, 1869 Cfg.Device.cMsSchedulingHint * 3); 1870 uint32_t const cbCircBuf = PDMAudioPropsMilliToBytes(&Cfg.Props, cMsCircBuf); 1922 uint32_t cMsCircBuf = Cfg.enmDir == PDMAUDIODIR_IN ? pThis->cMsCircBufIn : pThis->cMsCircBufOut; 1923 cMsCircBuf = RT_MAX(cMsCircBuf, cMsDmaMinBuf); 1924 cMsCircBuf = RT_MAX(cMsCircBuf, Cfg.Device.cMsSchedulingHint * 3); 1925 cMsCircBuf = RT_MIN(cMsCircBuf, RT_MS_1SEC * 2); /** @todo make sure the DMA timer doesn't go over 500ms (use uTimerHz as max, really). */ 1926 uint32_t const cbCircBuf = PDMAudioPropsMilliToBytes(&Cfg.Props, cMsCircBuf); 1871 1927 1872 1928 if (pStreamCC->State.pCircBuf && RTCircBufSize(pStreamCC->State.pCircBuf) == cbCircBuf) … … 1874 1930 else 1875 1931 { 1876 LogFlowFunc(("Re-creating circular buffer with size %u ms / %#x bytes (was %#x)\n", 1877 cMsCircBuf, cbCircBuf, pStreamCC->State.StatDmaBufSize)); 1932 LogFlowFunc(("Re-creating circular buffer with size %u ms / %#x bytes (was %#x); cMsSchedulingHint=%u cMsDmaMinBuf=%u cMsCircBufXxx=%u\n", 1933 cMsCircBuf, cbCircBuf, pStreamCC->State.StatDmaBufSize, Cfg.Device.cMsSchedulingHint, cMsDmaMinBuf, 1934 Cfg.enmDir == PDMAUDIODIR_IN ? pThis->cMsCircBufIn : pThis->cMsCircBufOut)); 1878 1935 if (pStreamCC->State.pCircBuf) 1879 1936 RTCircBufDestroy(pStreamCC->State.pCircBuf);
Note:
See TracChangeset
for help on using the changeset viewer.