swesterfeld / liquidsfz

SFZ Sampler
Mozilla Public License 2.0
79 stars 12 forks source link

Sustain pedal realism #26

Open geckolinux opened 3 years ago

geckolinux commented 3 years ago

Hi there, Ever since I got into Linux audio for playing the piano with my MIDI keyboard, I noticed a unique, subtle trait of LinuxSampler together with SFZ soundfonts that made it feel distinctly more natural. With a sustain pedal, LinuxSampler allows for sustaining the residual resonance even after releasing all the keys. So basically, on a real piano, you hit some notes fairly hard, completely release them all, and then before their resonance dies out immediately hit the sustain pedal, and the residual resonance will continue for quite a while. LinuxSampler faithfully reproduces this behavior (only with SFZ and GIG soundfonts, the SF2 spec apparently doesn't support it), and to my knowledge it's the only free SFZ sampler that does this. Liquidsfz does not. Even the Sforzando player for Windows which is generally regarded as the standard for free SFZ players doesn't do this. Apart from LinuxSampler, the only thing on my system that also has proper sustain behavior is the commercial Pianoteq app. But the problem is that LinuxSampler doesn't seem to exist as a Linux VST (only for Windows apparently?) so it's hard to use it with other DAWs and synthesizer apps. Would it be possible to implement this behavior on liquidsfz? Thanks a lot!

jkbd commented 1 year ago

I think, this could be technically rephrased as: Problem with voice-stealing on the same key. Minimal example to reproduce with LiquidSFZ (Version 0.3.1) and any long-sustaining instrument:

liquidsfz> cc 0 64 127  # Lower the sustain pedal
liquidsfz> noteon 0 60 127 # Press key hard
liquidsfz> noteon 0 60 10 # Press key soft

Now the second NoteOn cuts the sustain of the first note, which sounds odd.

The expected behavior with most acoustic instruments is, in my opinion, the louder tone continues to resonate, while the silent tone joins somehow.

geckolinux commented 1 year ago

Hi @jkbd thanks for the reply! Yes, that sounds correct. FYI the Sfizz project implemented this sort of realism as an option, and it works extremely well, infinitely more playable: https://github.com/sfztools/sfizz/pull/898 They describe it as "the sustain pedal cancels note release".

jkbd commented 1 year ago

Hello @geckolinux, please don't confuse things. The SFZ-Engine of LinuxSampler and the Sfizz engine get it right, even without this new hint_sustain_cancels_release opcode.

I am skeptic about this envelope-state jumping. Example: The NoteOn-event triggers the envelope; then Attack- and Decay-phase follow; the Sustain-phase is not reached yet, when the second NoteOn-event arrives (like above). Sustain or Release are not involved here. (I know, Sfizz has even more envelope states...)

Furthermore, say the envelope is in its Release state and env(time) = 0.01. Sustain may be defined as 10%. What now? There should be no discontinuous jump, but else, how shall we smooth the envelope over time?

swesterfeld commented 1 year ago

@geckolinux thanks for the links related to hint_sustain_cancels_release. I must admit I never fully understood what you wanted liquidsfz to do to actually get the LinuxSampler behaviour, but the links and the implementation in sfizz makes it pretty clear what you need here. It should be possible to implement that.

@jkbd I think you are talking about something other than the initial issue here: liquidsfz doesn't really allow overlapping notes, so if you retrigger the same note on the same channel (as in your short example) at the start of the second note, the first note is released. One aspect here is also that if you don't cancel existing notes, and use the sustain pedal, many identical notes can pile up quickly, so you could either run out of cpu power or run out of voices at some point. "voice-stealing on the same key" as you call it helps quite a bit here.

So we could change this (simply keep both notes playing in your example). However, ideally before changing this it would be nice if liquidsfz implemented correct voice-stealing, recycling the oldest note (or similar) before it runs out of voices. Especially for piano & sustain pedal the older voices would normally not be very loud anyway, so one could hope that this "cheating" wouldn't be audible.

geckolinux commented 1 year ago

Hi @swesterfeld thanks very much for the reply! Really appreciate you taking this into account, and sorry for not explaining myself clearly in this issue.

jkbd commented 1 year ago

I just found, that a Kurzweil PC3K8 keyboard actually allows the sustain-pedal to "freeze" the amplitude envelope during release. And e.g. with a strings section sound, it's an interesting addition to the playability, I admit. I guess, this is exactly what hint_sustain_cancels_release is meant to do.

So shall we split this into two issues? One like "hint_sustain_cancels_release opcode wanted" and second "Allow for overlapping notes"?

@swesterfeld What I like about LiquidSFZ in particular, is that it is easy to be build with Buildroot for no-GUI usage. With Sfizz, Linuxsampler or Drumgizmo it's troublesome for different reasons, so...thumbs up and thanks for your good work, @swesterfeld!

swesterfeld commented 1 year ago

@jkbd yes, I think splitting this issue makes sense, as it will probably be fixed by two completely different commits. We can just keep this one for its original purpose, and you can re-report your request "allow for overlapping notes" (I think you want this only if the sustain pedal is down?).

jkbd commented 1 year ago

Let's discuss the pedal-state detail in #38.