mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-08 22:11:09 +00:00
953 lines
24 KiB
C++
953 lines
24 KiB
C++
|
/*
|
||
|
|
||
|
TiMidity -- Experimental MIDI to WAVE converter
|
||
|
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
|
||
|
|
||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
|
|
||
|
instrum.c
|
||
|
|
||
|
Code to load and unload GUS-compatible instrument patches.
|
||
|
|
||
|
*/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <math.h>
|
||
|
|
||
|
#include "timidity.h"
|
||
|
#include "m_swap.h"
|
||
|
|
||
|
namespace Timidity
|
||
|
{
|
||
|
|
||
|
extern InstrumentLayer *load_instrument_dls(Renderer *song, int drum, int bank, int instrument);
|
||
|
|
||
|
/* Some functions get aggravated if not even the standard banks are
|
||
|
available. */
|
||
|
ToneBank standard_tonebank, standard_drumset;
|
||
|
|
||
|
/* This is only used for tracks that don't specify a program */
|
||
|
int default_program = DEFAULT_PROGRAM;
|
||
|
|
||
|
|
||
|
static void free_instrument(Instrument *ip)
|
||
|
{
|
||
|
Sample *sp;
|
||
|
int i;
|
||
|
if (ip == NULL)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
for (i = 0, sp = &(ip->sample[0]); i < ip->samples; i++, sp++)
|
||
|
{
|
||
|
if (sp->data != NULL)
|
||
|
{
|
||
|
free(sp->data);
|
||
|
}
|
||
|
}
|
||
|
for (i = 0, sp = &(ip->right_sample[0]); i < ip->right_samples; i++)
|
||
|
{
|
||
|
if (sp->data != NULL)
|
||
|
{
|
||
|
free(sp->data);
|
||
|
}
|
||
|
}
|
||
|
free(ip->sample);
|
||
|
if (ip->right_sample != NULL)
|
||
|
{
|
||
|
free(ip->right_sample);
|
||
|
}
|
||
|
free(ip);
|
||
|
}
|
||
|
|
||
|
|
||
|
static void free_layer(InstrumentLayer *lp)
|
||
|
{
|
||
|
InstrumentLayer *next;
|
||
|
|
||
|
for (; lp; lp = next)
|
||
|
{
|
||
|
next = lp->next;
|
||
|
free_instrument(lp->instrument);
|
||
|
free(lp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void free_bank(int dr, int b)
|
||
|
{
|
||
|
int i;
|
||
|
ToneBank *bank = ((dr) ? drumset[b] : tonebank[b]);
|
||
|
for (i = 0; i < MAXPROG; i++)
|
||
|
{
|
||
|
if (bank->tone[i].layer != NULL)
|
||
|
{
|
||
|
/* Not that this could ever happen, of course */
|
||
|
if (bank->tone[i].layer != MAGIC_LOAD_INSTRUMENT)
|
||
|
{
|
||
|
free_layer(bank->tone[i].layer);
|
||
|
bank->tone[i].layer = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
int convert_envelope_rate_attack(Renderer *song, BYTE rate, BYTE fastness)
|
||
|
{
|
||
|
int r;
|
||
|
|
||
|
r = 3 - ((rate>>6) & 0x3);
|
||
|
r *= 3;
|
||
|
r = (int)(rate & 0x3f) << r; /* 6.9 fixed point */
|
||
|
|
||
|
/* 15.15 fixed point. */
|
||
|
return int(((r * 44100) / song->rate) * song->control_ratio) << 10;
|
||
|
}
|
||
|
|
||
|
int convert_envelope_rate(Renderer *song, BYTE rate)
|
||
|
{
|
||
|
int r;
|
||
|
|
||
|
r = 3 - ((rate>>6) & 0x3);
|
||
|
r *= 3;
|
||
|
r = (int)(rate & 0x3f) << r; /* 6.9 fixed point */
|
||
|
|
||
|
/* 15.15 fixed point. */
|
||
|
return int(((r * 44100) / song->rate) * song->control_ratio)
|
||
|
<< ((song->fast_decay) ? 10 : 9);
|
||
|
}
|
||
|
|
||
|
int convert_envelope_offset(BYTE offset)
|
||
|
{
|
||
|
/* This is not too good... Can anyone tell me what these values mean?
|
||
|
Are they GUS-style "exponential" volumes? And what does that mean? */
|
||
|
|
||
|
/* 15.15 fixed point */
|
||
|
return offset << (7 + 15);
|
||
|
}
|
||
|
|
||
|
int convert_tremolo_sweep(Renderer *song, BYTE sweep)
|
||
|
{
|
||
|
if (!sweep)
|
||
|
return 0;
|
||
|
|
||
|
return
|
||
|
int(((song->control_ratio * SWEEP_TUNING) << SWEEP_SHIFT) / (song->rate * sweep));
|
||
|
}
|
||
|
|
||
|
int convert_vibrato_sweep(Renderer *song, BYTE sweep, int vib_control_ratio)
|
||
|
{
|
||
|
if (!sweep)
|
||
|
return 0;
|
||
|
|
||
|
return
|
||
|
(int) (FSCALE((double) (vib_control_ratio) * SWEEP_TUNING, SWEEP_SHIFT) / (song->rate * sweep));
|
||
|
|
||
|
/* this was overflowing with seashore.pat
|
||
|
|
||
|
((vib_control_ratio * SWEEP_TUNING) << SWEEP_SHIFT) / (song->rate * sweep);
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
int convert_tremolo_rate(Renderer *song, BYTE rate)
|
||
|
{
|
||
|
return
|
||
|
int(((song->control_ratio * rate) << RATE_SHIFT) / (TREMOLO_RATE_TUNING * song->rate));
|
||
|
}
|
||
|
|
||
|
int convert_vibrato_rate(Renderer *song, BYTE rate)
|
||
|
{
|
||
|
/* Return a suitable vibrato_control_ratio value */
|
||
|
return
|
||
|
int((VIBRATO_RATE_TUNING * song->rate) / (rate * 2 * VIBRATO_SAMPLE_INCREMENTS));
|
||
|
}
|
||
|
|
||
|
static void reverse_data(sample_t *sp, int ls, int le)
|
||
|
{
|
||
|
sample_t s, *ep = sp + le;
|
||
|
sp += ls;
|
||
|
le -= ls;
|
||
|
le /= 2;
|
||
|
while (le--)
|
||
|
{
|
||
|
s = *sp;
|
||
|
*sp++ = *ep;
|
||
|
*ep-- = s;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
If panning or note_to_use != -1, it will be used for all samples,
|
||
|
instead of the sample-specific values in the instrument file.
|
||
|
|
||
|
For note_to_use, any value <0 or >127 will be forced to 0.
|
||
|
|
||
|
For other parameters, 1 means yes, 0 means no, other values are
|
||
|
undefined.
|
||
|
|
||
|
TODO: do reverse loops right */
|
||
|
static InstrumentLayer *load_instrument(Renderer *song, const char *name, int font_type, int percussion,
|
||
|
int panning, int amp, int cfg_tuning, int note_to_use,
|
||
|
int strip_loop, int strip_envelope,
|
||
|
int strip_tail, int bank, int gm_num, int sf_ix)
|
||
|
{
|
||
|
InstrumentLayer *lp, *lastlp, *headlp;
|
||
|
Instrument *ip;
|
||
|
FILE *fp;
|
||
|
BYTE tmp[239];
|
||
|
int i,j;
|
||
|
bool noluck = false;
|
||
|
bool sf2flag = false;
|
||
|
int right_samples = 0;
|
||
|
int stereo_channels = 1, stereo_layer;
|
||
|
int vlayer_list[19][4], vlayer, vlayer_count;
|
||
|
|
||
|
if (!name) return 0;
|
||
|
|
||
|
/* Open patch file */
|
||
|
if ((fp = open_file(name, 1, OF_NORMAL)) == NULL)
|
||
|
{
|
||
|
/* Try with various extensions */
|
||
|
FString tmp = name;
|
||
|
tmp += ".pat";
|
||
|
if ((fp = open_file(tmp, 1, OF_NORMAL)) == NULL)
|
||
|
{
|
||
|
#ifdef unix // Windows isn't case-sensitive.
|
||
|
tmp.ToUpper();
|
||
|
if ((fp = open_file(tmp, 1, OF_NORMAL)) == NULL)
|
||
|
#endif
|
||
|
{
|
||
|
noluck = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (noluck)
|
||
|
{
|
||
|
song->ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Instrument `%s' can't be found.", name);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*song->ctl->cmsg(CMSG_INFO, VERB_NOISY, "Loading instrument %s", current_filename);*/
|
||
|
|
||
|
/* Read some headers and do cursory sanity checks. There are loads
|
||
|
of magic offsets. This could be rewritten... */
|
||
|
|
||
|
if ((239 != fread(tmp, 1, 239, fp)) ||
|
||
|
(memcmp(tmp, "GF1PATCH110\0ID#000002", 22) &&
|
||
|
memcmp(tmp, "GF1PATCH100\0ID#000002", 22))) /* don't know what the
|
||
|
differences are */
|
||
|
{
|
||
|
song->ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: not an instrument", name);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* patch layout:
|
||
|
* bytes: info: starts at offset:
|
||
|
* 12 header (see above) 0
|
||
|
* 10 Gravis ID 12
|
||
|
* 60 description 22
|
||
|
* 1 instruments 82
|
||
|
* 1 voices 83
|
||
|
* 1 channels 84
|
||
|
* 2 number of waveforms 85
|
||
|
* 2 master volume 87
|
||
|
* 4 datasize 89
|
||
|
* 36 reserved, but now: 93
|
||
|
* 7 "SF2EXT\0" id 93
|
||
|
* 1 right samples 100
|
||
|
* 28 reserved 101
|
||
|
* 2 instrument number 129
|
||
|
* 16 instrument name 131
|
||
|
* 4 instrument size 147
|
||
|
* 1 number of layers 151
|
||
|
* 40 reserved 152
|
||
|
* 1 layer duplicate 192
|
||
|
* 1 layer number 193
|
||
|
* 4 layer size 194
|
||
|
* 1 number of samples 198
|
||
|
* 40 reserved 199
|
||
|
* 239
|
||
|
* THEN, for each sample, see below
|
||
|
*/
|
||
|
|
||
|
if (!memcmp(tmp + 93, "SF2EXT", 6))
|
||
|
{
|
||
|
sf2flag = true;
|
||
|
vlayer_count = tmp[152];
|
||
|
}
|
||
|
|
||
|
if (tmp[82] != 1 && tmp[82] != 0) /* instruments. To some patch makers, 0 means 1 */
|
||
|
{
|
||
|
song->ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle patches with %d instruments", tmp[82]);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (tmp[151] != 1 && tmp[151] != 0) /* layers. What's a layer? */
|
||
|
{
|
||
|
song->ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle instruments with %d layers", tmp[151]);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
if (sf2flag && vlayer_count > 0)
|
||
|
{
|
||
|
for (i = 0; i < 9; i++)
|
||
|
for (j = 0; j < 4; j++)
|
||
|
vlayer_list[i][j] = tmp[153+i*4+j];
|
||
|
for (i = 9; i < 19; i++)
|
||
|
for (j = 0; j < 4; j++)
|
||
|
vlayer_list[i][j] = tmp[199+(i-9)*4+j];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (i = 0; i < 19; i++)
|
||
|
for (j = 0; j < 4; j++)
|
||
|
vlayer_list[i][j] = 0;
|
||
|
vlayer_list[0][0] = 0;
|
||
|
vlayer_list[0][1] = 127;
|
||
|
vlayer_list[0][2] = tmp[198];
|
||
|
vlayer_list[0][3] = 0;
|
||
|
vlayer_count = 1;
|
||
|
}
|
||
|
|
||
|
lastlp = 0;
|
||
|
|
||
|
for (vlayer = 0; vlayer < vlayer_count; vlayer++)
|
||
|
{
|
||
|
lp = (InstrumentLayer *)safe_malloc(sizeof(InstrumentLayer));
|
||
|
lp->lo = vlayer_list[vlayer][0];
|
||
|
lp->hi = vlayer_list[vlayer][1];
|
||
|
ip = (Instrument *)safe_malloc(sizeof(Instrument));
|
||
|
lp->instrument = ip;
|
||
|
lp->next = 0;
|
||
|
|
||
|
if (lastlp != NULL)
|
||
|
{
|
||
|
lastlp->next = lp;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
headlp = lp;
|
||
|
}
|
||
|
|
||
|
lastlp = lp;
|
||
|
|
||
|
ip->type = sf2flag ? INST_SF2 : INST_GUS;
|
||
|
ip->samples = vlayer_list[vlayer][2];
|
||
|
ip->sample = (Sample *)safe_malloc(sizeof(Sample) * ip->samples);
|
||
|
ip->left_samples = ip->samples;
|
||
|
ip->left_sample = ip->sample;
|
||
|
right_samples = vlayer_list[vlayer][3];
|
||
|
ip->right_samples = right_samples;
|
||
|
if (right_samples)
|
||
|
{
|
||
|
ip->right_sample = (Sample *)safe_malloc(sizeof(Sample) * right_samples);
|
||
|
stereo_channels = 2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ip->right_sample = NULL;
|
||
|
}
|
||
|
|
||
|
song->ctl->cmsg(CMSG_INFO, VERB_NOISY, "%s%s[%d,%d] %s(%d-%d layer %d of %d)",
|
||
|
(percussion)? " ":"", name,
|
||
|
(percussion)? note_to_use : gm_num, bank,
|
||
|
(right_samples)? "(2) " : "",
|
||
|
lp->lo, lp->hi, vlayer+1, vlayer_count);
|
||
|
|
||
|
for (stereo_layer = 0; stereo_layer < stereo_channels; stereo_layer++)
|
||
|
{
|
||
|
int sample_count;
|
||
|
|
||
|
if (stereo_layer == 0)
|
||
|
{
|
||
|
sample_count = ip->left_samples;
|
||
|
}
|
||
|
else if (stereo_layer == 1)
|
||
|
{
|
||
|
sample_count = ip->right_samples;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < sample_count; i++)
|
||
|
{
|
||
|
BYTE fractions;
|
||
|
int tmplong;
|
||
|
WORD tmpshort;
|
||
|
WORD sample_volume;
|
||
|
BYTE tmpchar;
|
||
|
Sample *sp;
|
||
|
BYTE sf2delay;
|
||
|
|
||
|
#define READ_CHAR(thing) \
|
||
|
if (1 != fread(&tmpchar, 1, 1, fp)) goto fail; \
|
||
|
thing = tmpchar;
|
||
|
#define READ_SHORT(thing) \
|
||
|
if (1 != fread(&tmpshort, 2, 1, fp)) goto fail; \
|
||
|
thing = LittleShort(tmpshort);
|
||
|
#define READ_LONG(thing) \
|
||
|
if (1 != fread(&tmplong, 4, 1, fp)) goto fail; \
|
||
|
thing = LittleLong(tmplong);
|
||
|
|
||
|
/*
|
||
|
* 7 sample name
|
||
|
* 1 fractions
|
||
|
* 4 length
|
||
|
* 4 loop start
|
||
|
* 4 loop end
|
||
|
* 2 sample rate
|
||
|
* 4 low frequency
|
||
|
* 4 high frequency
|
||
|
* 4 root frequency
|
||
|
* 2 finetune
|
||
|
* 1 panning
|
||
|
* 6 envelope rates |
|
||
|
* 6 envelope offsets | 18 bytes
|
||
|
* 3 tremolo sweep, rate, depth |
|
||
|
* 3 vibrato sweep, rate, depth |
|
||
|
* 1 sample mode
|
||
|
* 2 scale frequency
|
||
|
* 2 scale factor | from 0 to 2048 or 0 to 2
|
||
|
* 2 sample volume (??)
|
||
|
* 34 reserved
|
||
|
* Now: 1 delay
|
||
|
* 33 reserved
|
||
|
*/
|
||
|
skip(fp, 7); /* Skip the wave name */
|
||
|
|
||
|
if (1 != fread(&fractions, 1, 1, fp))
|
||
|
{
|
||
|
fail:
|
||
|
song->ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Error reading sample %d", i);
|
||
|
if (stereo_layer == 1)
|
||
|
{
|
||
|
for (j = 0; j < i; j++)
|
||
|
{
|
||
|
free(ip->right_sample[j].data);
|
||
|
}
|
||
|
free(ip->right_sample);
|
||
|
i = ip->left_samples;
|
||
|
}
|
||
|
for (j = 0; j < i; j++)
|
||
|
{
|
||
|
free(ip->left_sample[j].data);
|
||
|
}
|
||
|
free(ip->left_sample);
|
||
|
free(ip);
|
||
|
free(lp);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (stereo_layer == 0)
|
||
|
{
|
||
|
sp = &(ip->left_sample[i]);
|
||
|
}
|
||
|
else if (stereo_layer == 1)
|
||
|
{
|
||
|
sp = &(ip->right_sample[i]);
|
||
|
}
|
||
|
|
||
|
READ_LONG(sp->data_length);
|
||
|
READ_LONG(sp->loop_start);
|
||
|
READ_LONG(sp->loop_end);
|
||
|
READ_SHORT(sp->sample_rate);
|
||
|
READ_LONG(sp->low_freq);
|
||
|
READ_LONG(sp->high_freq);
|
||
|
READ_LONG(sp->root_freq);
|
||
|
skip(fp, 2); /* Unused by GUS: Why have a "root frequency" and then "tuning"?? */
|
||
|
sp->low_vel = 0;
|
||
|
sp->high_vel = 127;
|
||
|
|
||
|
READ_CHAR(tmp[0]);
|
||
|
|
||
|
if (panning == -1)
|
||
|
sp->panning = (tmp[0] * 8 + 4) & 0x7f;
|
||
|
else
|
||
|
sp->panning = (BYTE)(panning & 0x7F);
|
||
|
sp->panning |= sp->panning << 7;
|
||
|
|
||
|
sp->resonance = 0;
|
||
|
sp->cutoff_freq = 0;
|
||
|
sp->reverberation = 0;
|
||
|
sp->chorusdepth = 0;
|
||
|
sp->exclusiveClass = 0;
|
||
|
sp->keyToModEnvHold = 0;
|
||
|
sp->keyToModEnvDecay = 0;
|
||
|
sp->keyToVolEnvHold = 0;
|
||
|
sp->keyToVolEnvDecay = 0;
|
||
|
|
||
|
if (cfg_tuning)
|
||
|
{
|
||
|
double tune_factor = (double)(cfg_tuning) / 1200.0;
|
||
|
tune_factor = pow(2.0, tune_factor);
|
||
|
sp->root_freq = (uint32)( tune_factor * (double)sp->root_freq );
|
||
|
}
|
||
|
|
||
|
/* envelope, tremolo, and vibrato */
|
||
|
if (18 != fread(tmp, 1, 18, fp)) goto fail;
|
||
|
|
||
|
if (!tmp[13] || !tmp[14])
|
||
|
{
|
||
|
sp->tremolo_sweep_increment = 0;
|
||
|
sp->tremolo_phase_increment = 0;
|
||
|
sp->tremolo_depth = 0;
|
||
|
song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " * no tremolo");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sp->tremolo_sweep_increment = convert_tremolo_sweep(song, tmp[12]);
|
||
|
sp->tremolo_phase_increment = convert_tremolo_rate(song, tmp[13]);
|
||
|
sp->tremolo_depth = tmp[14];
|
||
|
song->ctl->cmsg(CMSG_INFO, VERB_DEBUG,
|
||
|
" * tremolo: sweep %d, phase %d, depth %d",
|
||
|
sp->tremolo_sweep_increment, sp->tremolo_phase_increment,
|
||
|
sp->tremolo_depth);
|
||
|
}
|
||
|
|
||
|
if (!tmp[16] || !tmp[17])
|
||
|
{
|
||
|
sp->vibrato_sweep_increment = 0;
|
||
|
sp->vibrato_control_ratio = 0;
|
||
|
sp->vibrato_depth = 0;
|
||
|
song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " * no vibrato");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sp->vibrato_control_ratio = convert_vibrato_rate(song, tmp[16]);
|
||
|
sp->vibrato_sweep_increment= convert_vibrato_sweep(song, tmp[15], sp->vibrato_control_ratio);
|
||
|
sp->vibrato_depth = tmp[17];
|
||
|
song->ctl->cmsg(CMSG_INFO, VERB_DEBUG,
|
||
|
" * vibrato: sweep %d, ctl %d, depth %d",
|
||
|
sp->vibrato_sweep_increment, sp->vibrato_control_ratio,
|
||
|
sp->vibrato_depth);
|
||
|
|
||
|
}
|
||
|
|
||
|
READ_CHAR(sp->modes);
|
||
|
READ_SHORT(sp->freq_center);
|
||
|
READ_SHORT(sp->freq_scale);
|
||
|
|
||
|
if (sf2flag)
|
||
|
{
|
||
|
READ_SHORT(sample_volume);
|
||
|
READ_CHAR(sf2delay);
|
||
|
READ_CHAR(sp->exclusiveClass);
|
||
|
skip(fp, 32);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
skip(fp, 36);
|
||
|
}
|
||
|
|
||
|
/* Mark this as a fixed-pitch instrument if such a deed is desired. */
|
||
|
if (note_to_use != -1)
|
||
|
sp->note_to_use = (BYTE)(note_to_use);
|
||
|
else
|
||
|
sp->note_to_use = 0;
|
||
|
|
||
|
/* seashore.pat in the Midia patch set has no Sustain. I don't
|
||
|
understand why, and fixing it by adding the Sustain flag to
|
||
|
all looped patches probably breaks something else. We do it
|
||
|
anyway. */
|
||
|
|
||
|
if (sp->modes & MODES_LOOPING)
|
||
|
sp->modes |= MODES_SUSTAIN;
|
||
|
|
||
|
/* Strip any loops and envelopes we're permitted to */
|
||
|
if ((strip_loop == 1) &&
|
||
|
(sp->modes & (MODES_SUSTAIN | MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE)))
|
||
|
{
|
||
|
song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - Removing loop and/or sustain");
|
||
|
sp->modes &=~(MODES_SUSTAIN | MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE);
|
||
|
}
|
||
|
|
||
|
if (strip_envelope == 1)
|
||
|
{
|
||
|
if (sp->modes & MODES_ENVELOPE)
|
||
|
song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - Removing envelope");
|
||
|
sp->modes &= ~MODES_ENVELOPE;
|
||
|
}
|
||
|
else if (strip_envelope != 0)
|
||
|
{
|
||
|
/* Have to make a guess. */
|
||
|
if (!(sp->modes & (MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE)))
|
||
|
{
|
||
|
/* No loop? Then what's there to sustain? No envelope needed either... */
|
||
|
sp->modes &= ~(MODES_SUSTAIN|MODES_ENVELOPE);
|
||
|
song->ctl->cmsg(CMSG_INFO, VERB_DEBUG,
|
||
|
" - No loop, removing sustain and envelope");
|
||
|
}
|
||
|
else if (!memcmp(tmp, "??????", 6) || tmp[11] >= 100)
|
||
|
{
|
||
|
/* Envelope rates all maxed out? Envelope end at a high "offset"?
|
||
|
That's a weird envelope. Take it out. */
|
||
|
sp->modes &= ~MODES_ENVELOPE;
|
||
|
song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - Weirdness, removing envelope");
|
||
|
}
|
||
|
else if (!(sp->modes & MODES_SUSTAIN))
|
||
|
{
|
||
|
/* No sustain? Then no envelope. I don't know if this is
|
||
|
justified, but patches without sustain usually don't need the
|
||
|
envelope either... at least the Gravis ones. They're mostly
|
||
|
drums. I think. */
|
||
|
sp->modes &= ~MODES_ENVELOPE;
|
||
|
song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - No sustain, removing envelope");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sp->attenuation = 0;
|
||
|
|
||
|
for (j = ATTACK; j < DELAY; j++)
|
||
|
{
|
||
|
sp->envelope_rate[j] =
|
||
|
(j < 3) ? convert_envelope_rate_attack(song, tmp[j], 11) : convert_envelope_rate(song, tmp[j]);
|
||
|
sp->envelope_offset[j] = convert_envelope_offset(tmp[6+j]);
|
||
|
}
|
||
|
if (sf2flag)
|
||
|
{
|
||
|
if (sf2delay > 5)
|
||
|
{
|
||
|
sf2delay = 5;
|
||
|
}
|
||
|
sp->envelope_rate[DELAY] = (int)( (sf2delay * song->rate) / 1000 );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sp->envelope_rate[DELAY] = 0;
|
||
|
}
|
||
|
sp->envelope_offset[DELAY] = 0;
|
||
|
|
||
|
for (j = ATTACK; j < DELAY; j++)
|
||
|
{
|
||
|
sp->modulation_rate[j] = float(sp->envelope_rate[j]);
|
||
|
sp->modulation_offset[j] = float(sp->envelope_offset[j]);
|
||
|
}
|
||
|
sp->modulation_rate[DELAY] = sp->modulation_offset[DELAY] = 0;
|
||
|
sp->modEnvToFilterFc = 0;
|
||
|
sp->modEnvToPitch = 0;
|
||
|
sp->lfo_sweep_increment = 0;
|
||
|
sp->lfo_phase_increment = 0;
|
||
|
sp->modLfoToFilterFc = 0;
|
||
|
|
||
|
/* Then read the sample data */
|
||
|
if (((sp->modes & MODES_16BIT) && sp->data_length/2 > MAX_SAMPLE_SIZE) ||
|
||
|
(!(sp->modes & MODES_16BIT) && sp->data_length > MAX_SAMPLE_SIZE))
|
||
|
{
|
||
|
goto fail;
|
||
|
}
|
||
|
sp->data = (sample_t *)safe_malloc(sp->data_length + 1);
|
||
|
|
||
|
if (1 != fread(sp->data, sp->data_length, 1, fp))
|
||
|
goto fail;
|
||
|
|
||
|
convert_sample_data(sp, sp->data);
|
||
|
|
||
|
/* Reverse reverse loops and pass them off as normal loops */
|
||
|
if (sp->modes & MODES_REVERSE)
|
||
|
{
|
||
|
int t;
|
||
|
/* The GUS apparently plays reverse loops by reversing the
|
||
|
whole sample. We do the same because the GUS does not SUCK. */
|
||
|
|
||
|
song->ctl->cmsg(CMSG_WARNING, VERB_NORMAL, "Reverse loop in %s", name);
|
||
|
reverse_data((sample_t *)sp->data, 0, sp->data_length);
|
||
|
sp->data[sp->data_length] = sp->data[sp->data_length - 1];
|
||
|
|
||
|
t = sp->loop_start;
|
||
|
sp->loop_start = sp->data_length - sp->loop_end;
|
||
|
sp->loop_end = sp->data_length - t;
|
||
|
|
||
|
sp->modes &= ~MODES_REVERSE;
|
||
|
sp->modes |= MODES_LOOPING; /* just in case */
|
||
|
}
|
||
|
|
||
|
if (amp != -1)
|
||
|
{
|
||
|
sp->volume = (amp) / 100.f;
|
||
|
}
|
||
|
else if (sf2flag)
|
||
|
{
|
||
|
sp->volume = (sample_volume) / 255.f;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
#if defined(ADJUST_SAMPLE_VOLUMES)
|
||
|
/* Try to determine a volume scaling factor for the sample.
|
||
|
This is a very crude adjustment, but things sound more
|
||
|
balanced with it. Still, this should be a runtime option. */
|
||
|
int i, numsamps = sp->data_length;
|
||
|
sample_t maxamp = 0, a;
|
||
|
sample_t *tmp;
|
||
|
for (i = numsamps, tmp = sp->data; i; --i)
|
||
|
{
|
||
|
a = abs(*tmp++);
|
||
|
if (a > maxamp)
|
||
|
maxamp = a;
|
||
|
}
|
||
|
sp->volume = 1 / maxamp;
|
||
|
song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " * volume comp: %f", sp->volume);
|
||
|
#else
|
||
|
sp->volume = 1;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/* Then fractional samples */
|
||
|
sp->data_length <<= FRACTION_BITS;
|
||
|
sp->loop_start <<= FRACTION_BITS;
|
||
|
sp->loop_end <<= FRACTION_BITS;
|
||
|
|
||
|
/* Adjust for fractional loop points. */
|
||
|
sp->loop_start |= (fractions & 0x0F) << (FRACTION_BITS-4);
|
||
|
sp->loop_end |= ((fractions>>4) & 0x0F) << (FRACTION_BITS-4);
|
||
|
|
||
|
/* If this instrument will always be played on the same note,
|
||
|
and it's not looped, we can resample it now. */
|
||
|
if (sp->note_to_use && !(sp->modes & MODES_LOOPING))
|
||
|
pre_resample(song, sp);
|
||
|
|
||
|
if (strip_tail == 1)
|
||
|
{
|
||
|
/* Let's not really, just say we did. */
|
||
|
song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - Stripping tail");
|
||
|
sp->data_length = sp->loop_end;
|
||
|
}
|
||
|
} /* end of sample loop */
|
||
|
} /* end of stereo layer loop */
|
||
|
} /* end of vlayer loop */
|
||
|
|
||
|
|
||
|
close_file(fp);
|
||
|
return headlp;
|
||
|
}
|
||
|
|
||
|
void convert_sample_data(Sample *sp, const void *data)
|
||
|
{
|
||
|
/* convert everything to 32-bit floating point data */
|
||
|
sample_t *newdata;
|
||
|
|
||
|
switch (sp->modes & (MODES_16BIT | MODES_UNSIGNED))
|
||
|
{
|
||
|
case 0:
|
||
|
{ /* 8-bit, signed */
|
||
|
SBYTE *cp = (SBYTE *)data;
|
||
|
newdata = (sample_t *)safe_malloc((sp->data_length + 1) * sizeof(sample_t));
|
||
|
for (int i = 0; i < sp->data_length; ++i)
|
||
|
{
|
||
|
if (cp[i] < 0)
|
||
|
{
|
||
|
newdata[i] = float(cp[i]) / 128.f;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
newdata[i] = float(cp[i]) / 127.f;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MODES_UNSIGNED:
|
||
|
{ /* 8-bit, unsigned */
|
||
|
BYTE *cp = (BYTE *)data;
|
||
|
newdata = (sample_t *)safe_malloc((sp->data_length + 1) * sizeof(sample_t));
|
||
|
for (int i = 0; i < sp->data_length; ++i)
|
||
|
{
|
||
|
int c = cp[i] - 128;
|
||
|
if (c < 0)
|
||
|
{
|
||
|
newdata[i] = float(c) / 128.f;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
newdata[i] = float(c) / 127.f;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MODES_16BIT:
|
||
|
{ /* 16-bit, signed */
|
||
|
SWORD *cp = (SWORD *)data;
|
||
|
/* Convert these to samples */
|
||
|
sp->data_length >>= 1;
|
||
|
sp->loop_start >>= 1;
|
||
|
sp->loop_end >>= 1;
|
||
|
newdata = (sample_t *)safe_malloc((sp->data_length + 1) * sizeof(sample_t));
|
||
|
for (int i = 0; i < sp->data_length; ++i)
|
||
|
{
|
||
|
int c = LittleShort(cp[i]);
|
||
|
if (c < 0)
|
||
|
{
|
||
|
newdata[i] = float(c) / 32768.f;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
newdata[i] = float(c) / 32767.f;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MODES_16BIT | MODES_UNSIGNED:
|
||
|
{ /* 16-bit, unsigned */
|
||
|
WORD *cp = (WORD *)data;
|
||
|
/* Convert these to samples */
|
||
|
sp->data_length >>= 1;
|
||
|
sp->loop_start >>= 1;
|
||
|
sp->loop_end >>= 1;
|
||
|
newdata = (sample_t *)safe_malloc((sp->data_length + 1) * sizeof(sample_t));
|
||
|
for (int i = 0; i < sp->data_length; ++i)
|
||
|
{
|
||
|
int c = LittleShort(cp[i]) - 32768;
|
||
|
if (c < 0)
|
||
|
{
|
||
|
newdata[i] = float(c) / 32768.f;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
newdata[i] = float(c) / 32767.f;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
/* Duplicate the final sample for linear interpolation. */
|
||
|
newdata[sp->data_length] = newdata[sp->data_length - 1];
|
||
|
if (sp->data != NULL)
|
||
|
{
|
||
|
free(sp->data);
|
||
|
}
|
||
|
sp->data = newdata;
|
||
|
}
|
||
|
|
||
|
static int fill_bank(Renderer *song, int dr, int b)
|
||
|
{
|
||
|
int i, errors = 0;
|
||
|
ToneBank *bank = ((dr) ? drumset[b] : tonebank[b]);
|
||
|
if (bank == NULL)
|
||
|
{
|
||
|
song->ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
|
||
|
"Huh. Tried to load instruments in non-existent %s %d",
|
||
|
(dr) ? "drumset" : "tone bank", b);
|
||
|
return 0;
|
||
|
}
|
||
|
for (i = 0; i < MAXPROG; i++)
|
||
|
{
|
||
|
if (bank->tone[i].layer == MAGIC_LOAD_INSTRUMENT)
|
||
|
{
|
||
|
bank->tone[i].layer = load_instrument_dls(song, dr, b, i);
|
||
|
if (bank->tone[i].layer != NULL)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
if (bank->tone[i].name.IsEmpty())
|
||
|
{
|
||
|
song->ctl->cmsg(CMSG_WARNING, (b!=0) ? VERB_VERBOSE : VERB_NORMAL,
|
||
|
"No instrument mapped to %s %d, program %d%s",
|
||
|
(dr)? "drum set" : "tone bank", b, i,
|
||
|
(b!=0) ? "" : " - this instrument will not be heard");
|
||
|
if (b!=0)
|
||
|
{
|
||
|
/* Mark the corresponding instrument in the default
|
||
|
bank / drumset for loading (if it isn't already) */
|
||
|
if (!dr)
|
||
|
{
|
||
|
if (!(standard_tonebank.tone[i].layer))
|
||
|
standard_tonebank.tone[i].layer=
|
||
|
MAGIC_LOAD_INSTRUMENT;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!(standard_drumset.tone[i].layer))
|
||
|
standard_drumset.tone[i].layer=
|
||
|
MAGIC_LOAD_INSTRUMENT;
|
||
|
}
|
||
|
}
|
||
|
bank->tone[i].layer=0;
|
||
|
errors++;
|
||
|
}
|
||
|
else if (!(bank->tone[i].layer=
|
||
|
load_instrument(song, bank->tone[i].name,
|
||
|
bank->tone[i].font_type,
|
||
|
(dr) ? 1 : 0,
|
||
|
bank->tone[i].pan,
|
||
|
bank->tone[i].amp,
|
||
|
bank->tone[i].tuning,
|
||
|
(bank->tone[i].note!=-1) ?
|
||
|
bank->tone[i].note :
|
||
|
((dr) ? i : -1),
|
||
|
(bank->tone[i].strip_loop!=-1) ?
|
||
|
bank->tone[i].strip_loop :
|
||
|
((dr) ? 1 : -1),
|
||
|
(bank->tone[i].strip_envelope != -1) ?
|
||
|
bank->tone[i].strip_envelope :
|
||
|
((dr) ? 1 : -1),
|
||
|
bank->tone[i].strip_tail,
|
||
|
b,
|
||
|
((dr) ? i + 128 : i),
|
||
|
bank->tone[i].sf_ix
|
||
|
)))
|
||
|
{
|
||
|
song->ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
|
||
|
"Couldn't load instrument %s (%s %d, program %d)",
|
||
|
bank->tone[i].name,
|
||
|
(dr)? "drum set" : "tone bank", b, i);
|
||
|
errors++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return errors;
|
||
|
}
|
||
|
|
||
|
int Renderer::load_missing_instruments()
|
||
|
{
|
||
|
int i = MAXBANK, errors = 0;
|
||
|
while (i--)
|
||
|
{
|
||
|
if (tonebank[i] != NULL)
|
||
|
errors += fill_bank(this, 0,i);
|
||
|
if (drumset[i] != NULL)
|
||
|
errors += fill_bank(this, 1,i);
|
||
|
}
|
||
|
return errors;
|
||
|
}
|
||
|
|
||
|
void free_instruments()
|
||
|
{
|
||
|
int i = 128;
|
||
|
while (i--)
|
||
|
{
|
||
|
if (tonebank[i] != NULL)
|
||
|
free_bank(0,i);
|
||
|
if (drumset[i] != NULL)
|
||
|
free_bank(1,i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int Renderer::set_default_instrument(const char *name)
|
||
|
{
|
||
|
InstrumentLayer *lp;
|
||
|
if (!(lp = load_instrument(this, name, FONT_NORMAL, 0, -1, -1, 0, -1, -1, -1, -1, 0, -1, -1)))
|
||
|
return -1;
|
||
|
if (default_instrument)
|
||
|
free_layer(default_instrument);
|
||
|
default_instrument = lp;
|
||
|
default_program = SPECIAL_PROGRAM;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
}
|