What's new

Lua resources for UVI Falcon scripting

Now that Falcon 3 has midi out, does that mean we can theoretically use falcon3 as a general midi lua scripter plugin?

Where can I find the reference for the lua midi capabilities in Falcon3?
Hello, I don't know if this helps: I put Falcon in a midi track only with a LUA's script from @oeholmen along with the midi out. I put Kontakt on another track with an instrument taking midi from Falcon's track and it perfectly gets the midi events from the LUA script.
 
Hello, I don't know if this helps: I put Falcon in a midi track only with a LUA's script from @oeholmen along with the midi out. I put Kontakt on another track with an instrument taking midi from Falcon's track and it perfectly gets the midi events from the LUA script.
That is awesome! Glad you are enjoying the scripts. Can't wait to test midi out, haven't really gotten around to it yet. Have to test controlling an external hw synth!
 
Last edited:
That is awesome! Glad you are enjoying the script. Can't wait to test midi out, haven't really gotten around to it yet. Have to test controlling an external hw synth!
Yes and with the multipart power of Falcon, it seems that it would be possible to control a multitimbral hardware synth (I'll try with my old Sonic cell)
 
Yes and with the multipart power of Falcon, it seems that it would be possible to control a multitimbral hardware synth (I'll try with my old Sonic cell)
I'm working on another project now, that is an open sound control client that runs in any browser. In practice that means that I can control a hardware synth from my browser, via Falcon. Have not yet tested it with midi out, but it works well to control Falcon from my phone. The kicker is that I have added a function to call Open AI and create a new patch from a given prompt :D
 
So I found the general docs for falcon scripting and poked around in there as well as looked at a few example scripts.

One question that some of you might be able to answer for me is about timing of midi events. I can't seem to figure out the best way to "schedule" midi events which I want played at a precise time point in the future. What is the approach with this lua environment? It doesn't seem to operate on the process block as is typical for most plugin development. Its a higher level environment in falcon, where there are trigger functions, etc..but the function to send a note, sends it right now, no way that I could find to schedule it for later, other than calling wait a certain time and then send it, but even that is a bit foggy to me whether the time placemeant would be exactly as I want.

Is there some way to schedule midi events to be handled by other sections of falcon or sent to midi out at an exact time, whether that be midi tick or fractional beat or any other precise sample accurate point in time?
 
So I found the general docs for falcon scripting and poked around in there as well as looked at a few example scripts.

One question that some of you might be able to answer for me is about timing of midi events. I can't seem to figure out the best way to "schedule" midi events which I want played at a precise time point in the future. What is the approach with this lua environment? It doesn't seem to operate on the process block as is typical for most plugin development. Its a higher level environment in falcon, where there are trigger functions, etc..but the function to send a note, sends it right now, no way that I could find to schedule it for later, other than calling wait a certain time and then send it, but even that is a bit foggy to me whether the time placemeant would be exactly as I want.

Is there some way to schedule midi events to be handled by other sections of falcon or sent to midi out at an exact time, whether that be midi tick or fractional beat or any other precise sample accurate point in time?
You can use spawn/run in combination with waitBeat/wait. See my scripts for examples.
 
Is that the only way? still not precise and would mean forking a lot of threads often
It think that is the only way. You can either wait in the "main" program, but then you can do nothing until the wait is over, or you can spawn the wait in another thread.

I'm not sure exactly what you are trying to achieve, but if milliseconds isn't precise enough, then I don't know. If you tell me a bit more, maybe I can be of more assistance :)
 
I see. I have a number of different things I would be doing but unless I can do it sample accurately then I will probably not use falcon. I saw some things in the midi section of the api about midi sequences and midi ticks, so there must be a way for a midi sequence to store time of an event, at least to the accuracy of ticks. Does that part of the api have no way to schedule events for playback or must it always be handled by realtime lua and hoping the wait will be close enough in time to be accurate enough?

Forking a thread for every midi event could be costly on the cpu too, theoretically

More ideally we could schedule annevent at a designated beat number (as a fractional number) and falcon itself would ensure it’s played at exactly that time. Being played means either rendering audio inside falcon at exactly the desired beat number sample accurately; or adding the midi event to the midi buffer at the right time with a timestamp so the next plugin in the chain can potentially render audio sample accurately at exactly the right time. That is how all normal audio and midi plugins normally work, but falcon has buried that underneath an arguably simpler api, yet; I don’t currently have good confidence about sample accuracy.

Well anyway when I get some time I will play with it.
 
Hey everyone, Not new to sound design, but trying to find a shortcut in lua scripting so I don't have to spend alot of time on it. I've creating a gui in Falcon for my library and was wondering if there is a way to show macro's in that gui, so once I assign a function to the macro it's there and ready to roll. Hope I explained this correctly. Just need a quick "make macro show up in my gui" command.
 
Hey everyone, Not new to sound design, but trying to find a shortcut in lua scripting so I don't have to spend alot of time on it. I've creating a gui in Falcon for my library and was wondering if there is a way to show macro's in that gui, so once I assign a function to the macro it's there and ready to roll. Hope I explained this correctly. Just need a quick "make macro show up in my gui" command.
You can probably just itarate through the macros in the program. Let me know if you need some mock code for it :)
 
Yes yes, please. Hate that I'm so green with such, but I'll try to learn along the way.
A simple implementation, but it works. Remember you have to reload the script every time new macros are added, so it's not dynamic. I'm not sure if that would be possible anyway.

Code:
-- Print out all macros in the program --

local i = 1
local allMacros = {}

-- Collect all macros
while true do
    local macro = Program.modulations["Macro " .. i]
    if type(macro) == "nil" then
        break
    end
    print("Adding", "Macro " .. i)
    table.insert(allMacros, macro)
    i = i + 1
end

for i,macro in ipairs(allMacros) do
    print("Display", macro.name)
    local macroKnob = Knob("macro" .. i, 0, 0, 1)
    macroKnob.displayName = macro.name
    macroKnob.changed = function(self)
        macro:setParameter("Value", self.value)
    end
    macroKnob:changed()
end
 
A simple implementation, but it works. Remember you have to reload the script every time new macros are added, so it's not dynamic. I'm not sure if that would be possible anyway.

Code:
-- Print out all macros in the program --

local i = 1
local allMacros = {}

-- Collect all macros
while true do
    local macro = Program.modulations["Macro " .. i]
    if type(macro) == "nil" then
        break
    end
    print("Adding", "Macro " .. i)
    table.insert(allMacros, macro)
    i = i + 1
end

for i,macro in ipairs(allMacros) do
    print("Display", macro.name)
    local macroKnob = Knob("macro" .. i, 0, 0, 1)
    macroKnob.displayName = macro.name
    macroKnob.changed = function(self)
        macro:setParameter("Value", self.value)
    end
    macroKnob:changed()
end
Oh man, thank you so much!!
 
It think that is the only way. You can either wait in the "main" program, but then you can do nothing until the wait is over, or you can spawn the wait in another thread.
So I found this: https://www.uvi.net/uviscript/group___m_i_d_i.html#gafc28848de96267eaff31b813deae872e

This seems to be a way to send raw midi events with a timestamp, which I think should be sample accurate, but I guess the script would have to manage NoteOn and NoteOff manually this way. Have you tried anything related to this before?
 
Few answers here.

Spawn, run and wait are the way to go.
This is sample accurate if you use floating point millisecond time. The engine itself use frame timestamp but the API is ms or beat based for convenience.
It uses Lua coroutine system(not thread), so it's not heavy to spawn lots of those. Still you probably only need one.

postMidiEvent is just an helper to send an event from a MIDI Sequence object.
If you want to do a regular arp or sequencer, then use the regular postEvent or playNote


A simple arp would look a but like this
Code:
-------------------------------------------------
-- Arpegiator
-------------------------------------------------

resolutions = {0.5, 0.25, 0.125}
resolutionNames = {"8th","16th","32th"}

heldNotes = {};
velocity = 0;
res = Menu{"resolution", resolutionNames, selected=2}
duty = Knob("duty", 1, 0, 1)
numOctaves = Knob("numOctaves", 1, 1, 4, true)

--    repeat each held note at a fixed rate
function arpeg()
    local i=1;
    local octave=0

    while #heldNotes > 0 do
        if i > #heldNotes then
            i = 1 + (i-1) % (#heldNotes);
            octave = (octave+1) % numOctaves.value;
        end
      
    local note = (heldNotes[i])
    note = note + (octave)*12
    local p = resolutions[res.value]
        playNote(note, velocity, beat2ms(duty.value*p));
        waitBeat(p);
        i = i+1;
    end
end

function onNote(e)
    velocity = e.velocity;
    local first = nil
  if #heldNotes == 0 then first = true end
 
    table.insert(heldNotes, e.note);
    if first then
        arpeg()
  end
end

function onRelease(e)
  for i,v in  ipairs(heldNotes) do
    if v == e.note then
      table.remove(heldNotes, i)
      break
    end
  end
end
 
It may be a helper function but it does accept a timestamp for the midi event which I have much better confidence in then waiting for milliseconds to go by and hoping the code will run fast enough. By the way there are 48 samples per ms. So thst mwans .05 Ms precision would be needed and the spawn way doesn’t know how long it takes to run the code after waiting.

Generally when operating on a buffer such as audio or midi, you should not have to worry about timing your code in some kind of realtime fashion. You just need to schedule the events with a timestamp and pass it to the next plugin. Anyway I will experiment with both approaches when I get by Mac back. But i really do require sub millisecond precision which is normally easy with other midi scripters and/or using juce.
 
You are trying to apply a C++ paradigm to something that is not implement at all like that.
wait is not similar to a thread wait. It waits an exact number of frame and slice the processing buffer to place your event at the exact position in the c++ code. It is way easier to code a sequencer like that than it is in c++ thanks to lua coroutine which are cooperative.
Think to those spawn as event that are placed in a timed event fifo handled in the audio thread which just substract the remaining sample to your deadline and call the lua call when it should have occured.
There is no c++ thread used to support this.
Doing an arp like the example I have sent is a bit more complicated in c++. Here it's just very simple especially for non coder and it's implemented behind the scene like you would have done in c++ using some kind of std::function in a scheduler based on elapsed frame in the audio thread

Hope this clarify things.
 
The difference between run and spawn is just that run start before all event which happen on the same frame while spawn happen after those but still at the same frame. It's a like a state machine in a pseudo realtime thread where wait are simulated using frame elapsed in the processed buffer
 
I don’t really wish to argue but there is no c++ paradigm. Lua protoplug, for example, uses lua. It has simply to do with the fact that vst plugins normally allow you operate on a buffer that represents a time span, in a non real time manner. That is part of the whole point of using a buffer. This is more accurate and uses less cpu then trying to operate in some kind of real time manner in the code with wait’s or timers, etc.
 
Top Bottom