From: <man...@us...> - 2013-11-20 21:16:01
|
Revision: 3280 http://sourceforge.net/p/modplug/code/3280 Author: manxorist Date: 2013-11-20 21:15:52 +0000 (Wed, 20 Nov 2013) Log Message: ----------- [Ref] sounddev: Add ASIO/VST style timing information to the ISoundDevice rendering callbacks interface. A generic algorithm to gather a timing information erstimate is implemented which should work for any ISoundDevice. For devices that support accurate stream position query (waveout in the OpenMPT codebase), this is used to increase precision. The interface is prepared to support direct timing information forwarding from device APIs that support that (ASIO and PortAudio in the OpenMPT codebase), but this is not implemented yet. The timing information remains unused in GUI or plugin handling code as of now (this requires more work). Modified Paths: -------------- trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Mainfrm.h trunk/OpenMPT/sounddev/SoundDevice.cpp trunk/OpenMPT/sounddev/SoundDevice.h trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp trunk/OpenMPT/sounddev/SoundDeviceASIO.h trunk/OpenMPT/sounddev/SoundDeviceDirectSound.cpp trunk/OpenMPT/sounddev/SoundDeviceDirectSound.h trunk/OpenMPT/sounddev/SoundDevicePortAudio.cpp trunk/OpenMPT/sounddev/SoundDevicePortAudio.h trunk/OpenMPT/sounddev/SoundDeviceWaveout.cpp trunk/OpenMPT/sounddev/SoundDeviceWaveout.h Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2013-11-20 17:35:29 UTC (rev 3279) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2013-11-20 21:15:52 UTC (rev 3280) @@ -724,9 +724,10 @@ }; -void CMainFrame::AudioRead(const SoundDeviceSettings &settings, std::size_t numFrames, void *buffer) -//-------------------------------------------------------------------------------------------------- +void CMainFrame::AudioRead(const SoundDeviceSettings &settings, SoundTimeInfo timeInfo, std::size_t numFrames, void *buffer) +//-------------------------------------------------------------------------------------------------------------------------- { + MPT_UNREFERENCED_PARAMETER(timeInfo); ASSERT(InAudioThread()); OPENMPT_PROFILE_FUNCTION(Profiler::Audio); StereoVuMeterTargetWrapper target(settings.sampleFormat, m_Dither, buffer); @@ -749,10 +750,11 @@ } -void CMainFrame::AudioDone(const SoundDeviceSettings &settings, std::size_t numFrames, int64 streamPosition) -//---------------------------------------------------------------------------------------------------------- +void CMainFrame::AudioDone(const SoundDeviceSettings &settings, SoundTimeInfo timeInfo, std::size_t numFrames, int64 streamPosition) +//---------------------------------------------------------------------------------------------------------------------------------- { MPT_UNREFERENCED_PARAMETER(settings); + MPT_UNREFERENCED_PARAMETER(timeInfo); ASSERT(InAudioThread()); OPENMPT_PROFILE_FUNCTION(Profiler::Notify); DoNotification(numFrames, streamPosition); Modified: trunk/OpenMPT/mptrack/Mainfrm.h =================================================================== --- trunk/OpenMPT/mptrack/Mainfrm.h 2013-11-20 17:35:29 UTC (rev 3279) +++ trunk/OpenMPT/mptrack/Mainfrm.h 2013-11-20 21:15:52 UTC (rev 3280) @@ -332,8 +332,8 @@ // from ISoundSource void FillAudioBufferLocked(IFillAudioBuffer &callback); - void AudioRead(const SoundDeviceSettings &settings, std::size_t numFrames, void *buffer); - void AudioDone(const SoundDeviceSettings &settings, std::size_t numFrames, int64 streamPosition); + void AudioRead(const SoundDeviceSettings &settings, SoundTimeInfo timeInfo, std::size_t numFrames, void *buffer); + void AudioDone(const SoundDeviceSettings &settings, SoundTimeInfo timeInfo, std::size_t numFrames, int64 streamPosition); // from ISoundMessageReceiver void AudioMessage(const std::string &str); Modified: trunk/OpenMPT/sounddev/SoundDevice.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.cpp 2013-11-20 17:35:29 UTC (rev 3279) +++ trunk/OpenMPT/sounddev/SoundDevice.cpp 2013-11-20 21:15:52 UTC (rev 3280) @@ -106,6 +106,13 @@ } +void ISoundDevice::UpdateTimeInfo(SoundTimeInfo timeInfo) +//------------------------------------------------------- +{ + m_TimeInfo = timeInfo; +} + + bool ISoundDevice::Open(const SoundDeviceSettings &settings) //---------------------------------------------------------- { @@ -134,6 +141,13 @@ } +void ISoundDevice::FillAudioBuffer() +//---------------------------------- +{ + InternalFillAudioBuffer(); +} + + void ISoundDevice::SourceFillAudioBufferLocked() //---------------------------------------------- { @@ -144,6 +158,33 @@ } +void ISoundDevice::SourceAudioPreRead(std::size_t numFrames) +//---------------------------------------------------------- +{ + if(!InternalHasTimeInfo()) + { + if(InternalHasGetStreamPosition()) + { + SoundTimeInfo timeInfo; + timeInfo.StreamFrames = InternalHasGetStreamPosition(); + timeInfo.SystemTimestamp = m_Clock.Now() * (uint64)1000 * (uint64)1000; + timeInfo.Speed = 1.0; + UpdateTimeInfo(timeInfo); + } else + { + SoundTimeInfo timeInfo; + { + Util::lock_guard<Util::mutex> lock(m_StreamPositionMutex); + timeInfo.StreamFrames = m_StreamPositionRenderFrames + numFrames; + } + timeInfo.SystemTimestamp = (m_Clock.Now() + m_Settings.LatencyMS) * (uint64)1000 * (uint64)1000; + timeInfo.Speed = 1.0; + UpdateTimeInfo(timeInfo); + } + } +} + + void ISoundDevice::SourceAudioRead(void *buffer, std::size_t numFrames) //--------------------------------------------------------------------- { @@ -151,7 +192,7 @@ { return; } - m_Source->AudioRead(m_Settings, numFrames, buffer); + m_Source->AudioRead(m_Settings, m_TimeInfo, numFrames, buffer); } @@ -170,7 +211,7 @@ m_StreamPositionOutputFrames = m_StreamPositionRenderFrames - framesLatency; framesRendered = m_StreamPositionRenderFrames; } - m_Source->AudioDone(m_Settings, numFrames, framesRendered); + m_Source->AudioDone(m_Settings, m_TimeInfo, numFrames, framesRendered); } @@ -196,8 +237,10 @@ m_StreamPositionRenderFrames = 0; m_StreamPositionOutputFrames = 0; } + m_Clock.SetResolution(1); if(!InternalStart()) { + m_Clock.SetResolution(0); return false; } m_IsPlaying = true; @@ -213,6 +256,7 @@ if(IsPlaying()) { InternalStop(); + m_Clock.SetResolution(0); m_IsPlaying = false; { Util::lock_guard<Util::mutex> lock(m_StreamPositionMutex); Modified: trunk/OpenMPT/sounddev/SoundDevice.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.h 2013-11-20 17:35:29 UTC (rev 3279) +++ trunk/OpenMPT/sounddev/SoundDevice.h 2013-11-20 21:15:52 UTC (rev 3280) @@ -12,6 +12,7 @@ #pragma once #include "../common/mutex.h" +#include "../common/misc_util.h" #include "../soundlib/SampleFormat.h" #include <map> @@ -50,14 +51,29 @@ }; +struct SoundTimeInfo +{ + uint64 StreamFrames; + uint64 SystemTimestamp; + double Speed; + SoundTimeInfo() + : StreamFrames(0) + , SystemTimestamp(0) + , Speed(1.0) + { + return; + } +}; + + //================ class ISoundSource //================ { public: virtual void FillAudioBufferLocked(IFillAudioBuffer &callback) = 0; // take any locks needed while rendering audio and then call FillAudioBuffer - virtual void AudioRead(const SoundDeviceSettings &settings, std::size_t numFrames, void *buffer) = 0; - virtual void AudioDone(const SoundDeviceSettings &settings, std::size_t numFrames, int64 streamPosition) = 0; // in sample frames + virtual void AudioRead(const SoundDeviceSettings &settings, SoundTimeInfo timeInfo, std::size_t numFrames, void *buffer) = 0; + virtual void AudioDone(const SoundDeviceSettings &settings, SoundTimeInfo timeInfo, std::size_t numFrames, int64 streamPosition) = 0; // in sample frames }; @@ -250,6 +266,9 @@ bool m_IsPlaying; + Util::MultimediaClock m_Clock; + SoundTimeInfo m_TimeInfo; + mutable Util::mutex m_StreamPositionMutex; double m_CurrentUpdateInterval; int64 m_StreamPositionRenderFrames; @@ -257,9 +276,12 @@ protected: - virtual void FillAudioBuffer() = 0; + virtual void InternalFillAudioBuffer() = 0; + void FillAudioBuffer(); + void SourceFillAudioBufferLocked(); + void SourceAudioPreRead(std::size_t numFrames); void SourceAudioRead(void *buffer, std::size_t numFrames); void SourceAudioDone(std::size_t numFrames, int32 framesLatency); @@ -270,7 +292,10 @@ bool FillWaveFormatExtensible(WAVEFORMATEXTENSIBLE &WaveFormat); void UpdateBufferAttributes(SoundBufferAttributes attributes); + void UpdateTimeInfo(SoundTimeInfo timeInfo); + virtual bool InternalHasTimeInfo() const { return false; } + virtual bool InternalHasGetStreamPosition() const { return false; } virtual int64 InternalGetStreamPositionFrames() const { return 0; } Modified: trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2013-11-20 17:35:29 UTC (rev 3279) +++ trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2013-11-20 21:15:52 UTC (rev 3280) @@ -586,8 +586,8 @@ } -void CASIODevice::FillAudioBuffer() -//--------------------------------- +void CASIODevice::InternalFillAudioBuffer() +//----------------------------------------- { const bool rendersilence = (InterlockedExchangeAdd(&m_RenderSilence, 0) == 1); const int channels = m_Settings.Channels; @@ -598,6 +598,7 @@ std::memset(&m_SampleBuffer[0], 0, countChunk * channels * sizeof(int32)); } else { + SourceAudioPreRead(countChunk); SourceAudioRead(&m_SampleBuffer[0], countChunk); } for(int channel = 0; channel < channels; ++channel) @@ -695,7 +696,7 @@ InterlockedExchange(&m_RenderingSilence, rendersilence ? 1 : 0 ); if(rendersilence) { - FillAudioBuffer(); + InternalFillAudioBuffer(); } else { SourceFillAudioBufferLocked(); Modified: trunk/OpenMPT/sounddev/SoundDeviceASIO.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceASIO.h 2013-11-20 17:35:29 UTC (rev 3279) +++ trunk/OpenMPT/sounddev/SoundDeviceASIO.h 2013-11-20 21:15:52 UTC (rev 3280) @@ -58,7 +58,7 @@ public: bool InternalOpen(); bool InternalClose(); - void FillAudioBuffer(); + void InternalFillAudioBuffer(); bool InternalStart(); void InternalStop(); bool InternalIsOpen() const { return (m_pAsioDrv != nullptr); } Modified: trunk/OpenMPT/sounddev/SoundDeviceDirectSound.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceDirectSound.cpp 2013-11-20 17:35:29 UTC (rev 3279) +++ trunk/OpenMPT/sounddev/SoundDeviceDirectSound.cpp 2013-11-20 21:15:52 UTC (rev 3280) @@ -289,7 +289,7 @@ //---------------------------------------- { if(!m_pMixBuffer) return; - // done in FillAudioBuffer for now + // done in InternalFillAudioBuffer for now } @@ -363,8 +363,8 @@ } -void CDSoundDevice::FillAudioBuffer() -//----------------------------------- +void CDSoundDevice::InternalFillAudioBuffer() +//------------------------------------------- { LPVOID lpBuf1=NULL, lpBuf2=NULL; DWORD dwSize1=0, dwSize2=0; @@ -375,6 +375,10 @@ if (dwBytes) { const std::size_t bytesPerFrame = m_Settings.GetBytesPerFrame(); + std::size_t countChunk = 0; + if(lpBuf1 && (dwSize1 > 0)) countChunk += dwSize1/bytesPerFrame; + if(lpBuf2 && (dwSize2 > 0)) countChunk += dwSize2/bytesPerFrame; + SourceAudioPreRead(countChunk); if ((lpBuf1) && (dwSize1)) SourceAudioRead(lpBuf1, dwSize1/bytesPerFrame); if ((lpBuf2) && (dwSize2)) SourceAudioRead(lpBuf2, dwSize2/bytesPerFrame); UnlockBuffer(lpBuf1, dwSize1, lpBuf2, dwSize2); Modified: trunk/OpenMPT/sounddev/SoundDeviceDirectSound.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceDirectSound.h 2013-11-20 17:35:29 UTC (rev 3279) +++ trunk/OpenMPT/sounddev/SoundDeviceDirectSound.h 2013-11-20 21:15:52 UTC (rev 3280) @@ -42,7 +42,7 @@ public: bool InternalOpen(); bool InternalClose(); - void FillAudioBuffer(); + void InternalFillAudioBuffer(); void StartFromSoundThread(); void StopFromSoundThread(); bool InternalIsOpen() const { return (m_pMixBuffer != NULL); } Modified: trunk/OpenMPT/sounddev/SoundDevicePortAudio.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDevicePortAudio.cpp 2013-11-20 17:35:29 UTC (rev 3279) +++ trunk/OpenMPT/sounddev/SoundDevicePortAudio.cpp 2013-11-20 21:15:52 UTC (rev 3280) @@ -136,12 +136,13 @@ } -void CPortaudioDevice::FillAudioBuffer() -//-------------------------------------- +void CPortaudioDevice::InternalFillAudioBuffer() +//---------------------------------------------- { if(m_CurrentFrameCount == 0) return; + SourceAudioPreRead(m_CurrentFrameCount); SourceAudioRead(m_CurrentFrameBuffer, m_CurrentFrameCount); - SourceAudioDone(m_CurrentFrameCount, static_cast<ULONG>(m_CurrentRealLatency * m_StreamInfo->sampleRate)); + SourceAudioDone(m_CurrentFrameCount, Util::Round<int32>(m_CurrentRealLatency * m_StreamInfo->sampleRate)); } Modified: trunk/OpenMPT/sounddev/SoundDevicePortAudio.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDevicePortAudio.h 2013-11-20 17:35:29 UTC (rev 3279) +++ trunk/OpenMPT/sounddev/SoundDevicePortAudio.h 2013-11-20 21:15:52 UTC (rev 3280) @@ -46,7 +46,7 @@ public: bool InternalOpen(); bool InternalClose(); - void FillAudioBuffer(); + void InternalFillAudioBuffer(); bool InternalStart(); void InternalStop(); bool InternalIsOpen() const { return m_Stream ? true : false; } Modified: trunk/OpenMPT/sounddev/SoundDeviceWaveout.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceWaveout.cpp 2013-11-20 17:35:29 UTC (rev 3279) +++ trunk/OpenMPT/sounddev/SoundDeviceWaveout.cpp 2013-11-20 21:15:52 UTC (rev 3280) @@ -131,7 +131,7 @@ if(m_hWaveOut) { m_JustStarted = true; - // Actual starting is done in FillAudioBuffer to avoid crackling with tiny buffers. + // Actual starting is done in InternalFillAudioBuffer to avoid crackling with tiny buffers. } } @@ -147,8 +147,8 @@ } -void CWaveDevice::FillAudioBuffer() -//--------------------------------- +void CWaveDevice::InternalFillAudioBuffer() +//----------------------------------------- { if(!m_hWaveOut) { @@ -163,6 +163,7 @@ ULONG nBytesWritten = 0; while(oldBuffersPending < m_nPreparedHeaders) { + SourceAudioPreRead(m_nWaveBufferSize / bytesPerFrame); SourceAudioRead(m_WaveBuffers[m_nWriteBuffer].lpData, m_nWaveBufferSize / bytesPerFrame); nLatency += m_nWaveBufferSize; nBytesWritten += m_nWaveBufferSize; Modified: trunk/OpenMPT/sounddev/SoundDeviceWaveout.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceWaveout.h 2013-11-20 17:35:29 UTC (rev 3279) +++ trunk/OpenMPT/sounddev/SoundDeviceWaveout.h 2013-11-20 21:15:52 UTC (rev 3280) @@ -41,7 +41,7 @@ public: bool InternalOpen(); bool InternalClose(); - void FillAudioBuffer(); + void InternalFillAudioBuffer(); void StartFromSoundThread(); void StopFromSoundThread(); bool InternalIsOpen() const { return (m_hWaveOut != NULL); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |