#include "fluid_mod.h"
#include "fluid_chan.h"
#include "fluid_voice.h"
void
fluid_mod_clone(fluid_mod_t* mod, fluid_mod_t* src)
{
mod->dest = src->dest;
mod->src1 = src->src1;
mod->flags1 = src->flags1;
mod->src2 = src->src2;
mod->flags2 = src->flags2;
mod->amount = src->amount;
}
void
fluid_mod_set_source1(fluid_mod_t* mod, int src, int flags)
{
mod->src1 = src;
mod->flags1 = flags;
}
void
fluid_mod_set_source2(fluid_mod_t* mod, int src, int flags)
{
mod->src2 = src;
mod->flags2 = flags;
}
void
fluid_mod_set_dest(fluid_mod_t* mod, int dest)
{
mod->dest = dest;
}
void
fluid_mod_set_amount(fluid_mod_t* mod, double amount)
{
mod->amount = (double) amount;
}
int fluid_mod_get_source1(fluid_mod_t* mod)
{
return mod->src1;
}
int fluid_mod_get_flags1(fluid_mod_t* mod)
{
return mod->flags1;
}
int fluid_mod_get_source2(fluid_mod_t* mod)
{
return mod->src2;
}
int fluid_mod_get_flags2(fluid_mod_t* mod)
{
return mod->flags2;
}
int fluid_mod_get_dest(fluid_mod_t* mod)
{
return mod->dest;
}
double fluid_mod_get_amount(fluid_mod_t* mod)
{
return (fluid_real_t) mod->amount;
}
fluid_real_t
fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voice)
{
fluid_real_t v1 = 0.0, v2 = 1.0;
fluid_real_t range1 = 127.0, range2 = 127.0;
if (chan == NULL) {
return 0.0f;
}
if ((mod->src2 == FLUID_MOD_VELOCITY) &&
(mod->src1 == FLUID_MOD_VELOCITY) &&
(mod->flags1 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR
| FLUID_MOD_NEGATIVE | FLUID_MOD_LINEAR)) &&
(mod->flags2 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR
| FLUID_MOD_POSITIVE | FLUID_MOD_SWITCH)) &&
(mod->dest == GEN_FILTERFC)) {
return 0; }
if (mod->src1 > 0) {
if (mod->flags1 & FLUID_MOD_CC) {
v1 = fluid_channel_get_cc(chan, mod->src1);
} else {
switch (mod->src1) {
case FLUID_MOD_NONE:
v1 = range1;
break;
case FLUID_MOD_VELOCITY:
v1 = voice->vel;
break;
case FLUID_MOD_KEY:
v1 = voice->key;
break;
case FLUID_MOD_KEYPRESSURE:
v1 = fluid_channel_get_key_pressure(chan, voice->key);
break;
case FLUID_MOD_CHANNELPRESSURE:
v1 = chan->channel_pressure;
break;
case FLUID_MOD_PITCHWHEEL:
v1 = chan->pitch_bend;
range1 = 0x4000;
break;
case FLUID_MOD_PITCHWHEELSENS:
v1 = chan->pitch_wheel_sensitivity;
break;
default:
v1 = 0.0;
}
}
switch (mod->flags1 & 0x0f) {
case 0:
v1 /= range1;
break;
case 1:
v1 = 1.0f - v1 / range1;
break;
case 2:
v1 = -1.0f + 2.0f * v1 / range1;
break;
case 3:
v1 = 1.0f - 2.0f * v1 / range1;
break;
case 4:
v1 = fluid_concave(v1);
break;
case 5:
v1 = fluid_concave(127 - v1);
break;
case 6:
v1 = (v1 > 64)? fluid_concave(2 * (v1 - 64)) : -fluid_concave(2 * (64 - v1));
break;
case 7:
v1 = (v1 > 64)? -fluid_concave(2 * (v1 - 64)) : fluid_concave(2 * (64 - v1));
break;
case 8:
v1 = fluid_convex(v1);
break;
case 9:
v1 = fluid_convex(127 - v1);
break;
case 10:
v1 = (v1 > 64)? fluid_convex(2 * (v1 - 64)) : -fluid_convex(2 * (64 - v1));
break;
case 11:
v1 = (v1 > 64)? -fluid_convex(2 * (v1 - 64)) : fluid_convex(2 * (64 - v1));
break;
case 12:
v1 = (v1 >= 64)? 1.0f : 0.0f;
break;
case 13:
v1 = (v1 >= 64)? 0.0f : 1.0f;
break;
case 14:
v1 = (v1 >= 64)? 1.0f : -1.0f;
break;
case 15:
v1 = (v1 >= 64)? -1.0f : 1.0f;
break;
}
} else {
return 0.0;
}
if (v1 == 0.0f) {
return 0.0f;
}
if (mod->src2 > 0) {
if (mod->flags2 & FLUID_MOD_CC) {
v2 = fluid_channel_get_cc(chan, mod->src2);
} else {
switch (mod->src2) {
case FLUID_MOD_NONE:
v2 = range2;
break;
case FLUID_MOD_VELOCITY:
v2 = voice->vel;
break;
case FLUID_MOD_KEY:
v2 = voice->key;
break;
case FLUID_MOD_KEYPRESSURE:
v2 = fluid_channel_get_key_pressure(chan, voice->key);
break;
case FLUID_MOD_CHANNELPRESSURE:
v2 = chan->channel_pressure;
break;
case FLUID_MOD_PITCHWHEEL:
v2 = chan->pitch_bend;
break;
case FLUID_MOD_PITCHWHEELSENS:
v2 = chan->pitch_wheel_sensitivity;
break;
default:
v1 = 0.0f;
}
}
switch (mod->flags2 & 0x0f) {
case 0:
v2 /= range2;
break;
case 1:
v2 = 1.0f - v2 / range2;
break;
case 2:
v2 = -1.0f + 2.0f * v2 / range2;
break;
case 3:
v2 = -1.0f + 2.0f * v2 / range2;
break;
case 4:
v2 = fluid_concave(v2);
break;
case 5:
v2 = fluid_concave(127 - v2);
break;
case 6:
v2 = (v2 > 64)? fluid_concave(2 * (v2 - 64)) : -fluid_concave(2 * (64 - v2));
break;
case 7:
v2 = (v2 > 64)? -fluid_concave(2 * (v2 - 64)) : fluid_concave(2 * (64 - v2));
break;
case 8:
v2 = fluid_convex(v2);
break;
case 9:
v2 = 1.0f - fluid_convex(v2);
break;
case 10:
v2 = (v2 > 64)? -fluid_convex(2 * (v2 - 64)) : fluid_convex(2 * (64 - v2));
break;
case 11:
v2 = (v2 > 64)? -fluid_convex(2 * (v2 - 64)) : fluid_convex(2 * (64 - v2));
break;
case 12:
v2 = (v2 >= 64)? 1.0f : 0.0f;
break;
case 13:
v2 = (v2 >= 64)? 0.0f : 1.0f;
break;
case 14:
v2 = (v2 >= 64)? 1.0f : -1.0f;
break;
case 15:
v2 = (v2 >= 64)? -1.0f : 1.0f;
break;
}
} else {
v2 = 1.0f;
}
return (fluid_real_t) mod->amount * v1 * v2;
}
fluid_mod_t*
fluid_mod_new()
{
fluid_mod_t* mod = FLUID_NEW(fluid_mod_t);
if (mod == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory");
return NULL;
}
return mod;
};
void
fluid_mod_delete(fluid_mod_t * mod)
{
FLUID_FREE(mod);
};
int fluid_mod_test_identity(fluid_mod_t * mod1, fluid_mod_t * mod2){
if (mod1->dest != mod2->dest){return 0;};
if (mod1->src1 != mod2->src1){return 0;};
if (mod1->src2 != mod2->src2){return 0;};
if (mod1->flags1 != mod2->flags1){return 0;}
if (mod1->flags2 != mod2->flags2){return 0;}
return 1;
};
void fluid_dump_modulator(fluid_mod_t * mod){
int src1=mod->src1;
int dest=mod->dest;
int src2=mod->src2;
int flags1=mod->flags1;
int flags2=mod->flags2;
fluid_real_t amount=(fluid_real_t)mod->amount;
printf("Src: ");
if (flags1 & FLUID_MOD_CC){
printf("MIDI CC=%i",src1);
} else {
switch(src1){
case FLUID_MOD_NONE:
printf("None"); break;
case FLUID_MOD_VELOCITY:
printf("note-on velocity"); break;
case FLUID_MOD_KEY:
printf("Key nr"); break;
case FLUID_MOD_KEYPRESSURE:
printf("Poly pressure"); break;
case FLUID_MOD_CHANNELPRESSURE:
printf("Chan pressure"); break;
case FLUID_MOD_PITCHWHEEL:
printf("Pitch Wheel"); break;
case FLUID_MOD_PITCHWHEELSENS:
printf("Pitch Wheel sens"); break;
default:
printf("(unknown: %i)", src1);
};
};
if (flags1 & FLUID_MOD_NEGATIVE){printf("- ");} else {printf("+ ");};
if (flags1 & FLUID_MOD_BIPOLAR){printf("bip ");} else {printf("unip ");};
printf("-> ");
switch(dest){
case GEN_FILTERQ: printf("Q"); break;
case GEN_FILTERFC: printf("fc"); break;
case GEN_VIBLFOTOPITCH: printf("VibLFO-to-pitch"); break;
case GEN_MODENVTOPITCH: printf("ModEnv-to-pitch"); break;
case GEN_MODLFOTOPITCH: printf("ModLFO-to-pitch"); break;
case GEN_CHORUSSEND: printf("Chorus send"); break;
case GEN_REVERBSEND: printf("Reverb send"); break;
case GEN_PAN: printf("pan"); break;
case GEN_ATTENUATION: printf("att"); break;
default: printf("dest %i",dest);
};
printf(", amount %f flags %i src2 %i flags2 %i\n",amount, flags1, src2, flags2);
};