From ff44854cde9681e165425fd765206d50718cf1f5 Mon Sep 17 00:00:00 2001 From: "Raine M. Ekman" Date: Fri, 24 Apr 2015 21:17:27 +0300 Subject: [PATCH 1/7] MIDI import: don't call AutomationPattern::addObject all the time Should be enough to add the object to the automation pattern only once, as the objModel variable that is added will always be the same for the same value of ccid, which indexes the ccs array. This will speed up creation of automation tracks for MIDI CCs and pitch bend. --- plugins/MidiImport/MidiImport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/MidiImport/MidiImport.cpp b/plugins/MidiImport/MidiImport.cpp index a81b0e705..0ec05af49 100644 --- a/plugins/MidiImport/MidiImport.cpp +++ b/plugins/MidiImport/MidiImport.cpp @@ -182,8 +182,8 @@ public: ap = dynamic_cast( at->createTCO(0) ); ap->movePosition( pPos ); + ap->addObject( objModel ); } - ap->addObject( objModel ); lastPos = time; time = time - ap->startPosition(); From 2a72d5f119de59b02e0a56cd2622729eaa60ad2c Mon Sep 17 00:00:00 2001 From: "Raine M. Ekman" Date: Fri, 24 Apr 2015 22:26:31 +0300 Subject: [PATCH 2/7] MIDI import: ensure minimum note length 1 tick Too short notes had their duration rounded down to 0 on import, as MIDI precision allows way shorter notes than LMMS, and portsmf reports the duration as a double, where a beat == 1.0. Was going to use ceil() first, but that might round some notes up to a slightly longer duration. --- plugins/MidiImport/MidiImport.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/MidiImport/MidiImport.cpp b/plugins/MidiImport/MidiImport.cpp index 0ec05af49..afc49e7bb 100644 --- a/plugins/MidiImport/MidiImport.cpp +++ b/plugins/MidiImport/MidiImport.cpp @@ -357,7 +357,7 @@ bool MidiImport::readSMF( TrackContainer* tc ) // Tracks for( int t = 0; t < seq->tracks(); ++t ) { - QString trackName = ""; + QString trackName = QString("Track %1").arg(t); Alg_track_ptr trk = seq->track( t ); pd.setValue( t + preTrackSteps ); @@ -402,8 +402,8 @@ bool MidiImport::readSMF( TrackContainer* tc ) { smfMidiChannel * ch = chs[evt->chan].create( tc, trackName ); Alg_note_ptr noteEvt = dynamic_cast( evt ); - - Note n( noteEvt->get_duration() * ticksPerBeat, + double ticks = MidiTime( noteEvt->get_duration() * ticksPerBeat ); + Note n( (ticks < 1 ? 1 : ticks ), noteEvt->get_start_time() * ticksPerBeat, noteEvt->get_identifier() - 12, noteEvt->get_loud()); From 61ab0ed0938575ee3ce3e077d914ec3df96a9a1e Mon Sep 17 00:00:00 2001 From: "Raine M. Ekman" Date: Fri, 24 Apr 2015 22:44:02 +0300 Subject: [PATCH 3/7] MIDI import: add naming of AutomationTracks Name the automation tracks like "[MIDI trackname] CC ##". And don't call the automation track creation function for every CC event, as it now will involve constructing a QString. --- plugins/MidiImport/MidiImport.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/plugins/MidiImport/MidiImport.cpp b/plugins/MidiImport/MidiImport.cpp index afc49e7bb..004c33957 100644 --- a/plugins/MidiImport/MidiImport.cpp +++ b/plugins/MidiImport/MidiImport.cpp @@ -156,12 +156,15 @@ public: AutomationPattern * ap; MidiTime lastPos; - smfMidiCC & create( TrackContainer* tc ) + smfMidiCC & create( TrackContainer* tc, QString tn ) { if( !at ) { at = dynamic_cast( Track::create( Track::AutomationTrack, tc ) ); } + if( tn != "") { + at->setName( tn ); + } return *this; } @@ -487,7 +490,11 @@ bool MidiImport::readSMF( TrackContainer* tc ) } else { - ccs[ccid].create( tc ); + if( ccs[ccid].at == NULL ) { + ccs[ccid].create( tc, trackName + + (ccid == 128 ? " Pitch bend" : + QString(" CC %1").arg(ccid) ) ); + } ccs[ccid].putValue( time, objModel, cc ); } } From 06d87174e4b0a83de243f3a1ebdb6ebcd323c327 Mon Sep 17 00:00:00 2001 From: "Raine M. Ekman" Date: Sat, 25 Apr 2015 10:12:02 +0300 Subject: [PATCH 4/7] MIDI import: call qApp->processEvents(); before creating tracks This should keep LMMS responsive from the window managers POV, unless the user selects a huge enough default sound font that loading it takes too long. --- plugins/MidiImport/MidiImport.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/MidiImport/MidiImport.cpp b/plugins/MidiImport/MidiImport.cpp index 004c33957..4e4a03529 100644 --- a/plugins/MidiImport/MidiImport.cpp +++ b/plugins/MidiImport/MidiImport.cpp @@ -160,6 +160,7 @@ public: { if( !at ) { + qApp->processEvents(); at = dynamic_cast( Track::create( Track::AutomationTrack, tc ) ); } if( tn != "") { @@ -223,6 +224,7 @@ public: smfMidiChannel * create( TrackContainer* tc, QString tn ) { if( !it ) { + qApp->processEvents(); it = dynamic_cast( Track::create( Track::InstrumentTrack, tc ) ); #ifdef LMMS_HAVE_FLUIDSYNTH From 542250e127d7f1d3cb6a50de3169c79f09d9409b Mon Sep 17 00:00:00 2001 From: "Raine M. Ekman" Date: Sat, 25 Apr 2015 13:49:06 +0300 Subject: [PATCH 5/7] MIDI import: set default pitch bend range to +/-2 semitones AFAIK, this is how the General MIDI standard says it should be. --- plugins/MidiImport/MidiImport.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/MidiImport/MidiImport.cpp b/plugins/MidiImport/MidiImport.cpp index 4e4a03529..3b76d58b0 100644 --- a/plugins/MidiImport/MidiImport.cpp +++ b/plugins/MidiImport/MidiImport.cpp @@ -249,6 +249,8 @@ public: it->setName( tn ); } lastEnd = 0; + // General MIDI default + it->pitchRangeModel()->setInitValue( 2 ); } return this; } From 22b1e4fb4caaa1a69c647a4b22bd6481cd907ce1 Mon Sep 17 00:00:00 2001 From: "Raine M. Ekman" Date: Tue, 5 May 2015 22:21:33 +0300 Subject: [PATCH 6/7] Clarified the reason for qApp->processEvents(), changed an odd type juggling into something slightly saner. --- plugins/MidiImport/MidiImport.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/MidiImport/MidiImport.cpp b/plugins/MidiImport/MidiImport.cpp index 3b76d58b0..c9fa47070 100644 --- a/plugins/MidiImport/MidiImport.cpp +++ b/plugins/MidiImport/MidiImport.cpp @@ -160,6 +160,9 @@ public: { if( !at ) { + // Keep LMMS responsive, for now the import runs + // in the main thread. This should probably be + // removed if that ever changes. qApp->processEvents(); at = dynamic_cast( Track::create( Track::AutomationTrack, tc ) ); } @@ -224,6 +227,7 @@ public: smfMidiChannel * create( TrackContainer* tc, QString tn ) { if( !it ) { + // Keep LMMS responsive qApp->processEvents(); it = dynamic_cast( Track::create( Track::InstrumentTrack, tc ) ); @@ -409,7 +413,7 @@ bool MidiImport::readSMF( TrackContainer* tc ) { smfMidiChannel * ch = chs[evt->chan].create( tc, trackName ); Alg_note_ptr noteEvt = dynamic_cast( evt ); - double ticks = MidiTime( noteEvt->get_duration() * ticksPerBeat ); + int ticks = noteEvt->get_duration() * ticksPerBeat; Note n( (ticks < 1 ? 1 : ticks ), noteEvt->get_start_time() * ticksPerBeat, noteEvt->get_identifier() - 12, From c4f4fe3657c29c5d3ac8d7bd8da8690ed5a81134 Mon Sep 17 00:00:00 2001 From: "Raine M. Ekman" Date: Mon, 18 May 2015 21:54:21 +0300 Subject: [PATCH 7/7] MIDI import: i18n in default track names, control names for automation tracks --- plugins/MidiImport/MidiImport.cpp | 16 ++++++++++------ plugins/MidiImport/portsmf/allegro.cpp | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/plugins/MidiImport/MidiImport.cpp b/plugins/MidiImport/MidiImport.cpp index c9fa47070..bf51e6080 100644 --- a/plugins/MidiImport/MidiImport.cpp +++ b/plugins/MidiImport/MidiImport.cpp @@ -368,7 +368,7 @@ bool MidiImport::readSMF( TrackContainer* tc ) // Tracks for( int t = 0; t < seq->tracks(); ++t ) { - QString trackName = QString("Track %1").arg(t); + QString trackName = QString( tr( "Track" ) + " %1" ).arg( t ); Alg_track_ptr trk = seq->track( t ); pd.setValue( t + preTrackSteps ); @@ -388,8 +388,8 @@ bool MidiImport::readSMF( TrackContainer* tc ) if( evt->is_update() ) { QString attr = evt->get_attribute(); - if( attr == "tracknames" && evt->get_update_type() == 'a' ) { - trackName = evt->get_atom_value(); + if( attr == "tracknames" && evt->get_update_type() == 's' ) { + trackName = evt->get_string_value(); handled = true; } } @@ -488,6 +488,9 @@ bool MidiImport::readSMF( TrackContainer* tc ) objModel = ch->it->pitchModel(); cc = cc * 100.0f; break; + default: + //TODO: something useful for other CCs + break; } if( objModel ) @@ -499,9 +502,10 @@ bool MidiImport::readSMF( TrackContainer* tc ) else { if( ccs[ccid].at == NULL ) { - ccs[ccid].create( tc, trackName + - (ccid == 128 ? " Pitch bend" : - QString(" CC %1").arg(ccid) ) ); + ccs[ccid].create( tc, trackName + " > " + ( + objModel != NULL ? + objModel->displayName() : + QString("CC %1").arg(ccid) ) ); } ccs[ccid].putValue( time, objModel, cc ); } diff --git a/plugins/MidiImport/portsmf/allegro.cpp b/plugins/MidiImport/portsmf/allegro.cpp index c05f279e9..653ff4c07 100644 --- a/plugins/MidiImport/portsmf/allegro.cpp +++ b/plugins/MidiImport/portsmf/allegro.cpp @@ -517,7 +517,7 @@ char *Alg_event::get_string_value() assert(is_update()); Alg_update* update = (Alg_update *) this; assert(get_update_type() == 's'); - return update->parameter.attr_name(); + return update->parameter.a; }