Merge pull request #963 from paulfd/sustain-sostenuto-psa

Add a check for sustain and sostenuto in the LV2
This commit is contained in:
Paul Ferrand 2021-09-10 13:56:25 +02:00 committed by GitHub
commit fbac436cc0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 46 additions and 9 deletions

View file

@ -103,6 +103,7 @@ std::string getDescriptionBlob(sfizz_synth_t* handle)
synth.sendMessage(*client, 0, "/key/slots", "", nullptr); synth.sendMessage(*client, 0, "/key/slots", "", nullptr);
synth.sendMessage(*client, 0, "/sw/last/slots", "", nullptr); synth.sendMessage(*client, 0, "/sw/last/slots", "", nullptr);
synth.sendMessage(*client, 0, "/cc/slots", "", nullptr); synth.sendMessage(*client, 0, "/cc/slots", "", nullptr);
synth.sendMessage(*client, 0, "/sustain_or_sostenuto/slots", "", nullptr);
blob.shrink_to_fit(); blob.shrink_to_fit();
return blob; return blob;
@ -152,6 +153,8 @@ InstrumentDescription parseDescriptionBlob(absl::string_view blob)
copyArgToBitSpan(args[0], desc.keyswitchUsed.span()); copyArgToBitSpan(args[0], desc.keyswitchUsed.span());
else if (Messages::matchOSC("/cc/slots", path, indices) && !strcmp(sig, "b")) else if (Messages::matchOSC("/cc/slots", path, indices) && !strcmp(sig, "b"))
copyArgToBitSpan(args[0], desc.ccUsed.span()); copyArgToBitSpan(args[0], desc.ccUsed.span());
else if (Messages::matchOSC("/sustain_or_sostenuto/slots", path, indices) && !strcmp(sig, "b"))
copyArgToBitSpan(args[0], desc.sustainOrSostenuto.span());
else if (Messages::matchOSC("/key&/label", path, indices) && !strcmp(sig, "s")) else if (Messages::matchOSC("/key&/label", path, indices) && !strcmp(sig, "s"))
desc.keyLabel[indices[0]] = args[0].s; desc.keyLabel[indices[0]] = args[0].s;
else if (Messages::matchOSC("/sw/last/&/label", path, indices) && !strcmp(sig, "s")) else if (Messages::matchOSC("/sw/last/&/label", path, indices) && !strcmp(sig, "s"))

View file

@ -26,6 +26,7 @@ struct InstrumentDescription {
std::string image; std::string image;
BitArray<128> keyUsed {}; BitArray<128> keyUsed {};
BitArray<128> keyswitchUsed {}; BitArray<128> keyswitchUsed {};
BitArray<128> sustainOrSostenuto {};
BitArray<sfz::config::numCCs> ccUsed {}; BitArray<sfz::config::numCCs> ccUsed {};
std::array<std::string, 128> keyLabel {}; std::array<std::string, 128> keyLabel {};
std::array<std::string, 128> keyswitchLabel {}; std::array<std::string, 128> keyswitchLabel {};

View file

@ -683,6 +683,12 @@ sfizz_lv2_handle_atom_object(sfizz_plugin_t *self, int delay, const LV2_Atom_Obj
} }
} }
static bool
sfizz_is_sustain_or_sostenuto(sfizz_plugin_t* self, unsigned cc)
{
return (self->sustain_or_sostenuto[cc / 8] & (1 << (cc % 8)));
}
static void static void
sfizz_lv2_process_midi_event(sfizz_plugin_t *self, const LV2_Atom_Event *ev) sfizz_lv2_process_midi_event(sfizz_plugin_t *self, const LV2_Atom_Event *ev)
{ {
@ -704,14 +710,23 @@ sfizz_lv2_process_midi_event(sfizz_plugin_t *self, const LV2_Atom_Event *ev)
(int)msg[1], (int)msg[1],
msg[2]); msg[2]);
break; break;
// Note(jpc) CC must be mapped by host, not handled here.
// See LV2 midi:binding.
#if defined(SFIZZ_LV2_PSA)
case LV2_MIDI_MSG_CONTROLLER: case LV2_MIDI_MSG_CONTROLLER:
{ {
unsigned cc = msg[1]; unsigned cc = msg[1];
float value = float(msg[2]) * (1.0f / 127.0f); float value = float(msg[2]) * (1.0f / 127.0f);
// Send
if (sfizz_is_sustain_or_sostenuto(self, cc)) {
sfizz_automate_hdcc(self->synth,
(int)ev->time.frames,
(int)cc,
value);
break;
}
// Note(jpc) CC must be mapped by host, not handled here.
// See LV2 midi:binding.
#if defined(SFIZZ_LV2_PSA)
switch (cc) switch (cc)
{ {
default: default:
@ -733,9 +748,9 @@ sfizz_lv2_process_midi_event(sfizz_plugin_t *self, const LV2_Atom_Event *ev)
sfizz_all_sound_off(self->synth); sfizz_all_sound_off(self->synth);
break; break;
} }
#endif
} }
break; break;
#endif
case LV2_MIDI_MSG_CHANNEL_PRESSURE: case LV2_MIDI_MSG_CHANNEL_PRESSURE:
sfizz_send_channel_aftertouch(self->synth, sfizz_send_channel_aftertouch(self->synth,
(int)ev->time.frames, (int)ev->time.frames,
@ -1218,7 +1233,7 @@ sfizz_lv2_update_sfz_info(sfizz_plugin_t *self)
// //
const InstrumentDescription desc = parseDescriptionBlob(blob); const InstrumentDescription desc = parseDescriptionBlob(blob);
for (unsigned cc = 0; cc < sfz::config::numCCs; ++cc) { for (unsigned cc = 0; cc < sfz::config::numCCs; ++cc) {
if (desc.ccUsed.test(cc)) { if (desc.ccUsed.test(cc) && !desc.sustainOrSostenuto.test(cc)) {
// Mark all the used CCs for automation with default values // Mark all the used CCs for automation with default values
self->ccauto[cc] = desc.ccDefault[cc]; self->ccauto[cc] = desc.ccDefault[cc];
self->have_ccauto = true; self->have_ccauto = true;
@ -1226,6 +1241,9 @@ sfizz_lv2_update_sfz_info(sfizz_plugin_t *self)
self->cc_current[cc] = desc.ccDefault[cc]; self->cc_current[cc] = desc.ccDefault[cc];
} }
} }
memcpy(self->sustain_or_sostenuto, desc.sustainOrSostenuto.data(),
sizeof(self->sustain_or_sostenuto));
} }
static bool static bool
@ -1457,7 +1475,7 @@ save(LV2_Handle instance,
self->sfz_blob_mutex->unlock(); self->sfz_blob_mutex->unlock();
for (unsigned cc = 0; cc < sfz::config::numCCs; ++cc) { for (unsigned cc = 0; cc < sfz::config::numCCs; ++cc) {
if (desc.ccUsed.test(cc)) { if (desc.ccUsed.test(cc) && !desc.sustainOrSostenuto.test(cc)) {
LV2_URID urid = sfizz_lv2_ccmap_map(self->ccmap, int(cc)); LV2_URID urid = sfizz_lv2_ccmap_map(self->ccmap, int(cc));
store(handle, store(handle,
urid, urid,

View file

@ -127,6 +127,9 @@ struct sfizz_plugin_t
const uint8_t *volatile sfz_blob_data {}; const uint8_t *volatile sfz_blob_data {};
volatile uint32_t sfz_blob_size {}; volatile uint32_t sfz_blob_size {};
// Sostenuto or sustain
char sustain_or_sostenuto[16] {};
// Current CC values in the synth (synchronized by `synth_mutex`) // Current CC values in the synth (synchronized by `synth_mutex`)
// updated by hdcc or file load // updated by hdcc or file load
float *cc_current {}; float *cc_current {};

View file

@ -447,7 +447,7 @@ sfizz_ui_update_description(sfizz_ui_t *self, const InstrumentDescription& desc)
} }
for (unsigned cc = 0; cc < sfz::config::numCCs; ++cc) { for (unsigned cc = 0; cc < sfz::config::numCCs; ++cc) {
bool ccUsed = desc.ccUsed.test(cc); bool ccUsed = desc.ccUsed.test(cc) && !desc.sustainOrSostenuto.test(cc);
self->uiReceiveValue(editIdForCCUsed(cc), float(ccUsed)); self->uiReceiveValue(editIdForCCUsed(cc), float(ccUsed));
if (ccUsed) { if (ccUsed) {
self->uiReceiveValue(editIdForCCDefault(cc), desc.ccDefault[cc]); self->uiReceiveValue(editIdForCCDefault(cc), desc.ccDefault[cc]);

View file

@ -246,7 +246,7 @@ bool SfizzVstEditor::processUpdate(FUnknown* changedUnknown, int32 message)
} }
for (unsigned cc = 0; cc < sfz::config::numCCs; ++cc) { for (unsigned cc = 0; cc < sfz::config::numCCs; ++cc) {
bool ccUsed = desc.ccUsed.test(cc); bool ccUsed = desc.ccUsed.test(cc) && !desc.sustainOrSostenuto.test(cc);
uiReceiveValue(editIdForCCUsed(int(cc)), float(ccUsed)); uiReceiveValue(editIdForCCUsed(int(cc)), float(ccUsed));
if (ccUsed) { if (ccUsed) {
uiReceiveValue(editIdForCCDefault(int(cc)), desc.ccDefault[cc]); uiReceiveValue(editIdForCCDefault(int(cc)), desc.ccDefault[cc]);

View file

@ -271,6 +271,7 @@ void Synth::Impl::clear()
filePool.setRamLoading(config::loadInRam); filePool.setRamLoading(config::loadInRam);
clearCCLabels(); clearCCLabels();
currentUsedCCs_.clear(); currentUsedCCs_.clear();
sustainOrSostenuto_.clear();
changedCCsThisCycle_.clear(); changedCCsThisCycle_.clear();
changedCCsLastCycle_.clear(); changedCCsLastCycle_.clear();
clearKeyLabels(); clearKeyLabels();
@ -2111,8 +2112,11 @@ void Synth::Impl::collectUsedCCsFromModulations(BitArray<config::numCCs>& usedCC
BitArray<config::numCCs> Synth::Impl::collectAllUsedCCs() BitArray<config::numCCs> Synth::Impl::collectAllUsedCCs()
{ {
BitArray<config::numCCs> used; BitArray<config::numCCs> used;
for (const LayerPtr& layerPtr : layers_) for (const LayerPtr& layerPtr : layers_) {
collectUsedCCsFromRegion(used, layerPtr->getRegion()); collectUsedCCsFromRegion(used, layerPtr->getRegion());
sustainOrSostenuto_.set(layerPtr->region_.sustainCC);
sustainOrSostenuto_.set(layerPtr->region_.sostenutoCC);
}
collectUsedCCsFromModulations(used, resources_.getModMatrix()); collectUsedCCsFromModulations(used, resources_.getModMatrix());
return used; return used;
} }

View file

@ -180,6 +180,13 @@ void sfz::Synth::dispatchMessage(Client& client, int delay, const char* path, co
client.receive<'b'>(delay, path, &blob); client.receive<'b'>(delay, path, &blob);
} break; } break;
MATCH("/sustain_or_sostenuto/slots", "") {
const BitArray<128>& sustainOrSostenuto = impl.sustainOrSostenuto_;
sfizz_blob_t blob { sustainOrSostenuto.data(),
static_cast<uint32_t>(sustainOrSostenuto.byte_size()) };
client.receive<'b'>(delay, path, &blob);
} break;
//---------------------------------------------------------------------- //----------------------------------------------------------------------
MATCH("/mem/buffers", "") { MATCH("/mem/buffers", "") {

View file

@ -248,6 +248,7 @@ struct Synth::Impl final: public Parser::Listener {
std::map<int, size_t> keyLabelsMap_; std::map<int, size_t> keyLabelsMap_;
BitArray<128> keySlots_; BitArray<128> keySlots_;
BitArray<128> swLastSlots_; BitArray<128> swLastSlots_;
BitArray<128> sustainOrSostenuto_;
std::vector<NoteNamePair> keyswitchLabels_; std::vector<NoteNamePair> keyswitchLabels_;
std::map<int, size_t> keyswitchLabelsMap_; std::map<int, size_t> keyswitchLabelsMap_;