aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHanspeter Portner <dev@open-music-kontrollers.ch>2017-03-19 15:33:01 +0100
committerHanspeter Portner <dev@open-music-kontrollers.ch>2017-03-19 15:33:01 +0100
commit272d71acb6b97df57a1b27ed3ca9e8db370e146e (patch)
treefb9912b3d726a772fa428927663e7d2dcc0a326e
parente7db12af0954a831527b05476a9961219d9154ff (diff)
downloadvm.lv2-272d71acb6b97df57a1b27ed3ca9e8db370e146e.tar.xz
implement registry, more opcodes, presets.
-rw-r--r--vm.c298
-rw-r--r--vm.h116
-rw-r--r--vm.ttl141
-rw-r--r--vm_ui.c72
4 files changed, 524 insertions, 103 deletions
diff --git a/vm.c b/vm.c
index 9fc96b4..5e8eaed 100644
--- a/vm.c
+++ b/vm.c
@@ -22,13 +22,17 @@
#include <vm.h>
-#define SLOT_MAX 64
+#define SLOT_MAX 32
+#define REG_MAX 32
typedef struct _stack_t stack_t;
typedef struct _plughandle_t plughandle_t;
+typedef double num_t;
+
struct _stack_t {
- float slots [SLOT_MAX];
+ num_t slots [SLOT_MAX];
+ num_t regs [REG_MAX];
};
struct _plughandle_t {
@@ -36,6 +40,8 @@ struct _plughandle_t {
LV2_Atom_Forge forge;
LV2_Atom_Forge_Ref ref;
+ LV2_URID vm_graph;
+
LV2_Log_Log *log;
LV2_Log_Logger logger;
@@ -44,8 +50,8 @@ struct _plughandle_t {
const float *in [CTRL_MAX];
float *out [CTRL_MAX];
- float in0 [CTRL_MAX];
- float out0 [CTRL_MAX];
+ num_t in0 [CTRL_MAX];
+ num_t out0 [CTRL_MAX];
PROPS_T(props, MAX_NPROPS);
plugstate_t state;
@@ -56,8 +62,13 @@ struct _plughandle_t {
stack_t stack;
bool recalc;
+ bool sync;
+ bool is_dynamic;
command_t cmds [ITEMS_MAX];
+
+ num_t srate;
+ int64_t frame;
};
static inline void
@@ -68,18 +79,18 @@ _stack_clear(stack_t *stack)
}
static inline void
-_stack_push(stack_t *stack, float val)
+_stack_push(stack_t *stack, num_t val)
{
- for(unsigned i = SLOT_MAX - 1; i > 0; i--)
+ for(unsigned i = SLOT_MAX - 1; i >= 1; i--)
stack->slots[i] = stack->slots[i - 1];
stack->slots[0] = val;
}
-static inline float
+static inline num_t
_stack_pop(stack_t *stack)
{
- const float val = stack->slots[0];
+ const num_t val = stack->slots[0];
for(unsigned i = 0; i < SLOT_MAX - 1; i++)
stack->slots[i] = stack->slots[i + 1];
@@ -90,9 +101,9 @@ _stack_pop(stack_t *stack)
}
static inline void
-_stack_push_num(stack_t *stack, const float *val, unsigned num)
+_stack_push_num(stack_t *stack, const num_t *val, unsigned num)
{
- for(unsigned i = SLOT_MAX - num; i > 0; i--)
+ for(unsigned i = SLOT_MAX - 1; i >= num; i--)
stack->slots[i] = stack->slots[i - num];
for(unsigned i = 0; i < num; i++)
@@ -100,7 +111,7 @@ _stack_push_num(stack_t *stack, const float *val, unsigned num)
}
static inline void
-_stack_pop_num(stack_t *stack, float *val, unsigned num)
+_stack_pop_num(stack_t *stack, num_t *val, unsigned num)
{
for(unsigned i = 0; i < num; i++)
val[i] = stack->slots[i];
@@ -112,6 +123,14 @@ _stack_pop_num(stack_t *stack, float *val, unsigned num)
stack->slots[i] = 0.f;
}
+static inline num_t
+_stack_peek(stack_t *stack)
+{
+ const num_t val = stack->slots[0];
+
+ return val;
+}
+
static void
_intercept_graph(void *data, LV2_Atom_Forge *forge, int64_t frames,
props_event_t event, props_impl_t *impl)
@@ -121,8 +140,10 @@ _intercept_graph(void *data, LV2_Atom_Forge *forge, int64_t frames,
handle->graph_size = impl->value.size;
handle->recalc = true;
- vm_deserialize(&handle->opcode, &handle->forge, handle->cmds,
+ handle->is_dynamic = vm_deserialize(&handle->opcode, &handle->forge, handle->cmds,
impl->value.size, impl->value.body);
+
+ handle->sync = true;
}
static const props_def_t defs [MAX_NPROPS] = {
@@ -137,7 +158,7 @@ static const props_def_t defs [MAX_NPROPS] = {
};
static LV2_Handle
-instantiate(const LV2_Descriptor* descriptor, double rate,
+instantiate(const LV2_Descriptor* descriptor, num_t rate,
const char *bundle_path, const LV2_Feature *const *features)
{
plughandle_t *handle = calloc(1, sizeof(plughandle_t));
@@ -163,6 +184,8 @@ instantiate(const LV2_Descriptor* descriptor, double rate,
if(handle->log)
lv2_log_logger_init(&handle->logger, handle->map, handle->log);
+ handle->vm_graph = handle->map->map(handle->map->handle, VM__graph);
+
lv2_atom_forge_init(&handle->forge, handle->map);
vm_opcode_init(&handle->opcode, handle->map);
@@ -181,6 +204,7 @@ instantiate(const LV2_Descriptor* descriptor, double rate,
}
handle->recalc = true;
+ handle->srate = rate;
return handle;
}
@@ -240,6 +264,12 @@ run(LV2_Handle instance, uint32_t nsamples)
props_advance(&handle->props, &handle->forge, ev->time.frames, obj, &handle->ref);
}
+ if(handle->sync)
+ {
+ props_set(&handle->props, &handle->forge, nsamples - 1, handle->vm_graph, &handle->ref);
+ handle->sync = false;
+ }
+
for(unsigned i = 0; i < CTRL_MAX; i++)
{
if(handle->in0[i] != *handle->in[i])
@@ -249,7 +279,7 @@ run(LV2_Handle instance, uint32_t nsamples)
}
}
- if(handle->recalc)
+ if(handle->recalc || handle->is_dynamic)
{
_stack_clear(&handle->stack);
@@ -262,144 +292,294 @@ run(LV2_Handle instance, uint32_t nsamples)
{
case COMMAND_BOOL:
{
- const float c = cmd->i32;
+ const num_t c = cmd->i32;
_stack_push(&handle->stack, c);
} break;
case COMMAND_INT:
{
- const float c = cmd->i32;
+ const num_t c = cmd->i32;
_stack_push(&handle->stack, c);
} break;
case COMMAND_LONG:
{
- const float c = cmd->i64;
+ const num_t c = cmd->i64;
_stack_push(&handle->stack, c);
} break;
case COMMAND_FLOAT:
{
- const float c = cmd->f32;
+ const num_t c = cmd->f32;
_stack_push(&handle->stack, c);
} break;
case COMMAND_DOUBLE:
{
- const float c = cmd->f64;
+ const num_t c = cmd->f64;
_stack_push(&handle->stack, c);
} break;
case COMMAND_OPCODE:
{
switch(cmd->op)
{
- case OP_PUSH:
+ case OP_CTRL:
{
- int j = floorf(_stack_pop(&handle->stack)); //FIXME check
- if(j < 0)
- j = 0;
- if(j >= CTRL_MAX)
- j = CTRL_MAX - 1;
+ int idx = floor(_stack_pop(&handle->stack)); //FIXME check
+ if(idx < 0)
+ idx = 0;
+ if(idx >= CTRL_MAX)
+ idx = CTRL_MAX - 1;
- const float c = handle->in0[j];
+ const num_t c = handle->in0[idx];
+ _stack_push(&handle->stack, c);
+ } break;
+ case OP_PUSH:
+ {
+ const num_t c = _stack_peek(&handle->stack);
_stack_push(&handle->stack, c);
} break;
case OP_ADD:
{
- float ab [2];
+ num_t ab [2];
_stack_pop_num(&handle->stack, ab, 2);
- const float c = ab[0] + ab[1];
+ const num_t c = ab[1] + ab[0];
_stack_push(&handle->stack, c);
} break;
case OP_SUB:
{
- float ab [2];
+ num_t ab [2];
_stack_pop_num(&handle->stack, ab, 2);
- const float c = ab[0] - ab[1];
+ const num_t c = ab[1] - ab[0];
_stack_push(&handle->stack, c);
} break;
case OP_MUL:
{
- float ab [2];
+ num_t ab [2];
_stack_pop_num(&handle->stack, ab, 2);
- const float c = ab[0] * ab[1];
+ const num_t c = ab[1] * ab[0];
_stack_push(&handle->stack, c);
} break;
case OP_DIV:
{
- float ab [2];
+ num_t ab [2];
_stack_pop_num(&handle->stack, ab, 2);
- const float c = ab[0] / ab[1];
+ const num_t c = ab[0] == 0.0
+ ? 0.0
+ : ab[1] / ab[0];
_stack_push(&handle->stack, c);
} break;
case OP_NEG:
{
- const float a = _stack_pop(&handle->stack);
- const float c = -a;
+ const num_t a = _stack_pop(&handle->stack);
+ const num_t c = -a;
+ _stack_push(&handle->stack, c);
+ } break;
+ case OP_ABS:
+ {
+ const num_t a = _stack_pop(&handle->stack);
+ const num_t c = fabs(a);
_stack_push(&handle->stack, c);
} break;
case OP_POW:
{
- float ab [2];
+ num_t ab [2];
_stack_pop_num(&handle->stack, ab, 2);
- const float c = pow(ab[0], ab[1]);
+ const num_t c = pow(ab[1], ab[0]);
_stack_push(&handle->stack, c);
} break;
case OP_SQRT:
{
- const float a = _stack_pop(&handle->stack);
- const float c = sqrtf(a);
+ const num_t a = _stack_pop(&handle->stack);
+ const num_t c = sqrt(a);
+ _stack_push(&handle->stack, c);
+ } break;
+ case OP_MOD:
+ {
+ num_t ab [2];
+ _stack_pop_num(&handle->stack, ab, 2);
+ const num_t c = ab[0] == 0.0
+ ? 0.0
+ : fmod(ab[1], ab[0]);
_stack_push(&handle->stack, c);
} break;
case OP_EXP:
{
- const float a = _stack_pop(&handle->stack);
- const float c = expf(a);
+ const num_t a = _stack_pop(&handle->stack);
+ const num_t c = exp(a);
_stack_push(&handle->stack, c);
} break;
case OP_EXP_2:
{
- const float a = _stack_pop(&handle->stack);
- const float c = exp2f(a);
+ const num_t a = _stack_pop(&handle->stack);
+ const num_t c = exp2(a);
_stack_push(&handle->stack, c);
} break;
case OP_EXP_10:
{
- const float a = _stack_pop(&handle->stack);
- const float c = exp10f(a);
+ const num_t a = _stack_pop(&handle->stack);
+ const num_t c = exp10(a);
_stack_push(&handle->stack, c);
} break;
case OP_LOG:
{
- const float a = _stack_pop(&handle->stack);
- const float c = logf(a);
+ const num_t a = _stack_pop(&handle->stack);
+ const num_t c = log(a);
_stack_push(&handle->stack, c);
} break;
case OP_LOG_2:
{
- const float a = _stack_pop(&handle->stack);
- const float c = log2f(a);
+ const num_t a = _stack_pop(&handle->stack);
+ const num_t c = log2(a);
_stack_push(&handle->stack, c);
} break;
case OP_LOG_10:
{
- const float a = _stack_pop(&handle->stack);
- const float c = log10f(a);
+ const num_t a = _stack_pop(&handle->stack);
+ const num_t c = log10(a);
_stack_push(&handle->stack, c);
} break;
case OP_SIN:
{
- const float a = _stack_pop(&handle->stack);
- const float c = sinf(a);
+ const num_t a = _stack_pop(&handle->stack);
+ const num_t c = sin(a);
_stack_push(&handle->stack, c);
} break;
case OP_COS:
{
- const float a = _stack_pop(&handle->stack);
- const float c = cosf(a);
+ const num_t a = _stack_pop(&handle->stack);
+ const num_t c = cos(a);
_stack_push(&handle->stack, c);
} break;
case OP_SWAP:
{
- float ab [2];
+ num_t ab [2];
+ _stack_pop_num(&handle->stack, ab, 2);
+ const num_t cd [2] = {ab[1], ab[0]};
+ _stack_push_num(&handle->stack, cd, 2);
+ } break;
+ case OP_FRAME:
+ {
+ num_t c = handle->frame;
+ _stack_push(&handle->stack, c);
+ } break;
+ case OP_SRATE:
+ {
+ num_t c = handle->srate;
+ _stack_push(&handle->stack, c);
+ } break;
+ case OP_PI:
+ {
+ num_t c = M_PI;
+ _stack_push(&handle->stack, c);
+ } break;
+ case OP_EQ:
+ {
+ num_t ab [2];
_stack_pop_num(&handle->stack, ab, 2);
- _stack_push_num(&handle->stack, ab, 2);
+ const bool c = ab[1] == ab[0];
+ _stack_push(&handle->stack, c);
+ } break;
+ case OP_LT:
+ {
+ num_t ab [2];
+ _stack_pop_num(&handle->stack, ab, 2);
+ const bool c = ab[1] < ab[0];
+ _stack_push(&handle->stack, c);
+ } break;
+ case OP_GT:
+ {
+ num_t ab [2];
+ _stack_pop_num(&handle->stack, ab, 2);
+ const bool c = ab[1] > ab[0];
+ _stack_push(&handle->stack, c);
+ } break;
+ case OP_LE:
+ {
+ num_t ab [2];
+ _stack_pop_num(&handle->stack, ab, 2);
+ const bool c = ab[1] <= ab[0];
+ _stack_push(&handle->stack, c);
+ } break;
+ case OP_GE:
+ {
+ num_t ab [2];
+ _stack_pop_num(&handle->stack, ab, 2);
+ const bool c = ab[1] >= ab[0];
+ _stack_push(&handle->stack, c);
+ } break;
+ case OP_AND:
+ {
+ num_t ab [2];
+ _stack_pop_num(&handle->stack, ab, 2);
+ const bool c = ab[1] && ab[0];
+ _stack_push(&handle->stack, c);
+ } break;
+ case OP_OR:
+ {
+ num_t ab [2];
+ _stack_pop_num(&handle->stack, ab, 2);
+ const bool c = ab[1] || ab[0];
+ _stack_push(&handle->stack, c);
+ } break;
+ case OP_NOT:
+ {
+ const int a = _stack_pop(&handle->stack);
+ const bool c = !a;
+ _stack_push(&handle->stack, c);
+ } break;
+ case OP_BAND:
+ {
+ num_t ab [2];
+ _stack_pop_num(&handle->stack, ab, 2);
+ const unsigned a = ab[1];
+ const unsigned b = ab[0];
+ const unsigned c = a & b;
+ _stack_push(&handle->stack, c);
+ } break;
+ case OP_BOR:
+ {
+ num_t ab [2];
+ _stack_pop_num(&handle->stack, ab, 2);
+ const unsigned a = ab[1];
+ const unsigned b = ab[0];
+ const unsigned c = a | b;
+ _stack_push(&handle->stack, c);
+ } break;
+ case OP_BNOT:
+ {
+ const unsigned a = _stack_pop(&handle->stack);
+ const unsigned c = ~a;
+ _stack_push(&handle->stack, c);
+ } break;
+ case OP_TER:
+ {
+ num_t ab [3];
+ _stack_pop_num(&handle->stack, ab, 3);
+ const bool c = ab[0];
+ _stack_push(&handle->stack, c ? ab[2] : ab[1]);
+ } break;
+ case OP_STORE:
+ {
+ num_t ab [2];
+ _stack_pop_num(&handle->stack, ab, 2);
+
+ int idx = floorf(ab[0]);
+ if(idx < 0)
+ idx = 0;
+ if(idx >= REG_MAX)
+ idx = REG_MAX - 1;
+
+ handle->stack.regs[idx] = ab[1];
+ } break;
+ case OP_LOAD:
+ {
+ const num_t a = _stack_pop(&handle->stack);
+
+ int idx = floorf(a);
+ if(idx < 0)
+ idx = 0;
+ if(idx >= REG_MAX)
+ idx = REG_MAX - 1;
+
+ const num_t c = handle->stack.regs[idx];
+ _stack_push(&handle->stack, c);
} break;
case OP_NOP:
{
@@ -437,6 +617,8 @@ run(LV2_Handle instance, uint32_t nsamples)
for(unsigned i = 0; i < CTRL_MAX; i++)
*handle->out[i] = handle->out0[i];;
+
+ handle->frame += nsamples;
}
static void
diff --git a/vm.h b/vm.h
index 0986f85..3501630 100644
--- a/vm.h
+++ b/vm.h
@@ -38,14 +38,17 @@
#define VM__graph VM_PREFIX"graph"
#define VM__opNop VM_PREFIX"opNop"
+#define VM__opControl VM_PREFIX"opControl"
#define VM__opPush VM_PREFIX"opPush"
#define VM__opAdd VM_PREFIX"opAdd"
#define VM__opSub VM_PREFIX"opSub"
#define VM__opMul VM_PREFIX"opMul"
#define VM__opDiv VM_PREFIX"opDiv"
#define VM__opNeg VM_PREFIX"opNeg"
+#define VM__opAbs VM_PREFIX"opAbs"
#define VM__opPow VM_PREFIX"opPow"
#define VM__opSqrt VM_PREFIX"opSqrt"
+#define VM__opMod VM_PREFIX"opMod"
#define VM__opExp VM_PREFIX"opExp"
#define VM__opExp2 VM_PREFIX"opExp2"
#define VM__opExp10 VM_PREFIX"opExp10"
@@ -55,6 +58,23 @@
#define VM__opSin VM_PREFIX"opSin"
#define VM__opCos VM_PREFIX"opCos"
#define VM__opSwap VM_PREFIX"opSwap"
+#define VM__opFrame VM_PREFIX"opFrame"
+#define VM__opSampleRate VM_PREFIX"opSampleRate"
+#define VM__opPi VM_PREFIX"opPi"
+#define VM__opEq VM_PREFIX"opEq"
+#define VM__opLt VM_PREFIX"opLt"
+#define VM__opGt VM_PREFIX"opGt"
+#define VM__opLe VM_PREFIX"opLe"
+#define VM__opGe VM_PREFIX"opGe"
+#define VM__opAnd VM_PREFIX"opAnd"
+#define VM__opOr VM_PREFIX"opOr"
+#define VM__opNot VM_PREFIX"opNot"
+#define VM__opBAnd VM_PREFIX"opBAnd"
+#define VM__opBOr VM_PREFIX"opBOr"
+#define VM__opBNot VM_PREFIX"opBNot"
+#define VM__opTernary VM_PREFIX"opTernary"
+#define VM__opStore VM_PREFIX"opStore"
+#define VM__opLoad VM_PREFIX"opLoad"
#define MAX_NPROPS 1
#define CTRL_MAX 8
@@ -72,14 +92,17 @@ typedef struct _plugstate_t plugstate_t;
enum _opcode_enum_t{
OP_NOP = 0,
+ OP_CTRL,
OP_PUSH,
OP_ADD,
OP_SUB,
OP_MUL,
OP_DIV,
OP_NEG,
+ OP_ABS,
OP_POW,
OP_SQRT,
+ OP_MOD,
OP_EXP,
OP_EXP_2,
OP_EXP_10,
@@ -89,8 +112,25 @@ enum _opcode_enum_t{
OP_SIN,
OP_COS,
OP_SWAP,
-
- OP_MAX
+ OP_FRAME,
+ OP_SRATE,
+ OP_PI,
+ OP_EQ,
+ OP_LT,
+ OP_GT,
+ OP_LE,
+ OP_GE,
+ OP_AND,
+ OP_OR,
+ OP_NOT,
+ OP_BAND,
+ OP_BOR,
+ OP_BNOT,
+ OP_TER,
+ OP_STORE,
+ OP_LOAD,
+
+ OP_MAX,
};
enum _command_enum_t {
@@ -103,7 +143,7 @@ enum _command_enum_t {
COMMAND_FLOAT,
COMMAND_DOUBLE,
- COMMAND_MAX
+ COMMAND_MAX,
};
struct _opcode_t {
@@ -126,27 +166,52 @@ struct _plugstate_t {
uint8_t graph [GRAPH_SIZE];
};
+static const char *opcode_uris [OP_MAX] = {
+ [OP_NOP] = VM__opNop,
+ [OP_CTRL] = VM__opControl,
+ [OP_PUSH] = VM__opPush,
+ [OP_ADD] = VM__opAdd,
+ [OP_SUB] = VM__opSub,
+ [OP_MUL] = VM__opMul,
+ [OP_DIV] = VM__opDiv,
+ [OP_NEG] = VM__opNeg,
+ [OP_ABS] = VM__opAbs,
+ [OP_POW] = VM__opPow,
+ [OP_SQRT] = VM__opSqrt,
+ [OP_MOD] = VM__opMod,
+ [OP_EXP] = VM__opExp,
+ [OP_EXP_2] = VM__opExp2,
+ [OP_EXP_10] = VM__opExp10,
+ [OP_LOG] = VM__opLog,
+ [OP_LOG_2] = VM__opLog2,
+ [OP_LOG_10] = VM__opLog10,
+ [OP_SIN] = VM__opSin,
+ [OP_COS] = VM__opCos,
+ [OP_SWAP] = VM__opSwap,
+ [OP_FRAME] = VM__opFrame,
+ [OP_SRATE] = VM__opSampleRate,
+ [OP_PI] = VM__opPi,
+ [OP_EQ] = VM__opEq,
+ [OP_LT] = VM__opLt,
+ [OP_GT] = VM__opGt,
+ [OP_LE] = VM__opLe,
+ [OP_GE] = VM__opGe,
+ [OP_AND] = VM__opAnd,
+ [OP_OR] = VM__opOr,
+ [OP_NOT] = VM__opNot,
+ [OP_BAND] = VM__opBAnd,
+ [OP_BOR] = VM__opBOr,
+ [OP_BNOT] = VM__opBNot,
+ [OP_TER] = VM__opTernary,
+ [OP_STORE] = VM__opStore,
+ [OP_LOAD] = VM__opLoad,
+};
+
static inline void
vm_opcode_init(opcode_t *opcode, LV2_URID_Map *map)
{
- opcode->op[OP_NOP] = map->map(map->handle, VM__opNop);
- opcode->op[OP_PUSH] = map->map(map->handle, VM__opPush);
- opcode->op[OP_ADD] = map->map(map->handle, VM__opAdd);
- opcode->op[OP_SUB] = map->map(map->handle, VM__opSub);
- opcode->op[OP_MUL] = map->map(map->handle, VM__opMul);
- opcode->op[OP_DIV] = map->map(map->handle, VM__opDiv);
- opcode->op[OP_NEG] = map->map(map->handle, VM__opNeg);
- opcode->op[OP_POW] = map->map(map->handle, VM__opPow);
- opcode->op[OP_SQRT] = map->map(map->handle, VM__opSqrt);
- opcode->op[OP_EXP] = map->map(map->handle, VM__opExp);
- opcode->op[OP_EXP_2] = map->map(map->handle, VM__opExp2);
- opcode->op[OP_EXP_10] = map->map(map->handle, VM__opExp10);
- opcode->op[OP_LOG] = map->map(map->handle, VM__opLog);
- opcode->op[OP_LOG_2] = map->map(map->handle, VM__opLog2);
- opcode->op[OP_LOG_10] = map->map(map->handle, VM__opLog10);
- opcode->op[OP_SIN] = map->map(map->handle, VM__opSin);
- opcode->op[OP_COS] = map->map(map->handle, VM__opCos);
- opcode->op[OP_SWAP] = map->map(map->handle, VM__opSwap);
+ for(unsigned i = 0; i < OP_MAX; i++)
+ opcode->op[i] = map->map(map->handle, opcode_uris[i]);
}
static inline opcode_enum_t
@@ -229,13 +294,15 @@ vm_serialize(opcode_t *opcode, LV2_Atom_Forge *forge, const command_t *cmds)
return ref;
}
-static inline void
+static inline bool
vm_deserialize(opcode_t *opcode, LV2_Atom_Forge *forge,
command_t *cmds, uint32_t size, const LV2_Atom *body)
{
command_t *cmd = cmds;
memset(cmds, 0x0, sizeof(command_t)*ITEMS_MAX);
+ bool is_dynamic = false;
+
LV2_ATOM_TUPLE_BODY_FOREACH(body, size, item)
{
const LV2_Atom_Object *obj = (const LV2_Atom_Object *)item;
@@ -269,6 +336,9 @@ vm_deserialize(opcode_t *opcode, LV2_Atom_Forge *forge,
{
cmd->type = COMMAND_OPCODE;
cmd->op = vm_opcode_unmap(opcode, ((const LV2_Atom_URID *)item)->body);
+
+ if(cmd->op == OP_FRAME)
+ is_dynamic = true;
}
else
{
@@ -280,6 +350,8 @@ vm_deserialize(opcode_t *opcode, LV2_Atom_Forge *forge,
if(cmd >= cmds + ITEMS_MAX)
break;
}
+
+ return is_dynamic;
}
#endif // _VM_LV2_H
diff --git a/vm.ttl b/vm.ttl
index c109b45..95ef9f9 100644
--- a/vm.ttl
+++ b/vm.ttl
@@ -29,6 +29,7 @@
@prefix patch: <http://lv2plug.in/ns/ext/patch#> .
@prefix units: <http://lv2plug.in/ns/extensions/units#> .
@prefix work: <http://lv2plug.in/ns/ext/worker#> .
+@prefix pset: <http://lv2plug.in/ns/ext/presets#> .
@prefix lic: <http://opensource.org/licenses/> .
@prefix omk: <http://open-music-kontrollers.ch/ventosus#> .
@@ -55,9 +56,12 @@ vm:graph
rdfs:label "Graph" ;
rdfs:comment "vm graph tuple" .
-vm:opPush
+vm:opControl
a rdfs:Class, owl:Class ;
rdfs:label "Push Control" .
+vm:opPush
+ a rdfs:Class, owl:Class ;
+ rdfs:label "Push Top of stack" .
vm:opAdd
a rdfs:Class, owl:Class ;
rdfs:label "Addition" .
@@ -73,12 +77,18 @@ vm:opDiv
vm:opNeg
a rdfs:Class, owl:Class ;
rdfs:label "Negate" .
+vm:opAbs
+ a rdfs:Class, owl:Class ;
+ rdfs:label "Absolute" .
vm:opPow
a rdfs:Class, owl:Class ;
rdfs:label "Power" .
vm:opSqrt
a rdfs:Class, owl:Class ;
rdfs:label "Square root" .
+vm:opMod
+ a rdfs:Class, owl:Class ;
+ rdfs:label "Modulo" .
vm:opExp
a rdfs:Class, owl:Class ;
rdfs:label "Exponentiation" .
@@ -106,6 +116,57 @@ vm:opCos
vm:opSwap
a rdfs:Class, owl:Class ;
rdfs:label "Swap" .
+vm:opFrame
+ a rdfs:Class, owl:Class ;
+ rdfs:label "Frame" .
+vm:opSampleRate
+ a rdfs:Class, owl:Class ;
+ rdfs:label "SampleRate" .
+vm:opPi
+ a rdfs:Class, owl:Class ;
+ rdfs:label "Pi" .
+vm:opEq
+ a rdfs:Class, owl:Class ;
+ rdfs:label "Equal" .
+vm:opLt
+ a rdfs:Class, owl:Class ;
+ rdfs:label "Less than" .
+vm:opGt
+ a rdfs:Class, owl:Class ;
+ rdfs:label "Greater than" .
+vm:opLe
+ a rdfs:Class, owl:Class ;
+ rdfs:label "Less or equal" .
+vm:opGe
+ a rdfs:Class, owl:Class ;
+ rdfs:label "Greater or equal" .
+vm:opAnd
+ a rdfs:Class, owl:Class ;
+ rdfs:label "Boolean And" .
+vm:opOr
+ a rdfs:Class, owl:Class ;
+ rdfs:label "Boolean Or" .
+vm:opNot
+ a rdfs:Class, owl:Class ;
+ rdfs:label "Boolean Not" .
+vm:opBAnd
+ a rdfs:Class, owl:Class ;
+ rdfs:label "Bitwise And" .
+vm:opBOr
+ a rdfs:Class, owl:Class ;
+ rdfs:label "Bitwise Or" .
+vm:opBNot
+ a rdfs:Class, owl:Class ;
+ rdfs:label "Bitwise Not" .
+vm:opTernary
+ a rdfs:Class, owl:Class ;
+ rdfs:label "Ternary" .
+vm:opStore
+ a rdfs:Class, owl:Class ;
+ rdfs:label "Store in registry" .
+vm:opLoad
+ a rdfs:Class, owl:Class ;
+ rdfs:label "Load from registry" .
# Plugin
vm:vm
@@ -286,9 +347,85 @@ vm:vm
vm:graph [
a atom:Tuple ;
rdf:value (
- 0 vm:opPush
+ 7 vm:opControl
+ 6 vm:opControl
+ 5 vm:opControl
+ 4 vm:opControl
+ 3 vm:opControl
+ 2 vm:opControl
+ 1 vm:opControl
+ 0 vm:opControl
+ )
+ ]
+ ] .
+
+vm:dBFS
+ a pset:Preset ;
+ lv2:appliesTo vm:vm ;
+ rdfs:label "dBFS" ;
+
+ state:state [
+ vm:graph [
+ a atom:Tuple ;
+ rdf:value (
+ # dBFS := Log10( |Control0| ) * 20.0
+ 0 vm:opControl
+ vm:opAbs
+ vm:opLog10
+ 20.0 vm:opMul
+ )
+ ]
+ ] .
+
+vm:lfo
+ a pset:Preset ;
+ lv2:appliesTo vm:vm ;
+ rdfs:label "LFO" ;
+
+ state:state [
+ vm:graph [
+ a atom:Tuple ;
+ rdf:value (
+ # Phase := (Frame % (SampleRate * Control0) ) / (SampleRate * Control0)
+ vm:opSampleRate
+ 0 vm:opControl
+ vm:opMul
+ vm:opPush
+ vm:opFrame
+ vm:opSwap
+ vm:opMod
+ vm:opSwap
+ vm:opDiv
+ 0 vm:opStore
+
+ # SquareLFO := (Phase > 0.25) && (Phase < 0.75)
+ 0 vm:opLoad
+ 0.25 vm:opGt
+ 0 vm:opLoad
+ 0.75 vm:opLt
+ vm:opAnd
+
+ # TriangleLFO := (Phase > 0.5 ? (1.0 - Phase) : Phase) * 2.0
+ 1.0
+ 0 vm:opLoad
+ vm:opSub
+ 0 vm:opLoad
+ vm:opPush
+ 0.5 vm:opGt
+ vm:opTernary
+ 2.0 vm:opMul
+
+ # SineLFO := Sin( (Phase - 0.25) * 2.0 * PI) * 0.5 + 0.5
+ 0 vm:opLoad
+ 0.25 vm:opSub
+ 2.0 vm:opMul
+ vm:opPi vm:opMul
+ vm:opSin
0.5 vm:opMul
0.5 vm:opAdd
+
+ # push phase
+ 0 vm:opLoad
)
]
] .
diff --git a/vm_ui.c b/vm_ui.c
index c23d3fe..e83e414 100644
--- a/vm_ui.c
+++ b/vm_ui.c
@@ -77,30 +77,58 @@ struct _plughandle_t {
command_t cmds [ITEMS_MAX];
};
-static const char *op_labels [] = {
+typedef struct _desc_t desc_t;
+
+struct _desc_t {
+ const char *label;
+ unsigned npush;
+ unsigned npop;
+};
+
+static const char *op_labels [OP_MAX] = {
[OP_NOP] = "-",
- [OP_PUSH] = "Push",
- [OP_ADD] = "Add",
- [OP_SUB] = "Sub",
- [OP_MUL] = "Mul",
- [OP_DIV] = "Div",
- [OP_NEG] = "Neg",
- [OP_POW] = "Pow",
- [OP_SQRT] = "Sqrt",
- [OP_EXP] = "Exp",
- [OP_EXP_2] = "Exp2",
- [OP_EXP_10] = "Exp10",
- [OP_LOG] = "Log",
- [OP_LOG_2] = "Log2",
- [OP_LOG_10] = "Log10",
- [OP_SIN] = "Sin",
- [OP_COS] = "Cos",
- [OP_SWAP] = "Swap"
+ [OP_CTRL] = "Control (1:1)",
+ [OP_PUSH] = "Push (1:2)",
+ [OP_ADD] = "Add (2:1)",
+ [OP_SUB] = "Sub (2:1)",
+ [OP_MUL] = "Mul (2:1)",
+ [OP_DIV] = "Div (2:1)",
+ [OP_NEG] = "Neg (1:1)",
+ [OP_ABS] = "Abs (1:1)",
+ [OP_POW] = "Pow (2:1)",
+ [OP_SQRT] = "Sqrt (1:1)",
+ [OP_MOD] = "Mod (2:1)",
+ [OP_EXP] = "Exp (1:1)",
+ [OP_EXP_2] = "Exp2 (1:1)",
+ [OP_EXP_10] = "Exp10 (1:1)",
+ [OP_LOG] = "Log (1:1)",
+ [OP_LOG_2] = "Log2 (1:1)",
+ [OP_LOG_10] = "Log10 (1:1)",
+ [OP_SIN] = "Sin (1:1)",
+ [OP_COS] = "Cos (1:1)",
+ [OP_SWAP] = "Swap (2:2)",
+ [OP_FRAME] = "Frame (-:1)",
+ [OP_SRATE] = "Sample Rate (-:1)",
+ [OP_PI] = "Pi (-:1)",
+ [OP_EQ] = "Equal (2:1)",
+ [OP_LT] = "LessThan (2:1)",
+ [OP_GT] = "GreaterThan (2:1)",
+ [OP_LE] = "LessOrEqual (2:1)",
+ [OP_GE] = "GreaterOrEqual (2:1)",
+ [OP_AND] = "Boolean And (2:1)",
+ [OP_OR] = "Boolean Or (2:1)",
+ [OP_NOT] = "Boolean Not (1:1)",
+ [OP_BAND] = "Bitwise And (2:1)",
+ [OP_BOR] = "Bitwise Or (2:1)",
+ [OP_BNOT] = "Bitwise Not (1:1)",
+ [OP_TER] = "Ternary (3:1)",
+ [OP_STORE] = "Store (2:0)",
+ [OP_LOAD] = "Load (1:1)",
};
-static const char *cmd_labels [] = {
+static const char *cmd_labels [COMMAND_MAX] = {
[COMMAND_NOP] = "-",
- [COMMAND_OPCODE] = "OpCode" ,
+ [COMMAND_OPCODE] = "Op Code" ,
[COMMAND_BOOL] = "Boolean" ,
[COMMAND_INT] = "Integer" ,
[COMMAND_LONG] = "Long" ,
@@ -229,6 +257,7 @@ _expose(struct nk_context *ctx, struct nk_rect wbounds, void *data)
const float old_val = handle->in0[i];
nk_property_float(ctx, label, 0.f, &handle->in0[i], 1.f, 0.01f, 0.01f);
+ nk_slider_float(ctx, 0.f, &handle->in0[i], 1.f, 0.001f);
if(old_val != handle->in0[i])
handle->writer(handle->controller, i + 2, sizeof(float), 0, &handle->in0[i]);
}
@@ -244,6 +273,7 @@ _expose(struct nk_context *ctx, struct nk_rect wbounds, void *data)
char label [16];
snprintf(label, 16, "Output %u", i);
nk_value_float(ctx, label, handle->out0[i]);
+ nk_slide_float(ctx, 0.f, handle->out0[i], 1.f, 0.001f);
}
nk_tree_pop(ctx);
}
@@ -251,7 +281,7 @@ _expose(struct nk_context *ctx, struct nk_rect wbounds, void *data)
nk_group_end(ctx);
}
- if(nk_group_begin(ctx, "Operations", NK_WINDOW_TITLE | NK_WINDOW_BORDER))
+ if(nk_group_begin(ctx, "Program", NK_WINDOW_TITLE | NK_WINDOW_BORDER))
{
nk_layout_row_dynamic(ctx, dy, 2);
bool sync = false;