3. Line16 Data

3.1. Line16 Point

A point is a explicit point in a line.

3.1.1. Typedef

Data for this point is contained in a struct called line16_point.

<<line16_typedefs>>=
typedef struct line16_point line16_point;
<<line16_struct>>=
struct line16_point {
<<line16_point_contents>>
};

3.1.2. Init Function

A line16_point is initialized using the function line16_point_init.

<<line16_function_declarations>>=
static void line16_point_init(line16_point *pt);
<<line16_functions>>=
static void line16_point_init(line16_point *pt)
{
<<line16_point_init>>
}

3.1.3. Contents

3.1.3.1. Active

This is a boolean value. When not active, the point will be skipped. The last active value will determine the length of the line segment.

<<line16_point_contents>>=
int active;
<<line16_point_init>>=
pt->active = 0;
3.1.3.2. Value

The value of a point is a normalized GFFLT floating point value between 0 and 1.

<<line16_point_contents>>=
GFFLT val;
<<line16_point_init>>=
pt->val = 0;
3.1.3.3. Duration

The duration tells how long the segment is, and by definition also illustrates how long the interpolation time to the next value will be.

<<line16_point_contents>>=
GFFLT dur;
<<line16_point_init>>=
pt->dur = 0;
3.1.3.4. Aux Values

These are two aux values. These will be controllable via the arc. These will map to any special point functionalities that may arise in the future.

<<line16_point_contents>>=
GFFLT aux[2];
<<line16_point_init>>=
pt->aux[0] = 0;
pt->aux[1] = 0;
3.1.3.5. Playback Rate

Every point has their own playback rate amount. The idea is that this can be modified inside of graforge. By default, this is set to be 1 (normal speed).

<<line16_point_contents>>=
GFFLT rate;
<<line16_point_init>>=
pt->rate = 1;
3.1.3.6. Type

This refers to the point slope type. By default, it is set to be 0, or linear.

3.1.3.6.1. Struct Declaration

<<line16_macros>>=
enum {
SLOPE_LINEAR,
SLOPE_EXP_POSITIVE,
SLOPE_EXP_NEGATIVE,
SLOPE_BEZIER
};
<<line16_point_contents>>=
int type;
<<line16_point_init>>=
pt->type = SLOPE_LINEAR;

3.2. DONE Line16 Line

CLOSED: [2020-01-02 Thu 13:58] This is a struct which encapsulates a line.

3.2.1. Typedef

<<line16_typedefs>>=
typedef struct line16_line line16_line;
<<line16_struct>>=
struct line16_line {
<<line16_line_contents>>
};

3.2.2. Init

<<line16_function_declarations>>=
static void line16_line_init(line16_line *line);
<<line16_functions>>=
static void line16_line_init(line16_line *line)
{
<<line16_line_init>>
}

3.2.3. Contents

3.2.3.1. Point Bank

<<line16_line_contents>>=
line16_point points[16];
<<line16_line_init>>=
{
    int i;
    for (i = 0; i < 16; i++) {
        line16_point_init(&line->points[i]);
    }
}
3.2.3.2. Number Of Active Points

Keeps track of how many active points there are. If there are none, the line does not get saved.

<<line16_line_contents>>=
int nactive;
<<line16_line_init>>=
line->nactive = 0;

3.3. Line16 Main Data Contents

3.3.1. Monome State Data

<<page_line16_contents>>=
monolith_page_mstate *mstate;
<<line16_init>>=
monolith_page_mstate_new(pg, &line16->mstate);
<<line16_cleanup>>=
monolith_page_mstate_free(&line16->mstate);

3.3.2. Arc State Data

<<page_line16_contents>>=
monolith_page_arcstate *arcstate;
<<line16_init>>=
monolith_page_arcstate_new(pg, &line16->arcstate);
<<line16_cleanup>>=
monolith_page_arcstate_free(&line16->arcstate);

3.3.3. Line Point Bank (soon to be line bank).

This is being refactored. Instead of having a point bank, a newly introduced line struct with a point bank inside of it. This will be a line bank with up to 16 lines available for programming.

<<page_line16_contents>>=
line16_line lines[16];
<<line16_init>>=
for (i = 0; i < 16; i++) {
    line16_line_init(&line16->lines[i]);
}

3.3.4. Global Playback Rate

<<page_line16_contents>>=
GFFLT rate;
<<line16_init>>=
line16_rate_set(line16, 1);

This can be accessed with line16_rate_set and line16_rate_get.

<<line16_function_declarations>>=
static void line16_rate_set(page_line16_d *l, GFFLT x);
static GFFLT line16_rate_get(page_line16_d *l);
<<line16_functions>>=
static void line16_rate_set(page_line16_d *l, GFFLT x)
{
    l->rate = x;
}

static GFFLT line16_rate_get(page_line16_d *l)
{
    return l->rate;
}

3.3.5. Selected Point

The currently selected point in the main line sequencer.

<<page_line16_contents>>=
int selected_point;
<<line16_init>>=
line16->selected_point = 0;

3.3.6. Selected Line

<<page_line16_contents>>=
int selected_line;
<<line16_init>>=
line16->selected_line = 0;

3.3.7. Currently Playing Line

This is the line that is being played in the main sequencer. This can be different from the currently selected line.

<<page_line16_contents>>=
int playing_line;
<<line16_init>>=
line16->playing_line = 0;

3.3.8. Point Position

An integer value. This shows holds the current point value.

<<page_line16_contents>>=
int pointpos;
<<line16_init>>=
line16->pointpos = -1;

3.3.9. Last Point Position

Every time the point position is updated on the monome grid, it stores the previous value. This is done to prevent the main function from overloading the grid and causing libmonome to bugout.

Initially set this to any arbitrary postive value larger than 15, or any value less than -1 (-1 being the initial unset point position).

<<page_line16_contents>>=
int lpointpos;
<<line16_init>>=
line16->lpointpos = -100;

3.3.10. Timers

3.3.10.1. Update Timer

This is a special timer used rate limit the updates to the monome grid. The timer measures the duration between time segments. If the distance it too short, it will simply not update the monome.

Set to be a negative value by default, so the program knows it is only initialized and not time has passed.

<<page_line16_contents>>=
double timer;
<<line16_init>>=
line16->timer = -1;
<<line16_macros>>=
#define MIN_DUR 0.05
3.3.10.2. Aux Timer

This is used to rate limit updated values coming from graforge nodes. To prevent weird interruptions and glitches, a separate timer is used. This only needs to be set to 0.

<<page_line16_contents>>=
double aux_timer;
<<line16_init>>=
line16->aux_timer = 0;
<<line16_macros>>=
#define AUX_MIN_DUR 0.03

3.3.11. Next Point

Holds the integer value for the next point.

<<page_line16_contents>>=
int nextpoint;
<<line16_init>>=
line16->nextpoint = 0;

3.3.12. 1 / SR

This is a constant that is the inverse of the sampling rate.

<<page_line16_contents>>=
GFFLT onedsr;
<<line16_init>>=
line16->onedsr = 1.0 / gf_patch_srate_get(patch);

3.3.13. Counter

This is the counter, stored as a floating point value, in seconds. Stores the current duration of the line segment.

<<page_line16_contents>>=
GFFLT counter;
<<line16_init>>=
line16->counter = 0;

3.3.14. Graforge Cable

This holds a pre-allocated graforge cable with an internal block. At every render block, the line gets computed exactly once, and it is written to this cable.. Other nodes then retrieve the block and copy it over to their internal block.

<<page_line16_contents>>=
gf_cable out;
GFFLT *blk;

Still need to initialize with graforge block. Also need to allocate and bind a block.

<<line16_init>>=
gf_cable_init(NULL, &line16->out);
line16->blk = calloc(1,
                     gf_patch_blksize(patch) *
                     sizeof(GFFLT));
gf_cable_set_block(&line16->out,
                   line16->blk,
                   gf_patch_blksize(patch));

Said block needs to be freed here.

<<line16_cleanup>>=
free(line16->blk);

3.3.15. Number of active points (migrated!)

Migrated to the line struct.

3.3.16. Event Stack

When a point is told to be turned on or off via the grid or programatically, it pushes the command onto an event stack, which is then processed by the internal node. This is done as a measure to prevent weird bugs from happening related to finding the next available point. The event stack right now is only concerned with whether or not things get activated. Other events, such as setting a value, will be directly written to the point. I do not see any potential weirdness here.

3.3.16.1. [2019-08-09 Fri 15:22] Dispute

Okay. So I just realized the downfall of this event stack. It makes it so you have to include the main node in the audio graph in order to use. If you don't, the thing appears to be broken. Also, if the sound is paused, the thing will appear to be broken. Overall not a great design.

My interest I think is going to be maybe capturing the states of all the lines, and then copying over the states whenever a change is made.

3.3.16.1.1. [2019-12-19 Thu 17:13] believe this is resolved

3.3.16.2. Data

The intermediate state of a page is stored in an array of char values as booleans.

The actions variable is used to keep track of if any actions happened.

<<page_line16_contents>>=
unsigned char state[16];
int actions;
<<line16_init>>=
line16_state_init(line16);
3.3.16.3. Initializing the event stack

This just zeros out the stack.

<<line16_function_declarations>>=
static void line16_state_init(page_line16_d *l);
<<line16_functions>>=
static void line16_state_init(page_line16_d *l)
{
    int i;
    for(i = 0; i < 16; i++) {
        l->state[i] = 0;
    }
    l->actions = 0;
}
3.3.16.4. Set the state

Sets the state.

<<line16_function_declarations>>=
static void line16_state_set(page_line16_d *l, int pt, int s);
<<line16_functions>>=
static void line16_state_set(page_line16_d *l, int pt, int s)
{
    if(pt < 0 || pt >= 16) {
        return;
    }

    l->state[pt] = s;
    l->actions++;
}
3.3.16.5. Applying the state

Will take the intermeidate state and apply it to the point bank.

<<line16_function_declarations>>=
static void line16_state_apply(page_line16_d *l);
<<line16_function_declarations>>=
static void line16_state_apply(page_line16_d *l)
{
    int n;
    unsigned char *state;
    line16_point *pt;
    int nactive;
    line16_point *points;
    line16_line *line;

    line = &l->lines[l->selected_line];
    points = line->points;

    if (!l->actions) return;

    state = l->state;

    nactive = 0;
    for (n = 0; n < 16; n++) {
        pt = &points[n];
        pt->active = state[n];
        if(state[n]) nactive++;
    }

    line->nactive = nactive;
    l->actions = 0;
}
3.3.16.6. Copying Page to Event Stack

Does the reverse of line16_state_apply. Call it... line16_state_copy.

<<line16_function_declarations>>=
static void line16_state_copy(page_line16_d *l);
<<line16_function_declarations>>=
static void line16_state_copy(page_line16_d *l)
{
    int n;
    line16_point *pt;
    unsigned char *state;
    int nactive;
    line16_point *points;
    line16_line *line;

    state = l->state;

    line = &l->lines[l->selected_line];
    points = line->points;

    nactive = 0;
    for (n = 0; n < 16; n++) {
        pt = &points[n];
        state[n] = pt->active;
        if (state[n]) nactive++;
    }
    line->nactive = nactive;
}

3.3.17. min/max durations

This will set the range of possible durations for the line segments.

<<page_line16_contents>>=
GFFLT min;
GFFLT max;
<<line16_init>>=
line16_dur_min_set(line16, 0.1);
line16_dur_max_set(line16, 10);

These are accessible through setters and getters, defined below.

<<line16_function_declarations>>=
static void line16_dur_min_set(page_line16_d *l, GFFLT val);
static void line16_dur_max_set(page_line16_d *l, GFFLT val);
<<line16_functions>>=
static void line16_dur_min_set(page_line16_d *l, GFFLT val)
{
    l->min = val;
}
static void line16_dur_max_set(page_line16_d *l, GFFLT val)
{
    l->max = val;
}
<<line16_function_declarations>>=
static GFFLT line16_dur_min_get(page_line16_d *l);
static GFFLT line16_dur_max_get(page_line16_d *l);
<<line16_functions>>=
static GFFLT line16_dur_min_get(page_line16_d *l)
{
    return l->min;
}
static GFFLT line16_dur_max_get(page_line16_d *l)
{
    return l->max;
}

3.3.18. Aux Cache

3.3.18.1. Struct Contents

Any time a point changes, the point A's aux values at that point in time are saved. As a result, the nodes setting naturally go through a kind of sample and hold. Holding onto values for the duration of the line is more musical than if it were constantly changing because it allows more contrast to happen.

<<page_line16_contents>>=
GFFLT aux_cache[2];
<<line16_init>>=
line16->aux_cache[0] = 0;
line16->aux_cache[1] = 0;
3.3.18.2. Updating The Aux Cache

Any time the line is updated, the cache, too needs to be updated. This is done with line16_aux_cache_update.

<<line16_function_declarations>>=
static void line16_aux_cache_udpate(page_line16_d *l);
<<line16_functions>>=
static void line16_aux_cache_udpate(page_line16_d *l)
{
    line16_point *pt_a;
    pt_a = line16_get_point(l, l->pointpos);
    if(pt_a == NULL) return;

    l->aux_cache[0] = pt_a->aux[0];
    l->aux_cache[1] = pt_a->aux[1];
}

CLOSED: [2019-08-24 Sat 13:58]

3.3.19. Trigger Flag

This gets set every time there is a trigger, and is used to start a line up that waits for a trigger. When a trigger occurs, the sample position is stored.

<<page_line16_contents>>=
int trig;
<<line16_init>>=
line16->trig = -1;

3.4. Line16 Typedef Declaration

All line16 page data is contained in a struct called page_line16_d.

<<line16_typedefs>>=
typedef struct page_line16_d page_line16_d;
<<line16_struct>>=
struct page_line16_d {
<<page_line16_contents>>
};

3.5. Line16 Data Allocation/Initialization

Line16 data is initiatlized with the function page_line16_init.

<<line16_function_declarations>>=
static void page_line16_init(monolith_page *pg, page_line16_d *line16);
<<line16_functions>>=
static void page_line16_init(monolith_page *pg, page_line16_d *line16)
{
    int i;
    gf_patch *patch;

    patch = monolith_page_graforge(pg);
<<line16_init>>
    line16_redraw_points(line16);
    line16_select_point(line16, line16->selected_point);
}

3.6. Line16 Data Cleanup

Line16 data is freed with the funciton page_line16_free.

<<line16_function_declarations>>=
static void page_line16_cleanup(page_line16_d *line16);
<<line16_functions>>=
static void page_line16_cleanup(page_line16_d *line16)
{
<<line16_cleanup>>
}



prev | home | next