summaryrefslogtreecommitdiffstats
path: root/src/control.h
blob: 45e87ed6f9bcb7d89db572c18954fe6c33cad73a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#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 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 */