I just noticed that on the "Future of Fluidsynth" page, it lists non-real-time
rendering as feature. Um, I am currently using Fluidsynth for this very task in
my program, Z-Maestro (you can find it on the FluidSynth applications page).
Has this never been done before, or am I misreading it? I can render a complete
30 second project in roughly 2-5 seconds give or take depending on sample rate,
complexity of the song, and a few other things.
Since I'm doing it all in managed VB.NET, the code sample will probably be
almost useless, but I'll explain what I do as well. First, I take the music
project and process it, compiling a list of all MIDI events for every channel.
I sort the list of MIDI events by position to put them in chronological order.
Then, I have a function that loops from the beginning of the project to a point
measured in audio samples. Since the smallest increment of an event position is
a 16th note, I loop from the first 16th note to the last one inside the audio
sample range. For each 16th note, I send any events that exist at that position
and then I call fluid_synth_write_s16 (which is called FillBuffer in my
program) sending in the length, in audio samples, of a 16th note for the length
of the buffer. Finally, I simply append the result to my main buffer.
The final code in my program looks like this:
Protected Function RenderMIDI(ByVal length As Integer) As Short()
Dim instBuff As New ArrayList
Dim hasSampled As Boolean = False
Dim lastSamplePos As Integer
For i As Integer = _currentSamplePos To (_currentSamplePos + length
- 1)
If (i / _samplesPerMeasure) Mod (1 / 16) = 0 Then
If hasSampled Then
instBuff.AddRange(inst.Synthesizer.FillBuffer((1 / 16)
* _samplesPerMeasure))
SendEventsAtPos(i / _samplesPerMeasure)
Else
instBuff.AddRange(inst.Synthesizer.FillBuffer(i -
_currentSamplePos))
SendEventsAtPos(i / _samplesPerMeasure)
End If
hasSampled = True
lastSamplePos = i
End If
Next
instBuff.AddRange(inst.Synthesizer.FillBuffer(_currentSamplePos +
length - lastSamplePos))
Dim instBuffArr(instBuff.Count - 1) As Short
instBuff.CopyTo(instBuffArr)
Return instBuffArr
End Function
"inst.Synthesizer" is a managed wrapper class for a FluidSynth synthesizer.
"_currentSamplePos" is the starting sample to use. "_samplesPerMeasure" is a
precalculated value containing literally the number of audio samples per
measure based on the temp, sample rate, etc. The "AddRange" function simply
appends an array to the "ArrayList". The "SendEventsAtPos" method simply sends
any MIDI events existing at the specified position to the synthesizer.
Once again, if this is new, please tell me (and feel free to ask about the
algorithm). By the way, I'm using version 1.0.0 of FluidSynth due to some
upgrading issues, if that makes any difference._______________________________________________
fluid-dev mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/fluid-dev