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:
Randy Heit 2008-04-16 05:41:03 +00:00
parent 52eeff6db8
commit 9450db3cec
8 changed files with 789 additions and 1959 deletions

View file

@ -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.

View file

@ -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;
} }

View file

@ -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 */

View file

@ -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

View file

@ -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);

View file

@ -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
} }

View file

@ -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);