From: <man...@us...> - 2013-11-18 21:47:09
|
Revision: 3267 http://sourceforge.net/p/modplug/code/3267 Author: manxorist Date: 2013-11-18 21:46:59 +0000 (Mon, 18 Nov 2013) Log Message: ----------- [Fix] ASIO: Allow buffer sizes smaller than 32 samples. [Fix] ASIO: Actually honor user-selected latency value for devices that require power-of-2 buffer sizes instead of blindly falling back to peferred size (broken since at least r37 ). [Ref] ASIO: Rewrite buffer size selection code to be more tolerant about broken ASIO drivers. Revision Links: -------------- http://sourceforge.net/p/modplug/code/37 Modified Paths: -------------- trunk/OpenMPT/common/misc_util.h trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp trunk/OpenMPT/sounddev/SoundDeviceASIO.h Modified: trunk/OpenMPT/common/misc_util.h =================================================================== --- trunk/OpenMPT/common/misc_util.h 2013-11-18 20:39:03 UTC (rev 3266) +++ trunk/OpenMPT/common/misc_util.h 2013-11-18 21:46:59 UTC (rev 3267) @@ -382,6 +382,18 @@ const T intval = static_cast<T>(valRounded); return intval; } + + template<typename T> + T Weight(T x) + { + STATIC_ASSERT(std::numeric_limits<T>::is_integer); + T c; + for(c = 0; x; x >>= 1) + { + c += x & 1; + } + return c; + } } Modified: trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2013-11-18 20:39:03 UTC (rev 3266) +++ trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2013-11-18 21:46:59 UTC (rev 3267) @@ -267,32 +267,52 @@ minSize, maxSize, preferredSize, granularity); #endif m_nAsioBufferLen = ((m_Settings.LatencyMS * m_Settings.Samplerate) / 2000); - if (m_nAsioBufferLen < (UINT)minSize) m_nAsioBufferLen = minSize; else - if (m_nAsioBufferLen > (UINT)maxSize) m_nAsioBufferLen = maxSize; else - if (granularity < 0) - { - //rewbs.ASIOfix: - /*UINT n = (minSize < 32) ? 32 : minSize; - if (n % granularity) n = (n + granularity - 1) - (n % granularity); - while ((n+(n>>1) < m_nAsioBufferLen) && (n*2 <= (UINT)maxSize)) + if(minSize <= 0 || maxSize <= 0 || minSize > maxSize) + { // limits make no sense + if(preferredSize > 0) { - n *= 2; + m_nAsioBufferLen = preferredSize; + } else + { + // just leave the user value, perhaps it works } - m_nAsioBufferLen = n;*/ - //end rewbs.ASIOfix - m_nAsioBufferLen = preferredSize; - - } else - if (granularity > 0) - { - int n = (minSize < 32) ? 32 : minSize; - n = (n + granularity-1); - n -= (n % granularity); - while ((n+(granularity>>1) < (int)m_nAsioBufferLen) && (n+granularity <= maxSize)) + } else if(granularity < -1) + { // granularity value not allowed, just clamp value + m_nAsioBufferLen = Clamp(m_nAsioBufferLen, minSize, maxSize); + } else if(granularity == -1 && (Util::Weight(minSize) != 1 || Util::Weight(maxSize) != 1)) + { // granularity tells us we need power-of-2 sizes, but min or max sizes are no power-of-2 + m_nAsioBufferLen = Clamp(m_nAsioBufferLen, minSize, maxSize); + // just start at 1 and find a matching power-of-2 in range + const long bufTarget = m_nAsioBufferLen; + for(long bufSize = 1; bufSize <= maxSize && bufSize <= bufTarget; bufSize *= 2) { - n += granularity; + if(bufSize >= minSize) + { + m_nAsioBufferLen = bufSize; + } } - m_nAsioBufferLen = n; + // if no power-of-2 in range is found, just leave the clamped value alone, perhaps it works + } else if(granularity == -1) + { // sane values, power-of-2 size required between min and max + m_nAsioBufferLen = Clamp(m_nAsioBufferLen, minSize, maxSize); + // get the largest allowed buffer size that is smaller or equal to the target size + const long bufTarget = m_nAsioBufferLen; + for(long bufSize = minSize; bufSize <= maxSize && bufSize <= bufTarget; bufSize *= 2) + { + m_nAsioBufferLen = bufSize; + } + } else if(granularity > 0) + { // buffer size in granularity steps from min to max allowed + m_nAsioBufferLen = Clamp(m_nAsioBufferLen, minSize, maxSize); + // get the largest allowed buffer size that is smaller or equal to the target size + const long bufTarget = m_nAsioBufferLen; + for(long bufSize = minSize; bufSize <= maxSize && bufSize <= bufTarget; bufSize += granularity) + { + m_nAsioBufferLen = bufSize; + } + } else + { // should not happen + ASSERT(false); } #ifdef ASIO_LOG Log(" Using buffersize=%d samples\n", m_nAsioBufferLen); Modified: trunk/OpenMPT/sounddev/SoundDeviceASIO.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceASIO.h 2013-11-18 20:39:03 UTC (rev 3266) +++ trunk/OpenMPT/sounddev/SoundDeviceASIO.h 2013-11-18 21:46:59 UTC (rev 3267) @@ -34,7 +34,7 @@ enum { ASIO_MAX_CHANNELS=4 }; protected: IASIO *m_pAsioDrv; - UINT m_nAsioBufferLen; + long m_nAsioBufferLen; UINT m_nAsioSampleSize; bool m_Float; bool m_CanOutputReady; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |