summaryrefslogtreecommitdiffstats
path: root/src/control.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/control.h')
-rw-r--r--src/control.h81
1 files changed, 81 insertions, 0 deletions
diff --git a/src/control.h b/src/control.h
new file mode 100644
index 0000000..8eee97b
--- /dev/null
+++ b/src/control.h
@@ -0,0 +1,81 @@
+#ifndef CONTROL_H
+#define CONTROL_H
+
+/**
+ Control Component
+
+ The midi implementation polls the midi device every whenever and gets to
+ react to midi events. Any and all changes should not happen directly to the
+ active `value`, but rather to the `mod`. This way the sound engine can
+ smoothly interpolate the changed value while generating samples.
+
+ The sound engine fills a buffer with samples. The buffer has BUFFER_SIZE.
+ Each call of the sound callback will insert BUFFER_SIZE samples in the
+ buffer. Before we get the samples, we poll the synth's ccs for any changes.
+ This will set the target value to the `value + mod`, and the sound engine
+ will interpolate the `value` from value to target . It should also reset the
+ mod since other midi events might trigger until the next buffer generation.
+*/
+
+typedef struct cc_t {
+ char name[64];
+ int midi_cc;
+ float min, max;
+ float step;
+ float def;
+ float value; /* active value (start for interpolation) */
+ float mod; /* stores the modified value before it is set as target */
+ float target; /* target value (end for interpolation) */
+} cc_t;
+
+#ifndef CC
+#define CC2(NAME, MIN, MAX, STEP, DEF) \
+ (cc_t) { \
+ .name = NAME, \
+ .midi_cc = -1, \
+ .min = MIN, \
+ .max = MAX, \
+ .step = STEP, \
+ .def = DEF, \
+ .value = DEF, \
+ .mod = 0, \
+ .target = DEF \
+ };
+#define CC(SYNTH, NAME, MIN, MAX, STEP, DEF) \
+ strcpy(SYNTH.name, NAME); \
+ SYNTH.midi_cc = -1; \
+ SYNTH.min = MIN; \
+ SYNTH.max = MAX; \
+ SYNTH.step = STEP; \
+ SYNTH.def = DEF; \
+ SYNTH.value = DEF; \
+ SYNTH.mod = 0; \
+ SYNTH.target = DEF; \
+ synth->ccs[synth->cci++] = &SYNTH;
+#endif
+
+/**
+ Step the value of the target cc for `steps`.
+ `steps` can be positive or negative.
+
+ The change will occur in the mod value of the cc.
+
+ returns 1 if the value changed, 0 otherwise
+ */
+int cc_step(cc_t *cc, int steps);
+
+/**
+ Reset the cc to defaults
+ */
+void cc_reset(cc_t *cc);
+
+/**
+ Get the interpolated value from 0 to `max` in position `i`
+ */
+float cc_iget(cc_t *cc, unsigned int i, unsigned int max);
+void cc_prep(cc_t *cc);
+void cc_fix(cc_t *cc);
+
+const char * cc_to_str(cc_t *cc);
+
+#endif /* CONTROL_H */