From 614bca7f04ce1ea35a50b0ac823b784907e4046a Mon Sep 17 00:00:00 2001 From: Dominic Clark Date: Sun, 25 Nov 2018 17:09:08 +0000 Subject: [PATCH] Make ppqPos in VST sync sample accurate --- include/VstSyncController.h | 4 ++-- include/VstSyncData.h | 2 +- plugins/vst_base/RemoteVstPlugin.cpp | 22 ++++++++++++++++------ src/core/Song.cpp | 21 ++++++++++++++------- src/core/VstSyncController.cpp | 6 +++--- 5 files changed, 36 insertions(+), 19 deletions(-) diff --git a/include/VstSyncController.h b/include/VstSyncController.h index e858f5545..682291b9e 100644 --- a/include/VstSyncController.h +++ b/include/VstSyncController.h @@ -39,7 +39,7 @@ public: VstSyncController(); ~VstSyncController(); - void setAbsolutePosition( int ticks ); + void setAbsolutePosition( double ticks ); void setPlaybackState( bool enabled ) { @@ -77,7 +77,7 @@ private: struct VstSyncData { bool isPlaying; - float ppqPos; + double ppqPos; int timeSigNumer; int timeSigDenom; bool isCycle; diff --git a/include/VstSyncData.h b/include/VstSyncData.h index d8694f1b2..f9696252a 100644 --- a/include/VstSyncData.h +++ b/include/VstSyncData.h @@ -42,7 +42,7 @@ struct VstSyncData { bool isPlaying; - float ppqPos; + double ppqPos; int timeSigNumer; int timeSigDenom; bool isCycle; diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index e0fcb3ba6..fbffe4b34 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -395,8 +395,8 @@ private: // host to plugin synchronisation data structure struct in { - float lastppqPos; - float m_Timestamp; + double lastppqPos; + double m_Timestamp; int32_t m_lastFlags; } ; @@ -1605,10 +1605,20 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode, } else if( __plugin->m_vstSyncData->isPlaying ) { - __plugin->m_in->lastppqPos += ( - __plugin->m_vstSyncData->hasSHM ? - __plugin->m_vstSyncData->m_bpm : - __plugin->m_bpm ) / (float)10340; + if( __plugin->m_vstSyncData->hasSHM ) + { + __plugin->m_in->lastppqPos += + __plugin->m_vstSyncData->m_bpm / 60.0 + * __plugin->m_vstSyncData->m_bufferSize + / __plugin->m_vstSyncData->m_sampleRate; + } + else + { + __plugin->m_in->lastppqPos += + __plugin->m_bpm / 60.0 + * __plugin->bufferSize() + / __plugin->sampleRate(); + } _timeInfo.ppqPos = __plugin->m_in->lastppqPos; } // _timeInfo.ppqPos = __plugin->m_vstSyncData->ppqPos; diff --git a/src/core/Song.cpp b/src/core/Song.cpp index f715c8319..ba2659a6c 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -265,8 +265,6 @@ void Song::processNextBuffer() m_playPos[m_playMode].setTicks( tl->loopBegin().getTicks() ); - m_vstSyncController.setAbsolutePosition( - tl->loopBegin().getTicks() ); m_vstSyncController.setPlaybackJumped( true ); emit updateSampleTracks(); @@ -293,8 +291,6 @@ void Song::processNextBuffer() int ticks = m_playPos[m_playMode].getTicks() + ( int )( currentFrame / framesPerTick ); - m_vstSyncController.setAbsolutePosition( ticks ); - // did we play a whole tact? if( ticks >= MidiTime::ticksPerTact() ) { @@ -332,7 +328,6 @@ void Song::processNextBuffer() m_elapsedMilliSeconds = ( ticks * 60 * 1000 / 48 ) / getTempo(); - m_vstSyncController.setAbsolutePosition( ticks ); m_vstSyncController.setPlaybackJumped( true ); } } @@ -354,7 +349,6 @@ void Song::processNextBuffer() m_elapsedMilliSeconds = ( ticks * 60 * 1000 / 48 ) / getTempo(); - m_vstSyncController.setAbsolutePosition( ticks ); m_vstSyncController.setPlaybackJumped( true ); emit updateSampleTracks(); @@ -369,6 +363,16 @@ void Song::processNextBuffer() m_playPos[m_playMode].setCurrentFrame( currentFrame ); } + if( framesPlayed == 0 ) + { + // update VST sync position after we've corrected frame/ + // tick count but before actually playing any frames + m_vstSyncController.setAbsolutePosition( + m_playPos[m_playMode].getTicks() + + m_playPos[m_playMode].currentFrame() + / (double) framesPerTick ); + } + f_cnt_t framesToPlay = Engine::mixer()->framesPerPeriod() - framesPlayed; @@ -716,7 +720,10 @@ void Song::stop() m_playPos[m_playMode].setCurrentFrame( 0 ); m_vstSyncController.setPlaybackState( m_exporting ); - m_vstSyncController.setAbsolutePosition( m_playPos[m_playMode].getTicks() ); + m_vstSyncController.setAbsolutePosition( + m_playPos[m_playMode].getTicks() + + m_playPos[m_playMode].currentFrame() + / (double) Engine::framesPerTick() ); // remove all note-play-handles that are active Engine::mixer()->clear(); diff --git a/src/core/VstSyncController.cpp b/src/core/VstSyncController.cpp index b441d0507..dd9660cb5 100644 --- a/src/core/VstSyncController.cpp +++ b/src/core/VstSyncController.cpp @@ -136,12 +136,12 @@ VstSyncController::~VstSyncController() -void VstSyncController::setAbsolutePosition( int ticks ) +void VstSyncController::setAbsolutePosition( double ticks ) { #ifdef VST_SNC_LATENCY - m_syncData->ppqPos = ( ( ticks + 0 ) / (float)48 ) - m_syncData->m_latency; + m_syncData->ppqPos = ( ( ticks + 0 ) / 48.0 ) - m_syncData->m_latency; #else - m_syncData->ppqPos = ( ( ticks + 0 ) / (float)48 ); + m_syncData->ppqPos = ( ( ticks + 0 ) / 48.0 ); #endif }