[ANN] lua~


    Oct 26 2007 | 5:43 pm
    Hi all,
    The lua~ external is back online:
    Lua~ is a Max/MSP external embedding the Lua language along with some DSP functions and a scheduler supporting sample-accurate function calling using coroutines. A lua~ object embedded in a Max patch can load and interpret Lua scripts that receive, transform and produce MSP signals and Max messages. Lua~ is particularly well suited to granular synthesis, algorithmic microsound and accurate timing needs, helpfully circumventing some of the limitations of the Max/MSP environment for such work by supporting highly dynamic signal processing graphs in parallel processes according to timing specifications below block rate. Using an interpreted scripting language within a graphical programming environment such as Max offers advantages of control flow, generality of data and structure, high precision and control, complexity of data and functional interdependency and variable scoping.
    Here's a very simple code example:
    -- define a function function beep(dur) -- play a decaying sine to the signal outlet for dur seconds: play(Out, dur, Sine(440) * Decay(dur)) end
    -- repeat forever: while true do -- launch parallel coroutine, function beep with duration 0-200 ms go(beep, math.random() * 0.2)
    -- wait for up to two seconds wait(math.random() * 2) end
    There are a few special advantages to using Lua - its memory allocator/garbage collector and general efficiency supports interpreting script code in the audio thread, which means that sample- accurate function calls and control logic are possible. Lua also supports coroutines (collaborative multithreading), kind of like deterministic threads that are very cheap to run. I've extended them to be aware of sample time, so they can be used like Routines or Tasks in SuperCollider 3, but they can embed both control logic AND synthesis graphs like SuperCollider 2, and also like shreds in ChucK.
    The nicest aspect: you can generate, execute, change and remove any number of any types of unit generators to the signal processing with sample accuracy, below the block-size, at run-time, within deterministic parallel execution flows.
    The not so nice aspect: Binding Lua to Max/MSP is much less simple than binding to Jitter, because of the underlying object model in the SDK (Jitter objects have excellent reflection, while only the most recently obexed' Max objects do). The main issue is that it is not workable to create, connect and modify MSP objects from within a script binding. Unfortunately this means that I had to write a new set of elementary unit generators rather than re-using MSP object code. I'm also in the process of binding the STK library, so a standard, familiar set of ugens and so on will be available.
    Currently OSX only, but maybe I can get a windows box to compile the XP version in the next few weeks.
    Graham
    www.grahamwakefield.net

    • Oct 26 2007 | 6:00 pm
      Sounds awesome Graham, I am really looking forward to giving the XP version a spin. Please keep us posted.
      Anthony
    • Oct 26 2007 | 6:08 pm
      yeah, it sounds really great. will try it out as soon as i get some free time.
      it seems you are implying dynamic modifications to the signal chain without the familiar msp pop, is this correct?
    • Oct 26 2007 | 6:52 pm
      This is correct - and also independent of block-rate*. For example:
      -- changing an FM modulator graph at increasing periods from 1 to 10000 samples:
      -- duration of one sample in seconds: local sample = 1/samplerate
      -- add a sinewave to the output bus: local carrier = Out:add(Sine())
      for i=1, 100 do -- set pulse duration: local dur = i * i * sample print("duration", dur, "(s)")
      -- create new modulator carrier:freq(Sine(10, 0) * 500 + 1000) wait(dur)
      -- create new modulator carrier:freq(Square(20, 0) * 250 + 1500) wait(dur) end
      Out:remove(carrier)
      Graham
      *Though I have to stress the point - because of the current MSP architecture, I cannot use existing MSP unit generators inside of lua~, so I had to provide new unit generator DSP functions.
      On Oct 26, 2007, at 11:08 AM, Robert Ramirez wrote:
      > > yeah, it sounds really great. > will try it out as soon as i get some free time. > > it seems you are implying dynamic modifications to the signal chain > without the familiar msp pop, is this correct?
      grrr waaa www.grahamwakefield.net
    • Oct 27 2007 | 12:56 pm
      I download lua~ and tried it. It works very nicely but seems to cost a lot in cpu for even simple patches.
      On 10/26/07 2:52 PM, "Graham Wakefield" wrote:
      > This is correct - and also independent of block-rate*. For example: > > -- changing an FM modulator graph at increasing periods from 1 to > 10000 samples: > > -- duration of one sample in seconds: > local sample = 1/samplerate > > -- add a sinewave to the output bus: > local carrier = Out:add(Sine()) > > for i=1, 100 do > -- set pulse duration: > local dur = i * i * sample > print("duration", dur, "(s)") > > -- create new modulator > carrier:freq(Sine(10, 0) * 500 + 1000) > wait(dur) > > -- create new modulator > carrier:freq(Square(20, 0) * 250 + 1500) > wait(dur) > end > > Out:remove(carrier) > > > Graham > > *Though I have to stress the point - because of the current MSP > architecture, I cannot use existing MSP unit generators inside of > lua~, so I had to provide new unit generator DSP functions. > > > > On Oct 26, 2007, at 11:08 AM, Robert Ramirez wrote: > >> >> yeah, it sounds really great. >> will try it out as soon as i get some free time. >> >> it seems you are implying dynamic modifications to the signal chain >> without the familiar msp pop, is this correct? > > grrr waaa > www.grahamwakefield.net > > > >
      Cheers Gary Lee Nelson Oberlin College www.timara.oberlin.edu/GaryLeeNelson
    • Oct 27 2007 | 10:23 pm
      Hi,
      I had to rewrite lua~ almost from the ground up to get around many issues that were causing crashes due to multithreading (and it not always being exactly clear what calls are or are not thread-safe in the SDK). In the process, a lot of the optimizations I had previously had been removed, in order to reduce the number of possible causes. This week I'm going to re-introduce them one by one, and providing they all work, you should see quite a considerable improvement in CPU efficiency.
      ((That said, interpreted control, run-time modification and even generation of DSP graphs, with sample-accuracy, is never going to be as efficient as a static graph of C externs. But it can get close enough to be very useful...))
      Once the efficiency changes have been implemented, I'll post again to let you all know.
      Best,
      Graham
      On Oct 27, 2007, at 5:56 AM, Gary Lee Nelson wrote:
      > I download lua~ and tried it. It works very nicely but seems to > cost a lot > in cpu for even simple patches. > > > On 10/26/07 2:52 PM, "Graham Wakefield" > wrote: > >> This is correct - and also independent of block-rate*. For example: >> >> -- changing an FM modulator graph at increasing periods from 1 to >> 10000 samples: >> >> -- duration of one sample in seconds: >> local sample = 1/samplerate >> >> -- add a sinewave to the output bus: >> local carrier = Out:add(Sine()) >> >> for i=1, 100 do >> -- set pulse duration: >> local dur = i * i * sample >> print("duration", dur, "(s)") >> >> -- create new modulator >> carrier:freq(Sine(10, 0) * 500 + 1000) >> wait(dur) >> >> -- create new modulator >> carrier:freq(Square(20, 0) * 250 + 1500) >> wait(dur) >> end >> >> Out:remove(carrier) >> >> >> Graham >> >> *Though I have to stress the point - because of the current MSP >> architecture, I cannot use existing MSP unit generators inside of >> lua~, so I had to provide new unit generator DSP functions. >> >> >> >> On Oct 26, 2007, at 11:08 AM, Robert Ramirez wrote: >> >>> >>> yeah, it sounds really great. >>> will try it out as soon as i get some free time. >>> >>> it seems you are implying dynamic modifications to the signal chain >>> without the familiar msp pop, is this correct? >> >> grrr waaa >> www.grahamwakefield.net >> >> >> >> > > > Cheers > Gary Lee Nelson > Oberlin College > www.timara.oberlin.edu/GaryLeeNelson > >
      grrr waaa www.grahamwakefield.net
    • Oct 29 2007 | 11:35 pm
      Hi all,
      Just updated the lua~ external (still only OSX, sorry). A few minor fixes, and some optimizations.
      Best,
      Graham
      On Oct 27, 2007, at 3:23 PM, Graham Wakefield wrote:
      >> >> >> On 10/26/07 2:52 PM, "Graham Wakefield" >> wrote: >> >>> This is correct - and also independent of block-rate*. For example: >>> >>> -- changing an FM modulator graph at increasing periods from 1 to >>> 10000 samples: >>> >>> -- duration of one sample in seconds: >>> local sample = 1/samplerate >>> >>> -- add a sinewave to the output bus: >>> local carrier = Out:add(Sine()) >>> >>> for i=1, 100 do >>> -- set pulse duration: >>> local dur = i * i * sample >>> print("duration", dur, "(s)") >>> >>> -- create new modulator >>> carrier:freq(Sine(10, 0) * 500 + 1000) >>> wait(dur) >>> >>> -- create new modulator >>> carrier:freq(Square(20, 0) * 250 + 1500) >>> wait(dur) >>> end >>> >>> Out:remove(carrier) >>> >>> >>> Graham >>> >>> *Though I have to stress the point - because of the current MSP >>> architecture, I cannot use existing MSP unit generators inside of >>> lua~, so I had to provide new unit generator DSP functions. >>> >>> >>> >>> On Oct 26, 2007, at 11:08 AM, Robert Ramirez wrote: >>> >>>> >>>> yeah, it sounds really great. >>>> will try it out as soon as i get some free time. >>>> >>>> it seems you are implying dynamic modifications to the signal chain >>>> without the familiar msp pop, is this correct? >>> >>> grrr waaa >>> www.grahamwakefield.net >>> >>> >>> >>> >> >> >> Cheers >> Gary Lee Nelson >> Oberlin College >> www.timara.oberlin.edu/GaryLeeNelson >> >> > > grrr waaa > www.grahamwakefield.net > > > >
      grrr waaa www.grahamwakefield.net
    • Aug 31 2008 | 8:55 pm
      Thanx for all you've done with lua~, Graham!
      I've downloaded beta 6 and have been playing with it. I get the impression that lua~ is mostly designed for synthesis. So far, however, I've had no luck using it to replace some of the more logic and control functions I'm currently using Javascript for on a project... basically scripting the Jitter (and eventually MSP) processing chains. So some questions, please:
      Is it possible to pass variables in and out of lua~? The right output only seems to want to print to the Max window, and the other outs only seem to want the numeric output of ugens. If I could figure how to use Math or other ugen for the control calculations for the variables, I'd still need an I/O method for them (and I have a ton of arrayed vars). Looks like bus and play pretty much just push out numbers with no provision for identifiers. Assuming Math or other method can handle calculations, I thought maybe a worst-case I/O scenario would be to dedicate discrete ins and outs to handling communication of discrete variables... but I can't figure out how to get specific data in/out a specific bus. And if any/all of the above is possible, is it possible with local as well as global variables? If possible, examples of these issues would really help!
      Also, is it possible to have global variables shared across multiple instances of lua~ (and Lua scripts)?
      Is it possible to embed an actual lua~ script inside a Max runtime for the purpose of hiding it from the public?
      Thanks so much!
      Jeff
    • Aug 31 2008 | 11:54 pm
      > Is it possible to embed an actual lua~ script inside a Max runtime for the purpose of hiding it from the public?
      Heaven forbid that the public should actually know this stuff. Of course, if you're hiding it in a situation where you're charging "the public" money, did you check on clearance to use this in something that lines your pockets? :-)
    • Sep 04 2008 | 2:30 am
      Hi, Gregory...
      I VERY MUCH appreciate the open, sharing nature of Max and the Max community.
      Actually I was thinking more of an installation situation where one does everything they can to secure it from hardware theft and software tampering. If somebody with ill intent should gain access to the system, messing with an exposed script could compromise the entire public experience. Hence my question about "hiding a Lua script from the public". (I'm pretty sure the answer is negative by the very nature of scripts, but thought somebody might prove my perception wrong.)
      Anybody have any answers to my other lua~ questions?
      Thanks!
      Jeff
    • Sep 04 2008 | 1:23 pm
      Is there any word as to when there will be a windows version of lua~?
    • Sep 11 2008 | 5:37 pm
      Whoops, sorry for the delay, I've been taking (hopefully) the last exam in my life and it is a big one. Still not finished actually.
      On Aug 31, 2008, at 1:55 PM, Jeff Burger wrote:
      > > Thanx for all you've done with lua~, Graham! > > I've downloaded beta 6 and have been playing with it. I get the > impression that lua~ is mostly designed for synthesis.
      Well, I would say computational approaches to the control of synthesis, esp. microsound, but yes. That's what I was into when I made it.
      > So far, however, I've had no luck using it to replace some of the > more logic and control functions I'm currently using Javascript for > on a project... basically scripting the Jitter (and eventually MSP) > processing chains.
      I've had more joy with jit.gl.lua for scripting Jitter, but of course I have a little language bias. Unfortunately it's not as straightforward to script the MSP chains, as the way the chains are built isn't really suited to rapid construction/destruction/ reconfigurations, esp. at microtime. That's what lua~ was built for. You could think of it as a highly stripped down SC2 in a max object.
      > So some questions, please: > > Is it possible to pass variables in and out of lua~?
      Of course.
      send variables in: call, dostring, and set methods: http://www.mat.ucsb.edu/%7Ewakefield/lua%7E/lua%7E.htm#call
      Anything sent out will go to the right-most outlet. In the help patch, this is routed to the Max window by default, but you can do whatever you like with it.
      > If I could figure how to use Math or other ugen for the control > calculations for the variables, I'd still need an I/O method for > them (and I have a ton of arrayed vars). Looks like bus and play > pretty much just push out numbers with no provision for > identifiers. Assuming Math or other method can handle calculations, > I thought maybe a worst-case I/O scenario would be to dedicate > discrete ins and outs to handling communication of discrete > variables... but I can't figure out how to get specific data in/out > a specific bus. And if any/all of the above is possible, is it > possible with local as well as global variables? If possible, > examples of these issues would really help!
      It's a little hard for me to understand what you're asking. So, lua~ deals with two kinds of data, just like MSP. Audio signals are sent in to the inlets of the object and are represented in the lua script as the In bus. You can access individual channels of the bus as In [1], In[2] etc., representing the individual inlets of the lua~ object. The outlets are represented as the Out object. Right now there's no direct way to write to individual channels of Out, except using the Pan ugen, sorry. Anyway, these end up coming out of the lua~ object outlets. Connecting up a graph between In and Out is what the lua script can do, and it can change it according to functions, while loops, coroutines and so on, scheduled in time using go() and wait(). The second kind of data are messages in Max, and so messages sent to lua~ are converted into equivalent Lua data types. The Max messages call, dostring and set will all give you ways to send message data into lua~ and call functions in the script. Finally, ugens in lua~ can mostly take either other ugens or numbers for their parameters.
      I'm not sure what variables you mean when you say you need an I/O method for them. Do you want to send max lists and process them as audio? If so, this isn't really possible as such, lua~ is intended for real-time processing of audio streams.
      Bus and play() are just ways to connect unit generator graphs with active streams, dynamically. There are no identifiers, because these are just audio streams. The identifier as-such is the Lua variable in the script.
      I'm not sure what you mean by global/local variables, but all variables in a script can be global/local, it makes no difference to Max.
      OK an example attached at end of this mail. HTH
      > Also, is it possible to have global variables shared across > multiple instances of lua~ (and Lua scripts)?
      Not in the current version, but it *could* be possible.
      > Is it possible to embed an actual lua~ script inside a Max runtime > for the purpose of hiding it from the public?
      If you mean a collective/standalone, then yes, just like any other max object or file associated with a patch. The public will be able to see it however if they Show Package Contents on the collective/ standalone. FYI.
      BTW, lua~ is working more-or-less in Max5, except for the editor window etc. This may be updated when the max5 SDK is released, and probably the windows version around the same time. I have quite a few improvements for a v2, but no time. Bloody exams.
      Save the following as 'love.lua' in the same folder:
      -- make a little graph: local sine = Sine() local graph = Wrap(0.2, 0.8, sine)
      -- connect to signal outlet Out:add(graph)
      -- a global function is accessible to Max via the 'call' message: function choosesource(which) if type(which) == "number" then -- #In gives the number of channels In has. Works on all ugens. if which > 0 and which -- get a local reference to the inlet's audio stream: local inlet = In[which] -- set this as the frequency of the graph: sine:freq(inlet)
      outlet("changed the graph to inlet", which) else outlet("attempt to choose a nonexistent inlet:", which) end else outlet("choose function expects a number to select the inlet") end end
      print('I love exams')
      Finally, I probably won't upgra