summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2017-09-11 16:45:17 +0200
committerRobin Gareus <robin@gareus.org>2017-09-11 16:48:54 +0200
commit019f6643564cadc7805aa46bd1d232bdc3b3c3c5 (patch)
tree65664704f3a914f35dc075f4a57caf33dc16340f
parent3c813514136e328cfac2bf3bd05468aeec6287dd (diff)
Fix a-fluidsynth bank/program restore (during session load)
* set program in work-response, synchronous to run() * properly store bank per channel (for replay)
-rw-r--r--libs/plugins/a-fluidsynth.lv2/a-fluidsynth.cc64
1 files changed, 41 insertions, 23 deletions
diff --git a/libs/plugins/a-fluidsynth.lv2/a-fluidsynth.cc b/libs/plugins/a-fluidsynth.lv2/a-fluidsynth.cc
index 14e1ae4610..0c3e20a888 100644
--- a/libs/plugins/a-fluidsynth.lv2/a-fluidsynth.cc
+++ b/libs/plugins/a-fluidsynth.lv2/a-fluidsynth.cc
@@ -153,8 +153,6 @@ typedef struct {
bool reinit_in_progress; // set in run, cleared in work_response
bool queue_reinit; // set in restore, cleared in work_response
- uint8_t last_bank_lsb;
- uint8_t last_bank_msb;
BankProgram program_state[16];
fluid_midi_event_t* fmidi_event;
@@ -210,24 +208,6 @@ load_sf2 (AFluidSynth* self, const char* fn)
return false;
}
- for (chn = 0; chn < 16; ++chn) {
- if (self->program_state[chn].program < 0) {
- continue;
- }
- fluid_synth_program_select (self->synth, chn, synth_id,
- self->program_state[chn].bank, self->program_state[chn].program);
- }
-
- for (chn = 0; chn < 16; ++chn) {
- unsigned int sfid = 0;
- unsigned int bank = 0;
- unsigned int program = -1;
- if (FLUID_OK == fluid_synth_get_program (self->synth, chn, &sfid, &bank, &program)) {
- self->program_state[chn].bank = bank;
- self->program_state[chn].program = program;
- }
- }
-
return true;
}
@@ -550,14 +530,21 @@ run (LV2_Handle instance, uint32_t n_samples)
fluid_midi_event_set_value (self->fmidi_event, data[2]);
}
if (0xb0 /* CC */ == fluid_midi_event_get_type (self->fmidi_event)) {
- if (data[1] == 0x00) { self->last_bank_msb = data[2]; }
- if (data[1] == 0x20) { self->last_bank_lsb = data[2]; }
+ int chn = fluid_midi_event_get_channel (self->fmidi_event);
+ assert (chn >= 0 && chn < 16);
+ if (data[1] == 0x00) {
+ self->program_state[chn].bank &= 0x7f;
+ self->program_state[chn].bank |= (data[2] &0x7f) << 7;
+ }
+ if (data[1] == 0x20) {
+ self->program_state[chn].bank &= 0x3F80;
+ self->program_state[chn].bank |= data[2] & 0x7f;
+ }
}
}
if (ev->body.size == 2 && 0xc0 /* Pgm */ == fluid_midi_event_get_type (self->fmidi_event)) {
int chn = fluid_midi_event_get_channel (self->fmidi_event);
assert (chn >= 0 && chn < 16);
- self->program_state[chn].bank = (self->last_bank_msb << 7) | self->last_bank_lsb;
self->program_state[chn].program = data[1];
#ifdef LV2_EXTENDED
if (self->bankpatch) {
@@ -567,6 +554,7 @@ run (LV2_Handle instance, uint32_t n_samples)
}
#endif
}
+
fluid_synth_handle_midi_event (self->synth, self->fmidi_event);
}
}
@@ -672,6 +660,36 @@ work_response (LV2_Handle instance,
if (self->initialized) {
strcpy (self->current_sf2_file_path, self->queue_sf2_file_path);
+
+ for (int chn = 0; chn < 16; ++chn) {
+ if (self->program_state[chn].program < 0) {
+ continue;
+ }
+ /* cannot direcly call fluid_channel_set_bank_msb/fluid_channel_set_bank_lsb, use CCs */
+ fluid_midi_event_set_type (self->fmidi_event, 0xb0 /* CC */);
+ fluid_midi_event_set_channel (self->fmidi_event, chn);
+
+ fluid_midi_event_set_control (self->fmidi_event, 0x00); // BANK_SELECT_MSB
+ fluid_midi_event_set_value (self->fmidi_event, (self->program_state[chn].bank >> 7) & 0x7f);
+ fluid_synth_handle_midi_event (self->synth, self->fmidi_event);
+
+ fluid_midi_event_set_control (self->fmidi_event, 0x20); // BANK_SELECT_LSB
+ fluid_midi_event_set_value (self->fmidi_event, self->program_state[chn].bank & 0x7f);
+ fluid_synth_handle_midi_event (self->synth, self->fmidi_event);
+
+ fluid_synth_program_change (self->synth, chn, self->program_state[chn].program);
+ }
+
+ for (int chn = 0; chn < 16; ++chn) {
+ unsigned int sfid = 0;
+ unsigned int bank = 0;
+ unsigned int program = -1;
+ if (FLUID_OK == fluid_synth_get_program (self->synth, chn, &sfid, &bank, &program)) {
+ self->program_state[chn].bank = bank;
+ self->program_state[chn].program = program;
+ }
+ }
+
} else {
self->current_sf2_file_path[0] = 0;
}