From a247e60904516800a3874688e368979b9b1e7bf8 Mon Sep 17 00:00:00 2001 From: "Tim E. Real" Date: Tue, 13 Nov 2012 08:36:20 +0000 Subject: Added aftertouch controller to fluidsynth, and aftertouch/poly-aftertouch to DSSI. --- muse2/ChangeLog | 1 + muse2/muse/dssihost.cpp | 62 ++++++++++++++++++++++++++++++++++- muse2/muse/midiport.cpp | 4 ++- muse2/synti/fluidsynth/fluidsynti.cpp | 22 +++++++++---- muse2/synti/libsynti/mess.cpp | 4 ++- 5 files changed, 83 insertions(+), 10 deletions(-) (limited to 'muse2') diff --git a/muse2/ChangeLog b/muse2/ChangeLog index 63ef9713..0eb4c473 100644 --- a/muse2/ChangeLog +++ b/muse2/ChangeLog @@ -1,5 +1,6 @@ 12.11.2012: - Added aftertouch controllers to all relevant remaining instrument files. (Tim) + - Synths: Added aftertouch controller to fluidsynth, and aftertouch/poly-aftertouch to DSSI. (Tim) 11.11.2012: - Finished Aftertouch controllers: Removed PAfter and CAfter Event types. Quietly convert such events in old songs into the new controllers. Converted midi input (hopefully). (Tim) diff --git a/muse2/muse/dssihost.cpp b/muse2/muse/dssihost.cpp index c76631e4..70db2a47 100644 --- a/muse2/muse/dssihost.cpp +++ b/muse2/muse/dssihost.cpp @@ -1112,6 +1112,32 @@ bool DssiSynthIF::processEvent(const MusECore::MidiPlayEvent& e, snd_seq_event_t return true; } + if(a == MusECore::CTRL_AFTERTOUCH) + { + #ifdef DSSI_DEBUG + fprintf(stderr, "DssiSynthIF::processEvent midi event is MusECore::ME_CONTROLLER, dataA is MusECore::CTRL_AFTERTOUCH\n"); + #endif + + snd_seq_ev_clear(event); + event->queue = SND_SEQ_QUEUE_DIRECT; + snd_seq_ev_set_chanpress(event, chn, b); + // Event pointer filled. Return true. + return true; + } + + if((a | 0xff) == MusECore::CTRL_POLYAFTER) + { + #ifdef DSSI_DEBUG + fprintf(stderr, "DssiSynthIF::processEvent midi event is MusECore::ME_CONTROLLER, dataA is MusECore::CTRL_POLYAFTER\n"); + #endif + + snd_seq_ev_clear(event); + event->queue = SND_SEQ_QUEUE_DIRECT; + snd_seq_ev_set_keypress(event, chn, a & 0x7f, b & 0x7f); + // Event pointer filled. Return true. + return true; + } + const LADSPA_Descriptor* ld = dssi->LADSPA_Plugin; MusECore::ciMidiCtl2LadspaPort ip = synth->midiCtl2PortMap.find(a); @@ -1219,6 +1245,11 @@ bool DssiSynthIF::processEvent(const MusECore::MidiPlayEvent& e, snd_seq_event_t event->queue = SND_SEQ_QUEUE_DIRECT; snd_seq_ev_set_chanpress(event, chn, a); break; + case MusECore::ME_POLYAFTER: + snd_seq_ev_clear(event); + event->queue = SND_SEQ_QUEUE_DIRECT; + snd_seq_ev_set_keypress(event, chn, a & 0x7f, b & 0x7f); + break; case MusECore::ME_SYSEX: { #ifdef DSSI_DEBUG @@ -1615,6 +1646,19 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP if(!mp->setHwCtrlState(start_event->channel(), MusECore::CTRL_PITCH, da)) continue; } + else if(start_event->type() == MusECore::ME_AFTERTOUCH) + { + int da = mp->limitValToInstrCtlRange(MusECore::CTRL_AFTERTOUCH, start_event->dataA()); + if(!mp->setHwCtrlState(start_event->channel(), MusECore::CTRL_AFTERTOUCH, da)) + continue; + } + else if(start_event->type() == MusECore::ME_POLYAFTER) + { + int ctl = (MusECore::CTRL_POLYAFTER & ~0xff) | (start_event->dataA() & 0x7f); + int db = mp->limitValToInstrCtlRange(ctl, start_event->dataB()); + if(!mp->setHwCtrlState(start_event->channel(), ctl , db)) + continue; + } else if(start_event->type() == MusECore::ME_PROGRAM) { if(!mp->setHwCtrlState(start_event->channel(), MusECore::CTRL_PROGRAM, start_event->dataA())) @@ -2160,7 +2204,23 @@ void DssiSynthIF::populatePatchPopup(MusEGui::PopupMenu* menu, int /*ch*/, bool int DssiSynthIF::getControllerInfo(int id, const char** name, int* ctrl, int* min, int* max, int* initval) { int controlPorts = synth->_controlInPorts; - if(id >= controlPorts) + if(id == controlPorts || id == controlPorts + 1) + { + // + // It is unknown at this point whether or not a synth recognizes aftertouch and poly aftertouch + // (channel and key pressure) midi messages, so add support for them now (as controllers). + // + if(id == controlPorts) + *ctrl = MusECore::CTRL_POLYAFTER; + else if(id == controlPorts + 1) + *ctrl = MusECore::CTRL_AFTERTOUCH; + *min = 0; + *max = 127; + *initval = MusECore::CTRL_VAL_UNKNOWN; + *name = midiCtrlName(*ctrl).toLatin1().constData(); + return ++id; + } + else if(id >= controlPorts + 2) return 0; const DSSI_Descriptor* dssi = synth->dssi; diff --git a/muse2/muse/midiport.cpp b/muse2/muse/midiport.cpp index 61e7ab50..e4759d31 100644 --- a/muse2/muse/midiport.cpp +++ b/muse2/muse/midiport.cpp @@ -794,7 +794,9 @@ int MidiPort::limitValToInstrCtlRange(int ctl, int val) return val; MidiControllerList* cl = _instrument->controller(); - + + // FIXME: This might be optimized by calling midiController instead, + // and simply asking if it's a drum controller. Saves one list iteration. // Is it a drum controller? MidiController *mc = drumController(ctl); if(!mc) diff --git a/muse2/synti/fluidsynth/fluidsynti.cpp b/muse2/synti/fluidsynth/fluidsynti.cpp index 46f20156..3dd45105 100644 --- a/muse2/synti/fluidsynth/fluidsynti.cpp +++ b/muse2/synti/fluidsynth/fluidsynti.cpp @@ -76,6 +76,7 @@ FluidCtrl FluidSynth::fluidCtrl[] = { { "Channel reverb send", MusECore::CTRL_REVERB_SEND, 0, 127, 40}, { "Channel chorus send", MusECore::CTRL_CHORUS_SEND, 0, 127, 0}, { "Pitch", MusECore::CTRL_PITCH, -8192, 8191, 0}, + { "Channel pressure", MusECore::CTRL_AFTERTOUCH, 0, 127, 0}, // Added by T356 { "Pitch bend sensitivity", FS_PITCHWHEELSENS, 0, 24, 2} }; @@ -508,7 +509,9 @@ bool FluidSynth::processEvent(const MusECore::MidiPlayEvent& ev) case MusECore::ME_PITCHBEND: setController(ev.channel(), MusECore::CTRL_PITCH, ev.dataA(), false); break; - + case MusECore::ME_AFTERTOUCH: + setController(ev.channel(), MusECore::CTRL_AFTERTOUCH, ev.dataA(), false); + break; case MusECore::ME_PROGRAM: setController(ev.channel(), MusECore::CTRL_PROGRAM, ev.dataA(), false); break; @@ -983,15 +986,20 @@ void FluidSynth::setController(int channel, int id, int val, bool fromGui) // case MusECore::CTRL_PITCH: // MusE's range is from -8192 to +8191, fluidsynth seems to be [0, 16384] - val +=8192; - err = fluid_synth_pitch_bend (fluidsynth, channel, val); + if(val != MusECore::CTRL_VAL_UNKNOWN) + { + val +=8192; + err = fluid_synth_pitch_bend (fluidsynth, channel, val); + } + break; + case MusECore::CTRL_AFTERTOUCH: + if(val != MusECore::CTRL_VAL_UNKNOWN) + err = fluid_synth_channel_pressure (fluidsynth, channel, val); break; - - // Added by T356 case FS_PITCHWHEELSENS: - err = fluid_synth_pitch_wheel_sens(fluidsynth, channel, val); + if(val != MusECore::CTRL_VAL_UNKNOWN) + err = fluid_synth_pitch_wheel_sens(fluidsynth, channel, val); break; - case MusECore::CTRL_PROGRAM: { //Check if MusE is trying to set a preset on an unspecified font. If so, ignore. if (FS_DEBUG) diff --git a/muse2/synti/libsynti/mess.cpp b/muse2/synti/libsynti/mess.cpp index 027a30c1..de24ac00 100644 --- a/muse2/synti/libsynti/mess.cpp +++ b/muse2/synti/libsynti/mess.cpp @@ -145,8 +145,10 @@ bool Mess::processEvent(const MusECore::MidiPlayEvent& ev) return sysex(ev.len(), ev.data()); case MusECore::ME_CONTROLLER: return setController(ev.channel(), ev.dataA(), ev.dataB()); - case MusECore::ME_PITCHBEND: // Tim. + case MusECore::ME_PITCHBEND: return setController(ev.channel(), MusECore::CTRL_PITCH, ev.dataA()); + case MusECore::ME_AFTERTOUCH: + return setController(ev.channel(), MusECore::CTRL_AFTERTOUCH, ev.dataA()); } return false; } -- cgit v1.2.3