From f33d1f4972b08234d372130be2b6633bfdf85f8d Mon Sep 17 00:00:00 2001 From: Vesa Date: Wed, 9 Jul 2014 19:18:17 +0300 Subject: [PATCH] Instrument track, mixer... --- include/InstrumentTrack.h | 4 +++- include/Mixer.h | 8 +++++--- src/core/Mixer.cpp | 5 +++++ src/tracks/InstrumentTrack.cpp | 33 +++++++++++++++++++++++---------- 4 files changed, 36 insertions(+), 14 deletions(-) diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index ec9c22d00..cc1ef4ae5 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -230,7 +230,9 @@ private: AudioPort m_audioPort; MidiPort m_midiPort; - QAtomicPointer m_notes[NumKeys]; + NotePlayHandle* m_notes[NumKeys]; + QMutex m_notesMutex; + int m_runningMidiNotes[NumKeys]; bool m_sustainPedalPressed; diff --git a/include/Mixer.h b/include/Mixer.h index c10bbffbc..b52842ea3 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -211,9 +211,9 @@ public: { if( criticalXRuns() == false ) { - lock(); - m_playHandles.push_back( handle ); - unlock(); + m_playHandleMutex.lock(); + m_newPlayHandles.append( handle ); + m_playHandleMutex.unlock(); return true; } @@ -428,6 +428,8 @@ private: int m_numWorkers; QWaitCondition m_queueReadyWaitCond; + PlayHandleList m_newPlayHandles; // place where new playhandles are added temporarily + QMutex m_playHandleMutex; // mutex used only for adding playhandles PlayHandleList m_playHandles; ConstPlayHandleList m_playHandlesToRemove; diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 928129271..4e53e8388 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -341,6 +341,11 @@ const surroundSampleFrame * Mixer::renderNextBuffer() // now we have to make sure no other thread does anything bad // while we're acting... lock(); + // add all play-handles that have to be added + m_playHandleMutex.lock(); + m_playHandles += m_newPlayHandles; + m_newPlayHandles.clear(); + m_playHandleMutex.unlock(); // remove all play-handles that have to be deleted and delete // them if they still exist... diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 2d6761167..01d337dae 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -264,6 +264,7 @@ MidiEvent InstrumentTrack::applyMasterKey( const MidiEvent& event ) void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset ) { + qDebug( "pIE" ); bool eventHandled = false; switch( event.type() ) @@ -275,16 +276,23 @@ void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& ti if( event.velocity() > 0 ) { NotePlayHandle* nph; - m_notes[event.key()].testAndSetOrdered( NULL, ( nph = new NotePlayHandle( this, offset, - typeInfo::max() / 2, - note( MidiTime(), MidiTime(), event.key(), event.volume( midiPort()->baseVelocity() ) ), - NULL, event.channel(), - NotePlayHandle::OriginMidiInput ) ) ); - if( ! engine::mixer()->addPlayHandle( nph ) ) + if( m_notes[event.key()] == NULL ) { - m_notes[event.key()].testAndSetOrdered( nph, NULL ); + qDebug( "note on" ); + m_notesMutex.lock(); + nph = new NotePlayHandle( this, offset, + typeInfo::max() / 2, + note( MidiTime(), MidiTime(), event.key(), event.volume( midiPort()->baseVelocity() ) ), + NULL, event.channel(), + NotePlayHandle::OriginMidiInput ); + m_notes[event.key()] = nph; + if( ! engine::mixer()->addPlayHandle( nph ) ) + { + m_notes[event.key()] = NULL; + delete nph; + } + m_notesMutex.unlock(); } - qDebug( "ok" ); eventHandled = true; break; } @@ -292,10 +300,12 @@ void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& ti case MidiNoteOff: if( m_notes[event.key()] != NULL ) { + m_notesMutex.lock(); // do actual note off and remove internal reference to NotePlayHandle (which itself will // be deleted later automatically) m_notes[event.key()]->noteOff( offset ); m_notes[event.key()] = NULL; + m_notesMutex.unlock(); } eventHandled = true; break; @@ -372,6 +382,7 @@ void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& ti void InstrumentTrack::processOutEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset ) { + qDebug( "pOE" ); // do nothing if we do not have an instrument instance (e.g. when loading settings) if( m_instrument == NULL ) { @@ -388,7 +399,7 @@ void InstrumentTrack::processOutEvent( const MidiEvent& event, const MidiTime& t if( key >= 0 && key < NumKeys ) { - + qDebug( "poe noteon" ); if( m_runningMidiNotes[key] > 0 ) { m_instrument->handleMidiEvent( MidiEvent( MidiNoteOff, midiPort()->realOutputChannel(), key, 0 ), time, offset ); @@ -424,13 +435,15 @@ void InstrumentTrack::processOutEvent( const MidiEvent& event, const MidiTime& t void InstrumentTrack::silenceAllNotes( bool removeIPH ) { - engine::mixer()->lock(); + m_notesMutex.lock(); for( int i = 0; i < NumKeys; ++i ) { m_notes[i] = NULL; m_runningMidiNotes[i] = 0; } + m_notesMutex.unlock(); + engine::mixer()->lock(); // invalidate all NotePlayHandles linked to this track m_processHandles.clear(); engine::mixer()->removePlayHandles( this, removeIPH );