13
0
livetrax/libs/fluidsynth/src/fluid_adsr_env.h

169 lines
4.0 KiB
C

/* FluidSynth - A Software Synthesizer
*
* Copyright (C) 2003 Peter Hanappe and others.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
*/
#ifndef _FLUID_ADSR_ENVELOPE_H
#define _FLUID_ADSR_ENVELOPE_H
#include "fluidsynth_priv.h"
#include "fluid_sys.h"
/*
* envelope data
*/
struct _fluid_env_data_t
{
unsigned int count;
fluid_real_t coeff;
fluid_real_t increment;
fluid_real_t min;
fluid_real_t max;
};
/* Indices for envelope tables */
enum fluid_voice_envelope_index_t
{
FLUID_VOICE_ENVDELAY,
FLUID_VOICE_ENVATTACK,
FLUID_VOICE_ENVHOLD,
FLUID_VOICE_ENVDECAY,
FLUID_VOICE_ENVSUSTAIN,
FLUID_VOICE_ENVRELEASE,
FLUID_VOICE_ENVFINISHED,
FLUID_VOICE_ENVLAST
};
typedef enum fluid_voice_envelope_index_t fluid_adsr_env_section_t;
typedef struct _fluid_adsr_env_t fluid_adsr_env_t;
struct _fluid_adsr_env_t
{
fluid_env_data_t data[FLUID_VOICE_ENVLAST];
unsigned int count;
int section;
fluid_real_t val; /* the current value of the envelope */
};
/* For performance, all functions are inlined */
static FLUID_INLINE void
fluid_adsr_env_calc(fluid_adsr_env_t *env, int is_volenv)
{
fluid_env_data_t *env_data;
fluid_real_t x;
env_data = &env->data[env->section];
/* skip to the next section of the envelope if necessary */
while(env->count >= env_data->count)
{
// If we're switching envelope stages from decay to sustain, force the value to be the end value of the previous stage
// Hmm, should this only apply to volenv? It was so before refactoring, so keep it for now. [DH]
if(env->section == FLUID_VOICE_ENVDECAY && is_volenv)
{
env->val = env_data->min * env_data->coeff;
}
env_data = &env->data[++env->section];
env->count = 0;
}
/* calculate the envelope value and check for valid range */
x = env_data->coeff * env->val + env_data->increment;
if(x < env_data->min)
{
x = env_data->min;
env->section++;
env->count = 0;
}
else if(x > env_data->max)
{
x = env_data->max;
env->section++;
env->count = 0;
}
else
{
env->count++;
}
env->val = x;
}
/* This one cannot be inlined since it is referenced in
the event queue */
DECLARE_FLUID_RVOICE_FUNCTION(fluid_adsr_env_set_data);
static FLUID_INLINE void
fluid_adsr_env_reset(fluid_adsr_env_t *env)
{
env->count = 0;
env->section = 0;
env->val = 0.0f;
}
static FLUID_INLINE fluid_real_t
fluid_adsr_env_get_val(fluid_adsr_env_t *env)
{
return env->val;
}
static FLUID_INLINE void
fluid_adsr_env_set_val(fluid_adsr_env_t *env, fluid_real_t val)
{
env->val = val;
}
static FLUID_INLINE fluid_adsr_env_section_t
fluid_adsr_env_get_section(fluid_adsr_env_t *env)
{
return env->section;
}
static FLUID_INLINE void
fluid_adsr_env_set_section(fluid_adsr_env_t *env,
fluid_adsr_env_section_t section)
{
env->section = section;
env->count = 0;
}
/* Used for determining which voice to kill.
Returns max amplitude from now, and forward in time.
*/
static FLUID_INLINE fluid_real_t
fluid_adsr_env_get_max_val(fluid_adsr_env_t *env)
{
if(env->section > FLUID_VOICE_ENVATTACK)
{
return env->val * 1000;
}
else
{
return env->data[FLUID_VOICE_ENVATTACK].max;
}
}
#endif