Fix a-fluidsynth bank/program restore (during session load)

* set program in work-response, synchronous to run()
* properly store bank per channel (for replay)
This commit is contained in:
Robin Gareus 2017-09-11 16:45:17 +02:00
parent 3c81351413
commit 019f664356

View File

@ -153,8 +153,6 @@ typedef struct {
bool reinit_in_progress; // set in run, cleared in work_response bool reinit_in_progress; // set in run, cleared in work_response
bool queue_reinit; // set in restore, 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]; BankProgram program_state[16];
fluid_midi_event_t* fmidi_event; fluid_midi_event_t* fmidi_event;
@ -210,24 +208,6 @@ load_sf2 (AFluidSynth* self, const char* fn)
return false; 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; return true;
} }
@ -550,14 +530,21 @@ run (LV2_Handle instance, uint32_t n_samples)
fluid_midi_event_set_value (self->fmidi_event, data[2]); fluid_midi_event_set_value (self->fmidi_event, data[2]);
} }
if (0xb0 /* CC */ == fluid_midi_event_get_type (self->fmidi_event)) { if (0xb0 /* CC */ == fluid_midi_event_get_type (self->fmidi_event)) {
if (data[1] == 0x00) { self->last_bank_msb = data[2]; } int chn = fluid_midi_event_get_channel (self->fmidi_event);
if (data[1] == 0x20) { self->last_bank_lsb = data[2]; } 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)) { 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); int chn = fluid_midi_event_get_channel (self->fmidi_event);
assert (chn >= 0 && chn < 16); 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]; self->program_state[chn].program = data[1];
#ifdef LV2_EXTENDED #ifdef LV2_EXTENDED
if (self->bankpatch) { if (self->bankpatch) {
@ -567,6 +554,7 @@ run (LV2_Handle instance, uint32_t n_samples)
} }
#endif #endif
} }
fluid_synth_handle_midi_event (self->synth, self->fmidi_event); fluid_synth_handle_midi_event (self->synth, self->fmidi_event);
} }
} }
@ -672,6 +660,36 @@ work_response (LV2_Handle instance,
if (self->initialized) { if (self->initialized) {
strcpy (self->current_sf2_file_path, self->queue_sf2_file_path); 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 { } else {
self->current_sf2_file_path[0] = 0; self->current_sf2_file_path[0] = 0;
} }