Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mono modes in MPE #756

Merged
merged 1 commit into from
Mar 9, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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