From 60c82a72fedd719f69c1f1de896aca00784a2881 Mon Sep 17 00:00:00 2001 From: gramanas Date: Tue, 27 Jun 2023 22:37:53 +0300 Subject: Changes --- src/control.h | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 src/control.h (limited to 'src/control.h') 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 */ -- cgit v1.2.3