// -------------------------------------------------------------- // -------------------------------------------------------------- #include #include #include #include #include "synth_defs.h" #include "vcf.h" #include "voice.h" #include "param_scale.h" static const param_info_t param_info[] = { { SYNTH_PARAM_VOLUME, "Master Volume", /*Base*/10.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_VOICE_PAN_SPREAD, "Voice Pan Spread", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_TUNE, "Master Tune", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.1 }, { SYNTH_PARAM_TOTAL_NUM_VOICES, "Total num. Voices", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/MAX_POLYPHONY, /*interval*/1 }, { SYNTH_PARAM_HUMANIZE_ENABLE, "Humanize Enable", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1 }, { SYNTH_PARAM_HUMANIZE_VAR_VCO, "Humanize Spread VCO", /*Base*/10.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_HUMANIZE_VAR_VCF, "Humanize Spread VCF", /*Base*/10.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_HUMANIZE_VAR_ENV, "Humanize Spread ENV", /*Base*/10.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_MONOPHONIC_ENABLE, "Monophonic Enable", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1 }, { SYNTH_PARAM_MONOPHONIC_RETRIGGER_ENABLE, "Monophonic Retrigger Enable", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1 }, { SYNTH_PARAM_UNISONO_ENABLE, "Unisono Enable", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1 }, { SYNTH_PARAM_UNISONO_NUM_VOICES, "Unisono num. Voices", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/MAX_POLYPHONY, /*interval*/1 }, { SYNTH_PARAM_PORTAMENTO_TIME, "Portamento Time", /*Base*/10.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0.001, /*pcenter*/-1, /*max*/0.5, /*interval*/0.001 }, { SYNTH_PARAM_OSC_0_ENABLE, "OSC1 enable", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1 }, { SYNTH_PARAM_OSC_1_ENABLE, "OSC2 enable", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1 }, { SYNTH_PARAM_OSC_0_RESTART_ON_TRIGGER, "OSC1 restart on trigger", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1 }, { SYNTH_PARAM_OSC_1_RESTART_ON_TRIGGER, "OSC2 restart on trigger", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1 }, { SYNTH_PARAM_OSC_0_LEVEL, "OSC1 level", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_OSC_1_LEVEL, "OSC2 level", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_OSC_0_DUTYCYCLE, "OSC1 pulse width", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_OSC_1_DUTYCYCLE, "OSC2 pulse width", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_OSC_0_DETUNE, "OSC1 detune", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-50, /*pcenter*/0, /*max*/+50, /*interval*/0.1 }, { SYNTH_PARAM_OSC_1_DETUNE, "OSC2 detune", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-50, /*pcenter*/0, /*max*/+50, /*interval*/0.1 }, { SYNTH_PARAM_OSC_0_TRANSPOSE, "OSC1 transpose", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-48.0, /*pcenter*/0, /*max*/+48.0, /*interval*/1 }, { SYNTH_PARAM_OSC_1_TRANSPOSE, "OSC2 transpose", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-48.0, /*pcenter*/0, /*max*/+48.0, /*interval*/1 }, { SYNTH_PARAM_OSC_0_WAVEFORM, "OSC1 shape", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/OSC_NUM_WAVEFORMS-1, /*interval*/1 }, { SYNTH_PARAM_OSC_1_WAVEFORM, "OSC2 shape", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/OSC_NUM_WAVEFORMS-1, /*interval*/1 }, { SYNTH_PARAM_OSC_0_PB_RANGE_MIN, "OSC1 pitch bender minimum", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-48.0, /*pcenter*/0, /*max*/+48.0, /*interval*/1 }, { SYNTH_PARAM_OSC_1_PB_RANGE_MIN, "OSC2 pitch bender minimum", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-48.0, /*pcenter*/0, /*max*/+48.0, /*interval*/1 }, { SYNTH_PARAM_OSC_0_PB_RANGE_MAX, "OSC1 pitch bender maximum", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-48.0, /*pcenter*/0, /*max*/+48.0, /*interval*/1 }, { SYNTH_PARAM_OSC_1_PB_RANGE_MAX, "OSC2 pitch bender maximum", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-48.0, /*pcenter*/0, /*max*/+48.0, /*interval*/1 }, { SYNTH_PARAM_OSC_0_FM_AMT_0, "OSC1 FM amt 1", /*Base*/10, /*kexp*/2.5, /*scenter*/0.5, /*min*/-48, /*pcenter*/0, /*max*/+48, /*interval*/0.01 }, { SYNTH_PARAM_OSC_1_FM_AMT_0, "OSC2 FM amt 1", /*Base*/10, /*kexp*/2.5, /*scenter*/0.5, /*min*/-48, /*pcenter*/0, /*max*/+48, /*interval*/0.01 }, { SYNTH_PARAM_OSC_0_FM_AMT_1, "OSC1 FM amt 2", /*Base*/1, /*kexp*/1, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.01 }, { SYNTH_PARAM_OSC_1_FM_AMT_1, "OSC2 FM amt 2", /*Base*/1, /*kexp*/1, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.01 }, { SYNTH_PARAM_OSC_0_FM_SRC_0, "OSC1 FM src 1", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1 }, { SYNTH_PARAM_OSC_1_FM_SRC_0, "OSC2 FM src 1", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1 }, { SYNTH_PARAM_OSC_0_FM_SRC_1, "OSC1 FM src 2", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1 }, { SYNTH_PARAM_OSC_1_FM_SRC_1, "OSC2 FM src 2", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1 }, { SYNTH_PARAM_OSC_0_FM_SRC_OP, "OSC1 FM src OP", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1 }, { SYNTH_PARAM_OSC_1_FM_SRC_OP, "OSC2 FM src OP", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1 }, { SYNTH_PARAM_OSC_0_AM_AMT_0, "OSC1 AM amt 1", /*Base*/1, /*kexp*/1, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.01 }, { SYNTH_PARAM_OSC_1_AM_AMT_0, "OSC2 AM amt 1", /*Base*/1, /*kexp*/1, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.01 }, { SYNTH_PARAM_OSC_0_AM_AMT_1, "OSC1 AM amt 2", /*Base*/1, /*kexp*/1, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.01 }, { SYNTH_PARAM_OSC_1_AM_AMT_1, "OSC2 AM amt 2", /*Base*/1, /*kexp*/1, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.01 }, { SYNTH_PARAM_OSC_0_AM_SRC_0, "OSC1 AM src 1", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1 }, { SYNTH_PARAM_OSC_1_AM_SRC_0, "OSC2 AM src 1", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1 }, { SYNTH_PARAM_OSC_0_AM_SRC_1, "OSC1 AM src 2", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1 }, { SYNTH_PARAM_OSC_1_AM_SRC_1, "OSC2 AM src 2", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1 }, { SYNTH_PARAM_OSC_0_AM_SRC_OP, "OSC1 AM src OP", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1 }, { SYNTH_PARAM_OSC_1_AM_SRC_OP, "OSC2 AM src OP", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1 }, { SYNTH_PARAM_OSC_0_PWM_AMT_0, "OSC1 PWM amt 1", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.1 }, { SYNTH_PARAM_OSC_1_PWM_AMT_0, "OSC2 PWM amt 1", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.1 }, { SYNTH_PARAM_OSC_0_PWM_AMT_1, "OSC1 PWM amt 2", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.1 }, { SYNTH_PARAM_OSC_1_PWM_AMT_1, "OSC2 PWM amt 2", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.1 }, { SYNTH_PARAM_OSC_0_PWM_SRC_0, "OSC1 PWM src 1", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1 }, { SYNTH_PARAM_OSC_1_PWM_SRC_0, "OSC2 PWM src 1", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1 }, { SYNTH_PARAM_OSC_0_PWM_SRC_1, "OSC1 PWM src 2", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1 }, { SYNTH_PARAM_OSC_1_PWM_SRC_1, "OSC2 PWM src 2", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1 }, { SYNTH_PARAM_OSC_0_PWM_SRC_OP, "OSC1 PWM src OP", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1 }, { SYNTH_PARAM_OSC_1_PWM_SRC_OP, "OSC2 PWM src OP", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1 }, { SYNTH_PARAM_NOISE_ENABLE, "Noise enable", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1, /*interval*/1 }, { SYNTH_PARAM_NOISE_LEVEL, "Noise level", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_NOISE_SHAPE, "Noise shape", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NOISE_NUM_SHAPES-1, /*interval*/1 }, { SYNTH_PARAM_VCA_ENV_AMT, "VCA Env amt", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_VCA_AM_AMT_0, "VCA AM amt 1", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_VCA_AM_SRC_0, "VCA AM src 1", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1 }, { SYNTH_PARAM_VCA_PAN_AMT_0, "VCA PAN amt 1", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_VCA_PAN_SRC_0, "VCA PAN src 1", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1 }, { SYNTH_PARAM_VCA_ENV_A, "VCA Attack", /*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1 }, { SYNTH_PARAM_VCA_ENV_D, "VCA Decay", /*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1 }, { SYNTH_PARAM_VCA_ENV_S, "VCA Sustain", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_VCF_ENV_A, "VCF Attack", /*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1 }, { SYNTH_PARAM_VCF_ENV_D, "VCF Decay", /*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1 }, { SYNTH_PARAM_VCF_ENV_S, "VCF Sustain", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_VCF_ENV_R, "VCF Release", /*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1 }, { SYNTH_PARAM_ENV_2_A, "ENV 2 Attack", /*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1 }, { SYNTH_PARAM_ENV_2_D, "ENV 2 Decay", /*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1 }, { SYNTH_PARAM_ENV_2_S, "ENV 2 Sustain", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_ENV_2_R, "ENV 2 Release", /*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1 }, { SYNTH_PARAM_ENV_3_A, "ENV 3 Attack", /*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1 }, { SYNTH_PARAM_ENV_3_D, "ENV 3 Decay", /*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1 }, { SYNTH_PARAM_ENV_3_S, "ENV 3 Sustain", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_ENV_3_R, "ENV 3 Release", /*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1 }, { SYNTH_PARAM_VCA_ENV_R, "VCA Release", /*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1 }, { SYNTH_PARAM_VCF_TYPE, "VCF type", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VCF_NUM_FILTERTYPES-1, /*interval*/1 }, { SYNTH_PARAM_VCF_ORDER, "VCF order", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VCF_NUM_FILTERORDER-1, /*interval*/1 }, { SYNTH_PARAM_VCF_F, "VCF Cutoff", /*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/FILTER_F_MIN, /*pcenter*/-1, /*max*/FILTER_F_MAX, /*interval*/0.1 }, { SYNTH_PARAM_VCF_Q, "VCF Res", /*Base*/10, /*kexp*/2.0, /*scenter*/0.0, /*min*/FILTER_Q_MIN, /*pcenter*/-1, /*max*/FILTER_Q_MAX, /*interval*/0.1 }, { SYNTH_PARAM_VCF_ENV_AMT, "VCF Env amt", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_VCF_F_AMT_0, "VCF Cutoff amt 1", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_VCF_F_AMT_1, "VCF Cutoff amt 2", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_VCF_F_SRC_0, "VCF Cutoff src 1", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1 }, { SYNTH_PARAM_VCF_F_SRC_1, "VCF Cutoff src 2", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1 }, { SYNTH_PARAM_VCF_F_SRC_OP, "VCF Cutoff src OP", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1 }, { SYNTH_PARAM_VCF_Q_AMT_0, "VCF Resonance amt 1", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_VCF_Q_AMT_1, "VCF Resonance amt 2", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_VCF_Q_SRC_0, "VCF Resonance src 1", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1 }, { SYNTH_PARAM_VCF_Q_SRC_1, "VCF Resonance src 2", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1 }, { SYNTH_PARAM_VCF_Q_SRC_OP, "VCF Resonance src OP", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1 }, { SYNTH_PARAM_LFO_0_SPEED, "LFO 1 speed", /*Base*/20, /*kexp*/1.0, /*scenter*/0.0, /*min*/0.01, /*pcenter*/-1, /*max*/200.0, /*interval*/0.01 }, { SYNTH_PARAM_LFO_1_SPEED, "LFO 2 speed", /*Base*/20, /*kexp*/1.0, /*scenter*/0.0, /*min*/0.01, /*pcenter*/-1, /*max*/200.0, /*interval*/0.01 }, { SYNTH_PARAM_LFO_2_SPEED, "LFO 3 speed", /*Base*/20, /*kexp*/1.0, /*scenter*/0.0, /*min*/0.01, /*pcenter*/-1, /*max*/200.0, /*interval*/0.01 }, { SYNTH_PARAM_LFO_3_SPEED, "LFO 4 speed", /*Base*/20, /*kexp*/1.0, /*scenter*/0.0, /*min*/0.01, /*pcenter*/-1, /*max*/200.0, /*interval*/0.01 }, { SYNTH_PARAM_LFO_0_SMOOTH, "LFO 1 smooth", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_LFO_1_SMOOTH, "LFO 2 smooth", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_LFO_2_SMOOTH, "LFO 3 smooth", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_LFO_3_SMOOTH, "LFO 4 smooth", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_LFO_0_DELAY, "LFO 1 Delay", /*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/30000, /*interval*/1 }, { SYNTH_PARAM_LFO_1_DELAY, "LFO 2 Delay", /*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/30000, /*interval*/1 }, { SYNTH_PARAM_LFO_2_DELAY, "LFO 3 Delay", /*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/30000, /*interval*/1 }, { SYNTH_PARAM_LFO_3_DELAY, "LFO 4 Delay", /*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/30000, /*interval*/1 }, { SYNTH_PARAM_LFO_0_ATTACK, "LFO 1 Attack", /*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1 }, { SYNTH_PARAM_LFO_1_ATTACK, "LFO 2 Attack", /*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1 }, { SYNTH_PARAM_LFO_2_ATTACK, "LFO 3 Attack", /*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1 }, { SYNTH_PARAM_LFO_3_ATTACK, "LFO 4 Attack", /*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1 }, { SYNTH_PARAM_LFO_0_SHAPE, "LFO 1 shape", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/LFO_NUM_WAVEFORMS-1, /*interval*/1 }, { SYNTH_PARAM_LFO_1_SHAPE, "LFO 2 shape", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/LFO_NUM_WAVEFORMS-1, /*interval*/1 }, { SYNTH_PARAM_LFO_2_SHAPE, "LFO 3 shape", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/LFO_NUM_WAVEFORMS-1, /*interval*/1 }, { SYNTH_PARAM_LFO_3_SHAPE, "LFO 4 shape", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/LFO_NUM_WAVEFORMS-1, /*interval*/1 }, { SYNTH_PARAM_LFO_0_MODE, "LFO 1 mode", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_MODES-1, /*interval*/1 }, { SYNTH_PARAM_LFO_1_MODE, "LFO 2 mode", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_MODES-1, /*interval*/1 }, { SYNTH_PARAM_LFO_2_MODE, "LFO 3 mode", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_MODES-1, /*interval*/1 }, { SYNTH_PARAM_LFO_3_MODE, "LFO 4 mode", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_MODES-1, /*interval*/1 }, { SYNTH_PARAM_LFO_0_SYNC, "LFO 1 sync", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_SYNCS-1, /*interval*/1 }, { SYNTH_PARAM_LFO_1_SYNC, "LFO 2 sync", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_SYNCS-1, /*interval*/1 }, { SYNTH_PARAM_LFO_2_SYNC, "LFO 3 sync", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_SYNCS-1, /*interval*/1 }, { SYNTH_PARAM_LFO_3_SYNC, "LFO 4 sync", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_SYNCS-1, /*interval*/1 }, { SYNTH_PARAM_LFO_0_SYMMETRY, "LFO 1 symmetry", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_LFO_1_SYMMETRY, "LFO 2 symmetry", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_LFO_2_SYMMETRY, "LFO 3 symmetry", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1 }, { SYNTH_PARAM_LFO_3_SYMMETRY, "LFO 4 symmetry", /*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1 } }; // -------------------------------------------------------------- // Exported functions // -------------------------------------------------------------- synth_float_t quantizeParam(param_info_t *pObj, synth_float_t p) { synth_float_t k, pq; if (pObj->pinterval == 0) return p; k = (synth_float_t)1/(pObj->pinterval - 0); if (p < 0) pq = ((int)(p*k - 0.5))*pObj->pinterval; else pq = ((int)(p*k + 0.5))*pObj->pinterval; return pq; } synth_float_t clampParam(param_info_t *pObj, synth_float_t p) { return (synth_float_t)min(pObj->pmax, max(pObj->pmin, quantizeParam(pObj, p))); } synth_float_t toParam(param_info_t *pObj, synth_float_t s) { synth_float_t p, pcenter; synth_float_t pmax, pmin, base, kexp, scenter; pmax = pObj->pmax; pmin = pObj->pmin; if (pmin == pmax) pmax += 1E-9; base = pObj->base; kexp = pObj->kexp; if (kexp == 0) kexp = 1E-9; scenter = pObj->scenter; pcenter = pObj->pcenter; if ((pcenter < pmin) || (pcenter > pmax)) pcenter = pmax*scenter + pmin*(1-scenter); s = (synth_float_t)min(1, max(0, s)); if (s < scenter) { if (base == 1) { // pcenter-(pcenter-pmin)*(scenter-s)/scenter; p = pcenter-(pcenter-pmin)*(scenter-s)/scenter; } else { // pcenter-(pcenter-pmin)*(B^(k*(scenter-s)/scenter)-1)/(B^k-1); p = pcenter-(pcenter-pmin)*(pow(base,kexp*(scenter-s)/scenter)-1)/(pow(base,kexp)-1); } } else { if (base == 1) { // pcenter+(pmax-pcenter)*(-scenter+s)/(1-scenter); p = pcenter+(pmax-pcenter)*(-scenter+s)/(1-scenter); } else { // pcenter+(pmax-pcenter)*(B^(k*(-scenter+s)/(1-scenter))-1)/(B^k-1); p = pcenter+(pmax-pcenter)*(pow(base,kexp*(-scenter+s)/(1-scenter))-1)/(pow(base,kexp)-1); } } return quantizeParam(pObj, p); } synth_float_t toSlider(param_info_t *pObj, synth_float_t p) { synth_float_t s, pcenter; synth_float_t pmax, pmin, base, kexp, scenter; pmax = pObj->pmax; pmin = pObj->pmin; if (pmin == pmax) pmax += 1E-9; base = pObj->base; kexp = pObj->kexp; if (kexp == 0) kexp = 1E-9; scenter = pObj->scenter; pcenter = pObj->pcenter; if ((pcenter < pmin) || (pcenter > pmax)) pcenter = pmax*scenter + pmin*(1-scenter); p = clampParam(pObj, p); if (p < pcenter) { if (base == 1) { // (-pmin+p)*scenter/(pcenter-pmin); s = (-pmin+p)*scenter/(pcenter-pmin); } else { // scenter*(log(B)*k-log(-(-pcenter*B^k+pmin+p*B^k-p)/(pcenter-pmin)))/log(B)/k; s = scenter*(log(base)*kexp-log(-(-pcenter*pow(base,kexp)+pmin+p*pow(base,kexp)-p)/(pcenter-pmin)))/log(base)/kexp; } } else { if (base == 1) { // (pcenter-scenter*pmax-p+scenter*p)/(-pmax+pcenter); s = (pcenter-scenter*pmax-p+scenter*p)/(-pmax+pcenter); } else { // (k*log(B)*scenter+log(-(-pcenter*B^k+pmax+p*B^k-p)/(-pmax+pcenter))-log(-(-pcenter*B^k+pmax+p*B^k-p)/(-pmax+pcenter))*scenter)/log(B)/k; s = (kexp*log(base)*scenter+log(-(-pcenter*pow(base,kexp)+pmax+p*pow(base,kexp)-p)/(-pmax+pcenter))-log(-(-pcenter*pow(base,kexp)+pmax+p*pow(base,kexp)-p)/(-pmax+pcenter))*scenter)/log(base)/kexp; } } return s; } void paramInfoInit(param_info_t *pObj, UINT32 id, const char *pName) { pObj->id = id; pObj->pName = NULL; if (pName) { pObj->pName = (char*)malloc(strlen(pName)+1); memcpy(pObj->pName, pName, strlen(pName)+1); } pObj->base = 1; pObj->kexp = 1; pObj->scenter = 0; pObj->pmin = 0; pObj->pcenter = 0; pObj->pmax = 1; pObj->pinterval = 0; } void paramInfoFree(param_info_t *pObj) { if (pObj->pName) free(pObj->pName); } void paramInfoSetPMIN(param_info_t *pObj, synth_float_t value) { pObj->pmin = value; } void paramInfoSetPMAX(param_info_t *pObj, synth_float_t value) { pObj->pmax = value; } void paramInfoSet(param_info_t *pObj, synth_float_t base, synth_float_t kexp, synth_float_t scenter, synth_float_t pmin, synth_float_t pcenter, synth_float_t pmax, synth_float_t pinterval) { pObj->base = base; pObj->kexp = kexp; pObj->scenter = scenter; pObj->pmin = pmin; pObj->pcenter = pcenter; pObj->pmax = pmax; pObj->pinterval = pinterval; } void paramInfoCopy(param_info_t *pDst, param_info_t const *pSrc) { pDst->base = pSrc->base; pDst->kexp = pSrc->kexp; pDst->scenter = pSrc->scenter; pDst->pmin = pSrc->pmin; pDst->pcenter = pSrc->pcenter; pDst->pmax = pSrc->pmax; pDst->pinterval = pSrc->pinterval; } param_info_t* getParamInfo(UINT32 type) { UINT32 i; if (type >= SYNTH_NUM_PARAMS) return NULL; for (i=0; i < SYNTH_NUM_PARAMS; i++) { if (param_info[i].id == type) break; } if (i == SYNTH_NUM_PARAMS) return NULL; return (param_info_t*)¶m_info[i]; }