Skip to content

Commit

Permalink
Glide ends after both notes released
Browse files Browse the repository at this point in the history
  • Loading branch information
rhargreaves committed Jul 23, 2024
1 parent 8b618ad commit 625c4b7
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 4 deletions.
9 changes: 6 additions & 3 deletions src/midi.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,13 @@ static void initDeviceChannel(u8 devChan)
updateDeviceChannelFromAssociatedMidiChannel(chan);
}

static DeviceChannel* findChannelPlayingNote(u8 midiChannel, u8 pitch)
static DeviceChannel* findChannelPlayingNote(u8 midiChannel, u8 pitch, bool portamento)
{
for (u16 i = 0; i < DEV_CHANS; i++) {
DeviceChannel* chan = &deviceChannels[i];
if (chan->noteOn && chan->midiChannel == midiChannel
&& (chan->pitch == pitch || chan->glideTargetPitch == pitch)) {
&& ((chan->pitch == pitch && !portamento)
|| (chan->glideTargetPitch == pitch && portamento))) {
return chan;
}
}
Expand Down Expand Up @@ -407,6 +408,8 @@ void midi_note_on(u8 chan, u8 pitch, u8 velocity)
if (note_priority_count(&midiChannel->notePriority) > 1 && midiChannel->portamento) {
devChan->glideTargetPitch = pitch;
return;
} else {
devChan->glideTargetPitch = 0;
}
}

Expand All @@ -423,7 +426,7 @@ void midi_note_off(u8 chan, u8 pitch)
note_priority_remove(&midiChannel->notePriority, pitch);

DeviceChannel* devChan;
while ((devChan = findChannelPlayingNote(chan, pitch)) != NULL) {
while ((devChan = findChannelPlayingNote(chan, pitch, midiChannel->portamento)) != NULL) {
u8 nextMostRecentPitch = note_priority_pop(&midiChannel->notePriority);
if (!dynamicMode && nextMostRecentPitch != 0) {

Expand Down
4 changes: 3 additions & 1 deletion tests/unit/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,9 @@ int main(void)
midi_portamento_test(test_midi_portamento_glides_note_up_and_down_on_early_release),
midi_portamento_test(test_midi_portamento_glides_only_if_target_set),
midi_portamento_test(test_midi_portamento_glide_ignores_unassigned_channels),
midi_portamento_test(test_midi_portamento_glides_note_up_down_and_back_up)
midi_portamento_test(test_midi_portamento_glides_note_up_down_and_back_up),
midi_portamento_test(test_midi_portamento_glide_ends_after_both_notes_off),
midi_portamento_test(test_midi_portamento_glides_fully_up_and_down)
// clang-format on
};

Expand Down
1 change: 1 addition & 0 deletions tests/unit/test_midi.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "synth.h"

#define MIDI_PITCH_A2 45
#define MIDI_PITCH_C3 48
#define MIDI_PITCH_C4 60
#define MIDI_PITCH_CS4 61
#define MIDI_PITCH_AS6 94
Expand Down
72 changes: 72 additions & 0 deletions tests/unit/test_midi_portamento.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,75 @@ static void test_midi_portamento_glides_only_if_target_set(UNUSED void** state)
midi_tick();
midi_tick();
}

static void test_midi_portamento_glide_ends_after_both_notes_off(UNUSED void** state)
{
u8 chan = 0;
debug_message("channel %d\n", chan);
__real_midi_cc(chan, CC_PORTAMENTO_ENABLE, 127);

expect_synth_pitch(chan, 2, 0x439);
expect_synth_volume_any();
expect_synth_noteOn(chan);
__real_midi_note_on(chan, MIDI_PITCH_A2, MAX_MIDI_VOLUME);
__real_midi_note_on(chan, MIDI_PITCH_C4, MAX_MIDI_VOLUME);

expect_synth_pitch(chan, 2, 0x43f);
midi_tick();
for (u16 i = 0; i < 74; i++) {
expect_synth_pitch_any();
midi_tick();
}

debug_message("note off\n");
__real_midi_note_off(chan, MIDI_PITCH_C4);
for (u16 i = 0; i < 37; i++) {
expect_synth_pitch_any();
midi_tick();
}

debug_message("note off\n");
expect_value(__wrap_synth_noteOff, channel, 0);
__real_midi_note_off(chan, MIDI_PITCH_A2);

midi_tick();

expect_synth_pitch(chan, 3, 0x284);
expect_synth_volume_any();
expect_synth_noteOn(chan);
__real_midi_note_on(chan, MIDI_PITCH_C3, MAX_MIDI_VOLUME);

midi_tick();
midi_tick();
}

static void test_midi_portamento_glides_fully_up_and_down(UNUSED void** state)
{
u8 chan = 0;
debug_message("channel %d\n", chan);
__real_midi_cc(chan, CC_PORTAMENTO_ENABLE, 127);

expect_synth_pitch(chan, 2, 0x439);
expect_synth_volume_any();
expect_synth_noteOn(chan);
__real_midi_note_on(chan, MIDI_PITCH_A2, MAX_MIDI_VOLUME);
__real_midi_note_on(chan, MIDI_PITCH_C4, MAX_MIDI_VOLUME);

expect_synth_pitch(chan, 2, 0x43f);
midi_tick();
for (u16 i = 0; i < 148; i++) {
expect_synth_pitch_any();
midi_tick();
}
expect_synth_pitch(chan, 4, 644);
midi_tick();

debug_message("note off\n");
__real_midi_note_off(chan, MIDI_PITCH_C4);
for (u16 i = 0; i < 148; i++) {
expect_synth_pitch_any();
midi_tick();
}
expect_synth_pitch(chan, 2, 0x43f);
midi_tick();
}

0 comments on commit 625c4b7

Please sign in to comment.