commit f3946b60102baf97e8684d6f9f95e0ecad5f8fc8
parent 96e803c9a6230ae3d00925821b0eda296a2d396b
Author: fundamental <mark.d.mccurry@gmail.com>
Date: Thu, 31 May 2012 23:31:44 -0400
Adds aftertouch support
Integrates MIDI aftertouch support for normal, legato, and mono notes.
- Patch by Olaf Schulz
Diffstat:
12 files changed, 118 insertions(+), 1 deletion(-)
diff --git a/AUTHORS.txt b/AUTHORS.txt
@@ -21,5 +21,6 @@ Contributors:
Hans Petter Selasky (OSS Midi, FreeBSD support, Bank UI bug fix)
Damien Goutte-Gattat (Bank select midi support)
Lieven Moors (Spike/Circle waveform)
+ Olaf Schulz (MIDI Aftertouch support)
Jonathan Liles (NSM support)
diff --git a/src/Misc/Master.cpp b/src/Misc/Master.cpp
@@ -157,6 +157,22 @@ void Master::noteOff(char chan, char note)
}
/*
+ * Pressure Messages (velocity=0 for NoteOff)
+ */
+void Master::polyphonicAftertouch(char chan, char note, char velocity)
+{
+ if(velocity) {
+ for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart)
+ if(chan == part[npart]->Prcvchn)
+ if(part[npart]->Penabled)
+ part[npart]->PolyphonicAftertouch(note, velocity, keyshift);
+
+ }
+ else
+ this->noteOff(chan, note);
+}
+
+/*
* Controllers
*/
void Master::setController(char chan, int type, int par)
diff --git a/src/Misc/Master.h b/src/Misc/Master.h
@@ -91,6 +91,7 @@ class Master
//Midi IN
void noteOn(char chan, char note, char velocity);
void noteOff(char chan, char note);
+ void polyphonicAftertouch(char chan, char note, char velocity);
void setController(char chan, int type, int par);
void setProgram(char chan, unsigned int pgm);
//void NRPN...
diff --git a/src/Misc/Part.cpp b/src/Misc/Part.cpp
@@ -645,6 +645,58 @@ void Part::NoteOff(unsigned char note) //relase the key
}
}
+void Part::PolyphonicAftertouch(unsigned char note,
+ unsigned char velocity,
+ int masterkeyshift)
+{
+ if(!Pnoteon || (note < Pminkey) || (note > Pmaxkey))
+ return;
+ if(Pdrummode)
+ return;
+
+ // MonoMem stuff:
+ if(!Ppolymode) // if Poly is off
+
+ monomem[note].velocity = velocity; // Store this note's velocity.
+
+
+ for(int i = 0; i < POLIPHONY; ++i)
+ if((partnote[i].note == note) && (partnote[i].status == KEY_PLAYING)) {
+ /* update velocity */
+ // compute the velocity offset
+ float vel =
+ VelF(velocity / 127.0f, Pvelsns) + (Pveloffs - 64.0f) / 64.0f;
+ vel = (vel < 0.0f) ? 0.0f : vel;
+ vel = (vel > 1.0f) ? 1.0f : vel;
+
+ if(!Pkitmode) { // "normal mode"
+ if(kit[0].Padenabled)
+ partnote[i].kititem[0].adnote->setVelocity(vel);
+ if(kit[0].Psubenabled)
+ partnote[i].kititem[0].subnote->setVelocity(vel);
+ if(kit[0].Ppadenabled)
+ partnote[i].kititem[0].padnote->setVelocity(vel);
+ }
+ else // "kit mode"
+ for(int item = 0; item < NUM_KIT_ITEMS; ++item) {
+ if(kit[item].Pmuted)
+ continue;
+ if((note < kit[item].Pminkey)
+ || (note > kit[item].Pmaxkey))
+ continue;
+
+ int ci = partnote[i].itemsplaying; // ci=current item
+ if(kit[item].Padenabled)
+ partnote[i].kititem[item].adnote->setVelocity(vel);
+ if(kit[item].Psubenabled)
+ partnote[i].kititem[item].subnote->setVelocity(vel);
+ if(kit[item].Ppadenabled)
+ partnote[i].kititem[item].padnote->setVelocity(vel);
+ }
+ }
+
+}
+
/*
* Controllers
*/
diff --git a/src/Misc/Part.h b/src/Misc/Part.h
@@ -56,6 +56,9 @@ class Part
unsigned char velocity,
int masterkeyshift);
void NoteOff(unsigned char note);
+ void PolyphonicAftertouch(unsigned char note,
+ unsigned char velocity,
+ int masterkeyshift);
void AllNotesOff(); //panic
void SetController(unsigned int type, int par);
void RelaseSustainedKeys(); //this is called when the sustain pedal is relased
diff --git a/src/Nio/AlsaEngine.cpp b/src/Nio/AlsaEngine.cpp
@@ -136,6 +136,14 @@ void *AlsaEngine::MidiThread(void)
InMgr::getInstance().putEvent(ev);
break;
+ case SND_SEQ_EVENT_KEYPRESS:
+ ev.type = M_PRESSURE;
+ ev.channel = event->data.note.channel;
+ ev.num = event->data.note.note;
+ ev.value = event->data.note.velocity;
+ InMgr::getInstance().putEvent(ev);
+ break;
+
case SND_SEQ_EVENT_PITCHBEND:
ev.type = M_CONTROLLER;
ev.channel = event->data.control.channel;
diff --git a/src/Nio/InMgr.cpp b/src/Nio/InMgr.cpp
@@ -86,6 +86,9 @@ void InMgr::flush()
case M_PGMCHANGE:
master.setProgram(ev.channel, ev.num);
break;
+ case M_PRESSURE:
+ master.polyphonicAftertouch(ev.channel, ev.num, ev.value);
+ break;
}
}
}
diff --git a/src/Nio/InMgr.h b/src/Nio/InMgr.h
@@ -8,8 +8,10 @@
enum midi_type {
M_NOTE = 1,
M_CONTROLLER = 2,
- M_PGMCHANGE = 3
+ M_PGMCHANGE = 3,
+ M_PRESSURE = 4
}; //type=1 for note, type=2 for controller, type=3 for program change
+//type=4 for polyphonic aftertouch
struct MidiEvent {
MidiEvent();
diff --git a/src/Nio/JackEngine.cpp b/src/Nio/JackEngine.cpp
@@ -368,6 +368,13 @@ void JackEngine::handleMidi(unsigned long frames)
InMgr::getInstance().putEvent(ev);
break;
+ case 0xA0: /* pressure, aftertouch */
+ ev.type = M_PRESSURE;
+ ev.num = midi_data[1];
+ ev.value = midi_data[2];
+ InMgr::getInstance().putEvent(ev);
+ break;
+
case 0xB0: /* controller */
ev.type = M_CONTROLLER;
ev.num = midi_data[1];
diff --git a/src/Nio/MidiIn.cpp b/src/Nio/MidiIn.cpp
@@ -45,6 +45,13 @@ void MidiIn::midiProcess(unsigned char head,
ev.value = value;
InMgr::getInstance().putEvent(ev);
break;
+ case 0xA0: /* pressure, aftertouch */
+ ev.type = M_PRESSURE;
+ ev.channel = chan;
+ ev.num = num;
+ ev.value = value;
+ InMgr::getInstance().putEvent(ev);
+ break;
case 0xb0: //Controller
ev.type = M_CONTROLLER;
ev.channel = chan;
diff --git a/src/Synth/SynthNote.cpp b/src/Synth/SynthNote.cpp
@@ -125,3 +125,10 @@ void SynthNote::Legato::apply(SynthNote ¬e, float *outl, float *outr)
break;
}
}
+
+void SynthNote::setVelocity(float velocity_) {
+ legato.setSilent(true); //Let legato.update(...) returns 0.
+ legatonote(legato.getFreq(), velocity_,
+ legato.getPortamento(), legato.getMidinote(), true);
+ legato.setDecounter(0); //avoid chopping sound due fade-in
+}
diff --git a/src/Synth/SynthNote.h b/src/Synth/SynthNote.h
@@ -45,6 +45,8 @@ class SynthNote
virtual void legatonote(float freq, float velocity,
int portamento_, int midinote_,
bool externcall) = 0;
+ /* For polyphonic aftertouch needed */
+ void setVelocity(float velocity_);
protected:
// Legato transitions
class Legato
@@ -70,6 +72,14 @@ class SynthNote
float freq, vel;
int portamento, midinote;
} param;
+
+ public: /* Some get routines for legatonote calls (aftertouch feature)*/
+ float getFreq() {return param.freq; }
+ float getVelocity() {return param.vel; }
+ int getPortamento() {return param.portamento; }
+ int getMidinote() {return param.midinote; }
+ void setSilent(bool silent_) {silent = silent_; }
+ void setDecounter(int decounter_) {decounter = decounter_; }
} legato;
};