USING LUA FOR AUDIOVISUAL COMPOSTIONSkip other details (including permanent urls, DOI, citation information)
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 3.0 License. Please contact firstname.lastname@example.org to use this work in a way not covered by the license. :
For more information, read Michigan Publishing's access and usage policy.
Page 00000342 research project ALUA  and recent high-level bindings for the CSound API) and none that provide the rich degree of control to satisfy the authors' needs. Following Lua's philosophy, the audio domain extensions in lua~ were designed to provide metamechanisms for digital music composition rather than a variety of preconceived musical structures (as appropriate for a domain so fraught with complexity and ambiguity ). Computer music compositions may involve serial and parallel processes and structures in a complex web of relationships, eventually producing samples of digital audio. Crucially, such processes and structures are dynamic and possibly actively determined in time. The lua~ external therefore extends Lua's excellent data-description and functional programming capabilities for digital audio domain in two principal areas, both evaluated under the control of a sampleaccurate scheduler: * Concurrent functional control (via coroutines) * Signal processing (via unit generator graphs) A lua~ object embedded in a Max patch can load and interpret Lua scripts that make use of these extended capabilities in order to receive, transform and produce MSP signals and Max messages accordingly. A code sample of a typical script is given in Figure 1. 2.1. Concurrent functional control Concurrent functional control is based upon an extension of Lua coroutines. A coroutine represents an independent thread of execution for deterministic scheduling (also known as collaborative multi-tasking). In lua~, such coroutines are extended to be aware of the sample-clock, with a small number of additional functions to interact with the scheduler. The scheduling of control flow using coroutines in lua~ is a variation of the continuation-based enactment design pattern . Coroutines are launched with the goo function, which takes a delay time as its first argument, and a function as its second argument'. Effectively a copy of this function is inserted into the scheduler's list of parallel activities, to be activated after the delay time has elapsed. All statements in a coroutine occur instantaneously with respect to the sample clock, with the exception of wait( and playQ. The wait(dur) call will yield execution of the function body for dur seconds, in which time other coroutines may execute or signal processing occur, and the now() call returns the number of seconds since the coroutine was launched. All specifications of time are sample-accurate. 2.2. Signal Processing Because the Max/MSP SDK API does not allow dynamic instantiation of any MSP object, a different set I Additional arguments are passed on to this function. of signal processing unit generators has been provided, based on the efficient C++ library Synz . An SDK to extend the DSP vocabulary is planned as future work. Signal processing primitives (unit generators) are created by calling library constructor functions, such as SineQ, EnvQ, Biquad( etc. The constructor functions may themselves take numeric or unit generator inputs as their arguments, such that for example the statement Sine (Sine (0.1) * 400 + 500) will create a basic FM synthesis graph modulating between 100 and 900Hz ten times per second. Note that basic operators (+, *, -, /, %0, A) are overloaded for unit generators to aid legibility. The play(bus, dur, unit) call adds the unit generator unit as an input to bus for a duration of dur seconds (yielding the coroutine in between). This bus may be the global Out bus, which represents the lua~ outlets in Max/MSP, or another bus created by the programmer using BusQ. it s -sONe:/dur, 0) *amp (),utdur, gr ph) erat f ade, 0.8 8*(motb awks S 19) it step =:t itlimit -amth.vrodom(12) gogandurratton / step, amp) walt(puLsewidth *s'tep) j stp (tp N imit) + -i Figure 1. Code sample layering multiple pulse-trains with distinct algorithmic control of pulse duration & pulse width in each train. 2.3. Avoiding block-rate The scheduler algorithm at the heart of the lua~ external manages the coroutines and the signal processing graphs, avoiding block-rate control limitations. The scheduler lazily evaluates graph sections only when deterministically necessary, maximizing vectorprocessing potential where possible. Latency between inputs and outputs is only incurred for graph sections with cycles (feedback), and can be minimized to arbitrary control rates. Lua~ thus permits a sample accurate articulation of the composition that may be dynamically deterministic. State changes that involve interpreted code to generate new signal graphs may 342