-
Notifications
You must be signed in to change notification settings - Fork 5
/
sampler.h
398 lines (354 loc) · 13.9 KB
/
sampler.h
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
/*
Calf Box, an open source musical instrument.
Copyright (C) 2010-2013 Krzysztof Foltman
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, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CBOX_SAMPLER_H
#define CBOX_SAMPLER_H
#include "biquad-float.h"
#include "envelope.h"
#include "module.h"
#include "onepole-float.h"
#include "prefetch_pipe.h"
#include "sampler_layer.h"
#include "sampler_prg.h"
#include "wavebank.h"
#include <stdint.h>
#define MAX_SAMPLER_VOICES 128
#define MAX_SAMPLER_PREVOICES 128
#define SAMPLER_NO_LOOP ((uint32_t)-1)
#define CBOX_SAMPLER_ERROR cbox_sampler_error_quark()
enum CboxSamplerError
{
CBOX_SAMPLER_ERROR_FAILED,
CBOX_SAMPLER_ERROR_INVALID_LAYER,
CBOX_SAMPLER_ERROR_INVALID_WAVEFORM,
CBOX_SAMPLER_ERROR_NO_PROGRAMS
};
struct sampler_noteinitfunc;
struct sampler_voice;
struct sampler_prevoice;
#define GET_RT_FROM_sampler_channel(channel) ((channel)->module->module.rt)
#define MAX_KEYSWITCH_GROUPS 16
struct sampler_channel
{
struct sampler_module *module;
int pitchwheel;
uint32_t switchmask[4];
uint32_t sustainmask[4];
uint32_t sostenutomask[4];
int previous_note, first_note_vel;
struct sampler_program *program;
struct sampler_voice *voices_running;
int active_voices, active_prevoices;
uint8_t prev_note_velocity[128];
uint8_t poly_pressure[128];
uint32_t prev_note_start_time[128];
int channel_volume_cc, channel_pan_cc;
int output_shift;
uint32_t poly_pressure_mask;
uint8_t intcc[smsrc_perchan_count];
float floatcc[smsrc_perchan_count];
uint8_t last_polyaft, last_chanaft;
uint8_t keyswitch_state[MAX_KEYSWITCH_GROUPS];
uint8_t keyswitch_lastkey[MAX_KEYSWITCH_GROUPS];
};
struct sampler_lfo
{
uint32_t phase, delta, xdelta;
uint32_t delay, fade;
int32_t wave;
float random_value;
};
struct sampler_gen
{
enum sampler_player_type mode;
int16_t *sample_data;
int16_t *scratch;
uint64_t bigpos, bigdelta;
uint64_t virtpos, virtdelta;
uint32_t loop_start, loop_end;
uint32_t cur_sample_end;
float lgain, rgain;
float last_lgain, last_rgain;
float fadein_counter;
uint64_t fadein_pos;
// In-memory mode only
uint32_t loop_overlap;
float loop_overlap_step;
float stretching_jump;
float stretching_crossfade;
uint32_t play_count, loop_count;
int16_t scratch_bandlimited[2 * MAX_INTERPOLATION_ORDER * 2];
// Streaming mode only
int16_t *streaming_buffer;
uint32_t consumed, consumed_credit, streaming_buffer_frames;
gboolean prefetch_only_loop, in_streaming_buffer;
};
struct sampler_prevoice
{
struct sampler_prevoice *prev, *next;
struct sampler_layer_data *layer_data;
struct sampler_channel *channel;
int note, vel;
uint32_t age;
double sync_trigger_time, sync_initial_time, sync_beats;
float delay_computed;
};
struct sampler_filter
{
struct cbox_biquadf_coeffs filter_coeffs, filter_coeffs_extra;
struct cbox_biquadf_coeffs *second_filter;
struct cbox_biquadf_state filter_left[3], filter_right[3];
};
struct sampler_voice
{
struct sampler_voice *prev, *next;
struct sampler_layer_data *layer;
// Note: may be NULL when program is being deleted
struct sampler_program *program;
struct cbox_waveform *last_waveform;
struct sampler_gen gen;
struct cbox_prefetch_pipe *current_pipe;
int note;
int vel;
int released, released_with_sustain, released_with_sostenuto, captured_sostenuto;
int off_by;
uint32_t age;
float pitch_shift;
float cutoff_shift, cutoff2_shift;
float gain_shift, gain_fromvel;
struct sampler_filter filter, filter2;
struct cbox_onepolef_state onepole_left, onepole_right;
struct cbox_onepolef_coeffs onepole_coeffs;
struct sampler_channel *channel;
struct cbox_envelope amp_env, filter_env, pitch_env;
struct sampler_lfo amp_lfo, filter_lfo, pitch_lfo;
enum sampler_loop_mode loop_mode;
int output_pair_no;
int send1bus, send2bus;
float send1gain, send2gain;
int serial_no;
struct cbox_envelope_shape vel_envs[3], cc_envs[3]; // amp, filter, pitch
struct cbox_biquadf_state eq_left[3], eq_right[3];
struct cbox_biquadf_coeffs eq_coeffs[3];
gboolean layer_changed;
int last_level;
uint64_t last_level_min_rate;
uint32_t last_eq_bitmask;
float reloffset;
uint32_t offset;
int off_vel;
uint64_t flexlfo_phase[MAX_FLEX_LFOS];
};
struct sampler_module
{
struct cbox_module module;
struct sampler_voice *voices_free, voices_all[MAX_SAMPLER_VOICES];
struct sampler_prevoice *prevoices_free, prevoices_all[MAX_SAMPLER_PREVOICES], *prevoices_running;
struct sampler_channel channels[16];
struct sampler_program **programs;
uint32_t program_count;
int active_voices, max_voices;
int active_prevoices;
int serial_no;
int output_pairs, aux_pairs;
uint32_t current_time;
gboolean deleting;
int disable_mixer_controls;
struct cbox_prefetch_stack *pipe_stack;
struct cbox_sincos sincos[12800];
};
#define MAX_RELEASED_GROUPS 16
struct sampler_released_groups
{
// Groups 1-32 use a bitmask
uint32_t low_groups;
int group_count;
int groups[MAX_RELEASED_GROUPS];
};
static inline void sampler_released_groups_init(struct sampler_released_groups *groups)
{
groups->low_groups = 0;
groups->group_count = 0;
}
static inline gboolean sampler_released_groups_check(struct sampler_released_groups *groups, int group)
{
if (group <= 32)
return (groups->low_groups >> (group - 1)) & 1;
for (int j = 0; j < groups->group_count; j++)
{
if (groups->groups[j] == group)
return TRUE;
}
return FALSE;
}
static inline void sampler_released_groups_add(struct sampler_released_groups *groups, int group)
{
if (group <= 32)
{
groups->low_groups |= (1 << (group - 1));
return;
}
if (groups->group_count >= MAX_RELEASED_GROUPS)
return;
if (!sampler_released_groups_check(groups, group))
groups->groups[groups->group_count++] = group;
}
extern GQuark cbox_sampler_error_quark(void);
extern void sampler_register_program(struct sampler_module *m, struct sampler_program *pgm);
extern gboolean sampler_select_program(struct sampler_module *m, int channel, const gchar *preset, GError **error);
extern void sampler_unselect_program(struct sampler_module *m, struct sampler_program *prg);
extern double sampler_get_current_beat(struct sampler_module *m);
extern void sampler_channel_init(struct sampler_channel *c, struct sampler_module *m);
// This function may only be called from RT thread!
extern void sampler_channel_set_program_RT(struct sampler_channel *c, struct sampler_program *prg);
// ... and this one is RT-safe
extern void sampler_channel_set_program(struct sampler_channel *c, struct sampler_program *prg);
extern void sampler_channel_start_note(struct sampler_channel *c, int note, int vel, enum sampler_trigger is_release_trigger);
extern void sampler_channel_stop_note(struct sampler_channel *c, int note, int vel, gboolean is_polyaft);
extern void sampler_channel_program_change(struct sampler_channel *c, int program);
extern void sampler_channel_stop_sustained(struct sampler_channel *c);
extern void sampler_channel_stop_sostenuto(struct sampler_channel *c);
extern void sampler_channel_capture_sostenuto(struct sampler_channel *c);
extern void sampler_channel_release_groups(struct sampler_channel *c, int note, struct sampler_released_groups *exgroups);
extern void sampler_channel_stop_all(struct sampler_channel *c);
extern void sampler_channel_process_cc(struct sampler_channel *c, int cc, int val);
extern void sampler_channel_reset_keyswitches(struct sampler_channel *c);
extern void sampler_voice_start(struct sampler_voice *v, struct sampler_channel *c, struct sampler_layer_data *l, int note, int vel, struct sampler_released_groups *exgroups);
extern void sampler_voice_start_silent(struct sampler_layer_data *l, struct sampler_released_groups *exgroups);
extern void sampler_voice_release(struct sampler_voice *v, gboolean is_polyaft);
extern void sampler_voice_process(struct sampler_voice *v, struct sampler_module *m, cbox_sample_t **outputs);
extern void sampler_voice_link(struct sampler_voice **pv, struct sampler_voice *v);
extern void sampler_voice_unlink(struct sampler_voice **pv, struct sampler_voice *v);
extern void sampler_voice_inactivate(struct sampler_voice *v, gboolean expect_active);
extern void sampler_voice_update_params_from_layer(struct sampler_voice *v);
extern float sampler_channel_get_expensive_cc(struct sampler_channel *c, struct sampler_voice *v, struct sampler_prevoice *pv, int cc_no);
extern void sampler_prevoice_start(struct sampler_prevoice *pv, struct sampler_channel *c, struct sampler_layer_data *l, int note, int vel);
extern int sampler_prevoice_process(struct sampler_prevoice *pv, struct sampler_module *m);
extern void sampler_prevoice_link(struct sampler_prevoice **pv, struct sampler_prevoice *v);
extern void sampler_prevoice_unlink(struct sampler_prevoice **pv, struct sampler_prevoice *v);
extern float sampler_sine_wave[2049];
static inline int sampler_channel_addcc(struct sampler_channel *c, int cc_no)
{
return (((int)c->intcc[cc_no]) << 7) + c->intcc[cc_no + 32];
}
static inline float sampler_channel_getcc(struct sampler_channel *c, struct sampler_voice *v, int cc_no)
{
if (cc_no < 128)
return c->floatcc[cc_no];
return sampler_channel_get_expensive_cc(c, v, NULL, cc_no);
}
static inline float sampler_program_get_curve_value(struct sampler_program *program, uint32_t curve_id, float val)
{
if (val < 0)
val = 0;
if (val > 1)
val = 1;
if (curve_id < MAX_MIDI_CURVES && program->interpolated_curves[curve_id])
{
float *curve = program->interpolated_curves[curve_id];
int vint = floorf(val * 127);
// Linear interpolation if within bounds
if (vint < 127)
{
float vfrac = val * 127 - vint;
val = curve[vint] + (curve[vint + 1] - curve[vint]) * vfrac;
}
else
val = curve[vint];
}
else
{
// possibly wrong implementation of built in curves
switch(curve_id)
{
case 0:
break;
case 1:
case 3:
// slightly fake bipolar, so that both 63 and 64 are 'neutral' (needs to be somewhat symmetric)
if (val < 63.f/127.f)
val = (curve_id == 3 ? -1 : 1) * -(63.f - 127 * val) / 63.f;
else if (val <= 64.f/127.f)
val = 0;
else
val = (curve_id == 3 ? -1 : 1) * (127 * val - 64) / 63.f;
break;
case 2:
val = 1 - val; break;
case 4:
val = val * val;
break; // maybe, or maybe it's inverted?
case 5: val = sqrtf(val);
break; // maybe
case 6: val = sqrtf(1-val);
break; // maybe
}
}
return val;
}
static inline float sampler_channel_getcc_mod(struct sampler_channel *c, struct sampler_voice *v, int cc_no, int curve_id, float step)
{
float val = (cc_no < 128) ? c->floatcc[cc_no] : sampler_channel_get_expensive_cc(c, v, NULL, cc_no);
if (step)
val = floorf(0.9999f * val * (step + 1)) / step;
if (curve_id || c->program->interpolated_curves[0])
val = sampler_program_get_curve_value(c->program, curve_id, val);
return val;
}
static inline int sampler_channel_getintcc(struct sampler_channel *c, struct sampler_voice *v, int cc_no)
{
if (cc_no < 128)
return c->intcc[cc_no];
return (int)127 * (sampler_channel_get_expensive_cc(c, v, NULL, cc_no));
}
static inline float sampler_channel_getcc_prevoice(struct sampler_channel *c, struct sampler_prevoice *pv, int cc_no, int curve_id, float step)
{
float val = (cc_no < 128) ? c->floatcc[cc_no] : sampler_channel_get_expensive_cc(c, NULL, pv, cc_no);
if (step)
val = floorf(0.9999f * val * (step + 1)) / step;
if (curve_id || c->program->interpolated_curves[0])
val = sampler_program_get_curve_value(c->program, curve_id, val);
return val;
}
static inline float sampler_channel_get_poly_pressure(struct sampler_channel *c, uint8_t note)
{
note &= 0x7F;
return (c->poly_pressure_mask & (1 << (note >> 2))) ? c->poly_pressure[note] * (1.f / 127.f) : 0;;
}
static inline gboolean sampler_cc_range_is_in(const struct sampler_cc_range *range, struct sampler_channel *c)
{
while(range)
{
int ccval = sampler_channel_getintcc(c, NULL, range->key.cc_number);
if (ccval < range->value.locc || ccval > range->value.hicc)
return FALSE;
range = range->next;
}
return TRUE;
}
#define FOREACH_VOICE(var, p) \
for (struct sampler_voice *p = (var), *p##_next = NULL; p && (p##_next = p->next, TRUE); p = p##_next)
#define FOREACH_PREVOICE(var, p) \
for (struct sampler_prevoice *p = (var), *p##_next = NULL; p && (p##_next = p->next, TRUE); p = p##_next)
#define CANCEL_PREVOICE(var, p) \
{\
struct sampler_prevoice *_tmp = (p); \
if (_tmp->prev) \
_tmp->prev->next = _tmp->next; \
else \
var = _tmp->next; \
_tmp->prev = _tmp->next = NULL; \
}
gboolean load_program_at(struct sampler_module *m, const char *cfg_section, const char *name, int prog_no, struct sampler_program **ppgm, GError **error);
#endif