What is Qua? Is it a midi sequencer? A midi patcher? An application sequencer? A
brand of illicit psychedelic? An algorithmic composition system? A wierd and funky virtual instrument?
The sound that
ducks make? There is a very good chance that it is all of those things and more...
The Fundamentals of Qua
Qua began as astandalone algorithmic composition, running on an Atari ST. Hey some of the ST code is still
there! It migrated to a Falcon, where it became a bit more generic, and was used to mangle The Quartet for The End Of Time into tabla patterns. This composition then evolved into a much more generic system, and landed onto BeOS,
fertile soil indeed, where it mutated severely, under the influence of _unmentionables_ and thundering doof. Somewhere
along the line there was an idea about turning poems about water into music, and this has left me with a bit of
wierd terminology, and some very wierd memories.
It is a sequencer for midi data, application messages, and programs, called voices, written
in its own script language, QuaScript.
It also has a crossbar switching system that can route (performing appropriate data conversions) from any of these
types of things to any other. Each of these objects has a crude graphic control panel, allowing them to be played and
manipulated in pre-determined ways. It offers facilities for offline and online (as soon as full PR appears) editting of
stored forms of this data. It allows for dynamic midi filtering.
Getting Started
Qua has a mime type of "application/x-vnd.DataSinkBeserker-Qua". This should be set in the
distributed binary, but if it's not, the app may not run, and the mime type needs be set manually.
Clicking on the duck foot icon will bring up two windows:
The main control panel. This has four buttons, and some menus. Overdub mode is currently ignored.
The palette window. This is a 256 color palette, used for coloring data objects in the sequencer:
click the color and drag it onto the desired object. This window can be done away with on the
main control panel.
Next step: bring up a sequencer page, through the main menu. Qua assumes that all reaonably
interesting apps have an APPI structure attached somewhere. If a file doesn't have one,
it will be assumed to be a savefile, if it has a header, otherwise it will be treated as an ascii text
file, and parsed appropriately.
The sequencer page will come up with:
A menu bar for saving loading and exitting.
A white "QuaObject" aquarium, where other files can be dropped onto. These files may be applications, ascii QuaScript
files, or savefiles. Most Objects displayed in here are picked up and placed onto the timegrid. The objects that will be
displayed here are:
Pool objects. These are dynamic data stuctures storing midi data, and BMessages, in a common format
where such data can be freely intermingled.
Voice objects: runnable QuaScript objects that can be placed on to the sequencer and will generate data to
whatever channel they have been coded for. Presently this is hard coded, so a voices allocated channel on the grid
is irrelevant for all but aesthetic reasons.
AppCtl objects. Activation controllers for apps that have been dropped onto Qua. Again channel on the
grid is irrelevant.
Source objects that have been defined in the top context (these can be defined in lower contexts as well, and these lower ones won't be displayed in this area). These are code/data objects that are used as
functions and named structures by voice objects, and as stream filters by channel and AppCtl functions.
These can't be used for sequencing, but it is certainly
a relief to have them displayed if you drop a file there that contains only such objects. And its always nice to know
what you've got lying around and handy.
In this area:
clicking an object will select it, while shift-click adds to the selection.
Double-clicking will bring up its control panel (if not already up, and its
the sort of thing that has one).
Dropping a color will change its color, and that of _subsequent_ objects spawned from it on the timegrid.
Presently
only objects in the aquarium can have their colors adjusted by the palette window.
A time grid, with bar/time/tempo information across the top. Objects are represented by colorored squares on this
grid, proportional to their duration. On this grid:
Duration can be stretched or contracted by a right click and stretch.
Object can be moved around. Positions are rounded to the nearest whole beat.
Objects can be seleced by a single click, or added to selection by click-shift.
Objects are copied by ctrl-click (with drag).
Currently selected objects will be deleted by the DEL key (no undelete yet).
For voices and apps, the activations on this grid correspond to waking and suspending its action. For the app, this means
that its wake or sleep block ios executed, and any messages produced are passed on. Generally these will produce
message to make it start/stop. For the voice, it will be woken/suspended. This means that track overlays for these objects
doesn't do anything, and the app/voice will be kept getting turned on or off. In the context of a parallel thread, which these
objects correspond to this makes certain sense. However, pool objects, being internal data structures can and will be
overlayed. We apologise for the inconsistency, but it's a sacrifice for sane usability.
A list of channels, numbered from 1-16. These can be clicked on to bring up the control panel for
that channel. The channel control panel allows access to the channels input destination, output destination,
Thru toggle, and input and output filters. These correspond to lines in the time grid. This is presently only
functionally relevant for pool objects, where the line in the grid will correspond to output to that channel.
I/O destinations can be set to a channel in midi1 or midi2 (referred respectively as A and B), or an application that
has been dropped onto Qua.
Press Go to start and Stop to stop. Overdub does nothing, as record presently records into new pools always.
And there's no easy way to edit names. Record starts recording from all selected channels, and pressed twice,
activates subsequent channels.
Control Panels
These provide a common interface to pools, apps, channels and voices, with a slight variation in accessible buttons
as appropriate. They are generated from the lexical structure of voices, and automatically for everything else. The top
set of button refers to the object itself usually, and subviews below correspond to sub-parts, either static function
calls or preset blocks: These subsections are generlly, and since dr8, unfortunately, termed nodes.
The activate button schedules them at the current point, and the stop button stops them.
Parameters that are unpassed in a script or otherwise fixed internally are given appropriate display/control boxes.
Sub menus generally give access to top level sources to be accessed as (say) a set of filters.
QuaScript
The QuaScript language is a dataflow language which gives access to almost every aspect of the running sequencer
to a source or voice. It maintains several types which can be accessed implicitly, particularly
the stream and the items in it, and their fields, and the following explicit objects:
bool: a boolean flag
byte: an 8 bit numeric
short: an 16 bit numeric
int: an 32 bit numeric
long: an 64 bit numeric
float: an 32 bit floating point numeric
pool: a local pool structure, or one from outside the block
source: a standard code block, which may contain further definitions. kind of a cross between a structure and
a function
voice: a voice of course: a schedulable code object.
The standard format for defines is clunky but workable: define# {# } []
Available modifiers are:
node: this source will have a place on the control panel. Sources when used as filters do automatically. Such
sources are called when their status is "running".
modal: modal node. only one modal node in a block can be on/
oncer: the source is deactivated when executed once
fixed: node is fixed on, but still displays parameters.
label: panel name for the source.
reset: re initialize the sources block on activation.
toggle: provide only a single button.
There are three kinds of lists:
{ , ... }
This is a standard block, in which data is placed in parallel (vertically/chordally) on the stream.
[, ... ]
This is a sequential block, in which data is placed linearly (sequentially) on the stream. These will hold execution of thier surrounding block until the sequence is complete.
{|, ... |}
This is a parallel block, in which data is placed in true parallel on the stream: this gets around hacks in the
first kind to enable embedding of sequential and parallel blocks. It's mainly used internally.
Expression syntax is standard C, with sin,cos,tan,acos,asin,atan,exp,log,pow defined and available. The comma is
used as a seperator, and is only used to disambiguate messy stuff for the parser. Time is measured in clocks
generally. Currently things are fixed at 12 clocks to the beat. Booleans are only evaluated when a sequence is complete.
Statements include:
assignment. standard, but if the lval refers to a stream item, the rval is performed for every element of the stream. e.g.
pitch = pitch + 10
transposes every stream element passed through it.
call of a source.
constructor:
tone(,,): a noteon/noteoff pair
ctrl(,): midi ctrl
sysx(): sysx, dumping the fields of the source/node into a sysx message
prog(): prog change
bend(,): pitch bend
mesg(,{,}, ...): construct a BMessage
The scheduling operator, <- which executes the block once, and then reschedules itself for execution
when the stream prroduced by the block is completed.
The scheduling operator, <-() which executes the block once, and then reschedules itself for execution
after the number of clocks given by expression.
wait(): halts execution of the list until exp is true.
<<: input from channel
>>: output to channel
::: do block if is trus
if ()else: do block if is trus else do block2
with ()else: do on items matchingelse put them through
::: do block if is trus
kill : signal voice
wake : signal voice
suspend : signal voice
The system provides lots of nice variables, most usefully:
self; the voice itself
pitch: field for a tone
dynamic: field for a tone
duration: field for a tone
bar: current bar #
beat: curtrent beat in the bar
clock: current subdivision of the beat
actualtime: in sec
clocktime: total # of sequencer clocks(i.e. pulses)
Other useful predefs include 2nd order markov chains, illustrated in piano_inst, and pool manipulation functions
(r08_inst)
(partly broken but back soon),
This has probably confused the hell out of you, but listen and look at the provided test patches. The "r08_inst", drum map
editor is currently broken, but contains some good examples of twisted but useful coding. The rest should be OK, but are
set up for EPS percussion and kit instruments. The afro_instrument is quite pretty on piano.
Known Bugs and Frailties
The list is manifold, but here it is so far:
The parser does not recover from errors at all well. At some stage, I'll redo it in yacc/bison, and
the situation should improve. A lot of this stuff had its birth on an Atari ST: need I say more?
In particular, paramater count mismatches on builtins may segfault.
Objects should be properly deletable from the aquarium.
The save file situation is flaky, will improve under testing, and will likely change in format slightly as
time progresses. There is enough information in the header to find out when something was saved,
and how it could be converted. Qua will probably do this automatically if anybody thinks this is a good idea.
Child processes get orphaned, and have to be killed with something like TManager. I haven't had time to
work out why, but I think it's something simple.
The Future of Qua
Lot's of stuff in the pipeline, particularly now that system APIs have settled:
The on-line stream editor (i.e. the interactive beast you would expect) will reappear very soon. It existed in the
past, but relied on the dr8 3dKit (which will go down now in memory as one of the Great APIs I Have Known Through
Ritualistic Examation Of Header Files).
A graphic editor for QuaScript. This is also slated fairly soon. Personally, I prefer ascii text, which is a nice scoring
tool for _some things_ and not others. I'm not overly fond of MAX's, but it will look interesting, and let mods be
done to running scripts on the fly.
Multiple meters, polyrhythms, tempos and other wierd timegrid overlays. Synchronizing multiple clocks is already
done internally, but simplicity of the interface has suggested the 4-to-the floor, 12 subdivision to the beat approach.
Anyway, most people can't dance to 7:5.
Import and export of general midi files. This is high priority.
Loadable addons for QuaScript. This is a bloody good, almost essential, idea, that I just haven't gotten around to.
Loadable addons for The ControlPanel interface class. Another cutie, but a bit messy, as it's a very twisted thing that
gets used in lots of wierd ways.
Thanks and Acknowledgements
I would particularly like to thank: Tamara Verhagen, for support above and beyond the call of
romance, and for maintaing my sanity when I didn't think it would hold out; Alistair Riddell,
for support, belief, and a sound ear; the manufacturers of Daffy Ducks; Adrian Sherriff,
and Andrew Gannon; Olivier Messiaen, whose quartet I've enjoyed mauling; Micheal Pallot,
for a gracious loan of an Atari Falcon (on which this morass was begun); anybody and everybody else
whose names I've forgotten because I was too drunk at the time.
Contact Point
Information on Qua, rack303, and other fabulous DataSink Beserker products
(soon to be announced) can be had from me at:
dak@zog.net.au
dak@cs.latrobe.edu.au
David Karla
29 Rushall cres,
North Fitzroy,
Melbourne, Australia, 3065.
I'm keen to here what people do with this beast, and I'm eager for bug reports and
suggestions.
Nano nano,