MIOS32: Velocity crossfaded keyboard zones (code included)
Simple keyboard zones
Rather than have the whole keyboard output the same midi channel (hence same sound) we may want to have "left hand ->Bass" and "right hand -> Treble" parts. This is accomplished by having a "zones" in this case upper and lower parts of the keyboard separated at a certain note on the keyboard ("split point").
A simple keyboard zone split is simple to define: for example output note numbers above a the split point on a different channel.
Velocity crossfaded zones
Rather than a sudden boundary dividing keys into one channel or another, crossfaded zones have an overlap. The incoming notes have their velocities scaled according to a curve best shown in a diagram:
Implementation
A simple split my be accomplished with a call to the following function with received midi package before sinding it on:
//*********************Simple split*************************************************************
mios32_midi_package_t split(mios32_midi_package_t m_p, u8 splitpoint)
{
if ((m_p.type == NoteOn || m_p.type == NoteOff)&& m_p.note>splitpoint)
m_p.chn++; //output on next channel
return m_p;
}
//**********************************************************************************************
The lower zone is output on the same channel as the input. The upper zone is output on the next channel.
Velocity crossfade zones are done with calls to two functions: upper and lower.
//********************Upper keyboard zone*******************************************************
mios32_midi_package_t VelocityCrossfadeUpper(mios32_midi_package_t m_p,u8 sp,u8 size,u8 chan){
m_p.chn=chan; //route to new channel regardless
if (m_p.type==NoteOn){ //other event types are passed through
if (m_p.velocity==0) return m_p; //note offs (vel==0) get passed through
if (m_p.note>(sp+size/2))return m_p; //above split region so return unmodified
if (m_p.note<(sp-size/2)){ //below split region so return velocity 0
m_p.velocity=0;
return m_p;
}else{ //within sp + or - size/2 so scale
m_p.velocity=(m_p.velocity*(m_p.note-(sp-size/2)))/size; //scale the velocity
return m_p;
}
} else return m_p; //NoteOffs (or other events types) get passed through
}
//**********************************************************************************************
//*******************Lower Keyboard zone********************************************************
mios32_midi_package_t VelocityCrossfadeLower(mios32_midi_package_t m_p,u8 sp,u8 size,u8 chan){
m_p.chn=chan; //route to new channel
if (m_p.type==NoteOn){
if (m_p.velocity==0) return m_p; //note offs (vel==0) get passed through
if (m_p.note<(sp-size/2)) return m_p; //below split region so return unmodified
if (m_p.note>(sp+size/2)){
m_p.velocity=0; //above split region so return velocity 0
return m_p;
}else{ //within sp + or - size/2 so scale
m_p.velocity=m_p.velocity-(m_p.velocity*(m_p.note-(sp-size/2)))/size;//scale the velocity
return m_p;
}
} else return m_p; //NoteOffs (or other events types) get passed through
}
//**********************************************************************************************
Application
The following application applies the crossfade split to note events on any channel of any (or all) ports. Midi packages on USB0 are not processed to keep the port available to MIOS Studio as a development convenience.
Usage
Inputs
notes on any channel
CC#110: Splitpoint location (note number)
CC#111: Split size (distance in midi notes)
Outputs
ch1: Lower zone output
ch2: Upper zone output
//***********Velocity crossfade zones app example******************************
void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t m_p)
{
static u8 splitpoint=60; //defaults
static u8 splitsize=12; //defaults
if (port!=USB0){ //reserve USB0 for MIOS Studio comms
//send lower split
MIOS32_MIDI_SendPackage(port,VelocityCrossfadeLower(m_p,splitpoint,splitsize,0));
//send upper split
MIOS32_MIDI_SendPackage(port,VelocityCrossfadeUpper(m_p,splitpoint,splitsize,1));
if (m_p.type==CC){ //update split params
switch(m_p.cc_number){
case 110: splitpoint=m_p.value;break;
case 111: splitsize=m_p.value;break;
}
}
}
}
Pictures and code © Duggle 2010
0 Comments
Recommended Comments
There are no comments to display.