diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index fe7625d300f..07350cde033 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -239,6 +239,9 @@ class LMMS_EXPORT InstrumentTrack : public Track, public MidiEventProcessor void autoAssignMidiDevice( bool ); + //! Returns a non-owning pointer to the model for the knob at the given index in the track's MIDI CC rack + FloatModel* midiCCModel(int index) const { return m_midiCCModel[index].get(); } + signals: void instrumentChanged(); void midiNoteOn( const lmms::Note& ); diff --git a/plugins/MidiImport/MidiImport.cpp b/plugins/MidiImport/MidiImport.cpp index 071ba65706b..faca048ee76 100644 --- a/plugins/MidiImport/MidiImport.cpp +++ b/plugins/MidiImport/MidiImport.cpp @@ -405,7 +405,9 @@ bool MidiImport::readSMF(TrackContainer* tc) } else if (evt->is_note()) { - smfMidiChannel* ch = chs[evt->chan].create(tc, trackName); + // LMMS does not currently support specifying the channel of a single note + // To be safe, put the notes from different channels on separate tracks so that no information is lost + smfMidiChannel* ch = chs[evt->chan + 16 * t].create(tc, trackName); auto noteEvt = dynamic_cast(evt); tick_t ticks = noteEvt->get_duration() * ticksPerBeat; Note n( @@ -419,7 +421,7 @@ bool MidiImport::readSMF(TrackContainer* tc) } else if (evt->is_update()) { - smfMidiChannel* ch = chs[evt->chan].create(tc, trackName); + smfMidiChannel* ch = chs[evt->chan + 16 * t].create(tc, trackName); double time = evt->time*ticksPerBeat; QString update(evt->get_attribute()); @@ -457,55 +459,57 @@ bool MidiImport::readSMF(TrackContainer* tc) if (ccid <= 128) { double cc = evt->get_real_value(); - AutomatableModel* objModel = nullptr; - + AutomatableModel* modelObject = nullptr; + // Some CC knobs correspond to specific things like pitch and volume, so in that case, set the lmms pitch/volume/etc knobs. + // Otherwise, set the knob in the instrument track CC rack switch (ccid) { case 0: if (ch->isSF2 && ch->it_inst) { - objModel = ch->it_inst->childModel("bank"); + modelObject = ch->it_inst->childModel("bank"); printf("BANK SELECT %f %d\n", cc, static_cast(cc * 127)); cc *= 127.0f; } break; case 7: - objModel = ch->it->volumeModel(); + modelObject = ch->it->volumeModel(); cc *= 100.0f; break; case 10: - objModel = ch->it->panningModel(); + modelObject = ch->it->panningModel(); cc = cc * 200.f - 100.0f; break; case 128: - objModel = ch->it->pitchModel(); + modelObject = ch->it->pitchModel(); cc = cc * 100.0f; break; default: - //TODO: something useful for other CCs + if (ccid >= 0 && ccid < 128) + { + modelObject = ch->it->midiCCModel(ccid); + cc = cc * 127.0f; + } break; } - if (objModel) + if (modelObject) { - if (time == 0 && objModel) + if (time == 0) { - objModel->setInitValue(cc); + modelObject->setInitValue(cc); } else { - if (ccs[ccid].at == nullptr) { - ccs[ccid].create(tc, trackName + " > " + - // This is inside if (objModel), so objModel should never be nullptr - // (objModel != nullptr ? objModel->displayName() : QString("CC %1").arg(ccid)) - objModel->displayName() - ); + if (ccs[ccid].at == nullptr) + { + ccs[ccid].create(tc, trackName + " > " + modelObject->displayName()); } - ccs[ccid].putValue(time, objModel, cc); + ccs[ccid].putValue(time, modelObject, cc); } } }