From 4b340f7d5f10297bd3f7198bb86877823fe89ede Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Sun, 26 Jan 2014 16:46:12 +0100 Subject: [PATCH] InstrumentTrack: manage MIDI note recording in NotePlayHandle We must not record notes when receiving external MidiNoteOff events as e.g. the sustain pedal still might be pressed. State tracking for features like these is done inside NotePlayHandle so move the recording- related signal emission from InstrumentTrack to NotePlayHandle. Closes #168. --- include/InstrumentTrack.h | 4 +-- src/core/note_play_handle.cpp | 12 ++++++++ src/gui/piano_roll.cpp | 12 ++------ src/tracks/InstrumentTrack.cpp | 50 +++++++--------------------------- 4 files changed, 27 insertions(+), 51 deletions(-) diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index 4057d7990..d4ca720c3 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -204,8 +204,8 @@ public: signals: void instrumentChanged(); void newNote(); - void noteOn( const note & _n ); - void noteOff( const note & _n ); + void midiNoteOn( const note& ); + void midiNoteOff( const note& ); void nameChanged(); diff --git a/src/core/note_play_handle.cpp b/src/core/note_play_handle.cpp index 96d93c3de..6a434aea6 100644 --- a/src/core/note_play_handle.cpp +++ b/src/core/note_play_handle.cpp @@ -105,6 +105,11 @@ notePlayHandle::notePlayHandle( InstrumentTrack * _it, setFrames( _frames ); + // inform attached components about new MIDI note (used for recording in Piano Roll) + if( m_origin == OriginMidiInput ) + { + m_instrumentTrack->midiNoteOn( *this ); + } if( !isTopNote() || !instrumentTrack()->isArpeggioEnabled() ) { @@ -122,6 +127,13 @@ notePlayHandle::~notePlayHandle() { noteOff( 0 ); + // inform attached components about MIDI finished (used for recording in Piano Roll) + if( m_origin == OriginMidiInput ) + { + setLength( MidiTime( static_cast( totalFramesPlayed() / engine::framesPerTick() ) ) ); + m_instrumentTrack->midiNoteOff( *this ); + } + if( isTopNote() ) { delete m_baseDetuning; diff --git a/src/gui/piano_roll.cpp b/src/gui/piano_roll.cpp index 6eace8b46..ddd450faa 100644 --- a/src/gui/piano_roll.cpp +++ b/src/gui/piano_roll.cpp @@ -765,15 +765,9 @@ void pianoRoll::setCurrentPattern( pattern * _new_pattern ) // of start-notes and so on...) resizeEvent( NULL ); - connect( m_pattern->instrumentTrack(), - SIGNAL( noteOn( const note & ) ), - this, SLOT( startRecordNote( const note & ) ) ); - connect( m_pattern->instrumentTrack(), - SIGNAL( noteOff( const note & ) ), - this, SLOT( finishRecordNote( const note & ) ) ); - connect( m_pattern->instrumentTrack()->pianoModel(), - SIGNAL( dataChanged() ), - this, SLOT( update() ) ); + connect( m_pattern->instrumentTrack(), SIGNAL( midiNoteOn( const note& ) ), this, SLOT( startRecordNote( const note& ) ) ); + connect( m_pattern->instrumentTrack(), SIGNAL( midiNoteOff( const note& ) ), this, SLOT( finishRecordNote( const note& ) ) ); + connect( m_pattern->instrumentTrack()->pianoModel(), SIGNAL( dataChanged() ), this, SLOT( update() ) ); setWindowTitle( tr( "Piano-Roll - %1" ).arg( m_pattern->name() ) ); diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index c05a379f1..e7a58834a 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -237,20 +237,16 @@ void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& ti { if( m_notes[event.key()] == NULL ) { - // create temporary note - note n; - n.setKey( event.key() ); - n.setVolume( event.volume() ); - // create (timed) note-play-handle - notePlayHandle* nph = new notePlayHandle( this, time.frames( engine::framesPerTick() ), typeInfo::max() / 2, - n, NULL, false, event.channel() ); + notePlayHandle* nph = new notePlayHandle( this, time.frames( engine::framesPerTick() ), + typeInfo::max() / 2, + note( MidiTime(), MidiTime(), event.key(), event.volume() ), + NULL, false, event.channel(), + notePlayHandle::OriginMidiInput ); if( engine::mixer()->addPlayHandle( nph ) ) { m_notes[event.key()] = nph; } - - emit noteOn( n ); } eventHandled = true; @@ -258,28 +254,15 @@ void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& ti } case MidiNoteOff: - { - notePlayHandle* nph = m_notes[event.key()]; - if( nph != NULL ) + if( m_notes[event.key()] != NULL ) { - // create dummy-note which has the same length - // as the played note for sending it later - // to all slots connected to signal noteOff() - // this is for example needed by piano-roll for - // recording notes into a pattern - note n( MidiTime( static_cast( nph->totalFramesPlayed() / engine::framesPerTick() ) ), - 0, nph->key(), nph->getVolume(), nph->getPanning() ); - - emit noteOff( n ); - - // now do actual note off and remove internal reference to NotePlayHandle (which itself will + // do actual note off and remove internal reference to NotePlayHandle (which itself will // be deleted later automatically) - nph->noteOff(); + m_notes[event.key()]->noteOff(); m_notes[event.key()] = NULL; } eventHandled = true; break; - } case MidiKeyPressure: if( m_notes[event.key()] != NULL ) @@ -467,24 +450,11 @@ QString InstrumentTrack::instrumentName() const -void InstrumentTrack::deleteNotePluginData( notePlayHandle * _n ) +void InstrumentTrack::deleteNotePluginData( notePlayHandle* n ) { if( m_instrument != NULL ) { - m_instrument->deleteNotePluginData( _n ); - } - - // Notes deleted when keys still pressed - if( m_notes[_n->key()] == _n ) - { - note done_note( MidiTime( static_cast( - _n->totalFramesPlayed() / - engine::framesPerTick() ) ), - 0, _n->key(), - _n->getVolume(), _n->getPanning() ); - _n->noteOff(); - m_notes[_n->key()] = NULL; - emit noteOff( done_note ); + m_instrument->deleteNotePluginData( n ); } }