<- Implementation
Signals and types
In this version, I chose to implement a simple synchronous evaluation model. The (unique) time is chopped-up in cycles of 1/800th of a second. Every signal is then represented by a temporal sequence of "signal buffers", each containing one cycle of that signal.

The signal buffers are typed:

  • Audio buffers contain 60 floating-point audio samples,
  • Bytebeat buffers contain 10 integer bytebeat samples,
  • UI buffers contain one 8x8 grid of booleans.
Thus, audio is sampled at 48000 KHz, bytebeat at 8 KHz and UI at 800 Hz.

The data structure that holds a signal buffer is "sig_head":

typedef struct
{
    sig_type type;
    int size;	// In bytes, including this header
} sig_head;

That structure is actually the header of a malloc()ed memory block and defines the signal type and the size of the buffer. It is then directly followed (in that memory block) by the signal data, which depends on the type of the signal. Thus, in order to access the audio data in an audio signal buffer, I use some pointer magic to "skip" the header:

sig_head *out;
sig_t_audio s_out;
s_out = (void *) (out + 1);

What motivated this rather dubious data structure is parametric polymorphism: it allows many parts of the code (including the evaluator) that only need to shuffle buffers around without "looking into them" to work on any signal, regardless of its type.

After that comes the definition of components and instances:

typedef sig_head *(*compop) (sig_head **, void **);

typedef struct component
{
    int empty;
    coord p;
    compop op;
    int num_inputs;
} component;

typedef struct instance
{
    int empty;
    component c;
    coord inputs[MAX_COMP_ARGS];
    void *state;
} instance;

First, "compop" (short for "component operation") describes a C function that takes an array of signal buffers (the inputs) and a handle to a state and returns a single signal buffer (the output).

Then a component is defined with a compop and the number of inputs of that component. Finally, an instance is defined with a component, an array of input coordinates and a pointer to a state.

When a component represents a stateful function, that state's structure is defined right above the function implementing its operation.

© 2000-2014 Mikael Bouillot (last updated 2014-05-13)