mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-24 21:21:04 +00:00
parameters. These seem to be used primarily to restrict percussion
instruments to specific notes. - Changed note velocity to not use the volume curve in recompute_amp(), since this sounds closer to TiMidity++, although I don't believe it's correct MIDI behavior. Also changed expression so that it scales the channel volume before going through the curve. - Reworked load_instrument to be less opaque. - Went through the TiMidity code and removed pretty much all of the SDL_mixer extensions. The only exception would be kill_others(), which I reworked into a kill_key_group() function, which should be useful for DLS instruments in the future. SVN r918 (trunk)
This commit is contained in:
parent
52eeff6db8
commit
9450db3cec
8 changed files with 789 additions and 1959 deletions
|
@ -1,3 +1,17 @@
|
||||||
|
April 15, 2008
|
||||||
|
- Added support for the GUS patch format's scale_frequency and scale_factor
|
||||||
|
parameters. These seem to be used primarily to restrict percussion
|
||||||
|
instruments to specific notes.
|
||||||
|
- Changed note velocity to not use the volume curve in recompute_amp(), since
|
||||||
|
this sounds closer to TiMidity++, although I don't believe it's correct
|
||||||
|
MIDI behavior. Also changed expression so that it scales the channel volume
|
||||||
|
before going through the curve.
|
||||||
|
- Reworked load_instrument to be less opaque.
|
||||||
|
- Went through the TiMidity code and removed pretty much all of the SDL_mixer
|
||||||
|
extensions. The only exception would be kill_others(), which I reworked
|
||||||
|
into a kill_key_group() function, which should be useful for DLS
|
||||||
|
instruments in the future.
|
||||||
|
|
||||||
April 15, 2008 (Changes by Graf Zahl)
|
April 15, 2008 (Changes by Graf Zahl)
|
||||||
- Added translation support to multipatch textures. Not tested yet!
|
- Added translation support to multipatch textures. Not tested yet!
|
||||||
- Added Martin Howe's morph weapon update.
|
- Added Martin Howe's morph weapon update.
|
||||||
|
|
|
@ -35,74 +35,48 @@
|
||||||
namespace Timidity
|
namespace Timidity
|
||||||
{
|
{
|
||||||
|
|
||||||
extern InstrumentLayer *load_instrument_dls(Renderer *song, int drum, int bank, int instrument);
|
extern Instrument *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;
|
|
||||||
extern int openmode;
|
extern int openmode;
|
||||||
|
|
||||||
|
Instrument::Instrument()
|
||||||
|
: type(INST_GUS), samples(0), sample(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static void free_instrument(Instrument *ip)
|
Instrument::~Instrument()
|
||||||
{
|
{
|
||||||
Sample *sp;
|
Sample *sp;
|
||||||
int i;
|
int i;
|
||||||
if (ip == NULL)
|
|
||||||
{
|
for (i = samples, sp = &(sample[0]); i != 0; i--, sp++)
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (i = 0, sp = &(ip->sample[0]); i < ip->samples; i++, sp++)
|
|
||||||
{
|
{
|
||||||
if (sp->data != NULL)
|
if (sp->data != NULL)
|
||||||
{
|
{
|
||||||
free(sp->data);
|
free(sp->data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = 0, sp = &(ip->right_sample[0]); i < ip->right_samples; i++)
|
free(sample);
|
||||||
{
|
|
||||||
if (sp->data != NULL)
|
|
||||||
{
|
|
||||||
free(sp->data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(ip->sample);
|
|
||||||
if (ip->right_sample != NULL)
|
|
||||||
{
|
|
||||||
free(ip->right_sample);
|
|
||||||
}
|
|
||||||
free(ip);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ToneBank::ToneBank()
|
||||||
static void free_layer(InstrumentLayer *lp)
|
|
||||||
{
|
{
|
||||||
InstrumentLayer *next;
|
tone = new ToneBankElement[128];;
|
||||||
|
for (int i = 0; i < MAXPROG; ++i)
|
||||||
for (; lp; lp = next)
|
|
||||||
{
|
{
|
||||||
next = lp->next;
|
instrument[i] = 0;
|
||||||
free_instrument(lp->instrument);
|
|
||||||
free(lp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_bank(int dr, int b)
|
ToneBank::~ToneBank()
|
||||||
{
|
{
|
||||||
int i;
|
delete[] tone;
|
||||||
ToneBank *bank = ((dr) ? drumset[b] : tonebank[b]);
|
for (int i = 0; i < MAXPROG; i++)
|
||||||
for (i = 0; i < MAXPROG; i++)
|
|
||||||
{
|
{
|
||||||
if (bank->tone[i].layer != NULL)
|
if (instrument[i] != NULL && instrument[i] != MAGIC_LOAD_INSTRUMENT)
|
||||||
{
|
{
|
||||||
/* Not that this could ever happen, of course */
|
delete instrument[i];
|
||||||
if (bank->tone[i].layer != MAGIC_LOAD_INSTRUMENT)
|
instrument[i] = NULL;
|
||||||
{
|
|
||||||
free_layer(bank->tone[i].layer);
|
|
||||||
bank->tone[i].layer = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,7 +84,6 @@ static void free_bank(int dr, int b)
|
||||||
|
|
||||||
int convert_envelope_rate(Renderer *song, BYTE rate)
|
int convert_envelope_rate(Renderer *song, BYTE rate)
|
||||||
{
|
{
|
||||||
#if 1
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = 3 - ((rate>>6) & 0x3);
|
r = 3 - ((rate>>6) & 0x3);
|
||||||
|
@ -118,12 +91,7 @@ int convert_envelope_rate(Renderer *song, BYTE rate)
|
||||||
r = (int)(rate & 0x3f) << r; /* 6.9 fixed point */
|
r = (int)(rate & 0x3f) << r; /* 6.9 fixed point */
|
||||||
|
|
||||||
/* 15.15 fixed point. */
|
/* 15.15 fixed point. */
|
||||||
return int(((r * 44100) / song->rate) * song->control_ratio) << ((song->fast_decay) ? 10 : 9);
|
return int(((r * 44100) / song->rate) * song->control_ratio) << 9;
|
||||||
#else
|
|
||||||
double frameadd = (double)(rate & 63) / (double)(1 << (3 * (rate >> 6)));
|
|
||||||
double realadd = (frameadd * 19293 / song->rate) * (1 << 15) * song->control_ratio;
|
|
||||||
return (int)realadd;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int convert_envelope_offset(BYTE offset)
|
int convert_envelope_offset(BYTE offset)
|
||||||
|
@ -137,7 +105,7 @@ int convert_envelope_offset(BYTE offset)
|
||||||
|
|
||||||
int convert_tremolo_sweep(Renderer *song, BYTE sweep)
|
int convert_tremolo_sweep(Renderer *song, BYTE sweep)
|
||||||
{
|
{
|
||||||
if (!sweep)
|
if (sweep == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -146,7 +114,7 @@ int convert_tremolo_sweep(Renderer *song, BYTE sweep)
|
||||||
|
|
||||||
int convert_vibrato_sweep(Renderer *song, BYTE sweep, int vib_control_ratio)
|
int convert_vibrato_sweep(Renderer *song, BYTE sweep, int vib_control_ratio)
|
||||||
{
|
{
|
||||||
if (!sweep)
|
if (sweep == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -195,21 +163,20 @@ For other parameters, 1 means yes, 0 means no, other values are
|
||||||
undefined.
|
undefined.
|
||||||
|
|
||||||
TODO: do reverse loops right */
|
TODO: do reverse loops right */
|
||||||
static InstrumentLayer *load_instrument(Renderer *song, const char *name, int font_type, int percussion,
|
static Instrument *load_instrument(Renderer *song, const char *name, int percussion,
|
||||||
int panning, int amp, int cfg_tuning, int note_to_use,
|
int panning, int amp, int note_to_use,
|
||||||
int strip_loop, int strip_envelope,
|
int strip_loop, int strip_envelope,
|
||||||
int strip_tail, int bank, int gm_num, int sf_ix)
|
int strip_tail)
|
||||||
{
|
{
|
||||||
InstrumentLayer *lp, *lastlp, *headlp;
|
|
||||||
Instrument *ip;
|
Instrument *ip;
|
||||||
|
Sample *sp;
|
||||||
FileReader *fp;
|
FileReader *fp;
|
||||||
BYTE tmp[239];
|
GF1PatchHeader header;
|
||||||
|
GF1InstrumentData idata;
|
||||||
|
GF1LayerData layer_data;
|
||||||
|
GF1PatchData patch_data;
|
||||||
int i, j;
|
int i, j;
|
||||||
bool noluck = false;
|
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;
|
if (!name) return 0;
|
||||||
|
|
||||||
|
@ -233,436 +200,226 @@ static InstrumentLayer *load_instrument(Renderer *song, const char *name, int fo
|
||||||
|
|
||||||
if (noluck)
|
if (noluck)
|
||||||
{
|
{
|
||||||
cmsg(CMSG_ERROR, VERB_NORMAL, "Instrument `%s' can't be found.", name);
|
cmsg(CMSG_ERROR, VERB_NORMAL, "Instrument `%s' can't be found.\n", name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*cmsg(CMSG_INFO, VERB_NOISY, "Loading instrument %s", current_filename);*/
|
cmsg(CMSG_INFO, VERB_NOISY, "Loading instrument %s\n", name);
|
||||||
|
|
||||||
/* Read some headers and do cursory sanity checks. There are loads
|
/* Read some headers and do cursory sanity checks. */
|
||||||
of magic offsets. This could be rewritten... */
|
|
||||||
|
|
||||||
if ((239 != fp->Read(tmp, 239)) ||
|
if (sizeof(header) != fp->Read(&header, sizeof(header)))
|
||||||
(memcmp(tmp, "GF1PATCH110\0ID#000002", 22) &&
|
|
||||||
memcmp(tmp, "GF1PATCH100\0ID#000002", 22))) /* don't know what the
|
|
||||||
differences are */
|
|
||||||
{
|
{
|
||||||
cmsg(CMSG_ERROR, VERB_NORMAL, "%s: not an instrument", name);
|
failread:
|
||||||
|
cmsg(CMSG_ERROR, VERB_NORMAL, "%s: Error reading instrument.\n", name);
|
||||||
|
delete fp;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (strncmp(header.Header, GF1_HEADER_TEXT, HEADER_SIZE - 4) != 0)
|
||||||
|
{
|
||||||
|
cmsg(CMSG_ERROR, VERB_NORMAL, "%s: Not an instrument.\n", name);
|
||||||
|
delete fp;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (strcmp(header.Header + 8, "110") < 0)
|
||||||
|
{
|
||||||
|
cmsg(CMSG_ERROR, VERB_NORMAL, "%s: Is an old and unsupported patch version.\n", name);
|
||||||
|
delete fp;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (sizeof(idata) != fp->Read(&idata, sizeof(idata)))
|
||||||
|
{
|
||||||
|
goto failread;
|
||||||
|
}
|
||||||
|
|
||||||
|
header.WaveForms = LittleShort(header.WaveForms);
|
||||||
|
header.MasterVolume = LittleShort(header.MasterVolume);
|
||||||
|
header.DataSize = LittleLong(header.DataSize);
|
||||||
|
idata.Instrument = LittleShort(idata.Instrument);
|
||||||
|
|
||||||
|
if (header.Instruments != 1 && header.Instruments != 0) /* instruments. To some patch makers, 0 means 1 */
|
||||||
|
{
|
||||||
|
cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle patches with %d instruments.\n", header.Instruments);
|
||||||
delete fp;
|
delete fp;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* patch layout:
|
if (idata.Layers != 1 && idata.Layers != 0) /* layers. What's a layer? */
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
vlayer_count = 0; // Silence, GCC
|
|
||||||
|
|
||||||
if (!memcmp(tmp + 93, "SF2EXT", 6))
|
|
||||||
{
|
{
|
||||||
sf2flag = true;
|
cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle instruments with %d layers.\n", idata.Layers);
|
||||||
vlayer_count = tmp[152];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tmp[82] != 1 && tmp[82] != 0) /* instruments. To some patch makers, 0 means 1 */
|
|
||||||
{
|
|
||||||
cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle patches with %d instruments", tmp[82]);
|
|
||||||
delete fp;
|
delete fp;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmp[151] != 1 && tmp[151] != 0) /* layers. What's a layer? */
|
if (sizeof(layer_data) != fp->Read(&layer_data, sizeof(layer_data)))
|
||||||
{
|
{
|
||||||
cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle instruments with %d layers", tmp[151]);
|
goto failread;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layer_data.Samples == 0)
|
||||||
|
{
|
||||||
|
cmsg(CMSG_ERROR, VERB_NORMAL, "Instrument has 0 samples.\n");
|
||||||
delete fp;
|
delete fp;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ip = new Instrument;
|
||||||
if (sf2flag && vlayer_count > 0)
|
ip->samples = layer_data.Samples;
|
||||||
|
ip->sample = (Sample *)safe_malloc(sizeof(Sample) * layer_data.Samples);
|
||||||
|
memset(ip->sample, 0, sizeof(Sample) * layer_data.Samples);
|
||||||
|
ip->type = INST_GUS;
|
||||||
|
for (i = 0; i < layer_data.Samples; ++i)
|
||||||
{
|
{
|
||||||
for (i = 0; i < 9; i++)
|
if (sizeof(patch_data) != fp->Read(&patch_data, sizeof(patch_data)))
|
||||||
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 = NULL;
|
|
||||||
headlp = NULL; // Silence, GCC
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sample_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 != fp->Read(&tmpchar,1)) goto fail; \
|
|
||||||
thing = tmpchar;
|
|
||||||
#define READ_SHORT(thing) \
|
|
||||||
if (2 != fp->Read(&tmpshort, 2)) goto fail; \
|
|
||||||
thing = LittleShort(tmpshort);
|
|
||||||
#define READ_LONG(thing) \
|
|
||||||
if (4 != fp->Read(&tmplong, 4)) 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
|
|
||||||
*/
|
|
||||||
fp->Seek(7, SEEK_CUR);
|
|
||||||
|
|
||||||
if (1 != fp->Read(&fractions, 1))
|
|
||||||
{
|
{
|
||||||
fail:
|
fail:
|
||||||
cmsg(CMSG_ERROR, VERB_NORMAL, "Error reading sample %d", i);
|
cmsg(CMSG_ERROR, VERB_NORMAL, "Error reading sample %d.\n", i);
|
||||||
if (stereo_layer == 1)
|
delete ip;
|
||||||
{
|
|
||||||
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);
|
|
||||||
delete fp;
|
delete fp;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stereo_layer == 0)
|
sp = &(ip->sample[i]);
|
||||||
{
|
|
||||||
sp = &(ip->left_sample[i]);
|
|
||||||
}
|
|
||||||
else if (stereo_layer == 1)
|
|
||||||
{
|
|
||||||
sp = &(ip->right_sample[i]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assert(0);
|
|
||||||
sp = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
READ_LONG(sp->data_length);
|
sp->data_length = LittleLong(patch_data.WaveSize);
|
||||||
READ_LONG(sp->loop_start);
|
sp->loop_start = LittleLong(patch_data.StartLoop);
|
||||||
READ_LONG(sp->loop_end);
|
sp->loop_end = LittleLong(patch_data.EndLoop);
|
||||||
READ_SHORT(sp->sample_rate);
|
sp->sample_rate = LittleShort(patch_data.SampleRate);
|
||||||
READ_LONG(sp->low_freq);
|
sp->low_freq = LittleLong(patch_data.LowFrequency);
|
||||||
READ_LONG(sp->high_freq);
|
sp->high_freq = LittleLong(patch_data.HighFrequency);
|
||||||
READ_LONG(sp->root_freq);
|
sp->root_freq = LittleLong(patch_data.RootFrequency);
|
||||||
fp->Seek(2, SEEK_CUR); /* Unused by GUS: Why have a "root frequency" and then "tuning"?? */
|
|
||||||
sp->low_vel = 0;
|
|
||||||
sp->high_vel = 127;
|
sp->high_vel = 127;
|
||||||
|
|
||||||
READ_CHAR(tmp[0]);
|
|
||||||
|
|
||||||
if (panning == -1)
|
if (panning == -1)
|
||||||
sp->panning = (tmp[0] * 8 + 4) & 0x7f;
|
{
|
||||||
|
sp->panning = patch_data.Balance & 0x0F;
|
||||||
|
sp->panning = (sp->panning << 3) | (sp->panning >> 1);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
sp->panning = (BYTE)(panning & 0x7F);
|
{
|
||||||
|
sp->panning = panning & 0x7f;
|
||||||
|
}
|
||||||
sp->panning |= sp->panning << 7;
|
sp->panning |= sp->panning << 7;
|
||||||
|
|
||||||
sp->resonance = 0;
|
/* tremolo */
|
||||||
sp->cutoff_freq = 0;
|
if (patch_data.TremoloRate == 0 || patch_data.TremoloDepth == 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 != fp->Read(tmp, 18)) goto fail;
|
|
||||||
|
|
||||||
if (!tmp[13] || !tmp[14])
|
|
||||||
{
|
{
|
||||||
sp->tremolo_sweep_increment = 0;
|
sp->tremolo_sweep_increment = 0;
|
||||||
sp->tremolo_phase_increment = 0;
|
sp->tremolo_phase_increment = 0;
|
||||||
sp->tremolo_depth = 0;
|
sp->tremolo_depth = 0;
|
||||||
cmsg(CMSG_INFO, VERB_DEBUG, " * no tremolo");
|
cmsg(CMSG_INFO, VERB_DEBUG, " * no tremolo\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sp->tremolo_sweep_increment = convert_tremolo_sweep(song, tmp[12]);
|
sp->tremolo_sweep_increment = convert_tremolo_sweep(song, patch_data.TremoloSweep);
|
||||||
sp->tremolo_phase_increment = convert_tremolo_rate(song, tmp[13]);
|
sp->tremolo_phase_increment = convert_tremolo_rate(song, patch_data.TremoloRate);
|
||||||
sp->tremolo_depth = tmp[14];
|
sp->tremolo_depth = patch_data.TremoloDepth;
|
||||||
cmsg(CMSG_INFO, VERB_DEBUG,
|
cmsg(CMSG_INFO, VERB_DEBUG, " * tremolo: sweep %d, phase %d, depth %d\n",
|
||||||
" * tremolo: sweep %d, phase %d, depth %d",
|
sp->tremolo_sweep_increment, sp->tremolo_phase_increment, sp->tremolo_depth);
|
||||||
sp->tremolo_sweep_increment, sp->tremolo_phase_increment,
|
|
||||||
sp->tremolo_depth);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tmp[16] || !tmp[17])
|
/* vibrato */
|
||||||
|
if (patch_data.VibratoRate == 0 || patch_data.VibratoDepth == 0)
|
||||||
{
|
{
|
||||||
sp->vibrato_sweep_increment = 0;
|
sp->tremolo_sweep_increment = 0;
|
||||||
sp->vibrato_control_ratio = 0;
|
sp->vibrato_control_ratio = 0;
|
||||||
sp->vibrato_depth = 0;
|
sp->vibrato_depth = 0;
|
||||||
cmsg(CMSG_INFO, VERB_DEBUG, " * no vibrato");
|
cmsg(CMSG_INFO, VERB_DEBUG, " * no vibrato\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sp->vibrato_control_ratio = convert_vibrato_rate(song, tmp[16]);
|
sp->vibrato_control_ratio = convert_vibrato_rate(song, patch_data.VibratoRate);
|
||||||
sp->vibrato_sweep_increment= convert_vibrato_sweep(song, tmp[15], sp->vibrato_control_ratio);
|
sp->tremolo_sweep_increment = convert_vibrato_sweep(song, patch_data.VibratoSweep, sp->vibrato_control_ratio);
|
||||||
sp->vibrato_depth = tmp[17];
|
sp->vibrato_depth = patch_data.VibratoDepth;
|
||||||
cmsg(CMSG_INFO, VERB_DEBUG,
|
cmsg(CMSG_INFO, VERB_DEBUG, " * vibrato: sweep %d, ctl %d, depth %d\n",
|
||||||
" * vibrato: sweep %d, ctl %d, depth %d",
|
sp->vibrato_sweep_increment, sp->vibrato_control_ratio, sp->vibrato_depth);
|
||||||
sp->vibrato_sweep_increment, sp->vibrato_control_ratio,
|
|
||||||
sp->vibrato_depth);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
READ_CHAR(sp->modes);
|
sp->modes = patch_data.Modes;
|
||||||
READ_SHORT(sp->freq_center);
|
|
||||||
READ_SHORT(sp->freq_scale);
|
|
||||||
|
|
||||||
if (sf2flag)
|
|
||||||
{
|
|
||||||
READ_SHORT(sample_volume);
|
|
||||||
READ_CHAR(sf2delay);
|
|
||||||
READ_CHAR(sp->exclusiveClass);
|
|
||||||
fp->Seek(32, SEEK_CUR);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fp->Seek(36, SEEK_CUR);
|
|
||||||
sample_volume = 0;
|
|
||||||
sf2delay = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mark this as a fixed-pitch instrument if such a deed is desired. */
|
/* Mark this as a fixed-pitch instrument if such a deed is desired. */
|
||||||
if (note_to_use != -1)
|
if (note_to_use != -1)
|
||||||
sp->note_to_use = (BYTE)(note_to_use);
|
{
|
||||||
|
sp->scale_note = note_to_use;
|
||||||
|
sp->scale_factor = 0;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
sp->note_to_use = 0;
|
{
|
||||||
|
sp->scale_note = LittleShort(patch_data.ScaleFrequency);
|
||||||
|
sp->scale_factor = LittleShort(patch_data.ScaleFactor);
|
||||||
|
if (sp->scale_factor != 1024)
|
||||||
|
{
|
||||||
|
cmsg(CMSG_INFO, VERB_DEBUG, " * Scale: note %d, factor %d\n",
|
||||||
|
sp->scale_note, sp->scale_factor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* seashore.pat in the Midia patch set has no Sustain. I don't
|
/* seashore.pat in the Midia patch set has no Sustain. I don't
|
||||||
understand why, and fixing it by adding the Sustain flag to
|
understand why, and fixing it by adding the Sustain flag to
|
||||||
all looped patches probably breaks something else. We do it
|
all looped patches probably breaks something else. We do it
|
||||||
anyway. */
|
anyway. */
|
||||||
|
|
||||||
if (sp->modes & MODES_LOOPING)
|
if (sp->modes & PATCH_LOOPEN)
|
||||||
sp->modes |= MODES_SUSTAIN;
|
{
|
||||||
|
sp->modes |= PATCH_SUSTAIN;
|
||||||
|
}
|
||||||
|
|
||||||
/* Strip any loops and envelopes we're permitted to */
|
/* Strip any loops and envelopes we're permitted to */
|
||||||
if ((strip_loop == 1) &&
|
if ((strip_loop == 1) &&
|
||||||
(sp->modes & (MODES_SUSTAIN | MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE)))
|
(sp->modes & (PATCH_SUSTAIN | PATCH_LOOPEN | PATCH_BIDIR | PATCH_BACKWARD)))
|
||||||
{
|
{
|
||||||
cmsg(CMSG_INFO, VERB_DEBUG, " - Removing loop and/or sustain");
|
cmsg(CMSG_INFO, VERB_DEBUG, " - Removing loop and/or sustain\n");
|
||||||
sp->modes &=~(MODES_SUSTAIN | MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE);
|
sp->modes &= ~(PATCH_SUSTAIN | PATCH_LOOPEN | PATCH_BIDIR | PATCH_BACKWARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strip_envelope == 1)
|
if (strip_envelope == 1)
|
||||||
{
|
{
|
||||||
if (sp->modes & MODES_ENVELOPE)
|
if (sp->modes & PATCH_NO_SRELEASE)
|
||||||
cmsg(CMSG_INFO, VERB_DEBUG, " - Removing envelope");
|
{
|
||||||
sp->modes &= ~MODES_ENVELOPE;
|
cmsg(CMSG_INFO, VERB_DEBUG, " - Removing envelope\n");
|
||||||
|
}
|
||||||
|
sp->modes &= ~PATCH_NO_SRELEASE;
|
||||||
}
|
}
|
||||||
else if (strip_envelope != 0)
|
else if (strip_envelope != 0)
|
||||||
{
|
{
|
||||||
/* Have to make a guess. */
|
/* Have to make a guess. */
|
||||||
if (!(sp->modes & (MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE)))
|
if (!(sp->modes & (PATCH_LOOPEN | PATCH_BIDIR | PATCH_BACKWARD)))
|
||||||
{
|
{
|
||||||
/* No loop? Then what's there to sustain? No envelope needed either... */
|
/* No loop? Then what's there to sustain? No envelope needed either... */
|
||||||
sp->modes &= ~(MODES_SUSTAIN|MODES_ENVELOPE);
|
sp->modes &= ~(PATCH_SUSTAIN | PATCH_NO_SRELEASE);
|
||||||
cmsg(CMSG_INFO, VERB_DEBUG,
|
cmsg(CMSG_INFO, VERB_DEBUG, " - No loop, removing sustain and envelope\n");
|
||||||
" - No loop, removing sustain and envelope");
|
|
||||||
}
|
}
|
||||||
else if (!memcmp(tmp, "??????", 6) || tmp[11] >= 100)
|
else if (memcmp(patch_data.EnvelopeRate, "??????", 6) == 0 || patch_data.EnvelopeOffset[RELEASEC] >= 100)
|
||||||
{
|
{
|
||||||
/* Envelope rates all maxed out? Envelope end at a high "offset"?
|
/* Envelope rates all maxed out? Envelope end at a high "offset"?
|
||||||
That's a weird envelope. Take it out. */
|
That's a weird envelope. Take it out. */
|
||||||
sp->modes &= ~MODES_ENVELOPE;
|
sp->modes &= ~PATCH_NO_SRELEASE;
|
||||||
cmsg(CMSG_INFO, VERB_DEBUG, " - Weirdness, removing envelope");
|
cmsg(CMSG_INFO, VERB_DEBUG, " - Weirdness, removing envelope\n");
|
||||||
}
|
}
|
||||||
else if (!(sp->modes & MODES_SUSTAIN))
|
else if (!(sp->modes & PATCH_SUSTAIN))
|
||||||
{
|
{
|
||||||
/* No sustain? Then no envelope. I don't know if this is
|
/* No sustain? Then no envelope. I don't know if this is
|
||||||
justified, but patches without sustain usually don't need the
|
justified, but patches without sustain usually don't need the
|
||||||
envelope either... at least the Gravis ones. They're mostly
|
envelope either... at least the Gravis ones. They're mostly
|
||||||
drums. I think. */
|
drums. I think. */
|
||||||
sp->modes &= ~MODES_ENVELOPE;
|
sp->modes &= ~PATCH_NO_SRELEASE;
|
||||||
cmsg(CMSG_INFO, VERB_DEBUG, " - No sustain, removing envelope");
|
cmsg(CMSG_INFO, VERB_DEBUG, " - No sustain, removing envelope\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sp->attenuation = 0;
|
for (j = 0; j < 6; j++)
|
||||||
|
|
||||||
for (j = ATTACK; j < DELAY; j++)
|
|
||||||
{
|
{
|
||||||
sp->envelope_rate[j] = convert_envelope_rate(song, tmp[j]);
|
sp->envelope_rate[j] = convert_envelope_rate(song, patch_data.EnvelopeRate[j]);
|
||||||
sp->envelope_offset[j] = convert_envelope_offset(tmp[6+j]);
|
sp->envelope_offset[j] = convert_envelope_offset(patch_data.EnvelopeOffset[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 */
|
/* Then read the sample data */
|
||||||
if (((sp->modes & MODES_16BIT) && sp->data_length/2 > MAX_SAMPLE_SIZE) ||
|
if (((sp->modes & PATCH_16) && sp->data_length/2 > MAX_SAMPLE_SIZE) ||
|
||||||
(!(sp->modes & MODES_16BIT) && sp->data_length > MAX_SAMPLE_SIZE))
|
(!(sp->modes & PATCH_16) && sp->data_length > MAX_SAMPLE_SIZE))
|
||||||
{
|
{
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
sp->data = (sample_t *)safe_malloc(sp->data_length + 1);
|
sp->data = (sample_t *)safe_malloc(sp->data_length);
|
||||||
|
|
||||||
if (sp->data_length != fp->Read(sp->data, sp->data_length))
|
if (sp->data_length != fp->Read(sp->data, sp->data_length))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -670,13 +427,13 @@ fail:
|
||||||
convert_sample_data(sp, sp->data);
|
convert_sample_data(sp, sp->data);
|
||||||
|
|
||||||
/* Reverse reverse loops and pass them off as normal loops */
|
/* Reverse reverse loops and pass them off as normal loops */
|
||||||
if (sp->modes & MODES_REVERSE)
|
if (sp->modes & PATCH_BACKWARD)
|
||||||
{
|
{
|
||||||
int t;
|
int t;
|
||||||
/* The GUS apparently plays reverse loops by reversing the
|
/* The GUS apparently plays reverse loops by reversing the
|
||||||
whole sample. We do the same because the GUS does not SUCK. */
|
whole sample. We do the same because the GUS does not SUCK. */
|
||||||
|
|
||||||
cmsg(CMSG_WARNING, VERB_NORMAL, "Reverse loop in %s", name);
|
cmsg(CMSG_WARNING, VERB_NORMAL, "Reverse loop in %s\n", name);
|
||||||
reverse_data((sample_t *)sp->data, 0, sp->data_length);
|
reverse_data((sample_t *)sp->data, 0, sp->data_length);
|
||||||
sp->data[sp->data_length] = sp->data[sp->data_length - 1];
|
sp->data[sp->data_length] = sp->data[sp->data_length - 1];
|
||||||
|
|
||||||
|
@ -684,35 +441,31 @@ fail:
|
||||||
sp->loop_start = sp->data_length - sp->loop_end;
|
sp->loop_start = sp->data_length - sp->loop_end;
|
||||||
sp->loop_end = sp->data_length - t;
|
sp->loop_end = sp->data_length - t;
|
||||||
|
|
||||||
sp->modes &= ~MODES_REVERSE;
|
sp->modes &= ~PATCH_BACKWARD;
|
||||||
sp->modes |= MODES_LOOPING; /* just in case */
|
sp->modes |= PATCH_LOOPEN; /* just in case */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (amp != -1)
|
if (amp != -1)
|
||||||
{
|
{
|
||||||
sp->volume = (amp) / 100.f;
|
sp->volume = (amp) / 100.f;
|
||||||
}
|
}
|
||||||
else if (sf2flag)
|
|
||||||
{
|
|
||||||
sp->volume = (sample_volume) / 255.f;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if defined(ADJUST_SAMPLE_VOLUMES)
|
#if defined(ADJUST_SAMPLE_VOLUMES)
|
||||||
/* Try to determine a volume scaling factor for the sample.
|
/* Try to determine a volume scaling factor for the sample.
|
||||||
This is a very crude adjustment, but things sound more
|
This is a very crude adjustment, but things sound more
|
||||||
balanced with it. Still, this should be a runtime option. */
|
balanced with it. Still, this should be a runtime option. */
|
||||||
int i, numsamps = sp->data_length;
|
int i;
|
||||||
sample_t maxamp = 0, a;
|
sample_t maxamp = 0, a;
|
||||||
sample_t *tmp;
|
sample_t *tmp;
|
||||||
for (i = numsamps, tmp = sp->data; i; --i)
|
for (i = sp->data_length, tmp = sp->data; i; --i)
|
||||||
{
|
{
|
||||||
a = abs(*tmp++);
|
a = abs(*tmp++);
|
||||||
if (a > maxamp)
|
if (a > maxamp)
|
||||||
maxamp = a;
|
maxamp = a;
|
||||||
}
|
}
|
||||||
sp->volume = 1 / maxamp;
|
sp->volume = 1 / maxamp;
|
||||||
cmsg(CMSG_INFO, VERB_DEBUG, " * volume comp: %f", sp->volume);
|
cmsg(CMSG_INFO, VERB_DEBUG, " * volume comp: %f\n", sp->volume);
|
||||||
#else
|
#else
|
||||||
sp->volume = 1;
|
sp->volume = 1;
|
||||||
#endif
|
#endif
|
||||||
|
@ -724,27 +477,25 @@ fail:
|
||||||
sp->loop_end <<= FRACTION_BITS;
|
sp->loop_end <<= FRACTION_BITS;
|
||||||
|
|
||||||
/* Adjust for fractional loop points. */
|
/* Adjust for fractional loop points. */
|
||||||
sp->loop_start |= (fractions & 0x0F) << (FRACTION_BITS-4);
|
sp->loop_start |= (patch_data.Fractions & 0x0F) << (FRACTION_BITS-4);
|
||||||
sp->loop_end |= ((fractions>>4) & 0x0F) << (FRACTION_BITS-4);
|
sp->loop_end |= (patch_data.Fractions & 0xF0) << (FRACTION_BITS-4-4);
|
||||||
|
|
||||||
/* If this instrument will always be played on the same note,
|
/* If this instrument will always be played on the same note,
|
||||||
and it's not looped, we can resample it now. */
|
and it's not looped, we can resample it now. */
|
||||||
if (sp->note_to_use && !(sp->modes & MODES_LOOPING))
|
if (sp->scale_factor == 0 && !(sp->modes & PATCH_LOOPEN))
|
||||||
|
{
|
||||||
pre_resample(song, sp);
|
pre_resample(song, sp);
|
||||||
|
}
|
||||||
|
|
||||||
if (strip_tail == 1)
|
if (strip_tail == 1)
|
||||||
{
|
{
|
||||||
/* Let's not really, just say we did. */
|
/* Let's not really, just say we did. */
|
||||||
cmsg(CMSG_INFO, VERB_DEBUG, " - Stripping tail");
|
cmsg(CMSG_INFO, VERB_DEBUG, " - Stripping tail\n");
|
||||||
sp->data_length = sp->loop_end;
|
sp->data_length = sp->loop_end;
|
||||||
}
|
}
|
||||||
} /* end of sample loop */
|
}
|
||||||
} /* end of stereo layer loop */
|
|
||||||
} /* end of vlayer loop */
|
|
||||||
|
|
||||||
|
|
||||||
delete fp;
|
delete fp;
|
||||||
return headlp;
|
return ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
void convert_sample_data(Sample *sp, const void *data)
|
void convert_sample_data(Sample *sp, const void *data)
|
||||||
|
@ -752,7 +503,7 @@ void convert_sample_data(Sample *sp, const void *data)
|
||||||
/* convert everything to 32-bit floating point data */
|
/* convert everything to 32-bit floating point data */
|
||||||
sample_t *newdata = NULL;
|
sample_t *newdata = NULL;
|
||||||
|
|
||||||
switch (sp->modes & (MODES_16BIT | MODES_UNSIGNED))
|
switch (sp->modes & (PATCH_16 | PATCH_UNSIGNED))
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
{ /* 8-bit, signed */
|
{ /* 8-bit, signed */
|
||||||
|
@ -772,7 +523,7 @@ void convert_sample_data(Sample *sp, const void *data)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case MODES_UNSIGNED:
|
case PATCH_UNSIGNED:
|
||||||
{ /* 8-bit, unsigned */
|
{ /* 8-bit, unsigned */
|
||||||
BYTE *cp = (BYTE *)data;
|
BYTE *cp = (BYTE *)data;
|
||||||
newdata = (sample_t *)safe_malloc((sp->data_length + 1) * sizeof(sample_t));
|
newdata = (sample_t *)safe_malloc((sp->data_length + 1) * sizeof(sample_t));
|
||||||
|
@ -791,7 +542,7 @@ void convert_sample_data(Sample *sp, const void *data)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case MODES_16BIT:
|
case PATCH_16:
|
||||||
{ /* 16-bit, signed */
|
{ /* 16-bit, signed */
|
||||||
SWORD *cp = (SWORD *)data;
|
SWORD *cp = (SWORD *)data;
|
||||||
/* Convert these to samples */
|
/* Convert these to samples */
|
||||||
|
@ -814,7 +565,7 @@ void convert_sample_data(Sample *sp, const void *data)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case MODES_16BIT | MODES_UNSIGNED:
|
case PATCH_16 | PATCH_UNSIGNED:
|
||||||
{ /* 16-bit, unsigned */
|
{ /* 16-bit, unsigned */
|
||||||
WORD *cp = (WORD *)data;
|
WORD *cp = (WORD *)data;
|
||||||
/* Convert these to samples */
|
/* Convert these to samples */
|
||||||
|
@ -853,23 +604,23 @@ static int fill_bank(Renderer *song, int dr, int b)
|
||||||
if (bank == NULL)
|
if (bank == NULL)
|
||||||
{
|
{
|
||||||
cmsg(CMSG_ERROR, VERB_NORMAL,
|
cmsg(CMSG_ERROR, VERB_NORMAL,
|
||||||
"Huh. Tried to load instruments in non-existent %s %d",
|
"Huh. Tried to load instruments in non-existent %s %d\n",
|
||||||
(dr) ? "drumset" : "tone bank", b);
|
(dr) ? "drumset" : "tone bank", b);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for (i = 0; i < MAXPROG; i++)
|
for (i = 0; i < MAXPROG; i++)
|
||||||
{
|
{
|
||||||
if (bank->tone[i].layer == MAGIC_LOAD_INSTRUMENT)
|
if (bank->instrument[i] == MAGIC_LOAD_INSTRUMENT)
|
||||||
{
|
{
|
||||||
bank->tone[i].layer = load_instrument_dls(song, dr, b, i);
|
bank->instrument[i] = load_instrument_dls(song, dr, b, i);
|
||||||
if (bank->tone[i].layer != NULL)
|
if (bank->instrument[i] != NULL)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (bank->tone[i].name.IsEmpty())
|
if (bank->tone[i].name.IsEmpty())
|
||||||
{
|
{
|
||||||
cmsg(CMSG_WARNING, (b != 0) ? VERB_VERBOSE : VERB_NORMAL,
|
cmsg(CMSG_WARNING, (b != 0) ? VERB_VERBOSE : VERB_NORMAL,
|
||||||
"No instrument mapped to %s %d, program %d%s",
|
"No instrument mapped to %s %d, program %d%s\n",
|
||||||
(dr) ? "drum set" : "tone bank", b, i,
|
(dr) ? "drum set" : "tone bank", b, i,
|
||||||
(b != 0) ? "" : " - this instrument will not be heard");
|
(b != 0) ? "" : " - this instrument will not be heard");
|
||||||
if (b != 0)
|
if (b != 0)
|
||||||
|
@ -878,44 +629,34 @@ static int fill_bank(Renderer *song, int dr, int b)
|
||||||
bank / drumset for loading (if it isn't already) */
|
bank / drumset for loading (if it isn't already) */
|
||||||
if (!dr)
|
if (!dr)
|
||||||
{
|
{
|
||||||
if (!(standard_tonebank.tone[i].layer))
|
if (tonebank[0]->instrument[i] != NULL)
|
||||||
standard_tonebank.tone[i].layer=
|
{
|
||||||
MAGIC_LOAD_INSTRUMENT;
|
tonebank[0]->instrument[i] = MAGIC_LOAD_INSTRUMENT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!(standard_drumset.tone[i].layer))
|
if (drumset[0]->instrument[i] != NULL)
|
||||||
standard_drumset.tone[i].layer=
|
{
|
||||||
MAGIC_LOAD_INSTRUMENT;
|
drumset[0]->instrument[i] = MAGIC_LOAD_INSTRUMENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bank->tone[i].layer=0;
|
}
|
||||||
|
bank->instrument[i] = NULL;
|
||||||
errors++;
|
errors++;
|
||||||
}
|
}
|
||||||
else if (!(bank->tone[i].layer=
|
else if (!(bank->instrument[i] =
|
||||||
load_instrument(song, bank->tone[i].name,
|
load_instrument(song, bank->tone[i].name,
|
||||||
bank->tone[i].font_type,
|
|
||||||
(dr) ? 1 : 0,
|
(dr) ? 1 : 0,
|
||||||
bank->tone[i].pan,
|
bank->tone[i].pan,
|
||||||
bank->tone[i].amp,
|
bank->tone[i].amp,
|
||||||
bank->tone[i].tuning,
|
(bank->tone[i].note != -1) ? bank->tone[i].note : ((dr) ? i : -1),
|
||||||
(bank->tone[i].note!=-1) ?
|
(bank->tone[i].strip_loop != -1) ? bank->tone[i].strip_loop : ((dr) ? 1 : -1),
|
||||||
bank->tone[i].note :
|
(bank->tone[i].strip_envelope != -1) ? bank->tone[i].strip_envelope : ((dr) ? 1 : -1),
|
||||||
((dr) ? i : -1),
|
bank->tone[i].strip_tail)))
|
||||||
(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
|
|
||||||
)))
|
|
||||||
{
|
{
|
||||||
cmsg(CMSG_ERROR, VERB_NORMAL,
|
cmsg(CMSG_ERROR, VERB_NORMAL,
|
||||||
"Couldn't load instrument %s (%s %d, program %d)",
|
"Couldn't load instrument %s (%s %d, program %d)\n",
|
||||||
bank->tone[i].name.GetChars(),
|
bank->tone[i].name.GetChars(),
|
||||||
(dr) ? "drum set" : "tone bank", b, i);
|
(dr) ? "drum set" : "tone bank", b, i);
|
||||||
errors++;
|
errors++;
|
||||||
|
@ -940,24 +681,34 @@ int Renderer::load_missing_instruments()
|
||||||
|
|
||||||
void free_instruments()
|
void free_instruments()
|
||||||
{
|
{
|
||||||
int i = 128;
|
int i = MAXBANK;
|
||||||
while (i--)
|
while (i--)
|
||||||
{
|
{
|
||||||
if (tonebank[i] != NULL)
|
if (tonebank[i] != NULL)
|
||||||
free_bank(0,i);
|
{
|
||||||
|
delete tonebank[i];
|
||||||
|
tonebank[i] = NULL;
|
||||||
|
}
|
||||||
if (drumset[i] != NULL)
|
if (drumset[i] != NULL)
|
||||||
free_bank(1,i);
|
{
|
||||||
|
delete drumset[i];
|
||||||
|
drumset[i] = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Renderer::set_default_instrument(const char *name)
|
int Renderer::set_default_instrument(const char *name)
|
||||||
{
|
{
|
||||||
InstrumentLayer *lp;
|
Instrument *ip;
|
||||||
if (!(lp = load_instrument(this, name, FONT_NORMAL, 0, -1, -1, 0, -1, -1, -1, -1, 0, -1, -1)))
|
if ((ip = load_instrument(this, name, 0, -1, -1, -1, 0, 0, 0)) == NULL)
|
||||||
|
{
|
||||||
return -1;
|
return -1;
|
||||||
if (default_instrument)
|
}
|
||||||
free_layer(default_instrument);
|
if (default_instrument != NULL)
|
||||||
default_instrument = lp;
|
{
|
||||||
|
delete default_instrument;
|
||||||
|
}
|
||||||
|
default_instrument = ip;
|
||||||
default_program = SPECIAL_PROGRAM;
|
default_program = SPECIAL_PROGRAM;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1121,29 +1121,29 @@ static void load_region_dls(Renderer *song, Sample *sample, DLS_Instrument *ins,
|
||||||
DLS_Region *rgn = &ins->regions[index];
|
DLS_Region *rgn = &ins->regions[index];
|
||||||
DLS_Wave *wave = &song->patches->waveList[rgn->wlnk->ulTableIndex];
|
DLS_Wave *wave = &song->patches->waveList[rgn->wlnk->ulTableIndex];
|
||||||
|
|
||||||
if (!(rgn->header->fusOptions & F_RGN_OPTION_SELFNONEXCLUSIVE))
|
sample->self_nonexclusive = !!(rgn->header->fusOptions & F_RGN_OPTION_SELFNONEXCLUSIVE);
|
||||||
{
|
sample->key_group = (SBYTE)rgn->header->usKeyGroup;
|
||||||
sample->exclusiveClass = (SBYTE)rgn->header->usKeyGroup;
|
|
||||||
}
|
|
||||||
sample->low_freq = SDWORD(note_to_freq(rgn->header->RangeKey.usLow));
|
sample->low_freq = SDWORD(note_to_freq(rgn->header->RangeKey.usLow));
|
||||||
sample->high_freq = SDWORD(note_to_freq(rgn->header->RangeKey.usHigh));
|
sample->high_freq = SDWORD(note_to_freq(rgn->header->RangeKey.usHigh));
|
||||||
sample->root_freq = SDWORD(note_to_freq(rgn->wsmp->usUnityNote));
|
sample->root_freq = SDWORD(note_to_freq(rgn->wsmp->usUnityNote));
|
||||||
sample->low_vel = rgn->header->RangeVelocity.usLow;
|
sample->low_vel = rgn->header->RangeVelocity.usLow;
|
||||||
sample->high_vel = rgn->header->RangeVelocity.usHigh;
|
sample->high_vel = rgn->header->RangeVelocity.usHigh;
|
||||||
|
|
||||||
sample->modes = wave->format->wBitsPerSample == 8 ? MODES_UNSIGNED : MODES_16BIT;
|
sample->modes = wave->format->wBitsPerSample == 8 ? PATCH_UNSIGNED : PATCH_16;
|
||||||
sample->sample_rate = wave->format->dwSamplesPerSec;
|
sample->sample_rate = wave->format->dwSamplesPerSec;
|
||||||
sample->data = NULL;
|
sample->data = NULL;
|
||||||
sample->data_length = wave->length;
|
sample->data_length = wave->length;
|
||||||
convert_sample_data(sample, wave->data);
|
convert_sample_data(sample, wave->data);
|
||||||
if (rgn->wsmp->cSampleLoops) {
|
if (rgn->wsmp->cSampleLoops)
|
||||||
sample->modes |= (MODES_LOOPING|MODES_SUSTAIN);
|
{
|
||||||
|
sample->modes |= (PATCH_LOOPEN | PATCH_SUSTAIN);
|
||||||
sample->loop_start = rgn->wsmp_loop->ulStart / 2;
|
sample->loop_start = rgn->wsmp_loop->ulStart / 2;
|
||||||
sample->loop_end = sample->loop_start + (rgn->wsmp_loop->ulLength / 2);
|
sample->loop_end = sample->loop_start + (rgn->wsmp_loop->ulLength / 2);
|
||||||
}
|
}
|
||||||
sample->volume = 1.0f;
|
sample->volume = 1.0f;
|
||||||
|
|
||||||
if (sample->modes & MODES_SUSTAIN) {
|
if (sample->modes & PATCH_SUSTAIN)
|
||||||
|
{
|
||||||
int value;
|
int value;
|
||||||
double attack, hold, decay, release; int sustain;
|
double attack, hold, decay, release; int sustain;
|
||||||
CONNECTIONLIST *art = NULL;
|
CONNECTIONLIST *art = NULL;
|
||||||
|
@ -1192,12 +1192,7 @@ static void load_region_dls(Renderer *song, Sample *sample, DLS_Instrument *ins,
|
||||||
sample->envelope_offset[RELEASEC] = to_offset(0);
|
sample->envelope_offset[RELEASEC] = to_offset(0);
|
||||||
sample->envelope_rate[RELEASEC] = to_offset(1);
|
sample->envelope_rate[RELEASEC] = to_offset(1);
|
||||||
|
|
||||||
sample->modes |= MODES_ENVELOPE;
|
sample->modes |= PATCH_NO_SRELEASE;
|
||||||
}
|
|
||||||
for (int j = ATTACK; j < DELAY; j++)
|
|
||||||
{
|
|
||||||
sample->modulation_rate[j] = float(sample->envelope_rate[j]);
|
|
||||||
sample->modulation_offset[j] = float(sample->envelope_offset[j]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sample->data_length <<= FRACTION_BITS;
|
sample->data_length <<= FRACTION_BITS;
|
||||||
|
@ -1205,55 +1200,54 @@ static void load_region_dls(Renderer *song, Sample *sample, DLS_Instrument *ins,
|
||||||
sample->loop_end <<= FRACTION_BITS;
|
sample->loop_end <<= FRACTION_BITS;
|
||||||
}
|
}
|
||||||
|
|
||||||
InstrumentLayer *load_instrument_dls(Renderer *song, int drum, int bank, int instrument)
|
Instrument *load_instrument_dls(Renderer *song, int drum, int bank, int instrument)
|
||||||
{
|
{
|
||||||
InstrumentLayer *layer;
|
Instrument *inst;
|
||||||
DWORD i;
|
DWORD i;
|
||||||
DLS_Instrument *dls_ins = NULL;
|
DLS_Instrument *dls_ins = NULL;
|
||||||
|
|
||||||
if (song->patches == NULL)
|
if (song->patches == NULL)
|
||||||
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
drum = drum ? 0x80000000 : 0;
|
drum = drum ? 0x80000000 : 0;
|
||||||
for (i = 0; i < song->patches->cInstruments; ++i) {
|
for (i = 0; i < song->patches->cInstruments; ++i)
|
||||||
|
{
|
||||||
dls_ins = &song->patches->instruments[i];
|
dls_ins = &song->patches->instruments[i];
|
||||||
if ((dls_ins->header->Locale.ulBank & 0x80000000) == (ULONG)drum &&
|
if ((dls_ins->header->Locale.ulBank & 0x80000000) == (ULONG)drum &&
|
||||||
((dls_ins->header->Locale.ulBank >> 8) & 0xFF) == (ULONG)bank &&
|
((dls_ins->header->Locale.ulBank >> 8) & 0xFF) == (ULONG)bank &&
|
||||||
dls_ins->header->Locale.ulInstrument == (ULONG)instrument)
|
dls_ins->header->Locale.ulInstrument == (ULONG)instrument)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i == song->patches->cInstruments && !bank) {
|
if (i == song->patches->cInstruments && bank == 0)
|
||||||
for (i = 0; i < song->patches->cInstruments; ++i) {
|
{
|
||||||
|
for (i = 0; i < song->patches->cInstruments; ++i)
|
||||||
|
{
|
||||||
dls_ins = &song->patches->instruments[i];
|
dls_ins = &song->patches->instruments[i];
|
||||||
if ((dls_ins->header->Locale.ulBank & 0x80000000) == (ULONG)drum &&
|
if ((dls_ins->header->Locale.ulBank & 0x80000000) == (ULONG)drum &&
|
||||||
dls_ins->header->Locale.ulInstrument == (ULONG)instrument)
|
dls_ins->header->Locale.ulInstrument == (ULONG)instrument)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i == song->patches->cInstruments) {
|
if (i == song->patches->cInstruments)
|
||||||
|
{
|
||||||
// SNDDBG(("Couldn't find %s instrument %d in bank %d\n", drum ? "drum" : "melodic", instrument, bank));
|
// SNDDBG(("Couldn't find %s instrument %d in bank %d\n", drum ? "drum" : "melodic", instrument, bank));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
layer = (InstrumentLayer *)safe_malloc(sizeof(InstrumentLayer));
|
inst = (Instrument *)safe_malloc(sizeof(Instrument));
|
||||||
layer->lo = 0;
|
inst->type = INST_DLS;
|
||||||
layer->hi = 127;
|
inst->samples = dls_ins->header->cRegions;
|
||||||
layer->instrument = (Instrument *)safe_malloc(sizeof(Instrument));
|
inst->sample = (Sample *)safe_malloc(inst->samples * sizeof(Sample));
|
||||||
layer->instrument->type = INST_DLS;
|
memset(inst->sample, 0, inst->samples * sizeof(Sample));
|
||||||
layer->instrument->samples = dls_ins->header->cRegions;
|
|
||||||
layer->instrument->sample = (Sample *)safe_malloc(layer->instrument->samples * sizeof(Sample));
|
|
||||||
layer->instrument->left_samples = layer->instrument->samples;
|
|
||||||
layer->instrument->left_sample = layer->instrument->sample;
|
|
||||||
layer->instrument->right_samples = 0;
|
|
||||||
layer->instrument->right_sample = NULL;
|
|
||||||
memset(layer->instrument->sample, 0, layer->instrument->samples * sizeof(Sample));
|
|
||||||
/*
|
/*
|
||||||
printf("Found %s instrument %d in bank %d named %s with %d regions\n", drum ? "drum" : "melodic", instrument, bank, dls_ins->name, inst->samples);
|
printf("Found %s instrument %d in bank %d named %s with %d regions\n", drum ? "drum" : "melodic", instrument, bank, dls_ins->name, inst->samples);
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < dls_ins->header->cRegions; ++i) {
|
for (i = 0; i < dls_ins->header->cRegions; ++i)
|
||||||
load_region_dls(song, &layer->instrument->sample[i], dls_ins, i);
|
{
|
||||||
|
load_region_dls(song, &inst->sample[i], dls_ins, i);
|
||||||
}
|
}
|
||||||
return layer;
|
return inst;
|
||||||
}
|
}
|
||||||
#endif /* !TEST_MAIN_DLS */
|
#endif /* !TEST_MAIN_DLS */
|
||||||
|
|
||||||
|
|
|
@ -37,15 +37,14 @@ int recompute_envelope(Voice *v)
|
||||||
|
|
||||||
stage = v->envelope_stage;
|
stage = v->envelope_stage;
|
||||||
|
|
||||||
if (stage >= DELAY)
|
if (stage > RELEASEC)
|
||||||
{
|
{
|
||||||
/* Envelope ran out. */
|
/* Envelope ran out. */
|
||||||
int tmp = (v->status == VOICE_DIE); /* Already displayed as dead */
|
|
||||||
v->status = VOICE_FREE;
|
v->status = VOICE_FREE;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v->sample->modes & MODES_ENVELOPE)
|
if (v->sample->modes & PATCH_NO_SRELEASE)
|
||||||
{
|
{
|
||||||
if (v->status == VOICE_ON || v->status == VOICE_SUSTAINED)
|
if (v->status == VOICE_ON || v->status == VOICE_SUSTAINED)
|
||||||
{
|
{
|
||||||
|
@ -60,7 +59,9 @@ int recompute_envelope(Voice *v)
|
||||||
v->envelope_stage = stage + 1;
|
v->envelope_stage = stage + 1;
|
||||||
|
|
||||||
if (v->envelope_volume == v->sample->envelope_offset[stage])
|
if (v->envelope_volume == v->sample->envelope_offset[stage])
|
||||||
|
{
|
||||||
return recompute_envelope(v);
|
return recompute_envelope(v);
|
||||||
|
}
|
||||||
v->envelope_target = v->sample->envelope_offset[stage];
|
v->envelope_target = v->sample->envelope_offset[stage];
|
||||||
v->envelope_increment = v->sample->envelope_rate[stage];
|
v->envelope_increment = v->sample->envelope_rate[stage];
|
||||||
if (v->envelope_target < v->envelope_volume)
|
if (v->envelope_target < v->envelope_volume)
|
||||||
|
@ -75,28 +76,30 @@ void apply_envelope_to_amp(Voice *v)
|
||||||
{
|
{
|
||||||
ramp = v->right_amp;
|
ramp = v->right_amp;
|
||||||
|
|
||||||
if (v->tremolo_phase_increment)
|
if (v->tremolo_phase_increment != 0)
|
||||||
{
|
{
|
||||||
lamp *= v->tremolo_volume;
|
lamp *= v->tremolo_volume;
|
||||||
ramp *= v->tremolo_volume;
|
ramp *= v->tremolo_volume;
|
||||||
}
|
}
|
||||||
if (v->sample->modes & MODES_ENVELOPE)
|
if (v->sample->modes & PATCH_NO_SRELEASE)
|
||||||
{
|
{
|
||||||
double vol = calc_vol(v->envelope_volume / float(1 << 30));
|
double vol = calc_vol(v->envelope_volume / float(1 << 30));
|
||||||
lamp *= vol;
|
lamp *= vol;
|
||||||
ramp *= vol;
|
ramp *= vol;
|
||||||
}
|
}
|
||||||
|
|
||||||
v->left_mix = float(lamp);
|
v->left_mix = float(lamp);
|
||||||
v->right_mix = float(ramp);
|
v->right_mix = float(ramp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (v->tremolo_phase_increment)
|
if (v->tremolo_phase_increment != 0)
|
||||||
|
{
|
||||||
lamp *= v->tremolo_volume;
|
lamp *= v->tremolo_volume;
|
||||||
if (v->sample->modes & MODES_ENVELOPE)
|
}
|
||||||
|
if (v->sample->modes & PATCH_NO_SRELEASE)
|
||||||
|
{
|
||||||
lamp *= calc_vol(v->envelope_volume / float(1 << 30));
|
lamp *= calc_vol(v->envelope_volume / float(1 << 30));
|
||||||
|
}
|
||||||
v->left_mix = float(lamp);
|
v->left_mix = float(lamp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,14 +107,15 @@ void apply_envelope_to_amp(Voice *v)
|
||||||
static int update_envelope(Voice *v)
|
static int update_envelope(Voice *v)
|
||||||
{
|
{
|
||||||
v->envelope_volume += v->envelope_increment;
|
v->envelope_volume += v->envelope_increment;
|
||||||
/* Why is there no ^^ operator?? */
|
|
||||||
if (((v->envelope_increment < 0) && (v->envelope_volume <= v->envelope_target)) ||
|
if (((v->envelope_increment < 0) && (v->envelope_volume <= v->envelope_target)) ||
|
||||||
((v->envelope_increment > 0) && (v->envelope_volume >= v->envelope_target)))
|
((v->envelope_increment > 0) && (v->envelope_volume >= v->envelope_target)))
|
||||||
{
|
{
|
||||||
v->envelope_volume = v->envelope_target;
|
v->envelope_volume = v->envelope_target;
|
||||||
if (recompute_envelope(v))
|
if (recompute_envelope(v))
|
||||||
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +123,7 @@ static void update_tremolo(Voice *v)
|
||||||
{
|
{
|
||||||
int depth = v->sample->tremolo_depth << 7;
|
int depth = v->sample->tremolo_depth << 7;
|
||||||
|
|
||||||
if (v->tremolo_sweep)
|
if (v->tremolo_sweep != 0)
|
||||||
{
|
{
|
||||||
/* Update sweep position */
|
/* Update sweep position */
|
||||||
|
|
||||||
|
@ -151,12 +155,14 @@ static void update_tremolo(Voice *v)
|
||||||
/* Returns 1 if the note died */
|
/* Returns 1 if the note died */
|
||||||
static int update_signal(Voice *v)
|
static int update_signal(Voice *v)
|
||||||
{
|
{
|
||||||
if (v->envelope_increment && update_envelope(v))
|
if (v->envelope_increment != 0 && update_envelope(v))
|
||||||
|
{
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
if (v->tremolo_phase_increment)
|
if (v->tremolo_phase_increment != 0)
|
||||||
|
{
|
||||||
update_tremolo(v);
|
update_tremolo(v);
|
||||||
|
}
|
||||||
apply_envelope_to_amp(v);
|
apply_envelope_to_amp(v);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -217,8 +217,8 @@ static int vib_phase_to_inc_ptr(int phase)
|
||||||
{
|
{
|
||||||
if (phase < VIBRATO_SAMPLE_INCREMENTS / 2)
|
if (phase < VIBRATO_SAMPLE_INCREMENTS / 2)
|
||||||
return VIBRATO_SAMPLE_INCREMENTS / 2 - 1 - phase;
|
return VIBRATO_SAMPLE_INCREMENTS / 2 - 1 - phase;
|
||||||
else if (phase >= 3*VIBRATO_SAMPLE_INCREMENTS/2)
|
else if (phase >= VIBRATO_SAMPLE_INCREMENTS * 3 / 2)
|
||||||
return 5*VIBRATO_SAMPLE_INCREMENTS/2-1-phase;
|
return VIBRATO_SAMPLE_INCREMENTS * 5 / 2 - 1 - phase;
|
||||||
else
|
else
|
||||||
return phase - VIBRATO_SAMPLE_INCREMENTS / 2;
|
return phase - VIBRATO_SAMPLE_INCREMENTS / 2;
|
||||||
}
|
}
|
||||||
|
@ -244,7 +244,7 @@ static int update_vibrato(float output_rate, Voice *vp, int sign)
|
||||||
/* Need to compute this sample increment. */
|
/* Need to compute this sample increment. */
|
||||||
depth = vp->sample->vibrato_depth << 7;
|
depth = vp->sample->vibrato_depth << 7;
|
||||||
|
|
||||||
if (vp->vibrato_sweep)
|
if (vp->vibrato_sweep != 0)
|
||||||
{
|
{
|
||||||
/* Need to update sweep */
|
/* Need to update sweep */
|
||||||
vp->vibrato_sweep_position += vp->vibrato_sweep;
|
vp->vibrato_sweep_position += vp->vibrato_sweep;
|
||||||
|
@ -265,7 +265,7 @@ static int update_vibrato(float output_rate, Voice *vp, int sign)
|
||||||
pb = (sine(vp->vibrato_phase * (1.0/(2*VIBRATO_SAMPLE_INCREMENTS)))
|
pb = (sine(vp->vibrato_phase * (1.0/(2*VIBRATO_SAMPLE_INCREMENTS)))
|
||||||
* (double)(depth) * VIBRATO_AMPLITUDE_TUNING);
|
* (double)(depth) * VIBRATO_AMPLITUDE_TUNING);
|
||||||
|
|
||||||
a *= pow(2.0, pb / (8191 * 12.f));
|
a *= pow(2.0, pb / (8192 * 12.f));
|
||||||
|
|
||||||
/* If the sweep's over, we can store the newly computed sample_increment */
|
/* If the sweep's over, we can store the newly computed sample_increment */
|
||||||
if (!vp->vibrato_sweep)
|
if (!vp->vibrato_sweep)
|
||||||
|
@ -511,11 +511,11 @@ sample_t *resample_voice(Renderer *song, Voice *vp, int *countptr)
|
||||||
|
|
||||||
if (vp->vibrato_control_ratio)
|
if (vp->vibrato_control_ratio)
|
||||||
{
|
{
|
||||||
if ((modes & MODES_LOOPING) &&
|
if ((modes & PATCH_LOOPEN) &&
|
||||||
((modes & MODES_ENVELOPE) ||
|
((modes & PATCH_NO_SRELEASE) ||
|
||||||
(vp->status == VOICE_ON || vp->status == VOICE_SUSTAINED)))
|
(vp->status == VOICE_ON || vp->status == VOICE_SUSTAINED)))
|
||||||
{
|
{
|
||||||
if (modes & MODES_PINGPONG)
|
if (modes & PATCH_BIDIR)
|
||||||
return rs_vib_bidir(song->resample_buffer, song->rate, vp, *countptr);
|
return rs_vib_bidir(song->resample_buffer, song->rate, vp, *countptr);
|
||||||
else
|
else
|
||||||
return rs_vib_loop(song->resample_buffer, song->rate, vp, *countptr);
|
return rs_vib_loop(song->resample_buffer, song->rate, vp, *countptr);
|
||||||
|
@ -527,11 +527,11 @@ sample_t *resample_voice(Renderer *song, Voice *vp, int *countptr)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((modes & MODES_LOOPING) &&
|
if ((modes & PATCH_LOOPEN) &&
|
||||||
((modes & MODES_ENVELOPE) ||
|
((modes & PATCH_NO_SRELEASE) ||
|
||||||
(vp->status == VOICE_ON || vp->status == VOICE_SUSTAINED)))
|
(vp->status == VOICE_ON || vp->status == VOICE_SUSTAINED)))
|
||||||
{
|
{
|
||||||
if (modes & MODES_PINGPONG)
|
if (modes & PATCH_BIDIR)
|
||||||
return rs_bidir(song->resample_buffer, vp, *countptr);
|
return rs_bidir(song->resample_buffer, vp, *countptr);
|
||||||
else
|
else
|
||||||
return rs_loop(song->resample_buffer, vp, *countptr);
|
return rs_loop(song->resample_buffer, vp, *countptr);
|
||||||
|
@ -554,11 +554,14 @@ void pre_resample(Renderer *song, Sample *sp)
|
||||||
"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"
|
"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"
|
||||||
};
|
};
|
||||||
|
|
||||||
cmsg(CMSG_INFO, VERB_NOISY, " * pre-resampling for note %d (%s%d)",
|
if (sp->scale_factor != 0)
|
||||||
sp->note_to_use,
|
return;
|
||||||
note_name[sp->note_to_use % 12], (sp->note_to_use & 0x7F) / 12);
|
|
||||||
|
|
||||||
a = (sp->sample_rate * note_to_freq(sp->note_to_use)) / (sp->root_freq * song->rate);
|
cmsg(CMSG_INFO, VERB_NOISY, " * pre-resampling for note %d (%s%d)\n",
|
||||||
|
sp->scale_note,
|
||||||
|
note_name[sp->scale_note % 12], (sp->scale_note & 0x7F) / 12);
|
||||||
|
|
||||||
|
a = (sp->sample_rate * note_to_freq(sp->scale_note)) / (sp->root_freq * song->rate);
|
||||||
if (a <= 0)
|
if (a <= 0)
|
||||||
return;
|
return;
|
||||||
newlen = (int)(sp->data_length / a);
|
newlen = (int)(sp->data_length / a);
|
||||||
|
|
|
@ -413,6 +413,13 @@ void FreeAll()
|
||||||
|
|
||||||
int LoadConfig(const char *filename)
|
int LoadConfig(const char *filename)
|
||||||
{
|
{
|
||||||
|
/* !!! FIXME: This may be ugly, but slightly less so than requiring the
|
||||||
|
* default search path to have only one element. I think.
|
||||||
|
*
|
||||||
|
* We only need to include the likely locations for the config
|
||||||
|
* file itself since that file should contain any other directory
|
||||||
|
* that needs to be added to the search path.
|
||||||
|
*/
|
||||||
clear_pathlist();
|
clear_pathlist();
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
add_to_pathlist("C:\\TIMIDITY");
|
add_to_pathlist("C:\\TIMIDITY");
|
||||||
|
@ -443,25 +450,21 @@ Renderer::Renderer(float sample_rate)
|
||||||
{
|
{
|
||||||
rate = sample_rate;
|
rate = sample_rate;
|
||||||
patches = NULL;
|
patches = NULL;
|
||||||
default_instrument = NULL;
|
|
||||||
#ifdef FAST_DECAY
|
|
||||||
fast_decay = true;
|
|
||||||
#else
|
|
||||||
fast_decay = false;
|
|
||||||
#endif
|
|
||||||
resample_buffer_size = 0;
|
resample_buffer_size = 0;
|
||||||
resample_buffer = NULL;
|
resample_buffer = NULL;
|
||||||
|
adjust_panning_immediately = false;
|
||||||
|
|
||||||
control_ratio = clamp(int(rate / CONTROLS_PER_SECOND), 1, MAX_CONTROL_RATIO);
|
control_ratio = clamp(int(rate / CONTROLS_PER_SECOND), 1, MAX_CONTROL_RATIO);
|
||||||
|
|
||||||
|
lost_notes = 0;
|
||||||
|
cut_notes = 0;
|
||||||
|
|
||||||
|
default_instrument = NULL;
|
||||||
|
default_program = DEFAULT_PROGRAM;
|
||||||
if (def_instr_name.IsNotEmpty())
|
if (def_instr_name.IsNotEmpty())
|
||||||
set_default_instrument(def_instr_name);
|
set_default_instrument(def_instr_name);
|
||||||
|
|
||||||
voices = DEFAULT_VOICES;
|
voices = DEFAULT_VOICES;
|
||||||
memset(voice, 0, sizeof(voice));
|
|
||||||
memset(drumvolume, 0, sizeof(drumvolume));
|
|
||||||
memset(drumpanpot, 0, sizeof(drumpanpot));
|
|
||||||
memset(drumreverberation, 0, sizeof(drumreverberation));
|
|
||||||
memset(drumchorusdepth, 0, sizeof(drumchorusdepth));
|
|
||||||
drumchannels = DEFAULT_DRUMCHANNELS;
|
drumchannels = DEFAULT_DRUMCHANNELS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -491,26 +494,11 @@ void Renderer::ComputeOutput(float *buffer, int count)
|
||||||
for (int i = 0; i < voices; i++, v++)
|
for (int i = 0; i < voices; i++, v++)
|
||||||
{
|
{
|
||||||
if (v->status != VOICE_FREE)
|
if (v->status != VOICE_FREE)
|
||||||
{
|
|
||||||
if (v->sample_offset == 0 && v->echo_delay_count)
|
|
||||||
{
|
|
||||||
if (v->echo_delay_count >= count)
|
|
||||||
{
|
|
||||||
v->echo_delay_count -= count;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mix_voice(this, buffer + v->echo_delay_count, v, count - v->echo_delay_count);
|
|
||||||
v->echo_delay_count = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
mix_voice(this, buffer, v, count);
|
mix_voice(this, buffer, v, count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::MarkInstrument(int banknum, int percussion, int instr)
|
void Renderer::MarkInstrument(int banknum, int percussion, int instr)
|
||||||
{
|
{
|
||||||
|
@ -520,6 +508,11 @@ void Renderer::MarkInstrument(int banknum, int percussion, int instr)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (banknum != 0)
|
||||||
|
{
|
||||||
|
/* Mark the standard bank in case it's not defined by this one. */
|
||||||
|
MarkInstrument(0, percussion, instr);
|
||||||
|
}
|
||||||
if (percussion)
|
if (percussion)
|
||||||
{
|
{
|
||||||
bank = drumset[banknum];
|
bank = drumset[banknum];
|
||||||
|
@ -532,9 +525,9 @@ void Renderer::MarkInstrument(int banknum, int percussion, int instr)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (bank->tone[instr].layer == NULL)
|
if (bank->instrument[instr] == NULL)
|
||||||
{
|
{
|
||||||
bank->tone[instr].layer = MAGIC_LOAD_INSTRUMENT;
|
bank->instrument[instr] = MAGIC_LOAD_INSTRUMENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,9 +550,6 @@ void cmsg(int type, int verbosity_level, const char *fmt, ...)
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
vsprintf(buf, fmt, args);
|
vsprintf(buf, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
size_t l = strlen(buf);
|
|
||||||
buf[l] = '\n';
|
|
||||||
buf[l+1] = '\0';
|
|
||||||
OutputDebugString(buf);
|
OutputDebugString(buf);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,11 +43,10 @@ config.h
|
||||||
#define DEFAULT_DRUMCHANNELS (1<<9)
|
#define DEFAULT_DRUMCHANNELS (1<<9)
|
||||||
/*#define DEFAULT_DRUMCHANNELS ((1<<9) | (1<<15))*/
|
/*#define DEFAULT_DRUMCHANNELS ((1<<9) | (1<<15))*/
|
||||||
|
|
||||||
/* Default sampling rate, default polyphony, and maximum polyphony.
|
/* Default polyphony, and maximum polyphony. */
|
||||||
All but the last can be overridden from the command line. */
|
|
||||||
#define DEFAULT_RATE 32000
|
|
||||||
#define DEFAULT_VOICES 32
|
#define DEFAULT_VOICES 32
|
||||||
#define MAX_VOICES 256
|
#define MAX_VOICES 256
|
||||||
|
|
||||||
#define MAXCHAN 16
|
#define MAXCHAN 16
|
||||||
#define MAXNOTE 128
|
#define MAXNOTE 128
|
||||||
|
|
||||||
|
@ -56,11 +55,6 @@ config.h
|
||||||
of envelopes and tremolo. The cost is CPU time. */
|
of envelopes and tremolo. The cost is CPU time. */
|
||||||
#define CONTROLS_PER_SECOND 1000
|
#define CONTROLS_PER_SECOND 1000
|
||||||
|
|
||||||
/* Make envelopes twice as fast. Saves ~20% CPU time (notes decay
|
|
||||||
faster) and sounds more like a GUS. There is now a command line
|
|
||||||
option to toggle this as well. */
|
|
||||||
//#define FAST_DECAY
|
|
||||||
|
|
||||||
/* How many bits to use for the fractional part of sample positions.
|
/* How many bits to use for the fractional part of sample positions.
|
||||||
This affects tonal accuracy. The entire position counter must fit
|
This affects tonal accuracy. The entire position counter must fit
|
||||||
in 32 bits, so with FRACTION_BITS equal to 12, the maximum size of
|
in 32 bits, so with FRACTION_BITS equal to 12, the maximum size of
|
||||||
|
@ -106,9 +100,9 @@ typedef float final_volume_t;
|
||||||
|
|
||||||
/* Vibrato and tremolo Choices of the Day */
|
/* Vibrato and tremolo Choices of the Day */
|
||||||
#define SWEEP_TUNING 38
|
#define SWEEP_TUNING 38
|
||||||
#define VIBRATO_AMPLITUDE_TUNING 1.0L
|
#define VIBRATO_AMPLITUDE_TUNING 1.0
|
||||||
#define VIBRATO_RATE_TUNING 38
|
#define VIBRATO_RATE_TUNING 38
|
||||||
#define TREMOLO_AMPLITUDE_TUNING 1.0L
|
#define TREMOLO_AMPLITUDE_TUNING 1.0
|
||||||
#define TREMOLO_RATE_TUNING 38
|
#define TREMOLO_RATE_TUNING 38
|
||||||
|
|
||||||
#define SWEEP_SHIFT 16
|
#define SWEEP_SHIFT 16
|
||||||
|
@ -188,21 +182,20 @@ FileReader *open_filereader(const char *name, int open, int *plumpnum);
|
||||||
controls.h
|
controls.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CMSG_INFO 0
|
enum
|
||||||
#define CMSG_WARNING 1
|
{
|
||||||
#define CMSG_ERROR 2
|
CMSG_INFO,
|
||||||
#define CMSG_FATAL 3
|
CMSG_WARNING,
|
||||||
#define CMSG_TRACE 4
|
CMSG_ERROR
|
||||||
#define CMSG_TIME 5
|
};
|
||||||
#define CMSG_TOTAL 6
|
|
||||||
#define CMSG_FILE 7
|
|
||||||
#define CMSG_TEXT 8
|
|
||||||
|
|
||||||
#define VERB_NORMAL 0
|
enum
|
||||||
#define VERB_VERBOSE 1
|
{
|
||||||
#define VERB_NOISY 2
|
VERB_NORMAL,
|
||||||
#define VERB_DEBUG 3
|
VERB_VERBOSE,
|
||||||
#define VERB_DEBUG_SILLY 4
|
VERB_NOISY,
|
||||||
|
VERB_DEBUG
|
||||||
|
};
|
||||||
|
|
||||||
void cmsg(int type, int verbosity_level, const char *fmt, ...);
|
void cmsg(int type, int verbosity_level, const char *fmt, ...);
|
||||||
|
|
||||||
|
@ -217,110 +210,170 @@ struct Sample
|
||||||
loop_start, loop_end, data_length,
|
loop_start, loop_end, data_length,
|
||||||
sample_rate, low_vel, high_vel, low_freq, high_freq, root_freq;
|
sample_rate, low_vel, high_vel, low_freq, high_freq, root_freq;
|
||||||
SDWORD
|
SDWORD
|
||||||
envelope_rate[7], envelope_offset[7];
|
envelope_rate[6], envelope_offset[6];
|
||||||
float
|
float
|
||||||
modulation_rate[7], modulation_offset[7];
|
volume;
|
||||||
float
|
|
||||||
volume, resonance,
|
|
||||||
modEnvToFilterFc, modEnvToPitch, modLfoToFilterFc;
|
|
||||||
sample_t *data;
|
sample_t *data;
|
||||||
SDWORD
|
SDWORD
|
||||||
tremolo_sweep_increment, tremolo_phase_increment,
|
tremolo_sweep_increment, tremolo_phase_increment,
|
||||||
lfo_sweep_increment, lfo_phase_increment,
|
vibrato_sweep_increment, vibrato_control_ratio;
|
||||||
vibrato_sweep_increment, vibrato_control_ratio,
|
|
||||||
cutoff_freq;
|
|
||||||
BYTE
|
BYTE
|
||||||
reverberation, chorusdepth,
|
|
||||||
tremolo_depth, vibrato_depth,
|
tremolo_depth, vibrato_depth,
|
||||||
modes,
|
modes;
|
||||||
attenuation;
|
|
||||||
WORD
|
WORD
|
||||||
freq_center, panning;
|
panning, scale_factor;
|
||||||
SBYTE
|
|
||||||
note_to_use, exclusiveClass;
|
|
||||||
SWORD
|
SWORD
|
||||||
keyToModEnvHold, keyToModEnvDecay,
|
scale_note;
|
||||||
keyToVolEnvHold, keyToVolEnvDecay;
|
bool
|
||||||
SDWORD
|
self_nonexclusive;
|
||||||
freq_scale;
|
BYTE
|
||||||
|
key_group;
|
||||||
};
|
};
|
||||||
|
|
||||||
void convert_sample_data(Sample *sample, const void *data);
|
void convert_sample_data(Sample *sample, const void *data);
|
||||||
void free_instruments();
|
void free_instruments();
|
||||||
|
|
||||||
/* Bits in modes: */
|
/* Patch definition: */
|
||||||
#define MODES_16BIT (1<<0)
|
enum
|
||||||
#define MODES_UNSIGNED (1<<1)
|
{
|
||||||
#define MODES_LOOPING (1<<2)
|
HEADER_SIZE = 12,
|
||||||
#define MODES_PINGPONG (1<<3)
|
ID_SIZE = 10,
|
||||||
#define MODES_REVERSE (1<<4)
|
DESC_SIZE = 60,
|
||||||
#define MODES_SUSTAIN (1<<5)
|
RESERVED_SIZE = 40,
|
||||||
#define MODES_ENVELOPE (1<<6)
|
PATCH_HEADER_RESERVED_SIZE = 36,
|
||||||
#define MODES_FAST_RELEASE (1<<7)
|
LAYER_RESERVED_SIZE = 40,
|
||||||
|
PATCH_DATA_RESERVED_SIZE = 36,
|
||||||
|
INST_NAME_SIZE = 16,
|
||||||
|
ENVELOPES = 6,
|
||||||
|
MAX_LAYERS = 4
|
||||||
|
};
|
||||||
|
#define GF1_HEADER_TEXT "GF1PATCH110"
|
||||||
|
|
||||||
#define INST_GUS 0
|
enum
|
||||||
#define INST_SF2 1
|
{
|
||||||
#define INST_DLS 2
|
PATCH_16 = (1<<0),
|
||||||
|
PATCH_UNSIGNED = (1<<1),
|
||||||
|
PATCH_LOOPEN = (1<<2),
|
||||||
|
PATCH_BIDIR = (1<<3),
|
||||||
|
PATCH_BACKWARD = (1<<4),
|
||||||
|
PATCH_SUSTAIN = (1<<5),
|
||||||
|
PATCH_NO_SRELEASE = (1<<6),
|
||||||
|
PATCH_FAST_REL = (1<<7)
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
#define GCC_PACKED
|
||||||
|
#else
|
||||||
|
#define GCC_PACKED __attribute__((__packed__))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct GF1PatchHeader
|
||||||
|
{
|
||||||
|
char Header[HEADER_SIZE];
|
||||||
|
char GravisID[ID_SIZE]; /* Id = "ID#000002" */
|
||||||
|
char Description[DESC_SIZE];
|
||||||
|
BYTE Instruments;
|
||||||
|
BYTE Voices;
|
||||||
|
BYTE Channels;
|
||||||
|
WORD WaveForms;
|
||||||
|
WORD MasterVolume;
|
||||||
|
DWORD DataSize;
|
||||||
|
BYTE Reserved[PATCH_HEADER_RESERVED_SIZE];
|
||||||
|
} GCC_PACKED;
|
||||||
|
|
||||||
|
struct GF1InstrumentData
|
||||||
|
{
|
||||||
|
WORD Instrument;
|
||||||
|
char InstrumentName[INST_NAME_SIZE];
|
||||||
|
int InstrumentSize;
|
||||||
|
BYTE Layers;
|
||||||
|
BYTE Reserved[RESERVED_SIZE];
|
||||||
|
} GCC_PACKED;
|
||||||
|
|
||||||
|
struct GF1LayerData
|
||||||
|
{
|
||||||
|
BYTE LayerDuplicate;
|
||||||
|
BYTE Layer;
|
||||||
|
int LayerSize;
|
||||||
|
BYTE Samples;
|
||||||
|
BYTE Reserved[LAYER_RESERVED_SIZE];
|
||||||
|
} GCC_PACKED;
|
||||||
|
|
||||||
|
struct GF1PatchData
|
||||||
|
{
|
||||||
|
char WaveName[7];
|
||||||
|
BYTE Fractions;
|
||||||
|
int WaveSize;
|
||||||
|
int StartLoop;
|
||||||
|
int EndLoop;
|
||||||
|
WORD SampleRate;
|
||||||
|
int LowFrequency;
|
||||||
|
int HighFrequency;
|
||||||
|
int RootFrequency;
|
||||||
|
SWORD Tune;
|
||||||
|
BYTE Balance;
|
||||||
|
BYTE EnvelopeRate[6];
|
||||||
|
BYTE EnvelopeOffset[6];
|
||||||
|
BYTE TremoloSweep;
|
||||||
|
BYTE TremoloRate;
|
||||||
|
BYTE TremoloDepth;
|
||||||
|
BYTE VibratoSweep;
|
||||||
|
BYTE VibratoRate;
|
||||||
|
BYTE VibratoDepth;
|
||||||
|
BYTE Modes;
|
||||||
|
SWORD ScaleFrequency;
|
||||||
|
WORD ScaleFactor; /* From 0 to 2048 or 0 to 2 */
|
||||||
|
BYTE Reserved[PATCH_DATA_RESERVED_SIZE];
|
||||||
|
} GCC_PACKED;
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma pack(pop)
|
||||||
|
#endif
|
||||||
|
#undef GCC_PACKED
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
INST_GUS,
|
||||||
|
INST_DLS
|
||||||
|
};
|
||||||
|
|
||||||
struct Instrument
|
struct Instrument
|
||||||
{
|
{
|
||||||
|
Instrument();
|
||||||
|
~Instrument();
|
||||||
|
|
||||||
int type;
|
int type;
|
||||||
int samples;
|
int samples;
|
||||||
Sample *sample;
|
Sample *sample;
|
||||||
int left_samples;
|
|
||||||
Sample *left_sample;
|
|
||||||
int right_samples;
|
|
||||||
Sample *right_sample;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InstrumentLayer
|
|
||||||
{
|
|
||||||
BYTE lo, hi;
|
|
||||||
Instrument *instrument;
|
|
||||||
InstrumentLayer *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cfg_type
|
|
||||||
{
|
|
||||||
int font_code;
|
|
||||||
int num;
|
|
||||||
const char *name;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define FONT_NORMAL 0
|
|
||||||
#define FONT_FFF 1
|
|
||||||
#define FONT_SBK 2
|
|
||||||
#define FONT_TONESET 3
|
|
||||||
#define FONT_DRUMSET 4
|
|
||||||
#define FONT_PRESET 5
|
|
||||||
|
|
||||||
struct ToneBankElement
|
struct ToneBankElement
|
||||||
{
|
{
|
||||||
ToneBankElement() : layer(NULL), font_type(0), sf_ix(0), tuning(0),
|
ToneBankElement() :
|
||||||
note(0), amp(0), pan(0), strip_loop(0), strip_envelope(0), strip_tail(0)
|
note(0), amp(0), pan(0), strip_loop(0), strip_envelope(0), strip_tail(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
FString name;
|
FString name;
|
||||||
InstrumentLayer *layer;
|
|
||||||
int font_type, sf_ix, tuning;
|
|
||||||
int note, amp, pan, strip_loop, strip_envelope, strip_tail;
|
int note, amp, pan, strip_loop, strip_envelope, strip_tail;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A hack to delay instrument loading until after reading the
|
/* A hack to delay instrument loading until after reading the
|
||||||
entire MIDI file. */
|
entire MIDI file. */
|
||||||
#define MAGIC_LOAD_INSTRUMENT ((InstrumentLayer *)(-1))
|
#define MAGIC_LOAD_INSTRUMENT ((Instrument *)(-1))
|
||||||
|
|
||||||
#define MAXPROG 128
|
enum
|
||||||
#define MAXBANK 130
|
{
|
||||||
#define SFXBANK (MAXBANK-1)
|
MAXPROG = 128,
|
||||||
#define SFXDRUM1 (MAXBANK-2)
|
MAXBANK = 128
|
||||||
#define SFXDRUM2 (MAXBANK-1)
|
};
|
||||||
#define XGDRUM 1
|
|
||||||
|
|
||||||
struct ToneBank
|
struct ToneBank
|
||||||
{
|
{
|
||||||
FString name;
|
ToneBank();
|
||||||
ToneBankElement tone[MAXPROG];
|
~ToneBank();
|
||||||
|
|
||||||
|
ToneBankElement *tone;
|
||||||
|
Instrument *instrument[MAXPROG];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -341,60 +394,55 @@ playmidi.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Midi events */
|
/* Midi events */
|
||||||
#define ME_NOTEOFF 0x80
|
enum
|
||||||
#define ME_NOTEON 0x90
|
{
|
||||||
#define ME_KEYPRESSURE 0xA0
|
ME_NOTEOFF = 0x80,
|
||||||
#define ME_CONTROLCHANGE 0xB0
|
ME_NOTEON = 0x90,
|
||||||
#define ME_PROGRAM 0xC0
|
ME_KEYPRESSURE = 0xA0,
|
||||||
#define ME_CHANNELPRESSURE 0xD0
|
ME_CONTROLCHANGE = 0xB0,
|
||||||
#define ME_PITCHWHEEL 0xE0
|
ME_PROGRAM = 0xC0,
|
||||||
|
ME_CHANNELPRESSURE = 0xD0,
|
||||||
|
ME_PITCHWHEEL = 0xE0
|
||||||
|
};
|
||||||
|
|
||||||
/* Controllers */
|
/* Controllers */
|
||||||
#define CTRL_BANK_SELECT 0
|
enum
|
||||||
#define CTRL_DATA_ENTRY 6
|
{
|
||||||
#define CTRL_VOLUME 7
|
CTRL_BANK_SELECT = 0,
|
||||||
#define CTRL_PAN 10
|
CTRL_DATA_ENTRY = 6,
|
||||||
#define CTRL_EXPRESSION 11
|
CTRL_VOLUME = 7,
|
||||||
#define CTRL_SUSTAIN 64
|
CTRL_PAN = 10,
|
||||||
#define CTRL_HARMONICCONTENT 71
|
CTRL_EXPRESSION = 11,
|
||||||
#define CTRL_RELEASETIME 72
|
CTRL_SUSTAIN = 64,
|
||||||
#define CTRL_ATTACKTIME 73
|
CTRL_HARMONICCONTENT = 71,
|
||||||
#define CTRL_BRIGHTNESS 74
|
CTRL_RELEASETIME = 72,
|
||||||
#define CTRL_REVERBERATION 91
|
CTRL_ATTACKTIME = 73,
|
||||||
#define CTRL_CHORUSDEPTH 93
|
CTRL_BRIGHTNESS = 74,
|
||||||
#define CTRL_NRPN_LSB 98
|
CTRL_REVERBERATION = 91,
|
||||||
#define CTRL_NRPN_MSB 99
|
CTRL_CHORUSDEPTH = 93,
|
||||||
#define CTRL_RPN_LSB 100
|
CTRL_NRPN_LSB = 98,
|
||||||
#define CTRL_RPN_MSB 101
|
CTRL_NRPN_MSB = 99,
|
||||||
#define CTRL_ALL_SOUNDS_OFF 120
|
CTRL_RPN_LSB = 100,
|
||||||
#define CTRL_RESET_CONTROLLERS 121
|
CTRL_RPN_MSB = 101,
|
||||||
#define CTRL_ALL_NOTES_OFF 123
|
CTRL_ALL_SOUNDS_OFF = 120,
|
||||||
|
CTRL_RESET_CONTROLLERS = 121,
|
||||||
/* NRPNs */
|
CTRL_ALL_NOTES_OFF = 123
|
||||||
#define NRPN_BRIGHTNESS 0x00A0
|
};
|
||||||
#define NRPN_HARMONICCONTENT 0x00A1
|
|
||||||
#define NRPN_DRUMVOLUME (26<<7) // drum number in low 7 bits
|
|
||||||
#define NRPN_DRUMPANPOT (28<<7) // "
|
|
||||||
#define NRPN_DRUMREVERBERATION (29<<7) // "
|
|
||||||
#define NRPN_DRUMCHORUSDEPTH (30<<7) // "
|
|
||||||
|
|
||||||
/* RPNs */
|
/* RPNs */
|
||||||
#define RPN_PITCH_SENS 0x0000
|
enum
|
||||||
#define RPN_FINE_TUNING 0x0001
|
{
|
||||||
#define RPN_COARSE_TUNING 0x0002
|
RPN_PITCH_SENS = 0x0000,
|
||||||
#define RPN_RESET 0x3fff
|
RPN_FINE_TUNING = 0x0001,
|
||||||
|
RPN_COARSE_TUNING = 0x0002,
|
||||||
#define SFX_BANKTYPE 64
|
RPN_RESET = 0x3fff
|
||||||
|
};
|
||||||
|
|
||||||
struct Channel
|
struct Channel
|
||||||
{
|
{
|
||||||
int
|
int
|
||||||
bank, program, sustain, pitchbend,
|
bank, program, sustain, pitchbend,
|
||||||
mono, /* one note only on this channel -- not implemented yet */
|
mono, /* one note only on this channel -- not implemented yet */
|
||||||
/* new stuff */
|
|
||||||
variationbank, reverberation, chorusdepth, harmoniccontent,
|
|
||||||
releasetime, attacktime, brightness, kit, sfx,
|
|
||||||
/* end new */
|
|
||||||
pitchsens;
|
pitchsens;
|
||||||
WORD
|
WORD
|
||||||
volume, expression;
|
volume, expression;
|
||||||
|
@ -404,8 +452,6 @@ struct Channel
|
||||||
rpn, nrpn;
|
rpn, nrpn;
|
||||||
bool
|
bool
|
||||||
nrpn_mode;
|
nrpn_mode;
|
||||||
char
|
|
||||||
transpose;
|
|
||||||
float
|
float
|
||||||
pitchfactor; /* precomputed pitch bend factor to save some fdiv's */
|
pitchfactor; /* precomputed pitch bend factor to save some fdiv's */
|
||||||
};
|
};
|
||||||
|
@ -413,75 +459,64 @@ struct Channel
|
||||||
/* Causes the instrument's default panning to be used. */
|
/* Causes the instrument's default panning to be used. */
|
||||||
#define NO_PANNING -1
|
#define NO_PANNING -1
|
||||||
/* envelope points */
|
/* envelope points */
|
||||||
#define MAXPOINT 7
|
#define MAXPOINT 6
|
||||||
|
|
||||||
struct Voice
|
struct Voice
|
||||||
{
|
{
|
||||||
BYTE
|
BYTE
|
||||||
status, channel, note, velocity, clone_type;
|
status, channel, note, velocity;
|
||||||
Sample *sample;
|
Sample *sample;
|
||||||
Sample *left_sample;
|
|
||||||
Sample *right_sample;
|
|
||||||
int clone_voice;
|
|
||||||
float
|
float
|
||||||
orig_frequency, frequency;
|
orig_frequency, frequency;
|
||||||
int
|
int
|
||||||
sample_offset, loop_start, loop_end;
|
sample_offset, sample_increment,
|
||||||
int
|
envelope_volume, envelope_target, envelope_increment,
|
||||||
envelope_volume, modulation_volume;
|
tremolo_sweep, tremolo_sweep_position,
|
||||||
int
|
tremolo_phase, tremolo_phase_increment,
|
||||||
envelope_target, modulation_target;
|
vibrato_sweep, vibrato_sweep_position;
|
||||||
int
|
|
||||||
tremolo_sweep, tremolo_sweep_position, tremolo_phase,
|
|
||||||
lfo_sweep, lfo_sweep_position, lfo_phase,
|
|
||||||
vibrato_sweep, vibrato_sweep_position, vibrato_depth,
|
|
||||||
echo_delay_count;
|
|
||||||
int
|
|
||||||
echo_delay,
|
|
||||||
sample_increment,
|
|
||||||
envelope_increment,
|
|
||||||
modulation_increment,
|
|
||||||
tremolo_phase_increment,
|
|
||||||
lfo_phase_increment;
|
|
||||||
|
|
||||||
final_volume_t left_mix, right_mix;
|
final_volume_t left_mix, right_mix;
|
||||||
|
|
||||||
float
|
float
|
||||||
left_amp, right_amp,
|
left_amp, right_amp, tremolo_volume;
|
||||||
volume, tremolo_volume, lfo_volume;
|
|
||||||
int
|
int
|
||||||
vibrato_sample_increment[VIBRATO_SAMPLE_INCREMENTS];
|
vibrato_sample_increment[VIBRATO_SAMPLE_INCREMENTS];
|
||||||
int
|
|
||||||
envelope_rate[MAXPOINT], envelope_offset[MAXPOINT];
|
|
||||||
int
|
int
|
||||||
vibrato_phase, vibrato_control_ratio, vibrato_control_counter,
|
vibrato_phase, vibrato_control_ratio, vibrato_control_counter,
|
||||||
envelope_stage, modulation_stage, control_counter,
|
envelope_stage, control_counter, panning, panned;
|
||||||
modulation_delay, modulation_counter, panning, panned;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Voice status options: */
|
/* Voice status options: */
|
||||||
#define VOICE_FREE 0
|
enum
|
||||||
#define VOICE_ON 1
|
{
|
||||||
#define VOICE_SUSTAINED 2
|
VOICE_FREE,
|
||||||
#define VOICE_OFF 3
|
VOICE_ON,
|
||||||
#define VOICE_DIE 4
|
VOICE_SUSTAINED,
|
||||||
|
VOICE_OFF,
|
||||||
|
VOICE_DIE
|
||||||
|
};
|
||||||
|
|
||||||
/* Voice panned options: */
|
/* Voice panned options: */
|
||||||
#define PANNED_MYSTERY 0
|
enum
|
||||||
#define PANNED_LEFT 1
|
{
|
||||||
#define PANNED_RIGHT 2
|
PANNED_MYSTERY,
|
||||||
#define PANNED_CENTER 3
|
PANNED_LEFT,
|
||||||
|
PANNED_RIGHT,
|
||||||
|
PANNED_CENTER
|
||||||
|
};
|
||||||
/* Anything but PANNED_MYSTERY only uses the left volume */
|
/* Anything but PANNED_MYSTERY only uses the left volume */
|
||||||
|
|
||||||
/* Envelope stages: */
|
/* Envelope stages: */
|
||||||
#define ATTACK 0
|
enum
|
||||||
#define HOLD 1
|
{
|
||||||
#define DECAY 2
|
ATTACK,
|
||||||
#define RELEASE 3
|
HOLD,
|
||||||
#define RELEASEB 4
|
DECAY,
|
||||||
#define RELEASEC 5
|
RELEASE,
|
||||||
#define DELAY 6
|
RELEASEB,
|
||||||
|
RELEASEC
|
||||||
|
};
|
||||||
|
|
||||||
#define ISDRUMCHANNEL(c) ((drumchannels & (1<<(c))))
|
#define ISDRUMCHANNEL(c) ((drumchannels & (1<<(c))))
|
||||||
|
|
||||||
|
@ -500,8 +535,6 @@ tables.h
|
||||||
#define note_to_freq(x) (float(8175.7989473096690661233836992789 * pow(2.0, (x) / 12.0)))
|
#define note_to_freq(x) (float(8175.7989473096690661233836992789 * pow(2.0, (x) / 12.0)))
|
||||||
#define calc_vol(x) (pow(2.0,((x)*6.0 - 6.0)))
|
#define calc_vol(x) (pow(2.0,((x)*6.0 - 6.0)))
|
||||||
|
|
||||||
#define XMAPMAX 800
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
timidity.h
|
timidity.h
|
||||||
*/
|
*/
|
||||||
|
@ -517,27 +550,16 @@ struct Renderer
|
||||||
{
|
{
|
||||||
float rate;
|
float rate;
|
||||||
DLS_Data *patches;
|
DLS_Data *patches;
|
||||||
InstrumentLayer *default_instrument;
|
Instrument *default_instrument;
|
||||||
int default_program;
|
int default_program;
|
||||||
bool fast_decay;
|
|
||||||
int resample_buffer_size;
|
int resample_buffer_size;
|
||||||
sample_t *resample_buffer;
|
sample_t *resample_buffer;
|
||||||
Channel channel[16];
|
Channel channel[16];
|
||||||
Voice voice[MAX_VOICES];
|
Voice voice[MAX_VOICES];
|
||||||
signed char drumvolume[MAXCHAN][MAXNOTE];
|
|
||||||
signed char drumpanpot[MAXCHAN][MAXNOTE];
|
|
||||||
signed char drumreverberation[MAXCHAN][MAXNOTE];
|
|
||||||
signed char drumchorusdepth[MAXCHAN][MAXNOTE];
|
|
||||||
int control_ratio, amp_with_poly;
|
int control_ratio, amp_with_poly;
|
||||||
int drumchannels;
|
int drumchannels;
|
||||||
int adjust_panning_immediately;
|
int adjust_panning_immediately;
|
||||||
int voices;
|
int voices;
|
||||||
int GM_System_On;
|
|
||||||
int XG_System_On;
|
|
||||||
int GS_System_On;
|
|
||||||
int XG_System_reverb_type;
|
|
||||||
int XG_System_chorus_type;
|
|
||||||
int XG_System_variation_type;
|
|
||||||
int lost_notes, cut_notes;
|
int lost_notes, cut_notes;
|
||||||
|
|
||||||
Renderer(float sample_rate);
|
Renderer(float sample_rate);
|
||||||
|
@ -558,10 +580,8 @@ struct Renderer
|
||||||
int convert_vibrato_rate(BYTE rate);
|
int convert_vibrato_rate(BYTE rate);
|
||||||
|
|
||||||
void recompute_amp(Voice *v);
|
void recompute_amp(Voice *v);
|
||||||
int vc_alloc(int not_this_voice);
|
void kill_key_group(int voice);
|
||||||
void kill_others(int voice);
|
float calculate_scaled_frequency(Sample *sample, int note);
|
||||||
void clone_voice(Instrument *ip, int v, int note, int vel, int clone_type, int variationbank);
|
|
||||||
void xremap(int *banknumpt, int *this_notept, int this_kit);
|
|
||||||
void start_note(int chan, int note, int vel, int voice);
|
void start_note(int chan, int note, int vel, int voice);
|
||||||
|
|
||||||
void note_on(int chan, int note, int vel);
|
void note_on(int chan, int note, int vel);
|
||||||
|
@ -579,7 +599,6 @@ struct Renderer
|
||||||
void reset_midi();
|
void reset_midi();
|
||||||
|
|
||||||
void select_sample(int voice, Instrument *instr, int vel);
|
void select_sample(int voice, Instrument *instr, int vel);
|
||||||
void select_stereo_samples(int voice, InstrumentLayer *layer, int vel);
|
|
||||||
void recompute_freq(int voice);
|
void recompute_freq(int voice);
|
||||||
|
|
||||||
void kill_note(int voice);
|
void kill_note(int voice);
|
||||||
|
|
Loading…
Reference in a new issue