Skip to content

Commit

Permalink
Apply fine tune parameter with bend/glide
Browse files Browse the repository at this point in the history
  • Loading branch information
rhargreaves committed Jul 27, 2024
1 parent 83b8d0e commit 702e568
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 11 deletions.
29 changes: 19 additions & 10 deletions src/midi.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ static void reset(void);
static void init(void);
static void devChanNoteOn(DeviceChannel* devChan, u8 pitch, u8 velocity);
static void devChanNoteOff(DeviceChannel* devChan, u8 pitch);
static void setDownstreamPitch(DeviceChannel* devChan, MidiChannel* midiChannel);

void midi_init(
const FmChannel** presets, const PercussionPreset** percussionPresets, const u8** envelopes)
Expand Down Expand Up @@ -347,9 +348,8 @@ static void updatePan(MidiChannel* midiChannel, DeviceChannel* devChan)
static void updatePitchBend(MidiChannel* midiChannel, DeviceChannel* devChan)
{
if (devChan->pitchBend != midiChannel->pitchBend) {
PitchCents pc = pitchcents_bend(devChan->pitch, devChan->cents, midiChannel->pitchBend);
devChan->ops->pitch(devChan->number, pc.pitch, pc.cents);
devChan->pitchBend = midiChannel->pitchBend;
setDownstreamPitch(devChan, midiChannel);
}
}

Expand Down Expand Up @@ -390,6 +390,20 @@ static DeviceChannel* findSuitableDeviceChannel(u8 midiChan)
return dynamicMode ? findFreeChannel(midiChan) : deviceChannelByMidiChannel(midiChan);
}

static void setDownstreamPitch(DeviceChannel* devChan, MidiChannel* midiChannel)
{
PitchCents pc = pitchcents_bend(devChan->pitch, devChan->cents, devChan->pitchBend);
pc = pitchcents_shift(pc, midiChannel->fineTune);
devChan->ops->pitch(devChan->number, pc.pitch, pc.cents);
}

static void setDownstreamNoteOn(DeviceChannel* devChan, u8 velocity)
{
PitchCents pc = pitchcents_bend(devChan->pitch, devChan->cents, devChan->pitchBend);
pc = pitchcents_shift(pc, midiChannels[devChan->midiChannel].fineTune);
devChan->ops->noteOn(devChan->number, pc.pitch, pc.cents, velocity);
}

void midi_note_on(u8 chan, u8 pitch, u8 velocity)
{
if (velocity == MIN_MIDI_VELOCITY) {
Expand Down Expand Up @@ -426,9 +440,7 @@ void midi_note_on(u8 chan, u8 pitch, u8 velocity)
devChan->cents = 0;
devChan->pitch = pitch;
updateDeviceChannelFromAssociatedMidiChannel(devChan);
PitchCents pc = pitchcents_bend(devChan->pitch, devChan->cents, devChan->pitchBend);
pc = pitchcents_shift(pc, midiChannel->fineTune);
devChan->ops->noteOn(devChan->number, pc.pitch, pc.cents, velocity);
setDownstreamNoteOn(devChan, velocity);
}

void midi_note_off(u8 chan, u8 pitch)
Expand Down Expand Up @@ -458,8 +470,7 @@ static void devChanNoteOn(DeviceChannel* devChan, u8 pitch, u8 velocity)
devChan->noteOn = true;
devChan->cents = 0;
devChan->pitch = pitch;
PitchCents pc = pitchcents_bend(devChan->pitch, devChan->cents, devChan->pitchBend);
devChan->ops->noteOn(devChan->number, pc.pitch, pc.cents, velocity);
setDownstreamNoteOn(devChan, velocity);
}

static void devChanNoteOff(DeviceChannel* devChan, u8 pitch)
Expand Down Expand Up @@ -984,9 +995,7 @@ static void processChannelGlide(DeviceChannel* chan, u16 portamentoTime)

chan->pitch = pc.pitch;
chan->cents = pc.cents;

pc = pitchcents_bend(pc.pitch, pc.cents, chan->pitchBend);
chan->ops->pitch(chan->number, pc.pitch, pc.cents);
setDownstreamPitch(chan, &midiChannels[chan->midiChannel]);
}

static void processPortamento(void)
Expand Down
4 changes: 3 additions & 1 deletion tests/unit/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,9 +402,11 @@ int main(void)
midi_portamento_test(test_midi_portamento_sets_portamento_time_to_minimum),
midi_portamento_test(test_midi_portamento_sets_portamento_time_to_maximum),
midi_portamento_test(test_midi_portamento_default_portamento_time_set),
midi_portamento_test(test_midi_portamento_glides_with_fine_tune),

midi_finetune_test(test_midi_finetune_max),
midi_finetune_test(test_midi_finetune_min)
midi_finetune_test(test_midi_finetune_min),
midi_finetune_test(test_midi_finetune_with_pitchbend),
// clang-format on
};

Expand Down
16 changes: 16 additions & 0 deletions tests/unit/test_midi_finetune.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,19 @@ static void test_midi_finetune_min(UNUSED void** state)
__real_midi_note_on(chan, MIDI_PITCH_A2, MAX_MIDI_VOLUME);
}
}

static void test_midi_finetune_with_pitchbend(UNUSED void** state)
{
for (u8 chan = 0; chan < MAX_FM_CHANS; chan++) {
debug_message("channel %d\n", chan);
__real_midi_cc(chan, CC_FINE_TUNE, 0);

expect_synth_pitch(chan, 2, 0x492);
__real_midi_pitch_bend(chan, MIDI_PITCH_BEND_MAX);

expect_synth_pitch(chan, 2, 0x492);
expect_synth_volume_any();
expect_synth_noteOn(chan);
__real_midi_note_on(chan, MIDI_PITCH_A2, MAX_MIDI_VOLUME);
}
}
16 changes: 16 additions & 0 deletions tests/unit/test_midi_portamento.c
Original file line number Diff line number Diff line change
Expand Up @@ -442,3 +442,19 @@ static void test_midi_portamento_default_portamento_time_set(UNUSED void** state
expect_synth_pitch(chan, 2, 0x457);
midi_tick();
}

static void test_midi_portamento_glides_with_fine_tune(UNUSED void** state)
{
const u8 chan = 0;
__real_midi_cc(chan, CC_PORTAMENTO_ENABLE, 127);
__real_midi_cc(chan, CC_FINE_TUNE, 127);

expect_synth_pitch(chan, 2, 0x461);
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, 0x468);
midi_tick();
}

0 comments on commit 702e568

Please sign in to comment.