Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

We’re showing branches in this repository, but you can also compare across forks.

base fork: m-labs/flickernoise
base: 3437cec^
...
head fork: m-labs/flickernoise
compare: e2bebe0
  • 12 commits
  • 13 files changed
  • 0 commit comments
  • 1 contributor
2  src/Makefile
View
@@ -61,7 +61,7 @@ ifeq ($(WITH_PDF),1)
endif
OBJS += $(addprefix translations/,french.o german.o)
OBJS += $(addprefix renderer/,framedescriptor.o analyzer.o sampler.o \
- eval.o line.o wave.o font.o osd.o raster.o renderer.o \
+ eval.o line.o wave.o font.o osd.o raster.o renderer.o stimuli.o \
videoinreconf.o)
OBJS += $(addprefix compiler/,compiler.o parser_helper.o scanner.o \
parser.o symtab.o)
35 src/compiler/compiler.c
View
@@ -187,13 +187,16 @@ static void all_initials_to_pfv(struct compiler_sc *sc)
static void pfv_bind_callback(void *_sc, struct fpvm_sym *sym, int reg)
{
struct compiler_sc *sc = _sc;
+ struct sym *s = FPVM2SYM(sym);
int pfv;
- pfv = pfv_from_sym(FPVM2SYM(sym));
+ pfv = pfv_from_sym(s);
if(pfv >= 0) {
pfv_update_patch_requires(sc, pfv);
sc->p->pfv_allocation[pfv] = reg;
}
+ if(s->cvar != -1)
+ sc->p->cvars[s->cvar].pfv_reg = reg;
}
static bool init_pfv(struct compiler_sc *sc)
@@ -265,13 +268,16 @@ static void pvv_update_patch_requires(struct compiler_sc *sc, int pvv)
static void pvv_bind_callback(void *_sc, struct fpvm_sym *sym, int reg)
{
struct compiler_sc *sc = _sc;
+ struct sym *s = FPVM2SYM(sym);
int pvv;
- pvv = pvv_from_sym(FPVM2SYM(sym));
+ pvv = pvv_from_sym(s);
if(pvv >= 0) {
pvv_update_patch_requires(sc, pvv);
sc->p->pvv_allocation[pvv] = reg;
}
+ if(s->cvar != -1)
+ sc->p->cvars[s->cvar].pvv_reg = reg;
}
static bool init_pvv(struct compiler_sc *sc)
@@ -483,6 +489,9 @@ struct patch *patch_compile(const char *basedir, const char *patch_code,
sc->p->require = 0;
sc->p->original = NULL;
sc->p->next = NULL;
+ sc->p->stim = NULL;
+ sc->p->ncvars = 0;
+ sc->p->cvars = NULL;
sc->basedir = basedir;
sc->rmc = rmc;
@@ -534,6 +543,18 @@ struct patch *patch_compile_filename(const char *filename,
return p;
}
+struct cvar *patch_add_cvar(struct patch *p)
+{
+ struct cvar *cv;
+
+ p->ncvars++;
+ p->cvars = realloc(p->cvars, sizeof(struct cvar)*p->ncvars);
+ cv = p->cvars+p->ncvars-1;
+ cv->val = 0;
+ cv->pfv_reg = cv->pvv_reg = -1;
+ return cv;
+}
+
#ifndef STANDALONE
struct patch *patch_copy(struct patch *p)
@@ -553,6 +574,14 @@ struct patch *patch_copy(struct patch *p)
img->filename = strdup(img->filename);
pixbuf_inc_ref(img->pixbuf);
}
+ new_patch->stim = stim_get(p->stim);
+ if(p->ncvars) {
+ size_t size = p->ncvars*sizeof(struct cvar);
+
+ new_patch->cvars = malloc(size);
+ memcpy(new_patch->cvars, p->cvars, size);
+ }
+ stim_redirect(p->stim, &p->cvars->val, &new_patch->cvars->val);
return new_patch;
}
@@ -567,6 +596,8 @@ void patch_free(struct patch *p)
pixbuf_dec_ref(img->pixbuf);
free((void *) img->filename);
}
+ stim_put(p->stim);
+ free(p->cvars);
free(p);
}
58 src/compiler/compiler.h
View
@@ -30,6 +30,7 @@
#include <fpvm/fpvm.h>
#include "../renderer/framedescriptor.h"
+#include "../renderer/stimuli.h"
#include "../pixbuf/pixbuf.h"
enum {
@@ -225,31 +226,56 @@ struct image {
struct stat st;
};
+struct cvar {
+ float val; /* current value */
+ int pfv_reg; /* per-frame register */
+ int pvv_reg; /* per-vertex register */
+};
+
struct patch {
/* per-frame */
- struct image images[IMAGE_COUNT]; /* < images used in this patch */
- float pfv_initial[COMP_PFV_COUNT]; /* < patch initial conditions */
- int pfv_allocation[COMP_PFV_COUNT]; /* < where per-frame variables are mapped in PFPU regf, -1 if unmapped */
- int perframe_prog_length; /* < how many instructions in perframe_prog */
- unsigned int perframe_prog[PFPU_PROGSIZE]; /* < PFPU per-frame microcode */
- float perframe_regs[PFPU_REG_COUNT]; /* < PFPU initial per-frame regf */
+ struct image images[IMAGE_COUNT]; /* images used in this patch */
+ float pfv_initial[COMP_PFV_COUNT]; /* patch initial conditions */
+ int pfv_allocation[COMP_PFV_COUNT]; /* where per-frame variables
+ are mapped in PFPU regf,
+ -1 if unmapped */
+ int perframe_prog_length; /* how many instructions in
+ perframe_prog */
+ unsigned int perframe_prog[PFPU_PROGSIZE];
+ /* PFPU per-frame microcode */
+ float perframe_regs[PFPU_REG_COUNT]; /* PFPU initial per-frame
+ register file */
/* per-vertex */
- int pvv_allocation[COMP_PVV_COUNT]; /* < where per-vertex variables are mapped in PFPU regf, -1 if unmapped */
- int pervertex_prog_length; /* < how many instructions in pervertex_prog */
- unsigned int pervertex_prog[PFPU_PROGSIZE]; /* < PFPU per-vertex microcode */
- float pervertex_regs[PFPU_REG_COUNT]; /* < PFPU initial per-vertex regf */
+ int pvv_allocation[COMP_PVV_COUNT]; /* where per-vertex variables
+ are mapped in PFPU regf,
+ -1 if unmapped */
+ int pervertex_prog_length; /* how many instructions in
+ pervertex_prog */
+ unsigned int pervertex_prog[PFPU_PROGSIZE];
+ /* PFPU per-vertex microcode */
+ float pervertex_regs[PFPU_REG_COUNT]; /* PFPU initial per-vertex
+ regf */
/* meta */
- unsigned int require; /* < bitmask: dmx, osc, midi, video */
- void *original; /* < original patch (with initial register values) */
- int ref; /* reference count */
- struct patch *next; /* < used when chaining patches in mashups */
+ unsigned int require; /* bitmask: dmx, osc, midi, video */
+ void *original; /* original patch (with initial register
+ values) */
+ int ref; /* reference count */
+ struct patch *next; /* used when chaining patches in mashups */
+
+ /* unified input events */
+ struct stimuli *stim; /* control variable hierarchy */
+ int ncvars; /* number of control variables */
+ struct cvar *cvars; /* control variables */
};
typedef void (*report_message)(const char *);
void init_fpvm(struct fpvm_fragment *fragment, int vector_mode);
-struct patch *patch_compile(const char *basedir, const char *patch_code, report_message rmc);
-struct patch *patch_compile_filename(const char *filename, const char *patch_code, report_message rmc);
+struct patch *patch_compile(const char *basedir, const char *patch_code,
+ report_message rmc);
+struct patch *patch_compile_filename(const char *filename,
+ const char *patch_code, report_message rmc);
+struct cvar *patch_add_cvar(struct patch *p);
struct patch *patch_copy(struct patch *p);
void patch_free(struct patch *p);
struct patch *patch_refresh(struct patch *p);
1  src/compiler/idgen
View
@@ -51,6 +51,7 @@ sed 's/#.*//;/^ *$/d' $1 | LANG=C sort | {
.pfv_idx = $2,
.pvv_idx = $3,
.flags = SF_SYSTEM,
+ .cvar = -1,
},
EOF
i=`expr $i + 1`
33 src/compiler/parser.y
View
@@ -28,9 +28,9 @@
#include <fpvm/fpvm.h>
#include "symtab.h"
+#include "parser.h"
#include "parser_itf.h"
#include "parser_helper.h"
-#include "parser.h"
struct yyParser;
@@ -295,6 +295,36 @@ assignment ::= ident(I) TOK_ASSIGN expr(N) opt_semi. {
parse_free(N);
}
+assignment ::= ident(I) TOK_ASSIGN TOK_MIDI TOK_LPAREN expr(A) TOK_COMMA
+ expr(B) TOK_RPAREN opt_semi. {
+ /* @@@ clean up this mess later */
+ struct patch *p = *(struct patch **) state->comm->u.sc;
+ struct sym *sym = I->sym;
+ struct cvar *cvar;
+
+ free(I);
+ if(sym->cvar != -1) {
+ FAIL("duplicate control variable");
+ return;
+ }
+ if(A->op != op_constant || B->op != op_constant) {
+ FAIL("midi(chan, ctrl) arguments must be constants");
+ return;
+ }
+ cvar = patch_add_cvar(p);
+ sym->cvar = cvar-p->cvars;
+ if(!p->stim)
+ p->stim = stim_new();
+ /* @@@ check range ! */
+ if(!stim_add(p->stim, A->contents.constant, B->contents.constant,
+ &cvar->val, midi_proc_lin)) {
+ FAIL("stim_add failed\n");
+ return;
+ }
+ parse_free(A);
+ parse_free(B);
+}
+
assignment ::= TOK_IMAGEFILE(I) TOK_ASSIGN TOK_FNAME(N). {
const char *msg;
@@ -581,6 +611,7 @@ ident(O) ::= unary_misc(I). { O = symbolify(I); }
ident(O) ::= binary(I). { O = symbolify(I); }
ident(O) ::= binary_misc(I). { O = symbolify(I); }
ident(O) ::= ternary(I). { O = symbolify(I); }
+ident(O) ::= TOK_MIDI(I). { O = symbolify(I); }
unary_misc(O) ::= TOK_ABS(I). { O = I; }
unary_misc(O) ::= TOK_COS(I). { O = I; }
5 src/compiler/ptest/Makefile
View
@@ -5,7 +5,7 @@ LIBFPVM_X86 = $(MMDIR)/software/libfpvm/x86-linux
CFLAGS_STANDALONE = -DSTANDALONE=\"standalone.h\"
CFLAGS = -Wall -g -I.. -I. $(CFLAGS_STANDALONE)
OBJS = ptest.o scanner.o parser.o parser_helper.o symtab.o compiler.o \
- libfpvm.a
+ stimuli.o libfpvm.a
LDLIBS = -lm
# ----- Verbosity control -----------------------------------------------------
@@ -42,6 +42,9 @@ ptest: $(OBJS)
%.o: ../%.c
$(CC) $(CFLAGS) -c -o $@ $<
+stimuli.o: ../../renderer/stimuli.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
%.c: %.re
$(GEN) re2c -c -o $@ $<
2  src/compiler/scanner.re
View
@@ -130,6 +130,8 @@ int scan(struct scanner *s)
<N>"per_pixel"[a-z_0-9]*
{ return TOK_PER_PIXEL_UGLY; }
+ <N>"midi" { return TOK_MIDI; }
+
<N>"imagefile"[1-9] { YYSETCONDITION(yycFNAME1);
return TOK_IMAGEFILE; }
2  src/compiler/symtab.c
View
@@ -107,6 +107,7 @@ struct sym *unique(const char *s)
new->fpvm_sym.name = strdup(s);
new->pfv_idx = new->pvv_idx = -1;
new->flags = 0;
+ new->cvar = -1;
return new;
}
@@ -132,6 +133,7 @@ struct sym *unique_n(const char *s, int n)
new->fpvm_sym.name = strdup_n(s, n);
new->pfv_idx = new->pvv_idx = -1;
new->flags = 0;
+ new->cvar = -1;
return new;
}
2  src/compiler/symtab.h
View
@@ -12,6 +12,7 @@
#define SYMTAB_H
#include <fpvm/symbol.h>
+#include "compiler.h"
#define SF_SYSTEM (1 << 0)
@@ -21,6 +22,7 @@
struct sym {
struct fpvm_sym fpvm_sym;
int pfv_idx, pvv_idx; /* index; -1 if not a variable known to FN */
+ int cvar; /* -1 if not a control variable */
int flags;
};
13 src/renderer/eval.c
View
@@ -58,6 +58,8 @@ static void write_pvv(struct patch *p, int pvv, float x)
static void transfer_pvv_regs(struct patch *p)
{
+ const struct cvar *cv;
+
write_pvv(p, pvv_texsize, renderer_texsize << TMU_FIXEDPOINT_SHIFT);
write_pvv(p, pvv_hmeshsize, 1.0/(float)renderer_hmeshlast);
write_pvv(p, pvv_vmeshsize, 1.0/(float)renderer_vmeshlast);
@@ -115,6 +117,10 @@ static void transfer_pvv_regs(struct patch *p)
write_pvv(p, pvv_midi6, read_pfv(p, pfv_midi6));
write_pvv(p, pvv_midi7, read_pfv(p, pfv_midi7));
write_pvv(p, pvv_midi8, read_pfv(p, pfv_midi8));
+
+ for(cv = p->cvars; cv != p->cvars+p->ncvars; cv++)
+ if(cv->pvv_reg >= 0)
+ p->pervertex_regs[cv->pvv_reg] = cv->val;
}
static void reinit_pfv(struct patch *p, int pfv)
@@ -129,12 +135,15 @@ static void reinit_pfv(struct patch *p, int pfv)
static void reinit_all_pfv(struct patch *p)
{
int i;
+
for(i=0;i<COMP_PFV_COUNT;i++)
reinit_pfv(p, i);
}
static void set_pfv_from_frd(struct patch *p, struct frame_descriptor *frd)
{
+ const struct cvar *cv;
+
write_pfv(p, pfv_time, frd->time);
write_pfv(p, pfv_frame, frd->frame);
write_pfv(p, pfv_bass, frd->bass);
@@ -166,6 +175,10 @@ static void set_pfv_from_frd(struct patch *p, struct frame_descriptor *frd)
write_pfv(p, pfv_midi6, frd->midi[5]);
write_pfv(p, pfv_midi7, frd->midi[6]);
write_pfv(p, pfv_midi8, frd->midi[7]);
+
+ for(cv = p->cvars; cv != p->cvars+p->ncvars; cv++)
+ if(cv->pfv_reg >= 0)
+ p->perframe_regs[cv->pfv_reg] = cv->val;
}
static void set_frd_from_pfv(struct patch *p, struct frame_descriptor *frd)
51 src/renderer/sampler.c
View
@@ -31,6 +31,8 @@
#include "../osc.h"
#include "../config.h"
#include "../input.h"
+#include "renderer.h"
+#include "stimuli.h"
#include "sampler.h"
struct snd_history {
@@ -261,19 +263,52 @@ static rtems_task sampler_task(rtems_task_argument argument)
rtems_task_delete(RTEMS_SELF);
}
+static void midi_ctrl_event(struct patch *p, mtk_event *e)
+{
+ int chan, ctrl, value;
+
+ chan = (e->press.code & 0x0f0000) >> 16;
+ ctrl = (e->press.code & 0x7f00) >> 8;
+ value = e->press.code & 0x7f;
+
+ if(chan == midi_channel)
+ midi_controllers[ctrl] = value;
+ stim_midi_ctrl(p->stim, chan, ctrl, value);
+}
+
+/*
+ * @@@ convert pitch events to stimuli later. Need to decide whether giving
+ * them another stimulus type or using the control #128 hack.
+ */
+
+static void midi_pitch_event(mtk_event *e)
+{
+ int chan, value;
+
+ chan = (e->press.code & 0x0f0000) >> 16;
+ value = e->press.code & 0x7f;
+
+ if(chan == midi_channel)
+ midi_controllers[128] = value;
+}
+
static void event_callback(mtk_event *e, int count)
{
+ struct patch *p;
int i;
- for(i=0;i<count;i++) {
- if(e[i].type == EVENT_TYPE_MIDI_CONTROLLER) {
- if(((e[i].press.code & 0x0f0000) >> 16) == midi_channel)
- midi_controllers[(e[i].press.code & 0x7f00) >> 8] = e[i].press.code & 0x7f;
- } else if(e[i].type == EVENT_TYPE_MIDI_PITCH) {
- if(((e[i].press.code & 0x0f0000) >> 16) == midi_channel)
- midi_controllers[128] = e[i].press.code & 0x7f;
+ renderer_lock_patch();
+ p = renderer_get_patch(0);
+ for(i=0;i<count;i++)
+ switch(e[i].type) {
+ case EVENT_TYPE_MIDI_CONTROLLER:
+ midi_ctrl_event(p, e+i);
+ break;
+ case EVENT_TYPE_MIDI_PITCH:
+ midi_pitch_event(e+i);
+ break;
}
- }
+ renderer_unlock_patch();
}
static rtems_id sampler_task_id;
126 src/renderer/stimuli.c
View
@@ -0,0 +1,126 @@
+/*
+ * stimuli.c - Unified control input handling
+ *
+ * Copyright 2012 by Werner Almesberger
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "stimuli.h"
+
+
+void midi_proc_lin(struct s_midi_ctrl *ct, int value)
+{
+ *ct->var = (float) value/127.0;
+}
+
+
+void midi_proc_accel(struct s_midi_ctrl *ct, int value)
+{
+ if(value < 64) {
+ ct->last += value;
+ if(ct->last > 127)
+ ct->last = 127;
+ } else {
+ ct->last -= 128-value;
+ if(ct->last & 0x80)
+ ct->last = 0;
+ }
+ *ct->var = (float) ct->last/127.0;
+}
+
+
+void stim_midi_ctrl(struct stimuli *s, int chan, int ctrl, int value)
+{
+ struct s_midi_ctrl *ct;
+
+ if(s && s->midi[chan]) {
+ ct = s->midi[chan]->ctrl[ctrl];
+ if(ct)
+ ct->proc(ct, value);
+ }
+}
+
+
+int stim_add(struct stimuli *s, int chan, int ctrl, float *var,
+ void (*proc)(struct s_midi_ctrl *ct, int value))
+{
+ struct s_midi_chan *ch;
+ struct s_midi_ctrl *ct;
+
+ if(!s->midi[chan]) {
+ s->midi[chan] = calloc(1, sizeof(struct s_midi_chan));
+ if(!s->midi[chan])
+ return 0;
+ }
+ ch = s->midi[chan];
+
+ if(!ch->ctrl[ctrl]) {
+ ch->ctrl[ctrl] = calloc(1, sizeof(struct s_midi_ctrl));
+ if(!ch->ctrl[ctrl])
+ return 0;
+ }
+ ct = ch->ctrl[ctrl];
+
+ ct->proc = proc;
+ ct->var = var;
+
+ return 1;
+}
+
+
+struct stimuli *stim_new(void)
+{
+ struct stimuli *s;
+
+ s = calloc(1, sizeof(struct stimuli));
+ if(s)
+ s->ref = 1;
+ return s;
+}
+
+
+struct stimuli *stim_get(struct stimuli *s)
+{
+ if(s)
+ s->ref++;
+ return s;
+}
+
+void stim_put(struct stimuli *s)
+{
+ int i, j;
+
+ if(!s)
+ return;
+ if(--s->ref)
+ return;
+ for(i = 0; i != MIDI_CHANS; i++)
+ if(s->midi[i]) {
+ for(j = 0; j != MIDI_CTRLS; j++)
+ free(s->midi[i]->ctrl[j]);
+ free(s->midi[i]);
+ }
+ free(s);
+}
+
+void stim_redirect(struct stimuli *s, const float *old, float *new)
+{
+ int i, j;
+ struct s_midi_ctrl *ct;
+
+ if(!s)
+ return;
+ for(i = 0; i != MIDI_CHANS; i++)
+ if(s->midi[i])
+ for(j = 0; j != MIDI_CTRLS; j++) {
+ ct = s->midi[i]->ctrl[j];
+ if (ct)
+ ct->var = new+(ct->var-old);
+ }
+}
51 src/renderer/stimuli.h
View
@@ -0,0 +1,51 @@
+/*
+ * stimuli.h - Unified control input handling
+ *
+ * Copyright 2012 by Werner Almesberger
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ */
+
+#ifndef STIMULI_H
+#define STIMULI_H
+
+#include <stdint.h>
+
+
+#define MIDI_CHANS 16
+#define MIDI_CTRLS 128
+
+
+struct s_midi_ctrl {
+ void (*proc)(struct s_midi_ctrl *sct, int value);
+ float *var;
+ uint8_t last; /* for midi_proc_accel */
+};
+
+struct s_midi_chan {
+ struct s_midi_ctrl *ctrl[MIDI_CTRLS];
+};
+
+struct stimuli {
+ struct s_midi_chan *midi[MIDI_CHANS];
+ int ref;
+};
+
+
+/* Linear mapping [0, 127] -> [0, 1] */
+void midi_proc_lin(struct s_midi_ctrl *ct, int value);
+
+/* "Acceleration" (signed 7 bit delta value) with linear mapping */
+void midi_proc_accel(struct s_midi_ctrl *ct, int value);
+
+void stim_midi_ctrl(struct stimuli *s, int chan, int ctrl, int value);
+int stim_add(struct stimuli *s, int chan, int ctrl, float *var,
+ void (*proc)(struct s_midi_ctrl *ct, int value));
+struct stimuli *stim_new(void);
+struct stimuli *stim_get(struct stimuli *s);
+void stim_put(struct stimuli *s);
+void stim_redirect(struct stimuli *s, const float *old, float *new);
+
+#endif /* STIMULI_H */

No commit comments for this range

Something went wrong with that request. Please try again.