From bad08a26323534d638ecd2fed854edc40b33d36b Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 6 Jun 2014 14:24:51 +0300 Subject: [PATCH] Ensure that NotePlayHandles get processed before the InstrumentPlayHandle on instruments that use both NotePlayHandles and InstrumentPlayHandle, such as LB302 and SF2-Player Issue: Currently, we use threads to process all PlayHandles, so there's no guarantee of the order they are processed in. This causes timing inaccuracy and jitter: notes of instruments that use both NPH's and IPH's can get randomly delayed by one entire period. The issue is solved thusly: - When processing an IPH, we check if the instrument is midi-based. If yes, we just process it normally (no NPH's to worry about). - If it's not, then it also uses NPH's, so we'll have the IPH wait until all NPH's belonging to same instrument have been processed. There's some similar code in the new FX mixer, I pretty much just copied how we do it there. --- include/Instrument.h | 4 ++-- include/InstrumentPlayHandle.h | 24 ++++++++++++++++++++++-- plugins/sf2_player/sf2_player.h | 2 +- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/include/Instrument.h b/include/Instrument.h index 3db88b980..88c8e9a19 100644 --- a/include/Instrument.h +++ b/include/Instrument.h @@ -119,13 +119,13 @@ public: virtual bool isFromTrack( const track * _track ) const; - -protected: inline InstrumentTrack * instrumentTrack() const { return m_instrumentTrack; } + +protected: // instruments may use this to apply a soft fade out at the end of // notes - method does this only if really less or equal // desiredReleaseFrames() frames are left diff --git a/include/InstrumentPlayHandle.h b/include/InstrumentPlayHandle.h index cf472db9e..c2fd5c918 100644 --- a/include/InstrumentPlayHandle.h +++ b/include/InstrumentPlayHandle.h @@ -22,11 +22,12 @@ * */ -#ifndef _INSTRUMENT_PLAY_HANDLE_H -#define _INSTRUMENT_PLAY_HANDLE_H +#ifndef INSTRUMENT_PLAY_HANDLE_H +#define INSTRUMENT_PLAY_HANDLE_H #include "PlayHandle.h" #include "Instrument.h" +#include "NotePlayHandle.h" class InstrumentPlayHandle : public PlayHandle @@ -45,6 +46,25 @@ public: virtual void play( sampleFrame * _working_buffer ) { + // if the instrument is midi-based, we can safely render right away + if( m_instrument->flags() & Instrument::IsMidiBased ) + { + m_instrument->play( _working_buffer ); + return; + } + + // if not, we need to ensure that all our nph's have been processed first + ConstNotePlayHandleList nphv = NotePlayHandle::nphsOfInstrumentTrack( m_instrument->instrumentTrack(), true ); + + foreach( const NotePlayHandle * cnph, nphv ) + { + NotePlayHandle * nph = const_cast( cnph ); + while( nph->state() != ThreadableJob::Done ) + { + nph->process(); + } + } + m_instrument->play( _working_buffer ); } diff --git a/plugins/sf2_player/sf2_player.h b/plugins/sf2_player/sf2_player.h index e27aa8a8a..5c2f5beb8 100644 --- a/plugins/sf2_player/sf2_player.h +++ b/plugins/sf2_player/sf2_player.h @@ -79,7 +79,7 @@ public: virtual Flags flags() const { - return IsSingleStreamed | IsMidiBased; + return IsSingleStreamed; } virtual PluginView * instantiateView( QWidget * _parent );