Created attachment 94 [details]
This is a work in progress to enhance linuxsampler's key group handling with polyphony. The patch is focused on sfz engine.
Key groups in sfz are configured by two separate opcodes: group and off_by/offby.
The format itself is ambiguous, because there's a <group> section and group opcode. Setting the same group opcode value for two regions (one <region> in sfz stands for one sfz::Voice instance in linuxsampler) doesn't mean exclusive playback. Regions will play simultaneously until they are muted with another region with group value equal to off_by value of a playing voice. This will shut down all voices regardless of polyphony settings.
All <regions> with the same group value should have the same off_by value (ARIA engine reports discrepancy if it's not like that).
Accodring to http://www.sfzformat.com/legacy/ default group and off_by value is 0, which would make instruments exclusive by default. To overcome this issue ARIA engine sets off_by to MAX (4294967295), so by default regions belong to group=0 and are muted with regions in group=4294967295 (but there are no regions in this group by default). Contrary to gig, group=0 and off_by=0 are valid settings for sfz.
There's a very interesting tutorial which shows the potential of these two opcodes to program accurate hi-hat muting behaviour.
It limits a number of concurrent <regions> with the same group opcode value. In my opinion when the limit is reached the engine should release the oldest voice first, and it should be released regardless of note_selfmask setting.
All <regions> with the same group value should have the same polyphony value. Default value is undocumented, it's set to MAX in ARIA engine, with polyphony=0 it prevents any <region> from being played within the same group.
Gig regions (in current trunk) with the same KeyGroup value (for example 1) behave like sfz regions with group=1, polyphony=1 and off_by=1. Gig SelfMask setting is being ignored in current trunk
It limits a number of concurrent <regions> with the same group opcode value triggered by the same MIDI key. In my opinion when the limit is reached the engine should release the oldest voice first (that's not how ARIA works), but regarding note_selfmask setting. The idea of self-masking is explained below.
All <regions> with the same group and key values should have the same note_polyphony value. Default value is undocumented, it's set to 0 in ARIA engine, which means there is no limit for note_polyphony. Maybe it should be unified in linuxsampler with polyphony default setting.
Self-masking makes instruments with long sustain more natural, because quieter voices will not mute louder voices (unless polyphony opcode limit is reached or a <region> with group opcode value equal to off_by opcode value of a playing voice is triggered)
This concept is present in a gig format with a SelfMask field inside a DimensionRegion class. The patch tried to implement support for gig engine self-masking with default values of NotePolyphony=1 and GroupPolyphony=1, but now I see it's flawed and the lower velocity voice will be shut down anyway by relaseByGroup flag. I will submit a correction later.
All <regions> with the same group and key values should have the same note_selfmask value. Default is on.
Thanks Jacek for your patch!
@Devs: Postponed for now due to several issues:
*** Bug 300 has been marked as a duplicate of this bug. ***
Created attachment 96 [details]
The patch v2.1
I've changed Voice interface to use two separate functions (GetKeyGroup and GetOffBy) to be more clear.
I've changed the internal algorithm to correctly (I hope) support self-masking for gig engine.
Created attachment 97 [details]
Created attachment 98 [details]
Correction of a correction ;)