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, "/sw/last/slots", "", nullptr);
synth.sendMessage(*client, 0, "/cc/slots", "", nullptr);
synth.sendMessage(*client, 0, "/sustain_or_sostenuto/slots", "", nullptr);
blob.shrink_to_fit();
return blob;
@ -152,6 +153,8 @@ InstrumentDescription parseDescriptionBlob(absl::string_view blob)
copyArgToBitSpan(args[0], desc.keyswitchUsed.span());
else if (Messages::matchOSC("/cc/slots", path, indices) && !strcmp(sig, "b"))
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"))
desc.keyLabel[indices[0]] = args[0].s;
else if (Messages::matchOSC("/sw/last/&/label", path, indices) && !strcmp(sig, "s"))

View file

@ -26,6 +26,7 @@ struct InstrumentDescription {
std::string image;
BitArray<128> keyUsed {};
BitArray<128> keyswitchUsed {};
BitArray<128> sustainOrSostenuto {};
BitArray<sfz::config::numCCs> ccUsed {};
std::array<std::string, 128> keyLabel {};
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
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],
msg[2]);
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:
{
unsigned cc = msg[1];
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)
{
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);
break;
}
#endif
}
break;
#endif
case LV2_MIDI_MSG_CHANNEL_PRESSURE:
sfizz_send_channel_aftertouch(self->synth,
(int)ev->time.frames,
@ -1218,7 +1233,7 @@ sfizz_lv2_update_sfz_info(sfizz_plugin_t *self)
//
const InstrumentDescription desc = parseDescriptionBlob(blob);
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
self->ccauto[cc] = desc.ccDefault[cc];
self->have_ccauto = true;
@ -1226,6 +1241,9 @@ sfizz_lv2_update_sfz_info(sfizz_plugin_t *self)
self->cc_current[cc] = desc.ccDefault[cc];
}
}
memcpy(self->sustain_or_sostenuto, desc.sustainOrSostenuto.data(),
sizeof(self->sustain_or_sostenuto));
}
static bool
@ -1457,7 +1475,7 @@ save(LV2_Handle instance,
self->sfz_blob_mutex->unlock();
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));
store(handle,
urid,

View file

@ -127,6 +127,9 @@ struct sfizz_plugin_t
const uint8_t *volatile sfz_blob_data {};
volatile uint32_t sfz_blob_size {};
// Sostenuto or sustain
char sustain_or_sostenuto[16] {};
// Current CC values in the synth (synchronized by `synth_mutex`)
// updated by hdcc or file load
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) {
bool ccUsed = desc.ccUsed.test(cc);
bool ccUsed = desc.ccUsed.test(cc) && !desc.sustainOrSostenuto.test(cc);
self->uiReceiveValue(editIdForCCUsed(cc), float(ccUsed));
if (ccUsed) {
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) {
bool ccUsed = desc.ccUsed.test(cc);
bool ccUsed = desc.ccUsed.test(cc) && !desc.sustainOrSostenuto.test(cc);
uiReceiveValue(editIdForCCUsed(int(cc)), float(ccUsed));
if (ccUsed) {
uiReceiveValue(editIdForCCDefault(int(cc)), desc.ccDefault[cc]);

View file

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

View file

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