[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [fluid-dev] pausing the sequencer
From: |
Tom M. |
Subject: |
Re: [fluid-dev] pausing the sequencer |
Date: |
Mon, 30 Nov 2020 22:14:21 +0100 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.4.2 |
Pls. make sure to include the mailing list when replying.
On 30.11.20 17:54, Jeroen Neve wrote:
Thanks for the reply, Tom.
Let's say I have a music notation program, and I want to use FluidSynth to
render an audio-file of the music as it is notated.
There are more than 16 voices in parallel, so MIDI is not an option 😉 (Which is
the main point of using FluidSynth.)
I tell FluidSynth to send its output to the file renderer, but as soon as I
feed the sequencer the MIDI events, the file starts rendering
What I'm worried about is that the rendering process (which for a file is much
faster than real-time) will be faster than the events I can collect from the
score.
If I cannot fill the sequencer fast enough with new events, then at some point
I tell the sequencer to send an event in the past.
It gets even worse: the events may not be sent to the sequencer in order. First
I send the events for the flutes, then the bassoon, the horns, the clarinet,
then the violins, etc.
So my ideal solution would be:
- pause the sequencer
- send all the events to the sequencer ( is that possible?)
- set up the file renderer (delete the audio-driver first!)
- continue the sequencer
- render the file until the callback function receives "done playing"
- delete the file renderer
Another solution is to collect all the events first, order them, and then send
them to the sequencer as fast as possible of course.
But that case is still a scenario of the hare outrunning the hounds. The hare
may escape, or it may not.
Full disclosure:
I am not the programmer of the project, but I did direct David to FluidSynth to
implement it as a new feature into his application. ( I do have a programming
background though! <g>)
I will point him to this mailing list, if he hasn't subscribed already!
Thanks again,
Jeroen Neve
> Let's say I have a music notation program, and I want to use
FluidSynth to render an audio-file of the music as it is notated.
Understood. Although it's not clear to me how you are planning to
connect that "music notation program" to fluidsynth. But, ok.
> There are more than 16 voices in parallel, so MIDI is not an option
(Which is the main point of using FluidSynth.)
I assume by "voices" you meant "channels". fluidsynth is heavily based
on MIDI. Those two things do not mutually exclude each other. The number
of MIDI channels can be tweaked in fluidsynth via the
synth.midi-channels
setting. So, putting aside the rest of your proposed solution (I don't
quite understand it, sry), I see two possible attempts:
1) If you *must* synthesize audio "as it is notated" (i.e. in real-time,
i.e. on-the-fly) you would:
- set synth.midi-channels to the desired number
- create the synth
- create a MIDI driver (http://www.fluidsynth.org/api/RealtimeMIDI.html)
--> Alsa and Jack MIDI drivers will honor synth.midi-channels, i.e.
they will create a total of "synth.midi-channels / 16" MIDI ports AND
they will adjust the channel number appropriately according to the port
they've received the event (not sure if others do currently)
- create the "file" audio driver (not to be confused with the fast file
renderer!)
- click the "play" button in your notation software
2) The non-realtime scenario:
- set synth.midi-channels to the desired number
- create the synth
- create the sequencer (new_fluid_sequencer2()) and tell it to use the
sample timer (rather than the system timer... perhaps this is where your
confusion of "pausing" things comes from)
- collect the events from the notation software somehow (unclear to me)
- parse those notation software events into "fluid_event"s
- feed all those events with correct *absolute* timestamp into the
sequencers event queue (fluid_sequencer_send_at())
- call fluid_sequencer_register_fluidsynth()
- note: at this point, no rendering has been done, i.e. the sequencer is
still at tick zero!
- finally to start the rendering: create the fast file renderer
new_fluid_file_renderer()
- pump audio via fluid_file_renderer_process_block() until the last
event has been processed
Remark: How to know when the last event has been processed from the
sequencers queue? By enqueuing a fluid_event_timer() that gives your
application a callback to set some termination-flag or so.
> It gets even worse: the events may not be sent to the sequencer in
order. First I send the events for the flutes, then the bassoon, the
horns, the clarinet, then the violins, etc.
For solution 2) this doesn't matter, because event's are ordered
according to the timestamp you have provided when enqueuing.
P.S.: Yes, you could (ab-)use fluidsynth's sequencer for solution 1) as
well. You could even enqueue sync-events into the sequencer's queue,
which give your application a callback in which you are free to do
anything. Since that callback comes from the "synth context", you could
even wait within that callback until the first flowers are blooming. But
it would be more effort and you would also successfully bypass many of
fluidsynth's primitives that already abstract that kind of work for
you... unless that "David's" surname is Back, in which case, I'm afraid,
this would be the way to go when having to sync up to four synth instances.
Tom