From 06be5bba82d8f9103e151d4fecab865ac1eb3b0f Mon Sep 17 00:00:00 2001 From: Vesa Date: Wed, 4 Jun 2014 04:23:16 +0300 Subject: [PATCH] Make MIDI timing sample-accurate - currently only affects Vestige - no idea whether this can also be used for Zyn and OpulenZ, I'm not sure if Zyn has any kind of mechanism for communicating frame offset to the synth, as for OpulenZ, @softrabbit would know the answer better - basically, I made it happen by simply adding an extra parameter in the processMidi{In|Out} functions, which is 0 by default, and made the necessary changes in instrumentTrack and nph to utilize it - I based this against 1.1 because I didn't think it's a very big change, and I don't see much possibility for things going wrong here, since we're basically just using the existing functionality in Vestige (there already was a frame offset being communicated to the remote plugin, just that it was always set to 0). However, if @tobydox thinks this is better to bump up to 1.2, I can rebase it for master... --- include/Instrument.h | 6 +++--- include/InstrumentTrack.h | 8 ++++---- include/MidiController.h | 8 ++++---- include/MidiEventProcessor.h | 8 ++++---- plugins/opl2/opl2instrument.cpp | 2 +- plugins/opl2/opl2instrument.h | 2 +- plugins/vestige/vestige.cpp | 4 ++-- plugins/vestige/vestige.h | 2 +- plugins/zynaddsubfx/ZynAddSubFx.cpp | 2 +- plugins/zynaddsubfx/ZynAddSubFx.h | 2 +- src/core/NotePlayHandle.cpp | 6 ++++-- src/core/midi/MidiController.cpp | 2 +- src/tracks/InstrumentTrack.cpp | 14 +++++++------- 13 files changed, 34 insertions(+), 32 deletions(-) diff --git a/include/Instrument.h b/include/Instrument.h index 987d1429f..3db88b980 100644 --- a/include/Instrument.h +++ b/include/Instrument.h @@ -23,8 +23,8 @@ * */ -#ifndef _INSTRUMENT_H -#define _INSTRUMENT_H +#ifndef INSTRUMENT_H +#define INSTRUMENT_H #include @@ -101,7 +101,7 @@ public: // sub-classes can re-implement this for receiving all incoming // MIDI-events - inline virtual bool handleMidiEvent( const MidiEvent&, const MidiTime& = MidiTime() ) + inline virtual bool handleMidiEvent( const MidiEvent&, const MidiTime& = MidiTime(), f_cnt_t offset = 0 ) { return true; } diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index 6f9a0c6cf..b09ecaa6f 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -23,8 +23,8 @@ * */ -#ifndef _INSTRUMENT_TRACK_H -#define _INSTRUMENT_TRACK_H +#ifndef INSTRUMENT_TRACK_H +#define INSTRUMENT_TRACK_H #include "AudioPort.h" #include "InstrumentFunctions.h" @@ -71,8 +71,8 @@ public: MidiEvent applyMasterKey( const MidiEvent& event ); - virtual void processInEvent( const MidiEvent& event, const MidiTime& time = MidiTime() ); - virtual void processOutEvent( const MidiEvent& event, const MidiTime& time = MidiTime() ); + virtual void processInEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ); + virtual void processOutEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ); // silence all running notes played by this track void silenceAllNotes(); diff --git a/include/MidiController.h b/include/MidiController.h index 2271e8659..4ffb460ce 100644 --- a/include/MidiController.h +++ b/include/MidiController.h @@ -22,8 +22,8 @@ * */ -#ifndef _MIDI_CONTROLLER_H -#define _MIDI_CONTROLLER_H +#ifndef MIDI_CONTROLLER_H +#define MIDI_CONTROLLER_H #include @@ -44,10 +44,10 @@ public: virtual ~MidiController(); virtual void processInEvent( const MidiEvent & _me, - const MidiTime & _time ); + const MidiTime & _time, f_cnt_t offset = 0 ); virtual void processOutEvent( const MidiEvent& _me, - const MidiTime & _time) + const MidiTime & _time, f_cnt_t offset = 0 ) { // No output yet } diff --git a/include/MidiEventProcessor.h b/include/MidiEventProcessor.h index dafcfb6cd..0ca6ce59e 100644 --- a/include/MidiEventProcessor.h +++ b/include/MidiEventProcessor.h @@ -22,8 +22,8 @@ * */ -#ifndef _MIDI_EVENT_PROCESSOR_H -#define _MIDI_EVENT_PROCESSOR_H +#ifndef MIDI_EVENT_PROCESSOR_H +#define MIDI_EVENT_PROCESSOR_H #include "MidiEvent.h" #include "MidiTime.h" @@ -42,8 +42,8 @@ public: } // to be implemented by inheriting classes - virtual void processInEvent( const MidiEvent& event, const MidiTime& time = MidiTime() ) = 0; - virtual void processOutEvent( const MidiEvent& event, const MidiTime& time = MidiTime() ) = 0; + virtual void processInEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ) = 0; + virtual void processOutEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ) = 0; } ; diff --git a/plugins/opl2/opl2instrument.cpp b/plugins/opl2/opl2instrument.cpp index 4704f0147..6a169c964 100644 --- a/plugins/opl2/opl2instrument.cpp +++ b/plugins/opl2/opl2instrument.cpp @@ -283,7 +283,7 @@ int opl2instrument::pushVoice(int v) { return i; } -bool opl2instrument::handleMidiEvent( const MidiEvent& event, const MidiTime& time ) +bool opl2instrument::handleMidiEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset ) { emulatorMutex.lock(); int key, vel, voice, tmp_pb; diff --git a/plugins/opl2/opl2instrument.h b/plugins/opl2/opl2instrument.h index e95357807..e388b0672 100644 --- a/plugins/opl2/opl2instrument.h +++ b/plugins/opl2/opl2instrument.h @@ -53,7 +53,7 @@ public: return IsSingleStreamed | IsMidiBased; } - virtual bool handleMidiEvent( const MidiEvent& event, const MidiTime& time ); + virtual bool handleMidiEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset = 0 ); virtual void play( sampleFrame * _working_buffer ); void saveSettings( QDomDocument & _doc, QDomElement & _this ); diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index 31a262771..4c907c9a2 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -310,12 +310,12 @@ void vestigeInstrument::play( sampleFrame * _buf ) -bool vestigeInstrument::handleMidiEvent( const MidiEvent& event, const MidiTime& time ) +bool vestigeInstrument::handleMidiEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset ) { m_pluginMutex.lock(); if( m_plugin != NULL ) { - m_plugin->processMidiEvent( event, time ); + m_plugin->processMidiEvent( event, offset ); } m_pluginMutex.unlock(); diff --git a/plugins/vestige/vestige.h b/plugins/vestige/vestige.h index 8a5ce639e..8854e4369 100644 --- a/plugins/vestige/vestige.h +++ b/plugins/vestige/vestige.h @@ -68,7 +68,7 @@ public: return IsSingleStreamed | IsMidiBased; } - virtual bool handleMidiEvent( const MidiEvent& event, const MidiTime& time ); + virtual bool handleMidiEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset = 0 ); virtual PluginView * instantiateView( QWidget * _parent ); diff --git a/plugins/zynaddsubfx/ZynAddSubFx.cpp b/plugins/zynaddsubfx/ZynAddSubFx.cpp index 8eca9fdae..40c2737c7 100644 --- a/plugins/zynaddsubfx/ZynAddSubFx.cpp +++ b/plugins/zynaddsubfx/ZynAddSubFx.cpp @@ -343,7 +343,7 @@ void ZynAddSubFxInstrument::play( sampleFrame * _buf ) -bool ZynAddSubFxInstrument::handleMidiEvent( const MidiEvent& event, const MidiTime& time ) +bool ZynAddSubFxInstrument::handleMidiEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset ) { // do not forward external MIDI Control Change events if the according // LED is not checked diff --git a/plugins/zynaddsubfx/ZynAddSubFx.h b/plugins/zynaddsubfx/ZynAddSubFx.h index ad78b95b4..ac9cdf3cc 100644 --- a/plugins/zynaddsubfx/ZynAddSubFx.h +++ b/plugins/zynaddsubfx/ZynAddSubFx.h @@ -70,7 +70,7 @@ public: virtual void play( sampleFrame * _working_buffer ); - virtual bool handleMidiEvent( const MidiEvent& event, const MidiTime& time = MidiTime() ); + virtual bool handleMidiEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ); virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); virtual void loadSettings( const QDomElement & _this ); diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp index 9ad49de41..db535474a 100644 --- a/src/core/NotePlayHandle.cpp +++ b/src/core/NotePlayHandle.cpp @@ -107,7 +107,8 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack, // send MidiNoteOn event m_instrumentTrack->processOutEvent( MidiEvent( MidiNoteOn, midiChannel(), midiKey(), midiVelocity( baseVelocity ) ), - MidiTime::fromFrames( offset(), engine::framesPerTick() ) ); + MidiTime::fromFrames( offset(), engine::framesPerTick() ), + offset() ); } } @@ -336,7 +337,8 @@ void NotePlayHandle::noteOff( const f_cnt_t _s ) // send MidiNoteOff event m_instrumentTrack->processOutEvent( MidiEvent( MidiNoteOff, midiChannel(), midiKey(), 0 ), - MidiTime::fromFrames( m_framesBeforeRelease, engine::framesPerTick() ) ); + MidiTime::fromFrames( m_framesBeforeRelease, engine::framesPerTick() ), + _s ); } // inform attached components about MIDI finished (used for recording in Piano Roll) diff --git a/src/core/midi/MidiController.cpp b/src/core/midi/MidiController.cpp index 5e65b5cd0..b7e78f10e 100644 --- a/src/core/midi/MidiController.cpp +++ b/src/core/midi/MidiController.cpp @@ -73,7 +73,7 @@ void MidiController::updateName() -void MidiController::processInEvent( const MidiEvent& event, const MidiTime& time ) +void MidiController::processInEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset ) { unsigned char controllerNum; switch( event.type() ) diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index d14728e05..532431e6c 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -232,7 +232,7 @@ MidiEvent InstrumentTrack::applyMasterKey( const MidiEvent& event ) -void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& time ) +void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset ) { engine::mixer()->lock(); @@ -335,7 +335,7 @@ void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& ti break; } - if( eventHandled == false && instrument()->handleMidiEvent( event, time ) == false ) + if( eventHandled == false && instrument()->handleMidiEvent( event, time, offset ) == false ) { qWarning( "InstrumentTrack: unhandled MIDI event %d", event.type() ); } @@ -346,7 +346,7 @@ void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& ti -void InstrumentTrack::processOutEvent( const MidiEvent& event, const MidiTime& time ) +void InstrumentTrack::processOutEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset ) { // do nothing if we do not have an instrument instance (e.g. when loading settings) if( m_instrument == NULL ) @@ -366,10 +366,10 @@ void InstrumentTrack::processOutEvent( const MidiEvent& event, const MidiTime& t { if( m_runningMidiNotes[key] > 0 ) { - m_instrument->handleMidiEvent( MidiEvent( MidiNoteOff, midiPort()->realOutputChannel(), key, 0 ), time ); + m_instrument->handleMidiEvent( MidiEvent( MidiNoteOff, midiPort()->realOutputChannel(), key, 0 ), time, offset ); } ++m_runningMidiNotes[key]; - m_instrument->handleMidiEvent( MidiEvent( MidiNoteOn, midiPort()->realOutputChannel(), key, event.velocity() ), time ); + m_instrument->handleMidiEvent( MidiEvent( MidiNoteOn, midiPort()->realOutputChannel(), key, event.velocity() ), time, offset ); emit newNote(); } @@ -381,12 +381,12 @@ void InstrumentTrack::processOutEvent( const MidiEvent& event, const MidiTime& t if( key >= 0 && key < NumKeys && --m_runningMidiNotes[key] <= 0 ) { m_runningMidiNotes[key] = qMax( 0, m_runningMidiNotes[key] ); - m_instrument->handleMidiEvent( MidiEvent( MidiNoteOff, midiPort()->realOutputChannel(), key, 0 ), time ); + m_instrument->handleMidiEvent( MidiEvent( MidiNoteOff, midiPort()->realOutputChannel(), key, 0 ), time, offset ); } break; default: - m_instrument->handleMidiEvent( transposedEvent, time ); + m_instrument->handleMidiEvent( transposedEvent, time, offset ); break; }