What is LOVE?
LOVE is the Live Occam Visual Environment, a demonstration of live graphical programming based on occam-pi. (If you're wondering what live programming is, have a look at the splendidly weird TOPLAP web pages.)
More to the point, LOVE is a framework and GUI for connecting up occam-pi processes that perform operations upon MIDI and audio streams; it's a graphical tool for making (simple) music with occam-pi.
The graphical process network editor idea has been done -- and done better -- many times before, but as far as I'm aware LOVE is the first graphical process network editor written almost entirely in occam-pi. Since the editor has minimal coupling to the processes it's manipulating (it just sends them channel ends using predefined protocols), it should be possible to rework it to be able to edit different types of process networks.
LOVE's processes consist of "obvious" occam-pi code -- the id process looks exactly like it does in basic occam courses -- with a simple wrapper to allow them to be replugged at runtime (following Carl Ritson's approach). The process author does not need to worry about repluggability.
LOVE's graphical output is entirely vector-based and resizable; the SDL_gfx library is used to draw graphics primitives onto an SDL surface. Graphical widgets are processes, which communicate with the frontend (exchanging lists of vectors to draw and input events) using channels.
LOVE is research-quality software; expect occasional oddities. If you're interested in using LOVE (or bits of it) for a project, then please let me (Adam Sampson, email@example.com) know, so I can clean up and document the code appropriately.
A Linux i386 binary of LOVE, along with the shared libraries it needs, is available from here:
The LOVE source code is available using the Darcs revision control system; once you've installed Darcs, you can type:
darcs get http://offog.org/darcs/love/
to download the latest version. If you don't have Darcs, you can still browse the latest source code by pointing a web browser at http://offog.org/darcs/love/.
To compile LOVE, you will need:
On a Debian or Ubuntu system, you should be able to install the non-KRoC prerequisites by doing:
apt-get install libsdl1.2-dev libsdl-gfx1.2-dev libasound2-dev
Typing make should compile the source and leave you with a love binary.
When you start LOVE, you'll get a square window with a grid (upon which processes can be placed) and a toolbar. There's an out process on the grid already. To place a new process, left-click on the process you want on the toolbar, then left-click on the grid to place it (or right-click to cancel, if you've decided you don't want that process after all). To move processes around, drag with the left mouse button.
Processes have input ports and output ports, represented by blobs on their left and right sides, which may be connected by wires (which are, to a pretty good approximation, occam-pi channels). Ports and wires come in two varieties: blue ports carry MIDI data (note events), and orange ports carry continuous "analogue" signals. To connect a wire between two ports, left-click on one port, then left-click on the other (or right-click to cancel). While you're connecting a wire, other ports will be coloured green or red depending on whether you're allowed to connect to them or not. To disconnect a wire, hover the mouse pointer over it (it'll be highlighted in yellow) and right-click. You can have as many inputs connected to one output as you like, but you may only have one output connected to each input.
Some processes have graphical elements you can interact with using the keyboard. Number entry boxes (like on const) represent a numeric value; to change it, hover the mouse pointer over the box, type the new number and press return (invalid entries will be ignored). Sliders represent a value between 0 and 1 as a horizontal pink bar on a grey background; to change it, hover the mouse pointer over it and press a number between 0 and 9 (for 0.0 to 0.9) or dash (for 1.0). (Yes, this is silly; I haven't implemented mouse events for widgets yet!)
The following processes are available:
out represents the sound output from LOVE; feed a stream of audio data into it, and you'll hear it. You get one of these processes automatically on startup, and you can't create any more.
id is the identity process: the output is a copy of the input.
const outputs a constant analogue value. The number entry box is the value it'll output.
scope is an oscilloscope for analogue values. It'll show you the waveform that's coming into its input, and the absolute peak value as a number. The output is a copy of the input (for ease of wiring).
+ and * have two inputs and one output; they add and multiply (respectively) their input values.
scale has two number entry boxes. For each analogue value coming in, it multiplies it by the value in the top box and adds the number in the bottom box.
mixer adds several inputs together, multiplied by the value of their respective sliders; this is useful for combining several streams together before output.
sine is a sine-wave oscillator; its input is a frequency value in Hertz, and its output is a sine wave with an amplitude of 1.0 at that frequency. (It's not actually a very good oscillator, which means that you can get interesting effects by chaining them together.)
MView is a MIDI viewing and entry component. If you connect a MIDI stream to its input, it'll show the pitch and velocity of the notes passing through it (rather like scope does). If you press keys while the mouse pointer is hovering over it, it'll generate notes (and show you what you're playing). You have two-and-a-bit octaves from C-3 to E-5 mapped onto the computer's keyboard in an approximation of a piano layout: Z is C-3, X is D-3, D is D#3, and so on. (If you're used to using a tracker, the keyboard layout will make sense.)
M->pg converts MIDI notes to two analogue signals. The top signal is the pitch (frequency) of the note; the bottom signal is the gate (amplitude). (In the real world, this would be a monophonic MIDI-to-CV converter.)
Trans tranposes incoming MIDI notes by a given number of pitch steps, which may be negative; for example, entering -12 would make it transpose down an octave.
Seq is a very simple MIDI sequencer with a variable step length: it stores an array of MIDI notes and plays them back at the requested rate. The bottom left number box is the number of steps (between 1 and 32); the bottom right box is the tempo in beats per minute. The boxes at the top show the note locations; the currently selected note is outlined in white, and boxes are either orange or black depending on whether they hold a note. It's either in record or playback mode; to toggle, press R while hovering the mouse over the top boxes. To record notes while in record mode, connect an MView to the input and play into it; you can insert a note's rest by pressing space over the boxes (not in the MView -- another thing to fix). In playback mode, it'll endlessly repeat the series of notes it's got recorded.
The simplest way to make a noise is to connect a const to a sine, and that to out -- which'll result in a constant (and rather annoying) tone. Play around with the const's value to change the frequency. Connect up a scope too, so you can see the shape of the waveform.
For a more interesting noise, chain several sines together:
If you'd like to hear the difference more clearly, use a mixer to combine the outputs from the different sines together:
You might also like to try multiplying or adding two sine waves together. If you add two sine waves at frequencies A and B, you'll hear both frequencies plus the beat note A-B (try 400 and 401 Hz -- you'll get a 1 Hz pulse). If you multiply two sine waves, you'll get A+B and A-B. It's a bit easier to see why on the scope:
And we can build a servicable police siren by using the output from one oscillator (scaled appropriately) as the frequency input of another:
This isn't really very musical as such, so let's add some MIDI control. Feed a sine from the pitch output of an M->pg, and multiply its output by the gate. You'll now be able to play notes on an MView and hear them come out the output -- and if you add some scopes, you can see what the pitch and gate signals look like (remember the numeric readout is the peak amplitude of the signal).
Now try connecting up a sequencer and getting it to play a loop of notes.
For more ideas, see the big example image at the top of the page.
While LOVE has already served its initial purpose -- to show that you can deform the semantics of occam channels sufficiently to permit live programming without making the language unusable -- there are still a number of things that I'd like to do to it to make it a more useful piece of software.
- MIDI input
- Live creation of reusable processes -- drag a box around a bunch of processes and you get a new toolbar item
- Get the C parts of LOVE (audio and SDL_gfx bindings) into the occam-pi standard library
- Consider splitting the "widgets" stuff into a separate GUI library
- Better interaction with widgets
- Polyphony -- a process that splits an incoming MIDI stream into several output streams
- Sample-accurate timing, based on Carl's multimedia processing work; this'd make it possible to build comb filters
- More oscillators and operators; it'd be nice to be at least DX7 equivalent