sfz on top of fluidsynth

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

sfz on top of fluidsynth

Stefan Westerfeld
   Hi!

I've been working on a sfz loader for fluidsynth. I've made the code
available on github, it is C++17, I use LGPL2.1+ like fluidsynth itself:

  https://github.com/swesterfeld/liquidsfz

So this adds the necessary bits to make fluidsynth be able to parse,
load and play sfz files. This is early in the development process, so
quite a few essential opcodes are still unsupported. Partially the
question is also to what degree fluidsynth itself could/should be
modified to get better sfz support.

For instance, in the SalamanderGrandPiano, a sound is supposed to be
played if a key is released (trigger=release):
  https://sfzformat.com/opcodes/trigger

Another sound is supposed to be played if the sustain pedal is pressed:
  https://sfzformat.com/opcodes/on_hiccN

As far as I can see, neither can possibly be implemented with the
existing loader API, because the loader API only allows me to define a
note_on function. Probably some more examples of unimplementable with
the current API (or even synthesis model) exist. So in the long run, I
see three ways to deal with this

- fluidsynth is actively extended to get better sfz support
- these opcodes will remain unsupported forever
- liquidsfz gets its own sampler and no longer uses fluidsynth

   Cu... Stefan
--
Stefan Westerfeld, http://space.twc.de/~stefan

_______________________________________________
fluid-dev mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/fluid-dev
Reply | Threaded
Open this post in threaded view
|

Re: sfz on top of fluidsynth

fluid-dev mailing list
First of all: Really nice work, thanks for sharing!

Regarding your question of how fluidsynth can be modified: This topic
was raised when implementing DLS support, which we will ship for
version 2.1 . The conclusion was that fluidsynth is and stays a
SoundFont2 synth. We integrated DLS because the synthesis model
basically is the same. At the same time, we refrained from supporting
GIG or SLI. fluidsynth won't claim to be some all-rounder synth,
supporting any format. Same is true for the SoundFont loader API:

"This API allows for virtual SoundFont files to be loaded and
synthesized, which may not actually be SoundFont files, as long as
they can be represented by the SoundFont synthesis model."

Where this non-representable thing starts (without changes to
fluidsynth) and what changes would still be acceptable to fluidsynth
would need to be discussed for individual cases.


The two examples of unimplemented opcodes you raised should not be
implemented in the loader API anyway, IMO. You would have to manually
intervene incoming MIDI events and react according to what the SFZ
specifies (e.g. if sustain pedal pressed or on noteoff received).
There are multiple ways to do this:

* Creating new_fluid_midi_driver() with a custom event handling function
* Using the midi router to intercept events
* Using the midi player with a custom callback function
(fluid_player_set_playback_callback())
* Don't use any MIDI stuff from fluidsynth and just use fluidsynth's
bare low-level synthesizer with manual calls to fluid_synth_noteon()
fluid_synth_noteoff() or even getting and manipulating individual
voices from the synth in real-time... the synth should provide all the
necessary functions.

You see, if you want to use fluidsynth for SFZ, it is not done by just
implementing a new soundfont loader. Instead, it would require a whole
user application that treats MIDI events according to the SFZ spec.

Perhaps another hint for liquidsfz: fluidsynth exposes its command
shell. If you decide to go with fluidsynth, perhaps it would be
charming to some users being able to just use the same commands
(noteon, noteoff, reverb, chorus etc.) as they use in the fluidsynth
executable.

Tom

_______________________________________________
fluid-dev mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/fluid-dev
Reply | Threaded
Open this post in threaded view
|

Re: sfz on top of fluidsynth

Stefan Westerfeld
   Hi!

Am 18.10.19 um 20:48 schrieb Tom M.:
> You see, if you want to use fluidsynth for SFZ, it is not done by just
> implementing a new soundfont loader. Instead, it would require a whole
> user application that treats MIDI events according to the SFZ spec.

Ah, right, that is a good idea how to solve my problem. I've now ported
my code to be a jack client and react to the midi events. This allows me
to execute custom code for note-on/note-off/cc events. So instead of
implementing a loader, I now handle the midi events myself and start new
voices and release old ones as needed.

To test this, I've now implement loop_mode=one_shot (often used for drum
samples), which doesn't release these regions on note off. So spawning
new voices on note off/cc should now also be possible.

There is a minor issue with the fluid synth public API here, which
allows creating new voices (fluid_synth_alloc_voice and
fluid_synth_start_voice), but there is no corresponding public API to
release a voice, which is needed for implementing note_off. So right now
I implemented fluid_synth_release_voice in my own fluidsynth repo.

https://github.com/swesterfeld/fluidsynth/commit/e2963c9227072384ed805c904300ee308c0674ee

It might be reasonable to wait for a while to see what else could be
needed before merging API additions upstream.

   Cu... Stefan
--
Stefan Westerfeld, http://space.twc.de/~stefan

_______________________________________________
fluid-dev mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/fluid-dev
Reply | Threaded
Open this post in threaded view
|

Re: sfz on top of fluidsynth

fluid-dev mailing list
> but there is no corresponding public API to
> release a voice, which is needed for implementing note_off

There is fluid_synth_stop() which forces the voice into release stage, unless it is sustained or sostenutoed. Instead of passing in the fluid_voice_t*, you have to use fluid_voice_get_id(voice) . This may be important, because the pointer points to a pool of voices. Voices may change during rendering calls (released, killed, stealed, etc.) so the pointer may not uniquely identify the voice. The ID on the other hand identifies a group of voices that are spawned by the same noteon event. If you want to control the voice ID yourself (e.g. one unique ID for a single voice), I suggest to use fluid_synth_start() .

Note that fluid_synth_noteon() and fluid_synth_noteoff() take care of proper legato playing. You won't have that when manually spawning voices, just in case that matters for you.

Also note that fluid_synth_noteon() kills overlapping notes.

Tom




_______________________________________________
fluid-dev mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/fluid-dev