summaryrefslogtreecommitdiff
path: root/libs/fluidsynth/src/fluid_adsr_env.h
diff options
context:
space:
mode:
Diffstat (limited to 'libs/fluidsynth/src/fluid_adsr_env.h')
-rw-r--r--libs/fluidsynth/src/fluid_adsr_env.h162
1 files changed, 162 insertions, 0 deletions
diff --git a/libs/fluidsynth/src/fluid_adsr_env.h b/libs/fluidsynth/src/fluid_adsr_env.h
new file mode 100644
index 0000000000..31303a9ce9
--- /dev/null
+++ b/libs/fluidsynth/src/fluid_adsr_env.h
@@ -0,0 +1,162 @@
+/* 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 Library General Public License
+ * as published by the Free Software Foundation; either version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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;
+ }
+
+ env->val = x;
+ env->count++;
+}
+
+/* This one cannot be inlined since it is referenced in
+ the event queue */
+void
+fluid_adsr_env_set_data(fluid_adsr_env_t* env,
+ fluid_adsr_env_section_t section,
+ unsigned int count,
+ fluid_real_t coeff,
+ fluid_real_t increment,
+ fluid_real_t min,
+ fluid_real_t max);
+
+static inline void
+fluid_adsr_env_reset(fluid_adsr_env_t* env)
+{
+ env->count = 0;
+ env->section = 0;
+ env->val = 0.0f;
+}
+
+static inline fluid_real_t
+fluid_adsr_env_get_val(fluid_adsr_env_t* env)
+{
+ return env->val;
+}
+
+static inline void
+fluid_adsr_env_set_val(fluid_adsr_env_t* env, fluid_real_t val)
+{
+ env->val = val;
+}
+
+static inline fluid_adsr_env_section_t
+fluid_adsr_env_get_section(fluid_adsr_env_t* env)
+{
+ return env->section;
+}
+
+static 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 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
+