diff --git a/src/wildmidi/common.h b/src/wildmidi/common.h
index 44e90efdd..efe08dd25 100644
--- a/src/wildmidi/common.h
+++ b/src/wildmidi/common.h
@@ -27,14 +27,14 @@
#ifndef __COMMON_H
#define __COMMON_H
-#define SAMPLE_16BIT 0x01
-#define SAMPLE_UNSIGNED 0x02
-#define SAMPLE_LOOP 0x04
-#define SAMPLE_PINGPONG 0x08
-#define SAMPLE_REVERSE 0x10
-#define SAMPLE_SUSTAIN 0x20
-#define SAMPLE_ENVELOPE 0x40
-#define SAMPLE_CLAMPED 0x80
+#define SAMPLE_16BIT 0x01
+#define SAMPLE_UNSIGNED 0x02
+#define SAMPLE_LOOP 0x04
+#define SAMPLE_PINGPONG 0x08
+#define SAMPLE_REVERSE 0x10
+#define SAMPLE_SUSTAIN 0x20
+#define SAMPLE_ENVELOPE 0x40
+#define SAMPLE_CLAMPED 0x80
#ifdef DEBUG_SAMPLES
#define SAMPLE_CONVERT_DEBUG(dx) printf("\r%s\n",dx)
@@ -45,21 +45,23 @@
extern unsigned short int _WM_SampleRate;
struct _sample {
- unsigned long int data_length;
- unsigned long int loop_start;
- unsigned long int loop_end;
- unsigned long int loop_size;
+ unsigned int data_length;
+ unsigned int loop_start;
+ unsigned int loop_end;
+ unsigned int loop_size;
unsigned char loop_fraction;
- unsigned short int rate;
- unsigned long int freq_low;
- unsigned long int freq_high;
- unsigned long int freq_root;
+ unsigned short rate;
+ unsigned int freq_low;
+ unsigned int freq_high;
+ unsigned int freq_root;
unsigned char modes;
- signed long int env_rate[7];
- signed long int env_target[7];
- unsigned long int inc_div;
+ signed int env_rate[7];
+ signed int env_target[7];
+ unsigned int inc_div;
signed short *data;
struct _sample *next;
+
+ unsigned int note_off_decay;
};
struct _env {
diff --git a/src/wildmidi/gus_pat.cpp b/src/wildmidi/gus_pat.cpp
index be3422db5..83d311367 100644
--- a/src/wildmidi/gus_pat.cpp
+++ b/src/wildmidi/gus_pat.cpp
@@ -1,31 +1,26 @@
/*
- gus_pat.c
-
- Midi Wavetable Processing library
-
- Copyright (C) Chris Ison 2001-2011
- Copyright (C) Bret Curtis 2013-2014
-
- This file is part of WildMIDI.
-
- WildMIDI is free software: you can redistribute and/or modify the player
- under the terms of the GNU General Public License and you can redistribute
- and/or modify the library under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation, either version 3 of
- the licenses, or(at your option) any later version.
-
- WildMIDI 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 and
- the GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU General Public License and the
- GNU Lesser General Public License along with WildMIDI. If not, see
- .
+ * gus_pat.c -- Midi Wavetable Processing library
+ *
+ * Copyright (C) WildMIDI Developers 2001-2015
+ *
+ * This file is part of WildMIDI.
+ *
+ * WildMIDI is free software: you can redistribute and/or modify the player
+ * under the terms of the GNU General Public License and you can redistribute
+ * and/or modify the library under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either version 3 of
+ * the licenses, or(at your option) any later version.
+ *
+ * WildMIDI 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 and
+ * the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License and the
+ * GNU Lesser General Public License along with WildMIDI. If not, see
+ * .
*/
-//#include "config.h"
-
#include
#include
#include
@@ -737,6 +732,8 @@ struct _sample * _WM_load_gus_pat(const char *filename, int fix_release) {
};
unsigned long int tmp_loop;
+ /*unused*/fix_release;
+
SAMPLE_CONVERT_DEBUG(__FUNCTION__); SAMPLE_CONVERT_DEBUG(filename);
if ((gus_patch = _WM_BufferFile(filename, &gus_size)) == NULL) {
@@ -839,17 +836,80 @@ struct _sample * _WM_load_gus_pat(const char *filename, int fix_release) {
/*
FIXME: Experimental Hacky Fix
+
+ This looks for "dodgy" release envelope settings that faulty editors
+ may have set and attempts to corrects it.
+ if (fix_release)
+ Lets make this automatic ...
*/
- if (fix_release) {
- if (env_time_table[gus_patch[gus_ptr + 40]]
- < env_time_table[gus_patch[gus_ptr + 41]]) {
- unsigned char tmp_hack_rate = gus_patch[gus_ptr + 41];
- gus_patch[gus_ptr + 41] = gus_patch[gus_ptr + 40];
- gus_patch[gus_ptr + 40] = tmp_hack_rate;
+ {
+ /*
+ After studying faulty gus_pats this way may work better
+ Testing to determine if any further adjustments are required
+ */
+ if (env_time_table[gus_patch[gus_ptr + 40]] < env_time_table[gus_patch[gus_ptr + 41]]) {
+ unsigned char tmp_hack_rate = 0;
+
+ if (env_time_table[gus_patch[gus_ptr + 41]] < env_time_table[gus_patch[gus_ptr + 42]]) {
+ // 1 2 3
+ tmp_hack_rate = gus_patch[gus_ptr + 40];
+ gus_patch[gus_ptr + 40] = gus_patch[gus_ptr + 42];
+ gus_patch[gus_ptr + 42] = tmp_hack_rate;
+ } else if (env_time_table[gus_patch[gus_ptr + 41]] == env_time_table[gus_patch[gus_ptr + 42]]) {
+ // 1 2 2
+ tmp_hack_rate = gus_patch[gus_ptr + 40];
+ gus_patch[gus_ptr + 40] = gus_patch[gus_ptr + 42];
+ gus_patch[gus_ptr + 41] = gus_patch[gus_ptr + 42];
+ gus_patch[gus_ptr + 42] = tmp_hack_rate;
+
+ } else {
+ if (env_time_table[gus_patch[gus_ptr + 40]] < env_time_table[gus_patch[gus_ptr + 42]]) {
+ // 1 3 2
+ tmp_hack_rate = gus_patch[gus_ptr + 40];
+ gus_patch[gus_ptr + 40] = gus_patch[gus_ptr + 41];
+ gus_patch[gus_ptr + 41] = gus_patch[gus_ptr + 42];
+ gus_patch[gus_ptr + 42] = tmp_hack_rate;
+ } else {
+ // 2 3 1 or 1 2 1
+ tmp_hack_rate = gus_patch[gus_ptr + 40];
+ gus_patch[gus_ptr + 40] = gus_patch[gus_ptr + 41];
+ gus_patch[gus_ptr + 41] = tmp_hack_rate;
+ }
+ }
+ } else if (env_time_table[gus_patch[gus_ptr + 41]] < env_time_table[gus_patch[gus_ptr + 42]]) {
+ unsigned char tmp_hack_rate = 0;
+
+ if (env_time_table[gus_patch[gus_ptr + 40]] < env_time_table[gus_patch[gus_ptr + 42]]) {
+ // 2 1 3
+ tmp_hack_rate = gus_patch[gus_ptr + 40];
+ gus_patch[gus_ptr + 40] = gus_patch[gus_ptr + 42];
+ gus_patch[gus_ptr + 42] = gus_patch[gus_ptr + 41];
+ gus_patch[gus_ptr + 41] = tmp_hack_rate;
+ } else {
+ // 3 1 2
+ tmp_hack_rate = gus_patch[gus_ptr + 41];
+ gus_patch[gus_ptr + 41] = gus_patch[gus_ptr + 42];
+ gus_patch[gus_ptr + 42] = tmp_hack_rate;
+ }
}
+
+#if 0
+ if ((env_time_table[gus_patch[gus_ptr + 40]] < env_time_table[gus_patch[gus_ptr + 41]]) && (env_time_table[gus_patch[gus_ptr + 41]] == env_time_table[gus_patch[gus_ptr + 42]])) {
+ uint8_t tmp_hack_rate = 0;
+ tmp_hack_rate = gus_patch[gus_ptr + 41];
+ gus_patch[gus_ptr + 41] = gus_patch[gus_ptr + 40];
+ gus_patch[gus_ptr + 42] = gus_patch[gus_ptr + 40];
+ gus_patch[gus_ptr + 40] = tmp_hack_rate;
+ tmp_hack_rate = gus_patch[gus_ptr + 47];
+ gus_patch[gus_ptr + 47] = gus_patch[gus_ptr + 46];
+ gus_patch[gus_ptr + 48] = gus_patch[gus_ptr + 46];
+ gus_patch[gus_ptr + 46] = tmp_hack_rate;
+ }
+#endif
}
for (i = 0; i < 6; i++) {
+ GUSPAT_INT_DEBUG("Envelope #",i);
if (gus_sample->modes & SAMPLE_ENVELOPE) {
unsigned char env_rate = gus_patch[gus_ptr + 37 + i];
gus_sample->env_target[i] = 16448 * gus_patch[gus_ptr + 43 + i];
@@ -886,6 +946,32 @@ struct _sample * _WM_load_gus_pat(const char *filename, int fix_release) {
return NULL;
}
+ /*
+ Test and set decay expected decay time after a note off
+ NOTE: This sets samples for full range decay
+ */
+ if (gus_sample->modes & SAMPLE_ENVELOPE) {
+ double samples_f = 0.0;
+
+ if (gus_sample->modes & SAMPLE_CLAMPED) {
+ samples_f = (4194301.0 - (float)gus_sample->env_target[5]) / gus_sample->env_rate[5];
+ } else {
+ if (gus_sample->modes & SAMPLE_SUSTAIN) {
+ samples_f = (4194301.0 - (float)gus_sample->env_target[3]) / gus_sample->env_rate[3];
+ samples_f += (float)(gus_sample->env_target[3] - gus_sample->env_target[4]) / gus_sample->env_rate[4];
+ } else {
+ samples_f = (4194301.0 - (float)gus_sample->env_target[4]) / gus_sample->env_rate[4];
+ }
+ samples_f += (float)(gus_sample->env_target[4] - gus_sample->env_target[5]) / gus_sample->env_rate[5];
+ }
+ samples_f += (float)gus_sample->env_target[5] / gus_sample->env_rate[6];
+
+ gus_sample->note_off_decay = (unsigned)samples_f;
+
+ } else {
+ gus_sample->note_off_decay = gus_sample->data_length * _WM_SampleRate / gus_sample->rate;
+ }
+
gus_ptr += tmp_cnt;
gus_sample->loop_start = (gus_sample->loop_start << 10)
| (((gus_sample->loop_fraction & 0x0f) << 10) / 16);