[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[fluid-dev] Non-Real-Time Rendering

From: Zachary Northrup
Subject: [fluid-dev] Non-Real-Time Rendering
Date: Thu, 26 Apr 2007 17:51:34 -0400

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)
                        instBuff.AddRange(inst.Synthesizer.FillBuffer(i - _currentSamplePos))
                        SendEventsAtPos(i / _samplesPerMeasure)
                    End If
                    hasSampled = True
                    lastSamplePos = i
                End If
            instBuff.AddRange(inst.Synthesizer.FillBuffer(_currentSamplePos + length - lastSamplePos))
            Dim instBuffArr(instBuff.Count - 1) As Short
            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.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]