Skip to content

Commit

Permalink
Mono modes in MPE (surge-synthesizer#756)
Browse files Browse the repository at this point in the history
The releases in MPE mode didn't correctly map to the MPE Channel
so ended up sticking. This fixes those problems by chosing the
right off-channel voice for legato adjustment or next-activation
in the mono modes.

Closes surge-synthesizer#339
Closes surge-synthesizer#742

Former-commit-id: 0c103487029a9a9b2ff8088d57495508af49f8d4 [formerly 107dca6]
Former-commit-id: 5acff8033437d69d9d54d01beabaf0310e85042d
Former-commit-id: 1f78d94eb942d82c6ff5fd658bb077dbbbb8661b
  • Loading branch information
baconpaul authored Mar 9, 2019
1 parent 8f9e954 commit b8cb857
Showing 1 changed file with 90 additions and 12 deletions.
102 changes: 90 additions & 12 deletions src/common/SurgeSynthesizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,16 @@ void SurgeSynthesizer::playVoice(int scene, char channel, char key, char velocit
{
v->legato(key, velocity, detune);
found_one = true;
if (mpeEnabled)
{
/*
** This voice was created on a channel but is being legato held to another channel
** so it needs to borrow the channel and channelState. Obviously this can only
** happen in MPE mode.
*/
v->state.channel = channel;
v->state.voiceChannelState = &channelState[channel];
}
break;
}
else
Expand Down Expand Up @@ -543,15 +553,49 @@ void SurgeSynthesizer::releaseNotePostHoldCheck(int scene, char channel, char ke
case pm_mono_fp:
case pm_latch:
{
/*
** In these modes, our job when we release a note is to see if
** any ohter note is held.
**
** In normal midi mode, that means scanning the keystate of our
** channel looking for another note.
**
** In MPE mode, where each note is per channel, that means
** scanning all non-main channels rather than ourself for the
** highest note
*/
if ((v->state.key == key) && (v->state.channel == channel))
{
int activateVoiceKey, activateVoiceChannel;

// v->release();
for (k = hikey; k >= lowkey; k--) // search downwards
if (!mpeEnabled)
{
if (channelState[channel].keyState[k].keystate)
for (k = hikey; k >= lowkey && !do_switch; k--) // search downwards
{
do_switch = true;
break;
if (channelState[channel].keyState[k].keystate)
{
do_switch = true;
activateVoiceKey = k;
activateVoiceChannel = channel;
break;
}
}
}
else
{
for (k = hikey; k >= lowkey && !do_switch; k--)
{
for (int mpeChan = 1; mpeChan < 16; ++mpeChan)
{
if (mpeChan != channel && channelState[mpeChan].keyState[k].keystate)
{
do_switch = true;
activateVoiceChannel = mpeChan;
activateVoiceKey = k;
break;
}
}
}
}
if (!do_switch)
Expand All @@ -564,27 +608,61 @@ void SurgeSynthesizer::releaseNotePostHoldCheck(int scene, char channel, char ke
// confirm that no notes are active
v->uber_release();
if (getNonUltrareleaseVoices(scene) == 0)
playVoice(scene, channel, k, velocity,
channelState[channel].keyState[k].lastdetune);
{
playVoice(scene, activateVoiceChannel, activateVoiceKey, velocity,
channelState[activateVoiceChannel].keyState[k].lastdetune);
}
}
}
}
break;
case pm_mono_st:
case pm_mono_st_fp:
{
if ((v->state.key == key) && (v->state.channel == channel))
/*
** In these modes the note will collide on the main channel
*/
int stateChannel = getMpeMainChannel(v->state.channel, v->state.key);
int noteChannel = getMpeMainChannel(channel, key);

if ((v->state.key == key) && (stateChannel == noteChannel))
{
bool do_release = true;
for (k = hikey; k >= lowkey; k--) // search downwards
/*
** Again the note I need to legato to is on my channel in non MPE and
** is on another channel in MPE mode
*/
if (!mpeEnabled)
{
if (channelState[channel].keyState[k].keystate)
for (k = hikey; k >= lowkey && do_release; k--) // search downwards
{
v->legato(k, velocity, channelState[channel].keyState[k].lastdetune);
do_release = false;
break;
if (channelState[channel].keyState[k].keystate)
{
v->legato(k, velocity, channelState[channel].keyState[k].lastdetune);
do_release = false;
break;
}
}
}
else
{
for (k = hikey; k >= lowkey && do_release; k--) // search downwards
{
for (int mpeChan = 1; mpeChan < 16; ++mpeChan)
{
if (mpeChan != channel && channelState[mpeChan].keyState[k].keystate)
{
v->legato(k, velocity, channelState[mpeChan].keyState[k].lastdetune);
do_release = false;
// See the comment above at the other _st legato spot
v->state.channel = mpeChan;
v->state.voiceChannelState = &channelState[mpeChan];
break;
}
}
}
}

if (do_release)
v->release();
}
Expand Down

0 comments on commit b8cb857

Please sign in to comment.