You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

611 lines
19 KiB

/*
Calf Box, an open source musical instrument.
Copyright (C) 2010-2011 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_LAYER_H
#define CBOX_SAMPLER_LAYER_H
#include "dom.h"
#include "wavebank.h"
#include <stdio.h>
#include <stdint.h>
// arbitrary value that doesn't collide with a useful range
#define SAMPLER_CURVE_GAP -100000
#define NO_HI_BPM_VALUE 10000
struct sampler_program;
struct sampler_voice;
struct sampler_prevoice;
struct sampler_noteinitfunc;
struct sampler_module;
enum sampler_player_type
{
spt_inactive,
spt_mono16,
spt_stereo16,
spt_finished
};
enum sampler_loop_mode
{
slm_unknown,
slm_no_loop,
slm_one_shot,
slm_loop_continuous,
slm_loop_sustain, // unsupported
slm_one_shot_chokeable,
slmcount
};
#define ENUM_VALUES_sampler_loop_mode(MACRO) \
MACRO("no_loop", slm_no_loop) \
MACRO("one_shot", slm_one_shot) \
MACRO("loop_continuous", slm_loop_continuous) \
MACRO("loop_sustain", slm_loop_sustain) \
MACRO("one_shot_chokeable", slm_one_shot_chokeable)
enum sampler_off_mode
{
som_unknown,
som_normal,
som_fast
};
#define ENUM_VALUES_sampler_off_mode(MACRO) \
MACRO("normal", som_normal) \
MACRO("fast", som_fast)
enum sampler_vel_mode
{
svm_unknown,
svm_current,
svm_previous
};
#define ENUM_VALUES_sampler_vel_mode(MACRO) \
MACRO("current", svm_current) \
MACRO("previous", svm_previous)
enum sampler_trigger
{
stm_attack,
stm_release,
stm_first,
stm_legato,
};
#define ENUM_VALUES_sampler_trigger(MACRO) \
MACRO("attack", stm_attack) \
MACRO("release", stm_release) \
MACRO("first", stm_first) \
MACRO("legato", stm_legato)
enum sampler_filter_type
{
sft_unknown,
sft_lp12,
sft_hp12,
sft_bp6,
sft_lp24,
sft_hp24,
sft_bp12,
sft_lp6,
sft_hp6,
sft_lp12nr,
sft_hp12nr,
sft_lp24nr,
sft_hp24nr,
sft_lp24hybrid,
sft_lp36,
};
#define ENUM_VALUES_sampler_filter_type(MACRO) \
MACRO("lpf_2p", sft_lp12) \
MACRO("hpf_2p", sft_hp12) \
MACRO("bpf_2p", sft_bp6) \
MACRO("lpf_4p", sft_lp24) \
MACRO("hpf_4p", sft_hp24) \
MACRO("bpf_4p", sft_bp12) \
MACRO("lpf_1p", sft_lp6) \
MACRO("hpf_1p", sft_hp6) \
MACRO("lpf_2p_nores", sft_lp12nr) \
MACRO("hpf_2p_nores", sft_hp12nr) \
MACRO("lpf_4p_nores", sft_lp24nr) \
MACRO("hpf_4p_nores", sft_hp24nr) \
MACRO("lpf_4p_hybrid", sft_lp24hybrid) \
MACRO("lpf_6p", sft_lp36) \
enum sampler_xf_curve
{
stxc_power,
stxc_gain,
};
#define ENUM_VALUES_sampler_xf_curve(MACRO) \
MACRO("power", stxc_power) \
MACRO("gain", stxc_gain)
#define ENUM_LIST(MACRO) \
MACRO(sampler_loop_mode) \
MACRO(sampler_off_mode) \
MACRO(sampler_vel_mode) \
MACRO(sampler_trigger) \
MACRO(sampler_filter_type) \
MACRO(sampler_xf_curve) \
#define MAKE_FROM_TO_STRING_EXTERN(enumtype) \
extern const char *enumtype##_to_string(enum enumtype value); \
extern gboolean enumtype##_from_string(const char *name, enum enumtype *value);
ENUM_LIST(MAKE_FROM_TO_STRING_EXTERN)
enum sampler_modsrc
{
smsrc_cc0 = 0,
smsrc_pitchbend = 128,
smsrc_chanaft_sfz2 = 129,
smsrc_lastpolyaft = 130, // ?
smsrc_noteonvel = 131,
smsrc_noteoffvel = 132,
smsrc_keynotenum = 133,
smsrc_keynotegate = 134,
smsrc_random_unipolar = 135,
smsrc_random_bipolar = 136,
smsrc_alternate = 137,
smsrc_keydelta = 140,
smsrc_keydelta_abs = 141,
smsrc_tempo = 142,
// those are per-note, not per-channel
smsrc_vel,
smsrc_chanaft,
smsrc_polyaft,
smsrc_pitch,
smsrc_pitchenv,
smsrc_filenv,
smsrc_ampenv,
smsrc_pitchlfo,
smsrc_fillfo,
smsrc_amplfo,
smsrc_none,
smsrccount,
smsrc_perchan_offset = 0,
smsrc_perchan_count = smsrc_vel,
smsrc_pernote_offset = smsrc_vel,
smsrc_pernote_count = smsrccount - smsrc_pernote_offset,
smsrc_ampeg = smsrc_ampenv,
smsrc_fileg = smsrc_filenv,
smsrc_pitcheg = smsrc_pitchenv,
};
enum sampler_moddest
{
smdest_gain,
smdest_pitch,
smdest_cutoff,
smdest_resonance,
smdest_tonectl,
smdest_pan,
smdest_amplitude,
smdest_cutoff2,
smdest_resonance2,
smdest_pitchlfo_freq,
smdest_fillfo_freq,
smdest_amplfo_freq,
smdest_eq1_freq,
smdest_eq1_bw,
smdest_eq1_gain,
smdest_eq2_freq,
smdest_eq2_bw,
smdest_eq2_gain,
smdest_eq3_freq,
smdest_eq3_bw,
smdest_eq3_gain,
smdestcount,
smdest_from_amplfo = smdest_gain,
smdest_from_fillfo = smdest_cutoff,
smdest_from_pitchlfo = smdest_pitch,
smdest_from_ampeg = smdest_gain,
smdest_from_fileg = smdest_cutoff,
smdest_from_pitcheg = smdest_pitch,
smdest_ampeg_stage = 0x80,
smdest_fileg_stage = 0x90,
smdest_pitcheg_stage = 0xA0,
smdest_eg_stage_start = 0x80,
smdest_eg_stage_end = 0xAF,
};
struct sampler_modulation
{
enum sampler_modsrc src;
enum sampler_modsrc src2;
enum sampler_moddest dest;
float amount;
float smooth;
float step;
unsigned int curve_id:12;
unsigned int has_amount:1;
unsigned int has_curve:1;
unsigned int has_smooth:1;
unsigned int has_step:1;
};
typedef void (*SamplerNoteInitFunc)(struct sampler_noteinitfunc *nif, struct sampler_voice *voice);
typedef void (*SamplerNoteInitFunc2)(struct sampler_noteinitfunc *nif, struct sampler_prevoice *prevoice);
struct sampler_noteinitfunc
{
SamplerNoteInitFunc notefunc_voice;
SamplerNoteInitFunc2 notefunc_prevoice;
int variant:31;
unsigned int has_value:1;
float param;
// XXXKF no destructor for now - might not be necessary
};
enum sampler_noteinitfunc_envelope_variant
{
snif_env_delay = 0,
snif_env_attack = 1,
snif_env_hold = 2,
snif_env_decay = 3,
snif_env_sustain = 4,
snif_env_release = 5,
snif_env_start = 6,
};
struct sampler_lfo_params
{
float freq;
float delay;
float fade;
int wave;
};
struct sampler_eq_params
{
float freq;
float bw;
float gain;
float effective_freq;
float vel2freq;
float vel2gain;
};
typedef int midi_note_t;
/*
* Transforms:
* notransform - self-explanatory
* dBamp - amplitude/gain stored as dB
*/
#define SAMPLER_FIXED_FIELDS(MACRO) \
MACRO##_string(sample) \
MACRO(uint32_t, offset, 0) \
MACRO(uint32_t, offset_random, 0) \
MACRO(uint32_t, loop_start, 0) \
MACRO(uint32_t, loop_end, 0) \
MACRO(uint32_t, end, 0) \
MACRO(uint32_t, loop_overlap, (uint32_t)-1) \
MACRO##_enum(sampler_loop_mode, loop_mode, slm_unknown) \
MACRO##_enum(sampler_trigger, trigger, stm_attack) \
MACRO##_dBamp(float, volume, 0) \
MACRO(float, amplitude, 100) \
MACRO(float, pan, 0) \
MACRO(float, position, 0) \
MACRO(float, width, 100) \
MACRO(float, tune, 0) \
MACRO(int, transpose, 0) \
MACRO(int, lochan, 1) \
MACRO(int, hichan, 16) \
MACRO(float, lorand, 0) \
MACRO(float, hirand, 1) \
MACRO(midi_note_t, key, -1) \
MACRO(midi_note_t, lokey, 0) \
MACRO(midi_note_t, hikey, 127) \
MACRO(midi_note_t, pitch_keycenter, 60) \
MACRO(int, pitch_keytrack, 100) \
MACRO(midi_note_t, fil_keycenter, 60) \
MACRO(int, fil_keytrack, 0) \
MACRO(midi_note_t, fil2_keycenter, 60) \
MACRO(int, fil2_keytrack, 0) \
MACRO(midi_note_t, amp_keycenter, 60) \
MACRO(int, amp_keytrack, 0) \
MACRO(int, fil_veltrack, 0) \
MACRO(int, fil2_veltrack, 0) \
MACRO(int, amp_veltrack, 100) \
MACRO(int, pitch_veltrack, 0) \
MACRO(int, lovel, 0) \
MACRO(int, hivel, 127) \
MACRO(int, lobend, -8192) \
MACRO(int, hibend, 8192) \
MACRO(int, lochanaft, 0) \
MACRO(int, hichanaft, 127) \
MACRO(int, lopolyaft, 0) \
MACRO(int, hipolyaft, 127) \
MACRO(float, lobpm, 0.0) \
MACRO(float, hibpm, NO_HI_BPM_VALUE) \
MACRO(int, velcurve_quadratic, 1) \
MACRO##_enum(sampler_filter_type, fil_type, sft_lp12) \
MACRO##_enum(sampler_filter_type, fil2_type, sft_lp12) \
MACRO##_enum(sampler_off_mode, off_mode, som_unknown) \
MACRO##_enum(sampler_vel_mode, vel_mode, svm_current) \
MACRO(float, cutoff, -1) \
MACRO##_dBamp(float, resonance, 0) \
MACRO(float, cutoff2, -1) \
MACRO##_dBamp(float, resonance2, 0) \
MACRO(midi_note_t, sw_lokey, 0) \
MACRO(midi_note_t, sw_hikey, 127) \
MACRO(midi_note_t, sw_last, -1) \
MACRO(midi_note_t, sw_down, -1) \
MACRO(midi_note_t, sw_up, -1) \
MACRO(midi_note_t, sw_previous, -1) \
MACRO(midi_note_t, sw_default, -1) \
MACRO(int, seq_position, 1) \
MACRO(int, seq_length, 1) \
MACRO(float, sync_offset, 0) \
MACRO(int, effect1bus, 1) \
MACRO(int, effect2bus, 2) \
MACRO(float, effect1, 0) \
MACRO(float, effect2, 0) \
MACRO(float, delay, 0) \
MACRO(int, output, 0) \
MACRO(int, group, 0) \
MACRO(int, off_by, 0) \
MACRO(int, count, 0) \
MACRO(int, bend_up, 200) \
MACRO(int, bend_down, -200) \
MACRO(int, bend_step, 1) \
MACRO(int, timestretch, 0) \
MACRO(float, timestretch_jump, 500) \
MACRO(float, timestretch_crossfade, 100) \
MACRO(float, rt_decay, 0) \
MACRO(float, tonectl, 0) \
MACRO(float, tonectl_freq, 0) \
MACRO(float, reloffset, 0) \
MACRO(float, xfin_lokey, 0) \
MACRO(float, xfin_hikey, 0) \
MACRO(float, xfout_lokey, 127) \
MACRO(float, xfout_hikey, 127) \
MACRO##_enum(sampler_xf_curve, xf_keycurve, stxc_power) \
MACRO(float, xfin_lovel, 0) \
MACRO(float, xfin_hivel, 0) \
MACRO(float, xfout_lovel, 127) \
MACRO(float, xfout_hivel, 127) \
MACRO##_enum(sampler_xf_curve, xf_velcurve, stxc_power) \
MACRO##_ccrange(xfin_cc, xfin_) \
MACRO##_ccrange(xfout_cc, xfout_) \
MACRO##_enum(sampler_xf_curve, xf_cccurve, stxc_power) \
MACRO##_dahdsr(amp_env, ampeg, 0) \
MACRO##_dahdsr(filter_env, fileg, 1) \
MACRO##_dahdsr(pitch_env, pitcheg, 2) \
MACRO##_lfo(amp_lfo, amplfo, 0) \
MACRO##_lfo(filter_lfo, fillfo, 1) \
MACRO##_lfo(pitch_lfo, pitchlfo, 2) \
MACRO##_eq(eq1, eq1, 0) \
MACRO##_eq(eq2, eq2, 1) \
MACRO##_eq(eq3, eq3, 2) \
MACRO##_ccrange(on_cc, on_) \
MACRO##_ccrange(cc, ) \
MACRO##_midicurve(amp_velcurve) \
// XXXKF: consider making send1gain the dBamp type... except it's
// a linear percentage value in SFZ spec - bit weird!
#define DAHDSR_FIELDS(MACRO, ...) \
MACRO(start, 0, 0, ## __VA_ARGS__) \
MACRO(delay, 1, 0, ## __VA_ARGS__) \
MACRO(attack, 2, 0, ## __VA_ARGS__) \
MACRO(hold, 3, 0, ## __VA_ARGS__) \
MACRO(decay, 4, 0, ## __VA_ARGS__) \
MACRO(sustain, 5, 100, ## __VA_ARGS__) \
MACRO(release, 6, 0.05, ## __VA_ARGS__) \
#define LFO_FIELDS(MACRO, ...) \
MACRO(freq, 0, 0, ## __VA_ARGS__) \
MACRO(delay, 1, 0, ## __VA_ARGS__) \
MACRO(fade, 2, 0, ## __VA_ARGS__) \
MACRO(wave, 3, 1, ## __VA_ARGS__) \
#define EQ_FIELDS(MACRO, ...) \
MACRO(freq, 0, 0, ## __VA_ARGS__) \
MACRO(bw, 1, 1, ## __VA_ARGS__) \
MACRO(gain, 2, 0, ## __VA_ARGS__) \
MACRO(vel2freq, 3, 0, ## __VA_ARGS__) \
MACRO(vel2gain, 5, 0, ## __VA_ARGS__) \
#define PROC_SUBSTRUCT_HAS_FIELD(name, index, param, def_value) \
unsigned int name:1;
#define PROC_SUBSTRUCT_RESET_FIELD(name, index, def_value, param, dst) \
dst->param.name = def_value;
#define PROC_SUBSTRUCT_RESET_HAS_FIELD(name, index, def_value, param, dst) \
dst->has_##param.name = 0;
#define PROC_SUBSTRUCT_CLONE(name, index, def_value, param, dst, src) \
dst->param.name = src->param.name; \
dst->has_##param.name = src->has_##param.name;
#define PROC_SUBSTRUCT_CLONEPARENT(name, index, def_value, param, l) \
if (!l->has_##param.name) \
l->param.name = parent ? parent->param.name : def_value;
struct sampler_dahdsr_has_fields
{
DAHDSR_FIELDS(PROC_SUBSTRUCT_HAS_FIELD, name)
};
struct sampler_lfo_has_fields
{
LFO_FIELDS(PROC_SUBSTRUCT_HAS_FIELD, name)
};
struct sampler_eq_has_fields
{
EQ_FIELDS(PROC_SUBSTRUCT_HAS_FIELD, name)
};
struct sampler_cc_range
{
uint8_t locc;
uint8_t hicc;
uint8_t cc_number;
uint8_t has_locc:1;
uint8_t has_hicc:1;
uint8_t is_active:1;
};
struct sampler_midi_curve
{
float values[128];
uint8_t has_values[128];
};
#define PROC_FIELDS_TO_STRUCT(type, name, def_value) \
type name;
#define PROC_FIELDS_TO_STRUCT_string(name) \
gchar *name; \
gboolean name##_changed;
#define PROC_FIELDS_TO_STRUCT_dBamp(type, name, def_value) \
type name; \
type name##_linearized;
#define PROC_FIELDS_TO_STRUCT_enum(enumtype, name, def_value) \
enum enumtype name;
#define PROC_FIELDS_TO_STRUCT_dahdsr(name, parname, index) \
struct cbox_dahdsr name; \
struct cbox_envelope_shape name##_shape;
#define PROC_FIELDS_TO_STRUCT_lfo(name, parname, index) \
struct sampler_lfo_params name;
#define PROC_FIELDS_TO_STRUCT_eq(name, parname, index) \
struct sampler_eq_params name;
#define PROC_FIELDS_TO_STRUCT_ccrange(name, parname) \
struct sampler_cc_range name;
#define PROC_FIELDS_TO_STRUCT_midicurve(name) \
struct sampler_midi_curve name; \
float eff_##name[128];
#define PROC_HAS_FIELD(type, name, def_value) \
unsigned int has_##name:1;
#define PROC_HAS_FIELD_string(name) \
unsigned int has_##name:1;
#define PROC_HAS_FIELD_dBamp(type, name, def_value) \
PROC_HAS_FIELD(type, name, def_value)
#define PROC_HAS_FIELD_enum(enumtype, name, def_value) \
PROC_HAS_FIELD(type, name, def_value)
#define PROC_HAS_FIELD_dahdsr(name, parname, index) \
struct sampler_dahdsr_has_fields has_##name;
#define PROC_HAS_FIELD_lfo(name, parname, index) \
struct sampler_lfo_has_fields has_##name;
#define PROC_HAS_FIELD_eq(name, parname, index) \
struct sampler_eq_has_fields has_##name;
#define PROC_HAS_FIELD_ccrange(name, parname)
#define PROC_HAS_FIELD_midicurve(name)
CBOX_EXTERN_CLASS(sampler_layer)
enum sampler_layer_mod_bitmasks
{
slmb_ampeg_cc = 0x01,
slmb_fileg_cc = 0x02,
slmb_pitcheg_cc = 0x04,
};
struct sampler_layer_data
{
SAMPLER_FIXED_FIELDS(PROC_FIELDS_TO_STRUCT)
SAMPLER_FIXED_FIELDS(PROC_HAS_FIELD)
GSList *modulations;
GSList *voice_nifs, *prevoice_nifs;
// computed values:
float eff_freq;
gboolean eff_use_keyswitch;
gboolean eff_use_simple_trigger_logic;
enum sampler_loop_mode eff_loop_mode;
struct cbox_waveform *eff_waveform;
int16_t scratch_loop[2 * MAX_INTERPOLATION_ORDER * 2];
int16_t scratch_end[2 * MAX_INTERPOLATION_ORDER * 2];
float resonance_scaled, resonance2_scaled;
float logcutoff, logcutoff2;
uint32_t eq_bitmask, mod_bitmask;
gboolean eff_use_xfcc;
gboolean use_prevoice;
int eff_num_stages, eff_num_stages2;
};
struct sampler_layer
{
CBOX_OBJECT_HEADER()
struct cbox_command_target cmd_target;
struct sampler_layer_data data, *runtime;
struct sampler_module *module;
struct sampler_program *parent_program;
struct sampler_layer *parent, *default_child;
int current_seq_position;
GHashTable *unknown_keys;
GHashTable *child_layers;
};
extern struct sampler_layer *sampler_layer_new(struct sampler_module *m, struct sampler_program *parent_program, struct sampler_layer *parent_group);
extern struct sampler_layer *sampler_layer_new_from_section(struct sampler_module *m, struct sampler_program *parent_program, struct sampler_layer *parent_group, const char *cfg_section);
extern struct sampler_layer *sampler_layer_new_clone(struct sampler_layer *layer, struct sampler_module *m, struct sampler_program *parent_program, struct sampler_layer *parent_group);
extern void sampler_layer_set_modulation(struct sampler_layer *l, enum sampler_modsrc src, enum sampler_modsrc src2, enum sampler_moddest dest, float amount, int flags);
extern void sampler_layer_set_modulation1(struct sampler_layer *l, enum sampler_modsrc src, enum sampler_moddest dest, float amount, int flags);
extern void sampler_layer_add_nif(struct sampler_layer *l, SamplerNoteInitFunc notefunc_voice, SamplerNoteInitFunc2 notefunc_prevoice, int variant, float param);
extern void sampler_layer_load_overrides(struct sampler_layer *l, const char *cfg_section);
extern void sampler_layer_data_finalize(struct sampler_layer_data *l, struct sampler_layer_data *parent, struct sampler_program *p);
extern void sampler_layer_reset_switches(struct sampler_layer *l, struct sampler_module *m);
extern gboolean sampler_layer_apply_param(struct sampler_layer *l, const char *key, const char *value, GError **error);
extern gboolean sampler_layer_unapply_param(struct sampler_layer *l, const char *key, GError **error);
extern gchar *sampler_layer_to_string(struct sampler_layer *l, gboolean show_inherited);
extern void sampler_layer_dump(struct sampler_layer *l, FILE *f);
extern void sampler_layer_update(struct sampler_layer *l);
extern void sampler_layer_data_clone(struct sampler_layer_data *dst, const struct sampler_layer_data *src, gboolean copy_hasattr);
extern void sampler_layer_data_close(struct sampler_layer_data *l);
extern void sampler_layer_data_destroy(struct sampler_layer_data *l);
extern void sampler_nif_vel2pitch(struct sampler_noteinitfunc *nif, struct sampler_voice *v);
extern void sampler_nif_vel2offset(struct sampler_noteinitfunc *nif, struct sampler_voice *v);
extern void sampler_nif_vel2reloffset(struct sampler_noteinitfunc *nif, struct sampler_voice *v);
extern void sampler_nif_vel2env(struct sampler_noteinitfunc *nif, struct sampler_voice *v);
extern void sampler_nif_cc2offset(struct sampler_noteinitfunc *nif, struct sampler_voice *v);
extern void sampler_nif_cc2reloffset(struct sampler_noteinitfunc *nif, struct sampler_voice *v);
extern void sampler_nif_addrandom(struct sampler_noteinitfunc *nif, struct sampler_voice *v);
extern void sampler_nif_cc2delay(struct sampler_noteinitfunc *nif, struct sampler_prevoice *pv);
extern void sampler_nif_addrandomdelay(struct sampler_noteinitfunc *nif, struct sampler_prevoice *pv);
extern void sampler_nif_syncbeats(struct sampler_noteinitfunc *nif, struct sampler_prevoice *pv);
extern void sampler_midi_curve_init(struct sampler_midi_curve *curve);
extern void sampler_midi_curve_interpolate(const struct sampler_midi_curve *curve, float dest[128], float def_start, float def_end, gboolean is_quadratic);
#endif