mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-02-06 15:51:02 +00:00
- Reduced volume, expression, and panning controllers back to 7 bits.
- Added very basic Soundfont support to the internal TiMidity. Things missing: filter, LFOs, modulation envelope, chorus, reverb, and modulators. May or may not be compatible with TiMidity++'s soundfont extensions. - Added support for quoted strings to the TiMidity config parser. SVN r957 (trunk)
This commit is contained in:
parent
d5563fe478
commit
e64586d86f
16 changed files with 3396 additions and 785 deletions
|
@ -1,9 +1,18 @@
|
||||||
|
May 8, 2008
|
||||||
|
- Reduced volume, expression, and panning controllers back to 7 bits.
|
||||||
|
- Added very basic Soundfont support to the internal TiMidity. Things missing:
|
||||||
|
filter, LFOs, modulation envelope, chorus, reverb, and modulators. May or
|
||||||
|
may not be compatible with TiMidity++'s soundfont extensions.
|
||||||
|
|
||||||
May 8, 2008 (Changes by Graf Zahl)
|
May 8, 2008 (Changes by Graf Zahl)
|
||||||
- Changed all thing coordinates that were stored as shorts into fixed_t.
|
- Changed all thing coordinates that were stored as shorts into fixed_t.
|
||||||
- Separated mapthing2_t into mapthinghexen_t and the internal FMapThing so
|
- Separated mapthing2_t into mapthinghexen_t and the internal FMapThing so
|
||||||
that it is easier to add new features in the UDMF map format.
|
that it is easier to add new features in the UDMF map format.
|
||||||
- Added some initial code to read UDMF maps.
|
- Added some initial code to read UDMF maps.
|
||||||
|
|
||||||
|
May 6, 2008
|
||||||
|
- Added support for quoted strings to the TiMidity config parser.
|
||||||
|
|
||||||
May 2, 2008 (Changes by Graf Zahl)
|
May 2, 2008 (Changes by Graf Zahl)
|
||||||
- Split off the slope creation code from p_Setup.cpp into its own file.
|
- Split off the slope creation code from p_Setup.cpp into its own file.
|
||||||
- Separated the linedef activation types into a bit mask that allows combination
|
- Separated the linedef activation types into a bit mask that allows combination
|
||||||
|
|
|
@ -101,7 +101,7 @@ struct FActionMap
|
||||||
|
|
||||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||||
|
|
||||||
static long ParseCommandLine (const char *args, int *argc, char **argv);
|
static long ParseCommandLine (const char *args, int *argc, char **argv, bool no_escapes);
|
||||||
static FConsoleCommand *FindNameInHashTable (FConsoleCommand **table, const char *name, size_t namelen);
|
static FConsoleCommand *FindNameInHashTable (FConsoleCommand **table, const char *name, size_t namelen);
|
||||||
static FConsoleCommand *ScanChainForName (FConsoleCommand *start, const char *name, size_t namelen, FConsoleCommand **prev);
|
static FConsoleCommand *ScanChainForName (FConsoleCommand *start, const char *name, size_t namelen, FConsoleCommand **prev);
|
||||||
|
|
||||||
|
@ -724,7 +724,7 @@ void AddCommandString (char *cmd, int keynum)
|
||||||
// \c becomes just TEXTCOLOR_ESCAPE
|
// \c becomes just TEXTCOLOR_ESCAPE
|
||||||
// $<cvar> is replaced by the contents of <cvar>
|
// $<cvar> is replaced by the contents of <cvar>
|
||||||
|
|
||||||
static long ParseCommandLine (const char *args, int *argc, char **argv)
|
static long ParseCommandLine (const char *args, int *argc, char **argv, bool no_escapes)
|
||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
char *buffplace;
|
char *buffplace;
|
||||||
|
@ -758,15 +758,15 @@ static long ParseCommandLine (const char *args, int *argc, char **argv)
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
stuff = *args++;
|
stuff = *args++;
|
||||||
if (stuff == '\\' && *args == '\"')
|
if (!no_escapes && stuff == '\\' && *args == '\"')
|
||||||
{
|
{
|
||||||
stuff = '\"', args++;
|
stuff = '\"', args++;
|
||||||
}
|
}
|
||||||
else if (stuff == '\\' && *args == '\\')
|
else if (!no_escapes && stuff == '\\' && *args == '\\')
|
||||||
{
|
{
|
||||||
args++;
|
args++;
|
||||||
}
|
}
|
||||||
else if (stuff == '\\' && *args == 'c')
|
else if (!no_escapes && stuff == '\\' && *args == 'c')
|
||||||
{
|
{
|
||||||
stuff = TEXTCOLOR_ESCAPE, args++;
|
stuff = TEXTCOLOR_ESCAPE, args++;
|
||||||
}
|
}
|
||||||
|
@ -824,11 +824,12 @@ static long ParseCommandLine (const char *args, int *argc, char **argv)
|
||||||
return (long)(buffplace - (char *)0);
|
return (long)(buffplace - (char *)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
FCommandLine::FCommandLine (const char *commandline)
|
FCommandLine::FCommandLine (const char *commandline, bool no_escapes)
|
||||||
{
|
{
|
||||||
cmd = commandline;
|
cmd = commandline;
|
||||||
_argc = -1;
|
_argc = -1;
|
||||||
_argv = NULL;
|
_argv = NULL;
|
||||||
|
noescapes = no_escapes;
|
||||||
}
|
}
|
||||||
|
|
||||||
FCommandLine::~FCommandLine ()
|
FCommandLine::~FCommandLine ()
|
||||||
|
@ -839,11 +840,20 @@ FCommandLine::~FCommandLine ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FCommandLine::Shift()
|
||||||
|
{
|
||||||
|
// Only valid after _argv has been filled.
|
||||||
|
for (int i = 1; i < _argc; ++i)
|
||||||
|
{
|
||||||
|
_argv[i - 1] = _argv[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int FCommandLine::argc ()
|
int FCommandLine::argc ()
|
||||||
{
|
{
|
||||||
if (_argc == -1)
|
if (_argc == -1)
|
||||||
{
|
{
|
||||||
argsize = ParseCommandLine (cmd, &_argc, NULL);
|
argsize = ParseCommandLine (cmd, &_argc, NULL, noescapes);
|
||||||
}
|
}
|
||||||
return _argc;
|
return _argc;
|
||||||
}
|
}
|
||||||
|
@ -855,7 +865,7 @@ char *FCommandLine::operator[] (int i)
|
||||||
int count = argc();
|
int count = argc();
|
||||||
_argv = new char *[count + (argsize+sizeof(char*)-1)/sizeof(char*)];
|
_argv = new char *[count + (argsize+sizeof(char*)-1)/sizeof(char*)];
|
||||||
_argv[0] = (char *)_argv + count*sizeof(char *);
|
_argv[0] = (char *)_argv + count*sizeof(char *);
|
||||||
ParseCommandLine (cmd, NULL, _argv);
|
ParseCommandLine (cmd, NULL, _argv, noescapes);
|
||||||
}
|
}
|
||||||
return _argv[i];
|
return _argv[i];
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,17 +64,19 @@ FString BuildString (int argc, char **argv);
|
||||||
class FCommandLine
|
class FCommandLine
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FCommandLine (const char *commandline);
|
FCommandLine (const char *commandline, bool no_escapes = false);
|
||||||
~FCommandLine ();
|
~FCommandLine ();
|
||||||
int argc ();
|
int argc ();
|
||||||
char *operator[] (int i);
|
char *operator[] (int i);
|
||||||
const char *args () { return cmd; }
|
const char *args () { return cmd; }
|
||||||
|
void Shift();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char *cmd;
|
const char *cmd;
|
||||||
int _argc;
|
int _argc;
|
||||||
char **_argv;
|
char **_argv;
|
||||||
long argsize;
|
long argsize;
|
||||||
|
bool noescapes;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*CCmdRun) (FCommandLine &argv, APlayerPawn *instigator, int key);
|
typedef void (*CCmdRun) (FCommandLine &argv, APlayerPawn *instigator, int key);
|
||||||
|
|
|
@ -623,13 +623,13 @@ FString TimidityMIDIDevice::GetStats()
|
||||||
{
|
{
|
||||||
dots << TEXTCOLOR_GREEN;
|
dots << TEXTCOLOR_GREEN;
|
||||||
}
|
}
|
||||||
if (Renderer->voice[i].envelope_increment == 0)
|
if (!Renderer->voice[i].eg1.env.bUpdating)
|
||||||
{
|
{
|
||||||
dots << "+";
|
dots << "+";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dots << ('0' + Renderer->voice[i].envelope_stage);
|
dots << ('0' + Renderer->voice[i].eg1.gf1.stage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
85
src/timidity/gf1patch.h
Normal file
85
src/timidity/gf1patch.h
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
/* GF1 Patch definition: */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
HEADER_SIZE = 12,
|
||||||
|
ID_SIZE = 10,
|
||||||
|
DESC_SIZE = 60,
|
||||||
|
RESERVED_SIZE = 40,
|
||||||
|
PATCH_HEADER_RESERVED_SIZE = 36,
|
||||||
|
LAYER_RESERVED_SIZE = 40,
|
||||||
|
PATCH_DATA_RESERVED_SIZE = 36,
|
||||||
|
INST_NAME_SIZE = 16,
|
||||||
|
ENVELOPES = 6,
|
||||||
|
MAX_LAYERS = 4
|
||||||
|
};
|
||||||
|
#define GF1_HEADER_TEXT "GF1PATCH110"
|
||||||
|
|
||||||
|
#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[ENVELOPES];
|
||||||
|
BYTE EnvelopeOffset[ENVELOPES];
|
||||||
|
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
|
|
@ -32,16 +32,15 @@
|
||||||
#include "m_swap.h"
|
#include "m_swap.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "templates.h"
|
#include "templates.h"
|
||||||
|
#include "gf1patch.h"
|
||||||
|
|
||||||
namespace Timidity
|
namespace Timidity
|
||||||
{
|
{
|
||||||
|
|
||||||
extern Instrument *load_instrument_dls(Renderer *song, int drum, int bank, int instrument);
|
extern Instrument *load_instrument_dls(Renderer *song, int drum, int bank, int instrument);
|
||||||
|
|
||||||
extern int openmode;
|
|
||||||
|
|
||||||
Instrument::Instrument()
|
Instrument::Instrument()
|
||||||
: type(INST_GUS), samples(0), sample(NULL)
|
: samples(0), sample(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +51,7 @@ Instrument::~Instrument()
|
||||||
|
|
||||||
for (i = samples, sp = &(sample[0]); i != 0; i--, sp++)
|
for (i = samples, sp = &(sample[0]); i != 0; i--, sp++)
|
||||||
{
|
{
|
||||||
if (sp->data != NULL)
|
if (sp->type == INST_GUS && sp->data != NULL)
|
||||||
{
|
{
|
||||||
free(sp->data);
|
free(sp->data);
|
||||||
}
|
}
|
||||||
|
@ -82,28 +81,6 @@ ToneBank::~ToneBank()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int convert_envelope_rate(Renderer *song, BYTE rate)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
|
|
||||||
r = 3 - ((rate>>6) & 0x3);
|
|
||||||
r *= 3;
|
|
||||||
r = (int)(rate & 0x3f) << r; /* 6.9 fixed point */
|
|
||||||
|
|
||||||
/* 15.15 fixed point. */
|
|
||||||
return int(((r * 44100) / song->rate) * song->control_ratio) << 9;
|
|
||||||
}
|
|
||||||
|
|
||||||
int convert_envelope_offset(BYTE offset)
|
|
||||||
{
|
|
||||||
/* This is not too good... Can anyone tell me what these values mean?
|
|
||||||
Are they GUS-style "exponential" volumes? And what does that mean? */
|
|
||||||
|
|
||||||
/* 15.15 fixed point */
|
|
||||||
return offset << (7 + 15);
|
|
||||||
}
|
|
||||||
|
|
||||||
int convert_tremolo_sweep(Renderer *song, BYTE sweep)
|
int convert_tremolo_sweep(Renderer *song, BYTE sweep)
|
||||||
{
|
{
|
||||||
if (sweep == 0)
|
if (sweep == 0)
|
||||||
|
@ -268,7 +245,6 @@ failread:
|
||||||
ip->samples = layer_data.Samples;
|
ip->samples = layer_data.Samples;
|
||||||
ip->sample = (Sample *)safe_malloc(sizeof(Sample) * layer_data.Samples);
|
ip->sample = (Sample *)safe_malloc(sizeof(Sample) * layer_data.Samples);
|
||||||
memset(ip->sample, 0, 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 < layer_data.Samples; ++i)
|
||||||
{
|
{
|
||||||
if (sizeof(patch_data) != fp->Read(&patch_data, sizeof(patch_data)))
|
if (sizeof(patch_data) != fp->Read(&patch_data, sizeof(patch_data)))
|
||||||
|
@ -286,22 +262,23 @@ fail:
|
||||||
sp->loop_start = LittleLong(patch_data.StartLoop);
|
sp->loop_start = LittleLong(patch_data.StartLoop);
|
||||||
sp->loop_end = LittleLong(patch_data.EndLoop);
|
sp->loop_end = LittleLong(patch_data.EndLoop);
|
||||||
sp->sample_rate = LittleShort(patch_data.SampleRate);
|
sp->sample_rate = LittleShort(patch_data.SampleRate);
|
||||||
sp->low_freq = LittleLong(patch_data.LowFrequency);
|
sp->low_freq = float(LittleLong(patch_data.LowFrequency));
|
||||||
sp->high_freq = LittleLong(patch_data.HighFrequency);
|
sp->high_freq = float(LittleLong(patch_data.HighFrequency)) + 0.9999f;
|
||||||
sp->root_freq = LittleLong(patch_data.RootFrequency);
|
sp->root_freq = float(LittleLong(patch_data.RootFrequency));
|
||||||
sp->high_vel = 127;
|
sp->high_vel = 127;
|
||||||
|
sp->velocity = -1;
|
||||||
|
sp->type = INST_GUS;
|
||||||
|
|
||||||
|
// Expand to SF2 range.
|
||||||
if (panning == -1)
|
if (panning == -1)
|
||||||
{
|
{
|
||||||
sp->panning = patch_data.Balance & 0x0F;
|
sp->panning = (patch_data.Balance & 0x0F) * 1000 / 15 - 500;
|
||||||
sp->panning = (sp->panning << 3) | (sp->panning >> 1);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sp->panning = panning & 0x7f;
|
sp->panning = (panning & 0x7f) * 1000 / 127 - 500;
|
||||||
}
|
}
|
||||||
sp->panning |= sp->panning << 7;
|
song->compute_pan((sp->panning + 500) / 1000.0, INST_GUS, sp->left_offset, sp->right_offset);
|
||||||
song->compute_pan(sp->panning, sp->left_offset, sp->right_offset);
|
|
||||||
|
|
||||||
/* tremolo */
|
/* tremolo */
|
||||||
if (patch_data.TremoloRate == 0 || patch_data.TremoloDepth == 0)
|
if (patch_data.TremoloRate == 0 || patch_data.TremoloDepth == 0)
|
||||||
|
@ -353,6 +330,10 @@ fail:
|
||||||
{
|
{
|
||||||
sp->scale_factor *= 1024;
|
sp->scale_factor *= 1024;
|
||||||
}
|
}
|
||||||
|
else if (sp->scale_factor > 2048)
|
||||||
|
{
|
||||||
|
sp->scale_factor = 1024;
|
||||||
|
}
|
||||||
if (sp->scale_factor != 1024)
|
if (sp->scale_factor != 1024)
|
||||||
{
|
{
|
||||||
cmsg(CMSG_INFO, VERB_DEBUG, " * Scale: note %d, factor %d\n",
|
cmsg(CMSG_INFO, VERB_DEBUG, " * Scale: note %d, factor %d\n",
|
||||||
|
@ -444,9 +425,9 @@ fail:
|
||||||
|
|
||||||
for (j = 0; j < 6; j++)
|
for (j = 0; j < 6; j++)
|
||||||
{
|
{
|
||||||
sp->envelope_rate[j] = convert_envelope_rate(song, patch_data.EnvelopeRate[j]);
|
sp->envelope.gf1.rate[j] = patch_data.EnvelopeRate[j];
|
||||||
/* [RH] GF1NEW clamps the offsets to the range [5,251], so we do too. */
|
/* [RH] GF1NEW clamps the offsets to the range [5,251], so we do too. */
|
||||||
sp->envelope_offset[j] = convert_envelope_offset(clamp<BYTE>(patch_data.EnvelopeOffset[j], 5, 251));
|
sp->envelope.gf1.offset[j] = clamp<BYTE>(patch_data.EnvelopeOffset[j], 5, 251);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Then read the sample data */
|
/* Then read the sample data */
|
||||||
|
@ -648,53 +629,62 @@ static int fill_bank(Renderer *song, int dr, int b)
|
||||||
{
|
{
|
||||||
if (bank->instrument[i] == MAGIC_LOAD_INSTRUMENT)
|
if (bank->instrument[i] == MAGIC_LOAD_INSTRUMENT)
|
||||||
{
|
{
|
||||||
|
bank->instrument[i] = NULL;
|
||||||
bank->instrument[i] = load_instrument_dls(song, dr, b, i);
|
bank->instrument[i] = load_instrument_dls(song, dr, b, i);
|
||||||
if (bank->instrument[i] != NULL)
|
if (bank->instrument[i] != NULL)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (bank->tone[i].name.IsEmpty())
|
Instrument *ip;
|
||||||
|
ip = load_instrument_font_order(song, 0, dr, b, i);
|
||||||
|
if (ip == NULL)
|
||||||
{
|
{
|
||||||
cmsg(CMSG_WARNING, (b != 0) ? VERB_VERBOSE : VERB_NORMAL,
|
if (bank->tone[i].fontbank >= 0)
|
||||||
"No instrument mapped to %s %d, program %d%s\n",
|
{
|
||||||
(dr) ? "drum set" : "tone bank", b, i,
|
ip = load_instrument_font(song, bank->tone[i].name, dr, b, i);
|
||||||
(b != 0) ? "" : " - this instrument will not be heard");
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ip = load_instrument(song, bank->tone[i].name,
|
||||||
|
(dr) ? 1 : 0,
|
||||||
|
bank->tone[i].pan,
|
||||||
|
bank->tone[i].amp,
|
||||||
|
(bank->tone[i].note != -1) ? bank->tone[i].note : ((dr) ? i : -1),
|
||||||
|
(bank->tone[i].strip_loop != -1) ? bank->tone[i].strip_loop : ((dr) ? 1 : -1),
|
||||||
|
(bank->tone[i].strip_envelope != -1) ? bank->tone[i].strip_envelope : ((dr) ? 1 : -1),
|
||||||
|
bank->tone[i].strip_tail);
|
||||||
|
}
|
||||||
|
if (ip == NULL)
|
||||||
|
{
|
||||||
|
ip = load_instrument_font_order(song, 1, dr, b, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bank->instrument[i] = ip;
|
||||||
|
if (ip == NULL)
|
||||||
|
{
|
||||||
|
if (bank->tone[i].name.IsEmpty())
|
||||||
|
{
|
||||||
|
cmsg(CMSG_WARNING, (b != 0) ? VERB_VERBOSE : VERB_NORMAL,
|
||||||
|
"No instrument mapped to %s %d, program %d%s\n",
|
||||||
|
(dr) ? "drum set" : "tone bank", b, i,
|
||||||
|
(b != 0) ? "" : " - this instrument will not be heard");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cmsg(CMSG_ERROR, VERB_NORMAL,
|
||||||
|
"Couldn't load instrument %s (%s %d, program %d)\n",
|
||||||
|
bank->tone[i].name.GetChars(),
|
||||||
|
(dr) ? "drum set" : "tone bank", b, i);
|
||||||
|
}
|
||||||
if (b != 0)
|
if (b != 0)
|
||||||
{
|
{
|
||||||
/* Mark the corresponding instrument in the default
|
/* Mark the corresponding instrument in the default
|
||||||
bank / drumset for loading (if it isn't already) */
|
bank / drumset for loading (if it isn't already) */
|
||||||
if (!dr)
|
if (((dr) ? drumset[0] : tonebank[0])->instrument[i] != NULL)
|
||||||
{
|
{
|
||||||
if (tonebank[0]->instrument[i] != NULL)
|
((dr) ? drumset[0] : tonebank[0])->instrument[i] = MAGIC_LOAD_INSTRUMENT;
|
||||||
{
|
|
||||||
tonebank[0]->instrument[i] = MAGIC_LOAD_INSTRUMENT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (drumset[0]->instrument[i] != NULL)
|
|
||||||
{
|
|
||||||
drumset[0]->instrument[i] = MAGIC_LOAD_INSTRUMENT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bank->instrument[i] = NULL;
|
|
||||||
errors++;
|
|
||||||
}
|
|
||||||
else if (!(bank->instrument[i] =
|
|
||||||
load_instrument(song, bank->tone[i].name,
|
|
||||||
(dr) ? 1 : 0,
|
|
||||||
bank->tone[i].pan,
|
|
||||||
bank->tone[i].amp,
|
|
||||||
(bank->tone[i].note != -1) ? bank->tone[i].note : ((dr) ? i : -1),
|
|
||||||
(bank->tone[i].strip_loop != -1) ? bank->tone[i].strip_loop : ((dr) ? 1 : -1),
|
|
||||||
(bank->tone[i].strip_envelope != -1) ? bank->tone[i].strip_envelope : ((dr) ? 1 : -1),
|
|
||||||
bank->tone[i].strip_tail)))
|
|
||||||
{
|
|
||||||
cmsg(CMSG_ERROR, VERB_NORMAL,
|
|
||||||
"Couldn't load instrument %s (%s %d, program %d)\n",
|
|
||||||
bank->tone[i].name.GetChars(),
|
|
||||||
(dr) ? "drum set" : "tone bank", b, i);
|
|
||||||
errors++;
|
errors++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1121,13 +1121,14 @@ 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];
|
||||||
|
|
||||||
|
sample->type = INST_DLS;
|
||||||
sample->self_nonexclusive = !!(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->key_group = (SBYTE)rgn->header->usKeyGroup;
|
||||||
sample->low_freq = SDWORD(note_to_freq(rgn->header->RangeKey.usLow));
|
sample->low_freq = note_to_freq(rgn->header->RangeKey.usLow);
|
||||||
sample->high_freq = SDWORD(note_to_freq(rgn->header->RangeKey.usHigh));
|
sample->high_freq = note_to_freq(rgn->header->RangeKey.usHigh);
|
||||||
sample->root_freq = SDWORD(note_to_freq(rgn->wsmp->usUnityNote));
|
sample->root_freq = note_to_freq(rgn->wsmp->usUnityNote);
|
||||||
sample->low_vel = rgn->header->RangeVelocity.usLow;
|
sample->low_vel = (BYTE)rgn->header->RangeVelocity.usLow;
|
||||||
sample->high_vel = rgn->header->RangeVelocity.usHigh;
|
sample->high_vel = (BYTE)rgn->header->RangeVelocity.usHigh;
|
||||||
|
|
||||||
sample->modes = wave->format->wBitsPerSample == 8 ? PATCH_UNSIGNED : PATCH_16;
|
sample->modes = wave->format->wBitsPerSample == 8 ? PATCH_UNSIGNED : PATCH_16;
|
||||||
sample->sample_rate = wave->format->dwSamplesPerSec;
|
sample->sample_rate = wave->format->dwSamplesPerSec;
|
||||||
|
@ -1174,25 +1175,12 @@ static void load_region_dls(Renderer *song, Sample *sample, DLS_Instrument *ins,
|
||||||
printf("%d, Rate=%d LV=%d HV=%d Low=%d Hi=%d Root=%d Pan=%d Attack=%f Hold=%f Sustain=%d Decay=%f Release=%f\n", index, sample->sample_rate, rgn->header->RangeVelocity.usLow, rgn->header->RangeVelocity.usHigh, sample->low_freq, sample->high_freq, sample->root_freq, sample->panning, attack, hold, sustain, decay, release);
|
printf("%d, Rate=%d LV=%d HV=%d Low=%d Hi=%d Root=%d Pan=%d Attack=%f Hold=%f Sustain=%d Decay=%f Release=%f\n", index, sample->sample_rate, rgn->header->RangeVelocity.usLow, rgn->header->RangeVelocity.usHigh, sample->low_freq, sample->high_freq, sample->root_freq, sample->panning, attack, hold, sustain, decay, release);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
sample->envelope_offset[ATTACK] = to_offset(255);
|
sample->envelope.sf2.decay_vol = 0;
|
||||||
sample->envelope_rate[ATTACK] = calc_rate(song, 255, sample->sample_rate, attack);
|
sample->envelope.sf2.attack_vol = (short)attack;
|
||||||
|
sample->envelope.sf2.hold_vol = (short)hold;
|
||||||
sample->envelope_offset[HOLD] = to_offset(250);
|
sample->envelope.sf2.decay_vol = (short)decay;
|
||||||
sample->envelope_rate[HOLD] = calc_rate(song, 5, sample->sample_rate, hold);
|
sample->envelope.sf2.release_vol = (short)release;
|
||||||
|
sample->envelope.sf2.sustain_vol = (short)sustain;
|
||||||
sample->envelope_offset[DECAY] = to_offset(sustain);
|
|
||||||
sample->envelope_rate[DECAY] = calc_rate(song, 255 - sustain, sample->sample_rate, decay);
|
|
||||||
|
|
||||||
sample->envelope_offset[RELEASE] = to_offset(0);
|
|
||||||
sample->envelope_rate[RELEASE] = calc_rate(song, 5 + sustain, sample->sample_rate, release);
|
|
||||||
|
|
||||||
sample->envelope_offset[RELEASEB] = to_offset(0);
|
|
||||||
sample->envelope_rate[RELEASEB] = to_offset(1);
|
|
||||||
|
|
||||||
sample->envelope_offset[RELEASEC] = to_offset(0);
|
|
||||||
sample->envelope_rate[RELEASEC] = to_offset(1);
|
|
||||||
|
|
||||||
sample->modes |= PATCH_NO_SRELEASE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sample->data_length <<= FRACTION_BITS;
|
sample->data_length <<= FRACTION_BITS;
|
||||||
|
@ -1236,7 +1224,6 @@ Instrument *load_instrument_dls(Renderer *song, int drum, int bank, int instrume
|
||||||
}
|
}
|
||||||
|
|
||||||
inst = (Instrument *)safe_malloc(sizeof(Instrument));
|
inst = (Instrument *)safe_malloc(sizeof(Instrument));
|
||||||
inst->type = INST_DLS;
|
|
||||||
inst->samples = dls_ins->header->cRegions;
|
inst->samples = dls_ins->header->cRegions;
|
||||||
inst->sample = (Sample *)safe_malloc(inst->samples * sizeof(Sample));
|
inst->sample = (Sample *)safe_malloc(inst->samples * sizeof(Sample));
|
||||||
memset(inst->sample, 0, inst->samples * sizeof(Sample));
|
memset(inst->sample, 0, inst->samples * sizeof(Sample));
|
||||||
|
|
131
src/timidity/instrum_font.cpp
Normal file
131
src/timidity/instrum_font.cpp
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "doomdef.h"
|
||||||
|
#include "m_swap.h"
|
||||||
|
#include "templates.h"
|
||||||
|
#include "timidity.h"
|
||||||
|
#include "sf2.h"
|
||||||
|
|
||||||
|
namespace Timidity
|
||||||
|
{
|
||||||
|
|
||||||
|
FontFile *Fonts;
|
||||||
|
|
||||||
|
FontFile *ReadDLS(const char *filename, FileReader *f)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void font_freeall()
|
||||||
|
{
|
||||||
|
FontFile *font, *next;
|
||||||
|
|
||||||
|
for (font = Fonts; font != NULL; font = next)
|
||||||
|
{
|
||||||
|
next = font->Next;
|
||||||
|
delete font;
|
||||||
|
}
|
||||||
|
Fonts = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
FontFile *font_find(const char *filename)
|
||||||
|
{
|
||||||
|
for (FontFile *font = Fonts; font != NULL; font = font->Next)
|
||||||
|
{
|
||||||
|
if (stricmp(filename, font->Filename) == 0)
|
||||||
|
{
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void font_add(const char *filename, int load_order)
|
||||||
|
{
|
||||||
|
FontFile *font;
|
||||||
|
|
||||||
|
font = font_find(filename);
|
||||||
|
if (font != NULL)
|
||||||
|
{
|
||||||
|
font->SetAllOrders(load_order);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FileReader *fp = open_filereader(filename, openmode, NULL);
|
||||||
|
|
||||||
|
if (fp != NULL)
|
||||||
|
{
|
||||||
|
if ((font = ReadSF2(filename, fp)) || (font = ReadDLS(filename, fp)))
|
||||||
|
{
|
||||||
|
font->SetAllOrders(load_order);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void font_remove(const char *filename)
|
||||||
|
{
|
||||||
|
FontFile *font;
|
||||||
|
|
||||||
|
font = font_find(filename);
|
||||||
|
if (font != NULL)
|
||||||
|
{
|
||||||
|
// Don't actually remove the font from the list, because instruments
|
||||||
|
// from it might be loaded using the %font extension.
|
||||||
|
font->SetAllOrders(255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void font_order(int order, int bank, int preset, int keynote)
|
||||||
|
{
|
||||||
|
for (FontFile *font = Fonts; font != NULL; font = font->Next)
|
||||||
|
{
|
||||||
|
font->SetOrder(order, bank, preset, keynote);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Instrument *load_instrument_font(struct Renderer *song, const char *font, int drum, int bank, int instr)
|
||||||
|
{
|
||||||
|
FontFile *fontfile = font_find(font);
|
||||||
|
if (fontfile != NULL)
|
||||||
|
{
|
||||||
|
return fontfile->LoadInstrument(song, drum, bank, instr);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Instrument *load_instrument_font_order(struct Renderer *song, int order, int drum, int bank, int instr)
|
||||||
|
{
|
||||||
|
for (FontFile *font = Fonts; font != NULL; font = font->Next)
|
||||||
|
{
|
||||||
|
Instrument *ip = font->LoadInstrument(song, drum, bank, instr);
|
||||||
|
if (ip != NULL)
|
||||||
|
{
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
FontFile::FontFile(FString filename)
|
||||||
|
: Filename(filename)
|
||||||
|
{
|
||||||
|
Next = Fonts;
|
||||||
|
Fonts = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
FontFile::~FontFile()
|
||||||
|
{
|
||||||
|
for (FontFile **probe = &Fonts; *probe != NULL; probe = &(*probe)->Next)
|
||||||
|
{
|
||||||
|
if (*probe == this)
|
||||||
|
{
|
||||||
|
*probe = Next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
1533
src/timidity/instrum_sf2.cpp
Normal file
1533
src/timidity/instrum_sf2.cpp
Normal file
File diff suppressed because it is too large
Load diff
|
@ -31,68 +31,117 @@
|
||||||
namespace Timidity
|
namespace Timidity
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Returns 1 if envelope runs out */
|
static int convert_envelope_rate(Renderer *song, BYTE rate)
|
||||||
int recompute_envelope(Voice *v)
|
|
||||||
{
|
{
|
||||||
int stage;
|
int r;
|
||||||
|
|
||||||
stage = v->envelope_stage;
|
r = 3 - ((rate>>6) & 0x3);
|
||||||
|
r *= 3;
|
||||||
|
r = (int)(rate & 0x3f) << r; /* 6.9 fixed point */
|
||||||
|
|
||||||
if (stage >= ENVELOPES)
|
/* 15.15 fixed point. */
|
||||||
|
return int(((r * 44100) / song->rate) * song->control_ratio) << 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Envelope::Init(Renderer *song, Voice *v)
|
||||||
|
{
|
||||||
|
Type = v->sample->type;
|
||||||
|
env.bUpdating = true;
|
||||||
|
if (Type == INST_GUS)
|
||||||
|
{
|
||||||
|
gf1.Init(song, v);
|
||||||
|
gf1.ApplyToAmp(v);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sf2.Init(song, v);
|
||||||
|
sf2.ApplyToAmp(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GF1Envelope::Init(Renderer *song, Voice *v)
|
||||||
|
{
|
||||||
|
/* Ramp up from 0 */
|
||||||
|
stage = 0;
|
||||||
|
volume = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; ++i)
|
||||||
|
{
|
||||||
|
offset[i] = v->sample->envelope.gf1.offset[i] << (7 + 15);
|
||||||
|
rate[i] = convert_envelope_rate(song, v->sample->envelope.gf1.rate[i]);
|
||||||
|
}
|
||||||
|
Recompute(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GF1Envelope::Release(Voice *v)
|
||||||
|
{
|
||||||
|
if (!(v->sample->modes & PATCH_NO_SRELEASE) || (v->sample->modes & PATCH_FAST_REL))
|
||||||
|
{
|
||||||
|
/* ramp out to minimum volume with rate from final release stage */
|
||||||
|
stage = GF1_RELEASEC+1;
|
||||||
|
target = 0;
|
||||||
|
increment = -rate[GF1_RELEASEC];
|
||||||
|
}
|
||||||
|
else if (v->sample->modes & PATCH_SUSTAIN)
|
||||||
|
{
|
||||||
|
if (stage < GF1_RELEASE)
|
||||||
|
{
|
||||||
|
stage = GF1_RELEASE;
|
||||||
|
}
|
||||||
|
Recompute(v);
|
||||||
|
}
|
||||||
|
bUpdating = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns 1 if envelope runs out */
|
||||||
|
bool GF1Envelope::Recompute(Voice *v)
|
||||||
|
{
|
||||||
|
int oldstage;
|
||||||
|
|
||||||
|
oldstage = stage;
|
||||||
|
|
||||||
|
if (oldstage > GF1_RELEASEC)
|
||||||
{
|
{
|
||||||
/* Envelope ran out. */
|
/* Envelope ran out. */
|
||||||
/* play sampled release */
|
/* play sampled release */
|
||||||
v->status &= ~(VOICE_SUSTAINING | VOICE_LPE);
|
v->status &= ~(VOICE_SUSTAINING | VOICE_LPE);
|
||||||
v->status |= VOICE_RELEASING;
|
v->status |= VOICE_RELEASING;
|
||||||
v->envelope_increment = 0;
|
increment = 0;
|
||||||
|
bUpdating = false;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stage == RELEASE && !(v->status & VOICE_RELEASING) && (v->sample->modes & PATCH_SUSTAIN))
|
if (oldstage == GF1_RELEASE && !(v->status & VOICE_RELEASING) && (v->sample->modes & PATCH_SUSTAIN))
|
||||||
{
|
{
|
||||||
v->status |= VOICE_SUSTAINING;
|
v->status |= VOICE_SUSTAINING;
|
||||||
/* Freeze envelope until note turns off. Trumpets want this. */
|
/* Freeze envelope until note turns off. Trumpets want this. */
|
||||||
v->envelope_increment = 0;
|
increment = 0;
|
||||||
|
bUpdating = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
v->envelope_stage = stage + 1;
|
stage = oldstage + 1;
|
||||||
|
|
||||||
if (v->envelope_volume == v->sample->envelope_offset[stage])
|
if (volume == offset[oldstage])
|
||||||
{
|
{
|
||||||
return recompute_envelope(v);
|
return Recompute(v);
|
||||||
}
|
}
|
||||||
v->envelope_target = v->sample->envelope_offset[stage];
|
target = offset[oldstage];
|
||||||
v->envelope_increment = v->sample->envelope_rate[stage];
|
increment = rate[oldstage];
|
||||||
if (v->envelope_target < v->envelope_volume)
|
if (target < volume)
|
||||||
v->envelope_increment = -v->envelope_increment;
|
increment = -increment;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply_envelope_to_amp(Voice *v)
|
bool GF1Envelope::Update(Voice *v)
|
||||||
{
|
{
|
||||||
float env_vol = v->attenuation;
|
volume += increment;
|
||||||
float final_amp = v->sample->volume * FINAL_MIX_SCALE;
|
if (((increment < 0) && (volume <= target)) || ((increment > 0) && (volume >= target)))
|
||||||
if (v->tremolo_phase_increment != 0)
|
|
||||||
{
|
{
|
||||||
env_vol *= v->tremolo_volume;
|
volume = target;
|
||||||
}
|
if (Recompute(v))
|
||||||
env_vol *= v->envelope_volume / float(1 << 30);
|
|
||||||
// Note: The pan offsets are negative.
|
|
||||||
v->left_mix = MAX(0.f, (float)calc_gf1_amp(env_vol + v->left_offset) * final_amp);
|
|
||||||
v->right_mix = MAX(0.f, (float)calc_gf1_amp(env_vol + v->right_offset) * final_amp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int update_envelope(Voice *v)
|
|
||||||
{
|
|
||||||
v->envelope_volume += v->envelope_increment;
|
|
||||||
if (((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;
|
|
||||||
if (recompute_envelope(v))
|
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -100,6 +149,214 @@ static int update_envelope(Voice *v)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GF1Envelope::ApplyToAmp(Voice *v)
|
||||||
|
{
|
||||||
|
double env_vol = v->attenuation;
|
||||||
|
double final_amp = v->sample->volume * FINAL_MIX_SCALE;
|
||||||
|
if (v->tremolo_phase_increment != 0)
|
||||||
|
{ // [RH] FIXME: This is wrong. Tremolo should offset the
|
||||||
|
// envelope volume, not scale it.
|
||||||
|
env_vol *= v->tremolo_volume;
|
||||||
|
}
|
||||||
|
env_vol *= volume / float(1 << 30);
|
||||||
|
env_vol = calc_gf1_amp(env_vol) * final_amp;
|
||||||
|
v->left_mix = float(env_vol * v->left_offset);
|
||||||
|
v->right_mix = float(env_vol * v->right_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SF2Envelope::Init(Renderer *song, Voice *v)
|
||||||
|
{
|
||||||
|
stage = 0;
|
||||||
|
volume = 0;
|
||||||
|
DelayTime = v->sample->envelope.sf2.delay_vol;
|
||||||
|
AttackTime = v->sample->envelope.sf2.attack_vol;
|
||||||
|
HoldTime = v->sample->envelope.sf2.hold_vol;
|
||||||
|
DecayTime = v->sample->envelope.sf2.decay_vol;
|
||||||
|
SustainLevel = v->sample->envelope.sf2.sustain_vol;
|
||||||
|
ReleaseTime = v->sample->envelope.sf2.release_vol;
|
||||||
|
SampleRate = song->rate;
|
||||||
|
HoldStart = 0;
|
||||||
|
RateMul = song->control_ratio / song->rate;
|
||||||
|
RateMul_cB = RateMul * 960;
|
||||||
|
bUpdating = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SF2Envelope::Release(Voice *v)
|
||||||
|
{
|
||||||
|
if (stage == SF2_ATTACK)
|
||||||
|
{
|
||||||
|
// The attack stage does not use an attenuation in cB like all the rest.
|
||||||
|
volume = log10(volume) * -200;
|
||||||
|
}
|
||||||
|
stage = SF2_RELEASE;
|
||||||
|
bUpdating = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static double timecent_to_sec(float timecent)
|
||||||
|
{
|
||||||
|
if (timecent == -32768)
|
||||||
|
return 0;
|
||||||
|
return pow(2.0, timecent / 1200.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static double calc_rate(double ratemul, double sec)
|
||||||
|
{
|
||||||
|
if (sec < 0.006)
|
||||||
|
sec = 0.006;
|
||||||
|
return ratemul / sec;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void shutoff_voice(Voice *v)
|
||||||
|
{
|
||||||
|
v->status &= ~(VOICE_SUSTAINING | VOICE_LPE);
|
||||||
|
v->status |= VOICE_RELEASING | VOICE_STOPPING;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool check_release(double RateMul, double sec)
|
||||||
|
{
|
||||||
|
double rate = calc_rate(960 * RateMul, sec);
|
||||||
|
|
||||||
|
// Is release rate very fast? If so, don't do the release, but do
|
||||||
|
// the voice off ramp instead.
|
||||||
|
return (rate < 960/20);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns 1 if envelope runs out */
|
||||||
|
bool SF2Envelope::Update(Voice *v)
|
||||||
|
{
|
||||||
|
double sec;
|
||||||
|
double newvolume;
|
||||||
|
|
||||||
|
switch (stage)
|
||||||
|
{
|
||||||
|
case SF2_DELAY:
|
||||||
|
if (v->sample_count >= timecent_to_sec(DelayTime) * SampleRate)
|
||||||
|
{
|
||||||
|
stage = SF2_ATTACK;
|
||||||
|
return Update(v);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case SF2_ATTACK:
|
||||||
|
sec = timecent_to_sec(AttackTime);
|
||||||
|
if (sec <= 0)
|
||||||
|
{ // instantaneous attack
|
||||||
|
newvolume = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newvolume = volume + calc_rate(RateMul, sec);
|
||||||
|
}
|
||||||
|
if (newvolume >= 1)
|
||||||
|
{
|
||||||
|
volume = 0;
|
||||||
|
HoldStart = v->sample_count;
|
||||||
|
if (HoldTime <= -32768)
|
||||||
|
{ // hold time is 0, so skip right to decay
|
||||||
|
stage = SF2_DECAY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stage = SF2_HOLD;
|
||||||
|
}
|
||||||
|
return Update(v);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SF2_HOLD:
|
||||||
|
if (v->sample_count - HoldStart >= timecent_to_sec(HoldTime) * SampleRate)
|
||||||
|
{
|
||||||
|
stage = SF2_DECAY;
|
||||||
|
return Update(v);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case SF2_DECAY:
|
||||||
|
sec = timecent_to_sec(DecayTime);
|
||||||
|
if (sec <= 0)
|
||||||
|
{ // instantaneous decay
|
||||||
|
newvolume = SustainLevel;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newvolume = volume + calc_rate(RateMul_cB, sec);
|
||||||
|
}
|
||||||
|
if (newvolume >= SustainLevel)
|
||||||
|
{
|
||||||
|
newvolume = SustainLevel;
|
||||||
|
stage = SF2_SUSTAIN;
|
||||||
|
bUpdating = false;
|
||||||
|
if (!(v->status & VOICE_RELEASING))
|
||||||
|
{
|
||||||
|
v->status |= VOICE_SUSTAINING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SF2_SUSTAIN:
|
||||||
|
// Stay here until released.
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case SF2_RELEASE:
|
||||||
|
sec = timecent_to_sec(ReleaseTime);
|
||||||
|
if (sec <= 0)
|
||||||
|
{ // instantaneous release
|
||||||
|
newvolume = 1000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newvolume = volume + calc_rate(RateMul_cB, sec);
|
||||||
|
}
|
||||||
|
if (newvolume >= 960)
|
||||||
|
{
|
||||||
|
stage = SF2_FINISHED;
|
||||||
|
shutoff_voice(v);
|
||||||
|
bUpdating = false;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SF2_FINISHED:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
volume = (float)newvolume;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EMU 8k/10k don't follow spec in regards to volume attenuation.
|
||||||
|
* This factor is used in the equation pow (10.0, cb / FLUID_ATTEN_POWER_FACTOR).
|
||||||
|
* By the standard this should be -200.0. */
|
||||||
|
#define FLUID_ATTEN_POWER_FACTOR (-531.509)
|
||||||
|
#define atten2amp(x) pow(10.0, (x) / FLUID_ATTEN_POWER_FACTOR)
|
||||||
|
|
||||||
|
void SF2Envelope::ApplyToAmp(Voice *v)
|
||||||
|
{
|
||||||
|
double amp;
|
||||||
|
|
||||||
|
if (stage == SF2_DELAY)
|
||||||
|
{
|
||||||
|
v->left_mix = 0;
|
||||||
|
v->right_mix = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (stage == SF2_ATTACK)
|
||||||
|
{
|
||||||
|
amp = atten2amp(v->attenuation) * volume;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
amp = atten2amp(v->attenuation) * cb_to_amp(volume);
|
||||||
|
}
|
||||||
|
amp *= FINAL_MIX_SCALE * 0.5;
|
||||||
|
v->left_mix = float(amp * v->left_offset);
|
||||||
|
v->right_mix = float(amp * v->right_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply_envelope_to_amp(Voice *v)
|
||||||
|
{
|
||||||
|
v->eg1.ApplyToAmp(v);
|
||||||
|
}
|
||||||
|
|
||||||
static void update_tremolo(Voice *v)
|
static void update_tremolo(Voice *v)
|
||||||
{
|
{
|
||||||
int depth = v->sample->tremolo_depth << 7;
|
int depth = v->sample->tremolo_depth << 7;
|
||||||
|
@ -136,7 +393,7 @@ 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 != 0 && update_envelope(v))
|
if (v->eg1.env.bUpdating && v->eg1.Update(v))
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -347,7 +604,7 @@ static void ramp_out(const sample_t *sp, float *lp, Voice *v, int c)
|
||||||
|
|
||||||
/* printf("Ramping out: left=%d, c=%d, li=%d\n", left, c, li); */
|
/* printf("Ramping out: left=%d, c=%d, li=%d\n", left, c, li); */
|
||||||
|
|
||||||
if (v->left_offset == 0) // All the way to the left
|
if (v->right_mix == 0) // All the way to the left
|
||||||
{
|
{
|
||||||
left = v->left_mix;
|
left = v->left_mix;
|
||||||
li = -(left/c);
|
li = -(left/c);
|
||||||
|
@ -362,7 +619,7 @@ static void ramp_out(const sample_t *sp, float *lp, Voice *v, int c)
|
||||||
lp += 2;
|
lp += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (v->right_offset == 0) // All the way to the right
|
else if (v->left_mix == 0) // All the way to the right
|
||||||
{
|
{
|
||||||
right = v->right_mix;
|
right = v->right_mix;
|
||||||
ri = -(right/c);
|
ri = -(right/c);
|
||||||
|
@ -441,7 +698,7 @@ void mix_voice(Renderer *song, float *buf, Voice *v, int c)
|
||||||
}
|
}
|
||||||
if (v->right_mix == 0) // All the way to the left
|
if (v->right_mix == 0) // All the way to the left
|
||||||
{
|
{
|
||||||
if (v->envelope_increment != 0 || v->tremolo_phase_increment != 0)
|
if (v->eg1.env.bUpdating || v->tremolo_phase_increment != 0)
|
||||||
{
|
{
|
||||||
mix_single_left_signal(song->control_ratio, sp, buf, v, count);
|
mix_single_left_signal(song->control_ratio, sp, buf, v, count);
|
||||||
}
|
}
|
||||||
|
@ -452,7 +709,7 @@ void mix_voice(Renderer *song, float *buf, Voice *v, int c)
|
||||||
}
|
}
|
||||||
else if (v->left_mix == 0) // All the way to the right
|
else if (v->left_mix == 0) // All the way to the right
|
||||||
{
|
{
|
||||||
if (v->envelope_increment != 0 || v->tremolo_phase_increment != 0)
|
if (v->eg1.env.bUpdating || v->tremolo_phase_increment != 0)
|
||||||
{
|
{
|
||||||
mix_single_right_signal(song->control_ratio, sp, buf, v, count);
|
mix_single_right_signal(song->control_ratio, sp, buf, v, count);
|
||||||
}
|
}
|
||||||
|
@ -463,7 +720,7 @@ void mix_voice(Renderer *song, float *buf, Voice *v, int c)
|
||||||
}
|
}
|
||||||
else // Somewhere in the middle
|
else // Somewhere in the middle
|
||||||
{
|
{
|
||||||
if (v->envelope_increment || v->tremolo_phase_increment)
|
if (v->eg1.env.bUpdating || v->tremolo_phase_increment)
|
||||||
{
|
{
|
||||||
mix_mystery_signal(song->control_ratio, sp, buf, v, count);
|
mix_mystery_signal(song->control_ratio, sp, buf, v, count);
|
||||||
}
|
}
|
||||||
|
@ -472,6 +729,7 @@ void mix_voice(Renderer *song, float *buf, Voice *v, int c)
|
||||||
mix_mystery(song->control_ratio, sp, buf, v, count);
|
mix_mystery(song->control_ratio, sp, buf, v, count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
v->sample_count += count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,6 @@
|
||||||
namespace Timidity
|
namespace Timidity
|
||||||
{
|
{
|
||||||
|
|
||||||
static const double log_of_2 = 0.69314718055994529;
|
|
||||||
|
|
||||||
void Renderer::reset_voices()
|
void Renderer::reset_voices()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < voices; i++)
|
for (int i = 0; i < voices; i++)
|
||||||
|
@ -44,8 +42,8 @@ void Renderer::reset_voices()
|
||||||
/* Process the Reset All Controllers event */
|
/* Process the Reset All Controllers event */
|
||||||
void Renderer::reset_controllers(int c)
|
void Renderer::reset_controllers(int c)
|
||||||
{
|
{
|
||||||
channel[c].volume = (100 << 7) | 100;
|
channel[c].volume = 100;
|
||||||
channel[c].expression = 0x3fff;
|
channel[c].expression = 127;
|
||||||
channel[c].sustain = 0;
|
channel[c].sustain = 0;
|
||||||
channel[c].pitchbend = 0x2000;
|
channel[c].pitchbend = 0x2000;
|
||||||
channel[c].pitchfactor = 0; /* to be computed */
|
channel[c].pitchfactor = 0; /* to be computed */
|
||||||
|
@ -68,55 +66,6 @@ void Renderer::reset_midi()
|
||||||
reset_voices();
|
reset_voices();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::select_sample(int v, Instrument *ip, int vel)
|
|
||||||
{
|
|
||||||
double f, cdiff, diff;
|
|
||||||
int s, i;
|
|
||||||
Sample *sp, *closest;
|
|
||||||
|
|
||||||
s = ip->samples;
|
|
||||||
sp = ip->sample;
|
|
||||||
|
|
||||||
if (s == 1)
|
|
||||||
{
|
|
||||||
voice[v].sample = sp;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
f = voice[v].orig_frequency;
|
|
||||||
for (i = 0; i < s; i++)
|
|
||||||
{
|
|
||||||
if (sp->low_vel <= vel && sp->high_vel >= vel &&
|
|
||||||
sp->low_freq <= f && sp->high_freq >= f)
|
|
||||||
{
|
|
||||||
voice[v].sample = sp;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sp++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
No suitable sample found! We'll select the sample whose root
|
|
||||||
frequency is closest to the one we want. (Actually we should
|
|
||||||
probably convert the low, high, and root frequencies to MIDI note
|
|
||||||
values and compare those.) */
|
|
||||||
|
|
||||||
cdiff = 1e10;
|
|
||||||
closest = sp = ip->sample;
|
|
||||||
for (i = 0; i < s; i++)
|
|
||||||
{
|
|
||||||
diff = fabs(sp->root_freq - f);
|
|
||||||
if (diff < cdiff)
|
|
||||||
{
|
|
||||||
cdiff = diff;
|
|
||||||
closest = sp;
|
|
||||||
}
|
|
||||||
sp++;
|
|
||||||
}
|
|
||||||
voice[v].sample = closest;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::recompute_freq(int v)
|
void Renderer::recompute_freq(int v)
|
||||||
{
|
{
|
||||||
Channel *ch = &channel[voice[v].channel];
|
Channel *ch = &channel[voice[v].channel];
|
||||||
|
@ -210,37 +159,59 @@ void Renderer::recompute_amp(Voice *v)
|
||||||
int chanvol = chan->volume;
|
int chanvol = chan->volume;
|
||||||
int chanexpr = chan->expression;
|
int chanexpr = chan->expression;
|
||||||
|
|
||||||
v->attenuation = (vol_table[(chanvol * chanexpr) / 2113407] * vol_table[v->velocity]) * ((127 + 64) / 12419775.f);
|
if (v->sample->type == INST_GUS)
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::compute_pan(int panning, float &left_offset, float &right_offset)
|
|
||||||
{
|
|
||||||
// Round the left- and right-most positions to their extremes, since
|
|
||||||
// most songs only do coarse panning.
|
|
||||||
if (panning < 128)
|
|
||||||
{
|
{
|
||||||
panning = 0;
|
v->attenuation = (vol_table[(chanvol * chanexpr) / 127] * vol_table[v->velocity]) * ((127 + 64) / 12419775.f);
|
||||||
}
|
|
||||||
else if (panning > 127*128)
|
|
||||||
{
|
|
||||||
panning = 32767;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (panning == 0)
|
|
||||||
{
|
|
||||||
left_offset = 0;
|
|
||||||
right_offset = (float)-HUGE_VAL;
|
|
||||||
}
|
|
||||||
else if (panning == 32767)
|
|
||||||
{
|
|
||||||
left_offset = (float)-HUGE_VAL;
|
|
||||||
right_offset = 0;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
double pan = panning * (1 / 32767.0);
|
// Implicit modulators from SF2 spec
|
||||||
right_offset = (float)(log(pan) * (1 / (log_of_2 * 32)));
|
double velatten, cc7atten, cc11atten;
|
||||||
left_offset = (float)(log(1 - pan) * (1 / (log_of_2 * 32)));
|
|
||||||
|
velatten = log10(127.0 / v->velocity);
|
||||||
|
cc7atten = log10(127.0 / chanvol);
|
||||||
|
cc11atten = log10(127.0 / chanexpr);
|
||||||
|
v->attenuation = float(400 * (velatten + cc7atten + cc11atten)) + v->sample->initial_attenuation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pan must be in the range [0,1]
|
||||||
|
void Renderer::compute_pan(double pan, int type, float &left_offset, float &right_offset)
|
||||||
|
{
|
||||||
|
if (pan <= 0)
|
||||||
|
{
|
||||||
|
left_offset = 1;
|
||||||
|
right_offset = 0;
|
||||||
|
}
|
||||||
|
else if (pan >= 127/128.0)
|
||||||
|
{
|
||||||
|
left_offset = 0;
|
||||||
|
right_offset = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (type == INST_GUS)
|
||||||
|
{
|
||||||
|
/* Original amp equation looks like this:
|
||||||
|
* calc_gf1_amp(atten + offset)
|
||||||
|
* which expands to:
|
||||||
|
* 2^(16*(atten + offset) - 16)
|
||||||
|
* Keeping in mind that 2^(x + y) == 2^x * 2^y, we can
|
||||||
|
* rewrite this to avoid doing two pows in GF1Envelope::ApplyToAmp():
|
||||||
|
* 2^(16*atten + 16*offset - 16)
|
||||||
|
* 2^(16*atten - 16 + 16 * offset + 16 - 16)
|
||||||
|
* 2^(16*atten - 16) * 2^(16*offset + 16 - 16)
|
||||||
|
* 2^(16*atten - 16) * 2^(16*(offset + 1) - 16)
|
||||||
|
* calc_gf1_amp(atten) * calc_gf1_amp(offset + 1)
|
||||||
|
*/
|
||||||
|
right_offset = (float)calc_gf1_amp((log(pan) * (1 / (log_of_2 * 32))) + 1);
|
||||||
|
left_offset = (float)calc_gf1_amp((log(1 - pan) * (1 / (log_of_2 * 32))) + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
left_offset = (float)db_to_amp(-20 * log10(sqrt(1 - pan)));
|
||||||
|
right_offset = (float)db_to_amp(-20 * log10(sqrt(pan)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,17 +235,112 @@ void Renderer::kill_key_group(int i)
|
||||||
|
|
||||||
float Renderer::calculate_scaled_frequency(Sample *sp, int note)
|
float Renderer::calculate_scaled_frequency(Sample *sp, int note)
|
||||||
{
|
{
|
||||||
double scalednote = (note - sp->scale_note) * sp->scale_factor / 1024.0 + sp->scale_note;
|
double scalednote = (note - sp->scale_note) * sp->scale_factor / 1024.0 + sp->scale_note + sp->tune * 0.01;
|
||||||
return (float)note_to_freq(scalednote);
|
return (float)note_to_freq(scalednote);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::start_note(int chan, int note, int vel, int i)
|
bool Renderer::start_region(int chan, int note, int vel, Sample *sp, float f)
|
||||||
|
{
|
||||||
|
int voicenum;
|
||||||
|
Voice *v;
|
||||||
|
|
||||||
|
voicenum = allocate_voice();
|
||||||
|
if (voicenum < 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
v = &voice[voicenum];
|
||||||
|
v->sample = sp;
|
||||||
|
|
||||||
|
if (sp->type == INST_GUS)
|
||||||
|
{
|
||||||
|
v->orig_frequency = f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (sp->scale_factor != 1024)
|
||||||
|
{
|
||||||
|
v->orig_frequency = calculate_scaled_frequency(sp, note);
|
||||||
|
}
|
||||||
|
else if (sp->tune != 0)
|
||||||
|
{
|
||||||
|
v->orig_frequency = note_to_freq(note + sp->tune * 0.01);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
v->orig_frequency = note_to_freq(note);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v->status = VOICE_RUNNING;
|
||||||
|
v->channel = chan;
|
||||||
|
v->note = note;
|
||||||
|
v->velocity = vel;
|
||||||
|
v->sample_offset = 0;
|
||||||
|
v->sample_increment = 0; /* make sure it isn't negative */
|
||||||
|
v->sample_count = 0;
|
||||||
|
|
||||||
|
v->tremolo_phase = 0;
|
||||||
|
v->tremolo_phase_increment = v->sample->tremolo_phase_increment;
|
||||||
|
v->tremolo_sweep = v->sample->tremolo_sweep_increment;
|
||||||
|
v->tremolo_sweep_position = 0;
|
||||||
|
|
||||||
|
v->vibrato_sweep = v->sample->vibrato_sweep_increment;
|
||||||
|
v->vibrato_sweep_position = 0;
|
||||||
|
v->vibrato_control_ratio = v->sample->vibrato_control_ratio;
|
||||||
|
v->vibrato_control_counter = v->vibrato_phase = 0;
|
||||||
|
|
||||||
|
kill_key_group(voicenum);
|
||||||
|
|
||||||
|
memset(v->vibrato_sample_increment, 0, sizeof(v->vibrato_sample_increment));
|
||||||
|
|
||||||
|
if (sp->type == INST_SF2)
|
||||||
|
{
|
||||||
|
// Channel pan is added to instrument pan.
|
||||||
|
double pan;
|
||||||
|
if (channel[chan].panning == NO_PANNING)
|
||||||
|
{
|
||||||
|
pan = (sp->panning + 500) / 1000.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pan = channel[chan].panning / 128.0 + sp->panning / 1000.0;
|
||||||
|
}
|
||||||
|
compute_pan(pan, sp->type, v->left_offset, v->right_offset);
|
||||||
|
}
|
||||||
|
else if (channel[chan].panning != NO_PANNING)
|
||||||
|
{
|
||||||
|
compute_pan(channel[chan].panning / 128.0, sp->type, v->left_offset, v->right_offset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
v->left_offset = v->sample->left_offset;
|
||||||
|
v->right_offset = v->sample->right_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
recompute_freq(voicenum);
|
||||||
|
recompute_amp(v);
|
||||||
|
v->control_counter = 0;
|
||||||
|
|
||||||
|
v->eg1.Init(this, v);
|
||||||
|
|
||||||
|
if (v->sample->modes & PATCH_LOOPEN)
|
||||||
|
{
|
||||||
|
v->status |= VOICE_LPE;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::start_note(int chan, int note, int vel)
|
||||||
{
|
{
|
||||||
Instrument *ip;
|
Instrument *ip;
|
||||||
|
Sample *sp;
|
||||||
int bank = channel[chan].bank;
|
int bank = channel[chan].bank;
|
||||||
int prog = channel[chan].program;
|
int prog = channel[chan].program;
|
||||||
Voice *v = &voice[i];
|
int i;
|
||||||
|
float f;
|
||||||
|
|
||||||
|
note &= 0x7f;
|
||||||
if (ISDRUMCHANNEL(chan))
|
if (ISDRUMCHANNEL(chan))
|
||||||
{
|
{
|
||||||
if (NULL == drumset[bank] || NULL == (ip = drumset[bank]->instrument[note]))
|
if (NULL == drumset[bank] || NULL == (ip = drumset[bank]->instrument[note]))
|
||||||
|
@ -282,7 +348,12 @@ void Renderer::start_note(int chan, int note, int vel, int i)
|
||||||
if (!(ip = drumset[0]->instrument[note]))
|
if (!(ip = drumset[0]->instrument[note]))
|
||||||
return; /* No instrument? Then we can't play. */
|
return; /* No instrument? Then we can't play. */
|
||||||
}
|
}
|
||||||
if (ip->type == INST_GUS && ip->samples != 1)
|
assert(ip != MAGIC_LOAD_INSTRUMENT);
|
||||||
|
if (ip == MAGIC_LOAD_INSTRUMENT)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ip->samples != 1 && ip->sample->type == INST_GUS)
|
||||||
{
|
{
|
||||||
cmsg(CMSG_WARNING, VERB_VERBOSE,
|
cmsg(CMSG_WARNING, VERB_VERBOSE,
|
||||||
"Strange: percussion instrument with %d samples!", ip->samples);
|
"Strange: percussion instrument with %d samples!", ip->samples);
|
||||||
|
@ -299,62 +370,85 @@ void Renderer::start_note(int chan, int note, int vel, int i)
|
||||||
if (NULL == (ip = tonebank[0]->instrument[prog]))
|
if (NULL == (ip = tonebank[0]->instrument[prog]))
|
||||||
return; /* No instrument? Then we can't play. */
|
return; /* No instrument? Then we can't play. */
|
||||||
}
|
}
|
||||||
|
assert(ip != MAGIC_LOAD_INSTRUMENT);
|
||||||
|
if (ip == MAGIC_LOAD_INSTRUMENT)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ip->sample->scale_factor != 1024)
|
|
||||||
|
if (NULL == ip->sample || ip->samples == 0)
|
||||||
|
return; /* No samples? Then nothing to play. */
|
||||||
|
|
||||||
|
// For GF1 patches, scaling is based solely on the first
|
||||||
|
// waveform in this layer.
|
||||||
|
if (ip->sample->type == INST_GUS && ip->sample->scale_factor != 1024)
|
||||||
{
|
{
|
||||||
v->orig_frequency = calculate_scaled_frequency(ip->sample, note & 0x7F);
|
f = calculate_scaled_frequency(ip->sample, note);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
v->orig_frequency = note_to_freq(note & 0x7F);
|
f = note_to_freq(note);
|
||||||
}
|
}
|
||||||
select_sample(i, ip, vel);
|
|
||||||
|
|
||||||
v->status = VOICE_RUNNING;
|
if (ip->sample->type == INST_GUS)
|
||||||
v->channel = chan;
|
|
||||||
v->note = note;
|
|
||||||
v->velocity = vel;
|
|
||||||
v->sample_offset = 0;
|
|
||||||
v->sample_increment = 0; /* make sure it isn't negative */
|
|
||||||
|
|
||||||
v->tremolo_phase = 0;
|
|
||||||
v->tremolo_phase_increment = voice[i].sample->tremolo_phase_increment;
|
|
||||||
v->tremolo_sweep = voice[i].sample->tremolo_sweep_increment;
|
|
||||||
v->tremolo_sweep_position = 0;
|
|
||||||
|
|
||||||
v->vibrato_sweep = voice[i].sample->vibrato_sweep_increment;
|
|
||||||
v->vibrato_sweep_position = 0;
|
|
||||||
v->vibrato_control_ratio = voice[i].sample->vibrato_control_ratio;
|
|
||||||
v->vibrato_control_counter = voice[i].vibrato_phase = 0;
|
|
||||||
|
|
||||||
kill_key_group(i);
|
|
||||||
|
|
||||||
memset(v->vibrato_sample_increment, 0, sizeof(v->vibrato_sample_increment));
|
|
||||||
|
|
||||||
if (channel[chan].panning != NO_PANNING)
|
|
||||||
{
|
{
|
||||||
v->left_offset = channel[chan].left_offset;
|
/* We're more lenient with matching ranges for GUS patches, since the
|
||||||
v->right_offset = channel[chan].right_offset;
|
* official Gravis ones don't cover the full range of possible
|
||||||
|
* frequencies for every instrument.
|
||||||
|
*/
|
||||||
|
if (ip->samples == 1)
|
||||||
|
{ // If there's only one sample, definitely play it.
|
||||||
|
start_region(chan, note, vel, ip->sample, f);
|
||||||
|
}
|
||||||
|
for (i = ip->samples, sp = ip->sample; i != 0; --i, ++sp)
|
||||||
|
{
|
||||||
|
// GUS patches don't have velocity ranges, so no need to compare against them.
|
||||||
|
if (sp->low_freq <= f && sp->high_freq >= f)
|
||||||
|
{
|
||||||
|
if (i > 1 && (sp + 1)->low_freq <= f && (sp + 1)->high_freq >= f)
|
||||||
|
{ /* If there is a range of contiguous regions that match our
|
||||||
|
* desired frequency, the last one in that block is used.
|
||||||
|
*/
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
start_region(chan, note, vel, sp, f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == 0)
|
||||||
|
{ /* Found nothing. Try again, but look for the one with the closest root frequency.
|
||||||
|
* As per the suggestion in the original TiMidity function, this search uses
|
||||||
|
* note values rather than raw frequencies.
|
||||||
|
*/
|
||||||
|
double cdiff = 1e10;
|
||||||
|
double want_note = freq_to_note(f);
|
||||||
|
Sample *closest = sp = ip->sample;
|
||||||
|
for (i = ip->samples; i != 0; --i, ++sp)
|
||||||
|
{
|
||||||
|
double diff = fabs(freq_to_note(sp->root_freq) - want_note);
|
||||||
|
if (diff < cdiff)
|
||||||
|
{
|
||||||
|
cdiff = diff;
|
||||||
|
closest = sp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
start_region(chan, note, vel, closest, f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
v->left_offset = v->sample->left_offset;
|
for (i = ip->samples, sp = ip->sample; i != 0; --i, ++sp)
|
||||||
v->right_offset = v->sample->right_offset;
|
{
|
||||||
}
|
if ((sp->low_vel <= vel && sp->high_vel >= vel &&
|
||||||
|
sp->low_freq <= f && sp->high_freq >= f))
|
||||||
recompute_freq(i);
|
{
|
||||||
recompute_amp(v);
|
if (!start_region(chan, note, vel, sp, f))
|
||||||
|
{ // Ran out of voices
|
||||||
/* Ramp up from 0 */
|
break;
|
||||||
v->envelope_stage = ATTACK;
|
}
|
||||||
v->envelope_volume = 0;
|
}
|
||||||
v->control_counter = 0;
|
}
|
||||||
recompute_envelope(v);
|
|
||||||
apply_envelope_to_amp(v);
|
|
||||||
|
|
||||||
if (v->sample->modes & PATCH_LOOPEN)
|
|
||||||
{
|
|
||||||
v->status |= VOICE_LPE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,7 +463,53 @@ void Renderer::kill_note(int i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only one instance of a note can be playing on a single channel. */
|
int Renderer::allocate_voice()
|
||||||
|
{
|
||||||
|
int i, lowest;
|
||||||
|
float lv, v;
|
||||||
|
|
||||||
|
for (i = 0; i < voices; ++i)
|
||||||
|
{
|
||||||
|
if (!(voice[i].status & VOICE_RUNNING))
|
||||||
|
{
|
||||||
|
return i; /* Can't get a lower volume than silence */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look for the decaying note with the lowest volume */
|
||||||
|
lowest = -1;
|
||||||
|
lv = 1e10;
|
||||||
|
i = voices;
|
||||||
|
while (i--)
|
||||||
|
{
|
||||||
|
if ((voice[i].status & VOICE_RELEASING) && !(voice[i].status & VOICE_STOPPING))
|
||||||
|
{
|
||||||
|
v = voice[i].attenuation;
|
||||||
|
if (v < lv)
|
||||||
|
{
|
||||||
|
lv = v;
|
||||||
|
lowest = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lowest >= 0)
|
||||||
|
{
|
||||||
|
/* This can still cause a click, but if we had a free voice to
|
||||||
|
spare for ramping down this note, we wouldn't need to kill it
|
||||||
|
in the first place... Still, this needs to be fixed. Perhaps
|
||||||
|
we could use a reserve of voices to play dying notes only. */
|
||||||
|
|
||||||
|
cut_notes++;
|
||||||
|
voice[lowest].status = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lost_notes++;
|
||||||
|
}
|
||||||
|
return lowest;
|
||||||
|
}
|
||||||
|
|
||||||
void Renderer::note_on(int chan, int note, int vel)
|
void Renderer::note_on(int chan, int note, int vel)
|
||||||
{
|
{
|
||||||
if (vel == 0)
|
if (vel == 0)
|
||||||
|
@ -378,16 +518,12 @@ void Renderer::note_on(int chan, int note, int vel)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = voices, lowest = -1;
|
int i = voices;
|
||||||
float lv = 1e10, v;
|
|
||||||
|
|
||||||
|
/* Only one instance of a note can be playing on a single channel. */
|
||||||
while (i--)
|
while (i--)
|
||||||
{
|
{
|
||||||
if (!(voice[i].status & VOICE_RUNNING))
|
if (voice[i].channel == chan && ((voice[i].note == note && !voice[i].sample->self_nonexclusive) || channel[chan].mono))
|
||||||
{
|
|
||||||
lowest = i; /* Can't get a lower volume than silence */
|
|
||||||
}
|
|
||||||
else if (voice[i].channel == chan && ((voice[i].note == note && !voice[i].sample->self_nonexclusive) || channel[chan].mono))
|
|
||||||
{
|
{
|
||||||
if (channel[chan].mono)
|
if (channel[chan].mono)
|
||||||
{
|
{
|
||||||
|
@ -400,46 +536,7 @@ void Renderer::note_on(int chan, int note, int vel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lowest != -1)
|
start_note(chan, note, vel);
|
||||||
{
|
|
||||||
/* Found a free voice. */
|
|
||||||
start_note(chan, note, vel, lowest);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Look for the decaying note with the lowest volume */
|
|
||||||
if (lowest == -1)
|
|
||||||
{
|
|
||||||
i = voices;
|
|
||||||
while (i--)
|
|
||||||
{
|
|
||||||
if ((voice[i].status & VOICE_RELEASING) && !(voice[i].status & VOICE_STOPPING))
|
|
||||||
{
|
|
||||||
v = voice[i].attenuation;
|
|
||||||
if (v < lv)
|
|
||||||
{
|
|
||||||
lv = v;
|
|
||||||
lowest = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lowest != -1)
|
|
||||||
{
|
|
||||||
/* This can still cause a click, but if we had a free voice to
|
|
||||||
spare for ramping down this note, we wouldn't need to kill it
|
|
||||||
in the first place... Still, this needs to be fixed. Perhaps
|
|
||||||
we could use a reserve of voices to play dying notes only. */
|
|
||||||
|
|
||||||
cut_notes++;
|
|
||||||
voice[lowest].status = 0;
|
|
||||||
start_note(chan, note, vel, lowest);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lost_notes++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::finish_note(int i)
|
void Renderer::finish_note(int i)
|
||||||
|
@ -455,23 +552,8 @@ void Renderer::finish_note(int i)
|
||||||
{
|
{
|
||||||
v->status &= ~VOICE_LPE; /* sampled release */
|
v->status &= ~VOICE_LPE; /* sampled release */
|
||||||
}
|
}
|
||||||
if (!(v->sample->modes & PATCH_NO_SRELEASE) || (v->sample->modes & PATCH_FAST_REL))
|
v->eg1.Release(v);
|
||||||
{
|
v->eg2.Release(v);
|
||||||
/* ramp out to minimum volume with rate from final release stage */
|
|
||||||
v->envelope_stage = RELEASEC;
|
|
||||||
recompute_envelope(v);
|
|
||||||
// Get rate from the final release ramp, but force the target to 0.
|
|
||||||
v->envelope_target = 0;
|
|
||||||
v->envelope_increment = -v->sample->envelope_rate[RELEASEC];
|
|
||||||
}
|
|
||||||
else if (v->sample->modes & PATCH_SUSTAIN)
|
|
||||||
{
|
|
||||||
if (v->envelope_stage < RELEASE)
|
|
||||||
{
|
|
||||||
v->envelope_stage = RELEASE;
|
|
||||||
}
|
|
||||||
recompute_envelope(v);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -554,15 +636,19 @@ void Renderer::adjust_pressure(int chan, int note, int amount)
|
||||||
void Renderer::adjust_panning(int chan)
|
void Renderer::adjust_panning(int chan)
|
||||||
{
|
{
|
||||||
Channel *chanp = &channel[chan];
|
Channel *chanp = &channel[chan];
|
||||||
compute_pan(chanp->panning, chanp->left_offset, chanp->right_offset);
|
|
||||||
int i = voices;
|
int i = voices;
|
||||||
while (i--)
|
while (i--)
|
||||||
{
|
{
|
||||||
if ((voice[i].channel == chan) && (voice[i].status & VOICE_RUNNING))
|
Voice *v = &voice[i];
|
||||||
|
if ((v->channel == chan) && (v->status & VOICE_RUNNING))
|
||||||
{
|
{
|
||||||
voice[i].left_offset = chanp->left_offset;
|
double pan = chanp->panning / 128.0;
|
||||||
voice[i].right_offset = chanp->right_offset;
|
if (v->sample->type == INST_SF2)
|
||||||
apply_envelope_to_amp(&voice[i]);
|
{ // Add instrument pan to channel pan.
|
||||||
|
pan += v->sample->panning / 500.0;
|
||||||
|
}
|
||||||
|
compute_pan(pan, v->sample->type, v->left_offset, v->right_offset);
|
||||||
|
apply_envelope_to_amp(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -674,32 +760,17 @@ void Renderer::HandleController(int chan, int ctrl, int val)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CTRL_VOLUME:
|
case CTRL_VOLUME:
|
||||||
channel[chan].volume = (channel[chan].volume & 0x007F) | (val << 7);
|
channel[chan].volume = val;
|
||||||
adjust_volume(chan);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CTRL_VOLUME+32:
|
|
||||||
channel[chan].volume = (channel[chan].volume & 0x3F80) | (val);
|
|
||||||
adjust_volume(chan);
|
adjust_volume(chan);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CTRL_EXPRESSION:
|
case CTRL_EXPRESSION:
|
||||||
channel[chan].expression = (channel[chan].expression & 0x007F) | (val << 7);
|
channel[chan].expression = val;
|
||||||
adjust_volume(chan);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CTRL_EXPRESSION+32:
|
|
||||||
channel[chan].expression = (channel[chan].expression & 0x3F80) | (val);
|
|
||||||
adjust_volume(chan);
|
adjust_volume(chan);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CTRL_PAN:
|
case CTRL_PAN:
|
||||||
channel[chan].panning = (channel[chan].panning & 0x007F) | (val << 7);
|
channel[chan].panning = val;
|
||||||
adjust_panning(chan);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CTRL_PAN+32:
|
|
||||||
channel[chan].panning = (channel[chan].panning & 0x3F80) | (val);
|
|
||||||
adjust_panning(chan);
|
adjust_panning(chan);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -509,6 +509,14 @@ sample_t *resample_voice(Renderer *song, Voice *vp, int *countptr)
|
||||||
/* Need to resample. Use the proper function. */
|
/* Need to resample. Use the proper function. */
|
||||||
modes = vp->sample->modes;
|
modes = vp->sample->modes;
|
||||||
|
|
||||||
|
if (vp->status & VOICE_LPE)
|
||||||
|
{
|
||||||
|
if (vp->sample->loop_end - vp->sample->loop_start < 2)
|
||||||
|
{ // Loop is too short; turn it off.
|
||||||
|
vp->status &= ~VOICE_LPE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (vp->vibrato_control_ratio)
|
if (vp->vibrato_control_ratio)
|
||||||
{
|
{
|
||||||
if (vp->status & VOICE_LPE)
|
if (vp->status & VOICE_LPE)
|
||||||
|
|
318
src/timidity/sf2.h
Normal file
318
src/timidity/sf2.h
Normal file
|
@ -0,0 +1,318 @@
|
||||||
|
typedef WORD SFGenerator;
|
||||||
|
|
||||||
|
struct SFRange
|
||||||
|
{
|
||||||
|
BYTE Lo;
|
||||||
|
BYTE Hi;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SFPreset
|
||||||
|
{
|
||||||
|
char Name[21];
|
||||||
|
BYTE LoadOrder:7;
|
||||||
|
BYTE bHasGlobalZone:1;
|
||||||
|
WORD Program;
|
||||||
|
WORD Bank;
|
||||||
|
WORD BagIndex;
|
||||||
|
/* Don't care about library, genre, and morphology */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SFBag
|
||||||
|
{
|
||||||
|
WORD GenIndex;
|
||||||
|
// WORD ModIndex; // If I am feeling ambitious, I might add support for modulators some day.
|
||||||
|
SFRange KeyRange;
|
||||||
|
SFRange VelRange;
|
||||||
|
int Target; // Either an instrument or sample index
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SFInst
|
||||||
|
{
|
||||||
|
char Name[21];
|
||||||
|
BYTE Pad:7;
|
||||||
|
BYTE bHasGlobalZone:1;
|
||||||
|
WORD BagIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SFSample
|
||||||
|
{
|
||||||
|
float *InMemoryData;
|
||||||
|
DWORD Start;
|
||||||
|
DWORD End;
|
||||||
|
DWORD StartLoop;
|
||||||
|
DWORD EndLoop;
|
||||||
|
DWORD SampleRate;
|
||||||
|
BYTE OriginalPitch;
|
||||||
|
SBYTE PitchCorrection;
|
||||||
|
WORD SampleLink;
|
||||||
|
WORD SampleType;
|
||||||
|
char Name[21];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Sample type bit fields (all but ROM are mutually exclusive)
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SFST_Mono = 1,
|
||||||
|
SFST_Right = 2,
|
||||||
|
SFST_Left = 4,
|
||||||
|
SFST_Linked = 8, /* SF2.04 defines this bit but not its function */
|
||||||
|
SFST_Bad = 16384, /* Used internally */
|
||||||
|
SFST_ROM = 32768
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generator definitions
|
||||||
|
|
||||||
|
struct SFGenList
|
||||||
|
{
|
||||||
|
SFGenerator Oper;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
SFRange Range;
|
||||||
|
SWORD Amount;
|
||||||
|
WORD uAmount;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
GEN_startAddrsOffset,
|
||||||
|
GEN_endAddrsOffset,
|
||||||
|
GEN_startloopAddrsOffset,
|
||||||
|
GEN_endloopAddrsOffset,
|
||||||
|
GEN_startAddrsCoarseOffset,
|
||||||
|
GEN_modLfoToPitch,
|
||||||
|
GEN_vibLfoToPitch,
|
||||||
|
GEN_modEnvToPitch,
|
||||||
|
GEN_initialFilterFC,
|
||||||
|
GEN_initialFilterQ,
|
||||||
|
GEN_modLfoToFilterFc,
|
||||||
|
GEN_modEnvToFilterFc,
|
||||||
|
GEN_endAddrsCoarseOffset,
|
||||||
|
GEN_modLfoToVolume,
|
||||||
|
GEN_unused1,
|
||||||
|
GEN_chorusEffectsSend,
|
||||||
|
GEN_reverbEffectsSend,
|
||||||
|
GEN_pan,
|
||||||
|
GEN_unused2,
|
||||||
|
GEN_unused3,
|
||||||
|
GEN_unused4,
|
||||||
|
GEN_delayModLFO,
|
||||||
|
GEN_freqModLFO,
|
||||||
|
GEN_delayVibLFO,
|
||||||
|
GEN_freqVibLFO,
|
||||||
|
GEN_delayModEnv,
|
||||||
|
GEN_attackModEnv,
|
||||||
|
GEN_holdModEnv,
|
||||||
|
GEN_decayModEnv,
|
||||||
|
GEN_sustainModEnv,
|
||||||
|
GEN_releaseModEnv,
|
||||||
|
GEN_keynumToModEnvHold,
|
||||||
|
GEN_keynumToModEnvDecay,
|
||||||
|
GEN_delayVolEnv,
|
||||||
|
GEN_attackVolEnv,
|
||||||
|
GEN_holdVolEnv,
|
||||||
|
GEN_decayVolEnv,
|
||||||
|
GEN_sustainVolEnv,
|
||||||
|
GEN_releaseVolEnv,
|
||||||
|
GEN_keynumToVolEnvHold,
|
||||||
|
GEN_keynumToVolEnvDecay,
|
||||||
|
GEN_instrument,
|
||||||
|
GEN_reserved1,
|
||||||
|
GEN_keyRange,
|
||||||
|
GEN_velRange,
|
||||||
|
GEN_startloopAddrsCoarseOffset,
|
||||||
|
GEN_keynum,
|
||||||
|
GEN_velocity,
|
||||||
|
GEN_initialAttenuation,
|
||||||
|
GEN_reserved2,
|
||||||
|
GEN_endloopAddrsCoarseOffset,
|
||||||
|
GEN_coarseTune,
|
||||||
|
GEN_fineTune,
|
||||||
|
GEN_sampleID,
|
||||||
|
GEN_sampleModes,
|
||||||
|
GEN_reserved3,
|
||||||
|
GEN_scaleTuning,
|
||||||
|
GEN_exclusiveClass,
|
||||||
|
GEN_overridingRootKey,
|
||||||
|
|
||||||
|
GEN_NumGenerators
|
||||||
|
};
|
||||||
|
|
||||||
|
// Modulator definitions
|
||||||
|
|
||||||
|
struct SFModulator
|
||||||
|
{
|
||||||
|
WORD Index:7;
|
||||||
|
WORD CC:1;
|
||||||
|
WORD Dir:1; /* 0 = min->max, 1 = max->min */
|
||||||
|
WORD Polarity:1; /* 0 = unipolar, 1 = bipolar */
|
||||||
|
WORD Type:6;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SFModList
|
||||||
|
{
|
||||||
|
SFModulator SrcOper;
|
||||||
|
SFGenerator DestOper;
|
||||||
|
SWORD Amount;
|
||||||
|
SFModulator AmtSrcOper;
|
||||||
|
WORD Transform;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Modulator sources when CC is 0
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SFMod_One = 0, // Psuedo-controller that always has the value 1
|
||||||
|
SFMod_NoteVelocity = 2,
|
||||||
|
SFMod_KeyNumber = 3,
|
||||||
|
SFMod_PolyPressure = 10,
|
||||||
|
SFMod_ChannelPressure = 13,
|
||||||
|
SFMod_PitchWheel = 14,
|
||||||
|
SFMod_PitchSens = 16,
|
||||||
|
SFMod_Link = 127
|
||||||
|
};
|
||||||
|
|
||||||
|
// Modulator types
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SFModType_Linear,
|
||||||
|
SFModType_Concave, // log(fabs(value)/(max value)^2)
|
||||||
|
SFModType_Convex,
|
||||||
|
SFModType_Switch
|
||||||
|
};
|
||||||
|
|
||||||
|
// Modulator transforms
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SFModTrans_Linear = 0,
|
||||||
|
SFModTrans_Abs = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
// All possible generators in a single structure
|
||||||
|
|
||||||
|
struct SFGenComposite
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
SFRange keyRange; // For normal use
|
||||||
|
struct // For intermediate percussion use
|
||||||
|
{
|
||||||
|
BYTE drumset;
|
||||||
|
BYTE key;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
SFRange velRange;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
WORD instrument; // At preset level
|
||||||
|
WORD sampleID; // At instrument level
|
||||||
|
};
|
||||||
|
SWORD modLfoToPitch;
|
||||||
|
SWORD vibLfoToPitch;
|
||||||
|
SWORD modEnvToPitch;
|
||||||
|
SWORD initialFilterFc;
|
||||||
|
SWORD initialFilterQ;
|
||||||
|
SWORD modLfoToFilterFc;
|
||||||
|
SWORD modEnvToFilterFc;
|
||||||
|
SWORD modLfoToVolume;
|
||||||
|
SWORD chorusEffectsSend;
|
||||||
|
SWORD reverbEffectsSend;
|
||||||
|
SWORD pan;
|
||||||
|
SWORD delayModLFO;
|
||||||
|
SWORD freqModLFO;
|
||||||
|
SWORD delayVibLFO;
|
||||||
|
SWORD freqVibLFO;
|
||||||
|
SWORD delayModEnv;
|
||||||
|
SWORD attackModEnv;
|
||||||
|
SWORD holdModEnv;
|
||||||
|
SWORD decayModEnv;
|
||||||
|
SWORD sustainModEnv;
|
||||||
|
SWORD releaseModEnv;
|
||||||
|
SWORD keynumToModEnvHold;
|
||||||
|
SWORD keynumToModEnvDecay;
|
||||||
|
SWORD delayVolEnv;
|
||||||
|
SWORD attackVolEnv;
|
||||||
|
SWORD holdVolEnv;
|
||||||
|
SWORD decayVolEnv;
|
||||||
|
SWORD sustainVolEnv;
|
||||||
|
SWORD releaseVolEnv;
|
||||||
|
SWORD keynumToVolEnvHold;
|
||||||
|
SWORD keynumToVolEnvDecay;
|
||||||
|
SWORD initialAttenuation;
|
||||||
|
SWORD coarseTune;
|
||||||
|
SWORD fineTune;
|
||||||
|
SWORD scaleTuning;
|
||||||
|
|
||||||
|
// The following are only for instruments:
|
||||||
|
SWORD startAddrsOffset, startAddrsCoarseOffset;
|
||||||
|
SWORD endAddrsOffset, endAddrsCoarseOffset;
|
||||||
|
SWORD startLoopAddrsOffset, startLoopAddrsCoarseOffset;
|
||||||
|
SWORD endLoopAddrsOffset, endLoopAddrsCoarseOffset;
|
||||||
|
SWORD keynum;
|
||||||
|
SWORD velocity;
|
||||||
|
WORD sampleModes;
|
||||||
|
SWORD exclusiveClass;
|
||||||
|
SWORD overridingRootKey;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Intermediate percussion representation
|
||||||
|
|
||||||
|
struct SFPerc
|
||||||
|
{
|
||||||
|
SFPreset *Preset;
|
||||||
|
SFGenComposite Generators;
|
||||||
|
BYTE LoadOrder;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Container for all parameters from a SoundFont file
|
||||||
|
|
||||||
|
struct SFFile : public Timidity::FontFile
|
||||||
|
{
|
||||||
|
SFFile(FString filename);
|
||||||
|
~SFFile();
|
||||||
|
Timidity::Instrument *LoadInstrument(struct Timidity::Renderer *song, int drum, int bank, int program);
|
||||||
|
Timidity::Instrument *LoadInstrumentOrder(struct Timidity::Renderer *song, int order, int drum, int bank, int program);
|
||||||
|
void SetOrder(int order, int drum, int bank, int program);
|
||||||
|
void SetAllOrders(int order);
|
||||||
|
|
||||||
|
bool FinalStructureTest();
|
||||||
|
void CheckBags();
|
||||||
|
void CheckZones(int start, int stop, bool instr);
|
||||||
|
void TranslatePercussions();
|
||||||
|
void TranslatePercussionPreset(SFPreset *preset);
|
||||||
|
void TranslatePercussionPresetZone(SFPreset *preset, SFBag *zone);
|
||||||
|
|
||||||
|
void SetInstrumentGenerators(SFGenComposite *composite, int start, int stop);
|
||||||
|
void AddPresetGenerators(SFGenComposite *composite, int start, int stop, SFPreset *preset);
|
||||||
|
void AddPresetGenerators(SFGenComposite *composite, int start, int stop, bool gen_set[GEN_NumGenerators]);
|
||||||
|
|
||||||
|
Timidity::Instrument *LoadPercussion(Timidity::Renderer *song, SFPerc *perc);
|
||||||
|
Timidity::Instrument *LoadPreset(Timidity::Renderer *song, SFPreset *preset);
|
||||||
|
void LoadSample(SFSample *sample);
|
||||||
|
void ApplyGeneratorsToRegion(SFGenComposite *gen, SFSample *sfsamp, Timidity::Renderer *song, Timidity::Sample *sp);
|
||||||
|
|
||||||
|
SFPreset *Presets;
|
||||||
|
SFBag *PresetBags;
|
||||||
|
SFGenList *PresetGenerators;
|
||||||
|
SFInst *Instruments;
|
||||||
|
SFBag *InstrBags;
|
||||||
|
SFGenList *InstrGenerators;
|
||||||
|
SFSample *Samples;
|
||||||
|
TArray<SFPerc> Percussion;
|
||||||
|
int MinorVersion;
|
||||||
|
DWORD SampleDataOffset;
|
||||||
|
DWORD SampleDataLSBOffset;
|
||||||
|
DWORD SizeSampleData;
|
||||||
|
DWORD SizeSampleDataLSB;
|
||||||
|
int NumPresets;
|
||||||
|
int NumPresetBags;
|
||||||
|
int NumPresetGenerators;
|
||||||
|
int NumInstruments;
|
||||||
|
int NumInstrBags;
|
||||||
|
int NumInstrGenerators;
|
||||||
|
int NumSamples;
|
||||||
|
};
|
||||||
|
|
||||||
|
SFFile *ReadSF2(const char *filename, FileReader *f);
|
|
@ -28,6 +28,7 @@
|
||||||
#include "m_alloc.h"
|
#include "m_alloc.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
#include "c_cvars.h"
|
#include "c_cvars.h"
|
||||||
|
#include "c_dispatch.h"
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
|
|
||||||
|
@ -42,13 +43,10 @@ ToneBank *tonebank[MAXBANK], *drumset[MAXBANK];
|
||||||
static FString def_instr_name;
|
static FString def_instr_name;
|
||||||
int openmode = OM_FILEORLUMP;
|
int openmode = OM_FILEORLUMP;
|
||||||
|
|
||||||
|
|
||||||
#define MAXWORDS 10
|
|
||||||
|
|
||||||
static int read_config_file(const char *name, bool ismain)
|
static int read_config_file(const char *name, bool ismain)
|
||||||
{
|
{
|
||||||
FileReader *fp;
|
FileReader *fp;
|
||||||
char tmp[1024], *w[MAXWORDS], *cp;
|
char tmp[1024], *cp;
|
||||||
ToneBank *bank = NULL;
|
ToneBank *bank = NULL;
|
||||||
int i, j, k, line = 0, words;
|
int i, j, k, line = 0, words;
|
||||||
static int rcf_count = 0;
|
static int rcf_count = 0;
|
||||||
|
@ -81,17 +79,29 @@ static int read_config_file(const char *name, bool ismain)
|
||||||
while (fp->Gets(tmp, sizeof(tmp)))
|
while (fp->Gets(tmp, sizeof(tmp)))
|
||||||
{
|
{
|
||||||
line++;
|
line++;
|
||||||
w[words = 0] = strtok(tmp, " \t\r\n\240");
|
FCommandLine w(tmp, true);
|
||||||
if (!w[0]) continue;
|
words = w.argc();
|
||||||
|
if (words == 0) continue;
|
||||||
|
|
||||||
/* Originally the TiMidity++ extensions were prefixed like this */
|
/* Originally the TiMidity++ extensions were prefixed like this */
|
||||||
if (strcmp(w[0], "#extension") == 0)
|
if (strcmp(w[0], "#extension") == 0)
|
||||||
words = -1;
|
{
|
||||||
|
w.Shift();
|
||||||
|
words--;
|
||||||
|
}
|
||||||
else if (*w[0] == '#')
|
else if (*w[0] == '#')
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
while (w[words] && *w[words] != '#' && (words < MAXWORDS))
|
for (i = 0; i < words; ++i)
|
||||||
w[++words] = strtok(0, " \t\r\n\240");
|
{
|
||||||
|
if (*w[i] == '#')
|
||||||
|
{
|
||||||
|
words = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TiMidity++ adds a number of extensions to the config file format.
|
* TiMidity++ adds a number of extensions to the config file format.
|
||||||
|
@ -155,19 +165,93 @@ static int read_config_file(const char *name, bool ismain)
|
||||||
*/
|
*/
|
||||||
Printf("FIXME: Implement \"altassign\" in TiMidity config.\n");
|
Printf("FIXME: Implement \"altassign\" in TiMidity config.\n");
|
||||||
}
|
}
|
||||||
else if (!strcmp(w[0], "soundfont") || !strcmp(w[0], "font"))
|
else if (!strcmp(w[0], "soundfont"))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* I can't find any documentation for these, but I guess they're
|
|
||||||
* an alternative way of loading/unloading instruments.
|
|
||||||
*
|
|
||||||
* "soundfont" sf_file "remove"
|
* "soundfont" sf_file "remove"
|
||||||
* "soundfont" sf_file ["order=" order] ["cutoff=" cutoff]
|
* "soundfont" sf_file ["order=" order] ["cutoff=" cutoff]
|
||||||
* ["reso=" reso] ["amp=" amp]
|
* ["reso=" reso] ["amp=" amp]
|
||||||
|
*/
|
||||||
|
if (words < 2)
|
||||||
|
{
|
||||||
|
Printf("%s: line %d: No soundfont given\n", name, line);
|
||||||
|
delete fp;
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
if (words > 2 && !strcmp(w[2], "remove"))
|
||||||
|
{
|
||||||
|
font_remove(w[1]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int order = 0;
|
||||||
|
|
||||||
|
for (i = 2; i < words; ++i)
|
||||||
|
{
|
||||||
|
if (!(cp = strchr(w[i], '=')))
|
||||||
|
{
|
||||||
|
Printf("%s: line %d: bad soundfont option %s\n", name, line, w[i]);
|
||||||
|
delete fp;
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
font_add(w[1], order);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!strcmp(w[0], "font"))
|
||||||
|
{
|
||||||
|
/*
|
||||||
* "font" "exclude" bank preset keynote
|
* "font" "exclude" bank preset keynote
|
||||||
* "font" "order" order bank preset keynote
|
* "font" "order" order bank preset keynote
|
||||||
*/
|
*/
|
||||||
Printf("FIXME: Implmement \"%s\" in TiMidity config.\n", w[0]);
|
int order, drum = -1, bank = -1, instr = -1;
|
||||||
|
|
||||||
|
if (words < 3)
|
||||||
|
{
|
||||||
|
Printf("%s: line %d: syntax error\n", name, line);
|
||||||
|
delete fp;
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(w[1], "exclude"))
|
||||||
|
{
|
||||||
|
order = 254;
|
||||||
|
i = 2;
|
||||||
|
}
|
||||||
|
else if (!strcmp(w[1], "order"))
|
||||||
|
{
|
||||||
|
order = atoi(w[2]);
|
||||||
|
i = 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Printf("%s: line %d: font subcommand must be 'order' or 'exclude'\n", name, line);
|
||||||
|
delete fp;
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
if (i < words)
|
||||||
|
{
|
||||||
|
drum = atoi(w[i++]);
|
||||||
|
}
|
||||||
|
if (i < words)
|
||||||
|
{
|
||||||
|
bank = atoi(w[i++]);
|
||||||
|
}
|
||||||
|
if (i < words)
|
||||||
|
{
|
||||||
|
instr = atoi(w[i++]);
|
||||||
|
}
|
||||||
|
if (drum != 128)
|
||||||
|
{
|
||||||
|
instr = bank;
|
||||||
|
bank = drum;
|
||||||
|
drum = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
drum = 1;
|
||||||
|
}
|
||||||
|
font_order(order, drum, bank, instr);
|
||||||
}
|
}
|
||||||
else if (!strcmp(w[0], "progbase"))
|
else if (!strcmp(w[0], "progbase"))
|
||||||
{
|
{
|
||||||
|
@ -289,12 +373,34 @@ static int read_config_file(const char *name, bool ismain)
|
||||||
delete fp;
|
delete fp;
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
bank->tone[i].name = w[1];
|
|
||||||
bank->tone[i].note = bank->tone[i].amp = bank->tone[i].pan =
|
bank->tone[i].note = bank->tone[i].amp = bank->tone[i].pan =
|
||||||
bank->tone[i].strip_loop = bank->tone[i].strip_envelope =
|
bank->tone[i].fontbank = bank->tone[i].fontpreset =
|
||||||
bank->tone[i].strip_tail = -1;
|
bank->tone[i].fontnote = bank->tone[i].strip_loop =
|
||||||
|
bank->tone[i].strip_envelope = bank->tone[i].strip_tail = -1;
|
||||||
|
|
||||||
for (j = 2; j<words; j++)
|
if (!strcmp(w[1], "%font"))
|
||||||
|
{
|
||||||
|
bank->tone[i].name = w[2];
|
||||||
|
bank->tone[i].fontbank = atoi(w[3]);
|
||||||
|
bank->tone[i].fontpreset = atoi(w[4]);
|
||||||
|
if (bank->tone[i].fontbank == 128 || (w[5][0] >= '0' && w[5][0] <= '9'))
|
||||||
|
{
|
||||||
|
bank->tone[i].fontnote = atoi(w[5]);
|
||||||
|
j = 6;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
j = 5;
|
||||||
|
}
|
||||||
|
font_add(w[2], 254);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bank->tone[i].name = w[1];
|
||||||
|
j = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; j<words; j++)
|
||||||
{
|
{
|
||||||
if (!(cp=strchr(w[j], '=')))
|
if (!(cp=strchr(w[j], '=')))
|
||||||
{
|
{
|
||||||
|
@ -397,6 +503,7 @@ static int read_config_file(const char *name, bool ismain)
|
||||||
void FreeAll()
|
void FreeAll()
|
||||||
{
|
{
|
||||||
free_instruments();
|
free_instruments();
|
||||||
|
font_freeall();
|
||||||
for (int i = 0; i < MAXBANK; ++i)
|
for (int i = 0; i < MAXBANK; ++i)
|
||||||
{
|
{
|
||||||
if (tonebank[i] != NULL)
|
if (tonebank[i] != NULL)
|
||||||
|
|
|
@ -177,6 +177,7 @@ extern void clear_pathlist();
|
||||||
extern void *safe_malloc(size_t count);
|
extern void *safe_malloc(size_t count);
|
||||||
|
|
||||||
FileReader *open_filereader(const char *name, int open, int *plumpnum);
|
FileReader *open_filereader(const char *name, int open, int *plumpnum);
|
||||||
|
extern int openmode;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
controls.h
|
controls.h
|
||||||
|
@ -204,53 +205,6 @@ void cmsg(int type, int verbosity_level, const char *fmt, ...);
|
||||||
instrum.h
|
instrum.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct Sample
|
|
||||||
{
|
|
||||||
SDWORD
|
|
||||||
loop_start, loop_end, data_length,
|
|
||||||
sample_rate, low_vel, high_vel, low_freq, high_freq, root_freq;
|
|
||||||
SDWORD
|
|
||||||
envelope_rate[6], envelope_offset[6];
|
|
||||||
float
|
|
||||||
volume;
|
|
||||||
sample_t *data;
|
|
||||||
SDWORD
|
|
||||||
tremolo_sweep_increment, tremolo_phase_increment,
|
|
||||||
vibrato_sweep_increment, vibrato_control_ratio;
|
|
||||||
BYTE
|
|
||||||
tremolo_depth, vibrato_depth,
|
|
||||||
modes;
|
|
||||||
WORD
|
|
||||||
panning, scale_factor;
|
|
||||||
SWORD
|
|
||||||
scale_note;
|
|
||||||
bool
|
|
||||||
self_nonexclusive;
|
|
||||||
BYTE
|
|
||||||
key_group;
|
|
||||||
float
|
|
||||||
left_offset, right_offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
void convert_sample_data(Sample *sample, const void *data);
|
|
||||||
void free_instruments();
|
|
||||||
|
|
||||||
/* Patch definition: */
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
HEADER_SIZE = 12,
|
|
||||||
ID_SIZE = 10,
|
|
||||||
DESC_SIZE = 60,
|
|
||||||
RESERVED_SIZE = 40,
|
|
||||||
PATCH_HEADER_RESERVED_SIZE = 36,
|
|
||||||
LAYER_RESERVED_SIZE = 40,
|
|
||||||
PATCH_DATA_RESERVED_SIZE = 36,
|
|
||||||
INST_NAME_SIZE = 16,
|
|
||||||
ENVELOPES = 6,
|
|
||||||
MAX_LAYERS = 4
|
|
||||||
};
|
|
||||||
#define GF1_HEADER_TEXT "GF1PATCH110"
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PATCH_16 = (1<<0),
|
PATCH_16 = (1<<0),
|
||||||
|
@ -263,80 +217,90 @@ enum
|
||||||
PATCH_FAST_REL = (1<<7)
|
PATCH_FAST_REL = (1<<7)
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
struct Sample
|
||||||
#pragma pack(push, 1)
|
|
||||||
#define GCC_PACKED
|
|
||||||
#else
|
|
||||||
#define GCC_PACKED __attribute__((__packed__))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct GF1PatchHeader
|
|
||||||
{
|
{
|
||||||
char Header[HEADER_SIZE];
|
SDWORD
|
||||||
char GravisID[ID_SIZE]; /* Id = "ID#000002" */
|
loop_start, loop_end, data_length,
|
||||||
char Description[DESC_SIZE];
|
sample_rate;
|
||||||
BYTE Instruments;
|
float
|
||||||
BYTE Voices;
|
low_freq, high_freq, root_freq;
|
||||||
BYTE Channels;
|
union
|
||||||
WORD WaveForms;
|
{
|
||||||
WORD MasterVolume;
|
struct
|
||||||
DWORD DataSize;
|
{
|
||||||
BYTE Reserved[PATCH_HEADER_RESERVED_SIZE];
|
BYTE rate[6], offset[6];
|
||||||
} GCC_PACKED;
|
} gf1;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
short delay_vol;
|
||||||
|
short attack_vol;
|
||||||
|
short hold_vol;
|
||||||
|
short decay_vol;
|
||||||
|
short sustain_vol;
|
||||||
|
short release_vol;
|
||||||
|
} sf2;
|
||||||
|
} envelope;
|
||||||
|
float
|
||||||
|
volume;
|
||||||
|
sample_t *data;
|
||||||
|
SDWORD
|
||||||
|
tremolo_sweep_increment, tremolo_phase_increment,
|
||||||
|
vibrato_sweep_increment, vibrato_control_ratio;
|
||||||
|
BYTE
|
||||||
|
tremolo_depth, vibrato_depth,
|
||||||
|
low_vel, high_vel,
|
||||||
|
modes, type;
|
||||||
|
SWORD
|
||||||
|
panning;
|
||||||
|
WORD
|
||||||
|
scale_factor, key_group;
|
||||||
|
SWORD
|
||||||
|
scale_note;
|
||||||
|
bool
|
||||||
|
self_nonexclusive;
|
||||||
|
float
|
||||||
|
left_offset, right_offset;
|
||||||
|
|
||||||
struct GF1InstrumentData
|
// SF2 stuff
|
||||||
{
|
SWORD tune;
|
||||||
WORD Instrument;
|
SBYTE velocity;
|
||||||
char InstrumentName[INST_NAME_SIZE];
|
|
||||||
int InstrumentSize;
|
|
||||||
BYTE Layers;
|
|
||||||
BYTE Reserved[RESERVED_SIZE];
|
|
||||||
} GCC_PACKED;
|
|
||||||
|
|
||||||
struct GF1LayerData
|
float initial_attenuation;
|
||||||
{
|
};
|
||||||
BYTE LayerDuplicate;
|
|
||||||
BYTE Layer;
|
|
||||||
int LayerSize;
|
|
||||||
BYTE Samples;
|
|
||||||
BYTE Reserved[LAYER_RESERVED_SIZE];
|
|
||||||
} GCC_PACKED;
|
|
||||||
|
|
||||||
struct GF1PatchData
|
void convert_sample_data(Sample *sample, const void *data);
|
||||||
{
|
void free_instruments();
|
||||||
char WaveName[7];
|
|
||||||
BYTE Fractions;
|
/* Magic file words */
|
||||||
int WaveSize;
|
|
||||||
int StartLoop;
|
#define ID_RIFF MAKE_ID('R','I','F','F')
|
||||||
int EndLoop;
|
#define ID_LIST MAKE_ID('L','I','S','T')
|
||||||
WORD SampleRate;
|
#define ID_INFO MAKE_ID('I','N','F','O')
|
||||||
int LowFrequency;
|
#define ID_sfbk MAKE_ID('s','f','b','k')
|
||||||
int HighFrequency;
|
#define ID_sdta MAKE_ID('s','d','t','a')
|
||||||
int RootFrequency;
|
#define ID_pdta MAKE_ID('p','d','t','a')
|
||||||
SWORD Tune;
|
#define ID_ifil MAKE_ID('i','f','i','l')
|
||||||
BYTE Balance;
|
#define ID_iver MAKE_ID('i','v','e','r')
|
||||||
BYTE EnvelopeRate[ENVELOPES];
|
#define ID_irom MAKE_ID('i','r','o','m')
|
||||||
BYTE EnvelopeOffset[ENVELOPES];
|
#define ID_smpl MAKE_ID('s','m','p','l')
|
||||||
BYTE TremoloSweep;
|
#define ID_sm24 MAKE_ID('s','m','2','4')
|
||||||
BYTE TremoloRate;
|
#define ID_phdr MAKE_ID('p','h','d','r')
|
||||||
BYTE TremoloDepth;
|
#define ID_pbag MAKE_ID('p','b','a','g')
|
||||||
BYTE VibratoSweep;
|
#define ID_pmod MAKE_ID('p','m','o','d')
|
||||||
BYTE VibratoRate;
|
#define ID_pgen MAKE_ID('p','g','e','n')
|
||||||
BYTE VibratoDepth;
|
#define ID_inst MAKE_ID('i','n','s','t')
|
||||||
BYTE Modes;
|
#define ID_ibag MAKE_ID('i','b','a','g')
|
||||||
SWORD ScaleFrequency;
|
#define ID_imod MAKE_ID('i','m','o','d')
|
||||||
WORD ScaleFactor; /* From 0 to 2048 or 0 to 2 */
|
#define ID_igen MAKE_ID('i','g','e','n')
|
||||||
BYTE Reserved[PATCH_DATA_RESERVED_SIZE];
|
#define ID_shdr MAKE_ID('s','h','d','r')
|
||||||
} GCC_PACKED;
|
|
||||||
#ifdef _MSC_VER
|
/* Instrument definitions */
|
||||||
#pragma pack(pop)
|
|
||||||
#endif
|
|
||||||
#undef GCC_PACKED
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
INST_GUS,
|
INST_GUS,
|
||||||
INST_DLS
|
INST_DLS,
|
||||||
|
INST_SF2
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Instrument
|
struct Instrument
|
||||||
|
@ -344,7 +308,6 @@ struct Instrument
|
||||||
Instrument();
|
Instrument();
|
||||||
~Instrument();
|
~Instrument();
|
||||||
|
|
||||||
int type;
|
|
||||||
int samples;
|
int samples;
|
||||||
Sample *sample;
|
Sample *sample;
|
||||||
};
|
};
|
||||||
|
@ -356,11 +319,10 @@ struct ToneBankElement
|
||||||
{}
|
{}
|
||||||
|
|
||||||
FString name;
|
FString name;
|
||||||
int note, amp, pan, strip_loop, strip_envelope, strip_tail;
|
int note, amp, pan, fontbank, fontpreset, fontnote, 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 ((Instrument *)(-1))
|
#define MAGIC_LOAD_INSTRUMENT ((Instrument *)(-1))
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -381,7 +343,34 @@ struct ToneBank
|
||||||
|
|
||||||
#define SPECIAL_PROGRAM -1
|
#define SPECIAL_PROGRAM -1
|
||||||
|
|
||||||
extern void pcmap(int *b, int *v, int *p, int *drums);
|
/*
|
||||||
|
instrum_font.cpp
|
||||||
|
*/
|
||||||
|
|
||||||
|
class FontFile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FontFile(FString filename);
|
||||||
|
virtual ~FontFile();
|
||||||
|
|
||||||
|
FString Filename;
|
||||||
|
FontFile *Next;
|
||||||
|
|
||||||
|
virtual Instrument *LoadInstrument(struct Renderer *song, int drum, int bank, int program) = 0;
|
||||||
|
virtual Instrument *LoadInstrumentOrder(struct Renderer *song, int order, int drum, int bank, int program) = 0;
|
||||||
|
virtual void SetOrder(int order, int drum, int bank, int program) = 0;
|
||||||
|
virtual void SetAllOrders(int order) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void font_freeall();
|
||||||
|
FontFile *font_find(const char *filename);
|
||||||
|
void font_add(const char *filename, int load_order);
|
||||||
|
void font_remove(const char *filename);
|
||||||
|
void font_order(int order, int bank, int preset, int keynote);
|
||||||
|
Instrument *load_instrument_font(struct Renderer *song, const char *font, int drum, int bank, int instrument);
|
||||||
|
Instrument *load_instrument_font_order(struct Renderer *song, int order, int drum, int bank, int instrument);
|
||||||
|
|
||||||
|
FontFile *ReadDLS(const char *filename, FileReader *f);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
mix.h
|
mix.h
|
||||||
|
@ -446,9 +435,9 @@ struct Channel
|
||||||
bank, program, sustain, pitchbend,
|
bank, program, sustain, pitchbend,
|
||||||
mono, /* one note only on this channel */
|
mono, /* one note only on this channel */
|
||||||
pitchsens;
|
pitchsens;
|
||||||
WORD
|
BYTE
|
||||||
volume, expression;
|
volume, expression;
|
||||||
SWORD
|
SBYTE
|
||||||
panning;
|
panning;
|
||||||
WORD
|
WORD
|
||||||
rpn, nrpn;
|
rpn, nrpn;
|
||||||
|
@ -456,13 +445,81 @@ struct Channel
|
||||||
nrpn_mode;
|
nrpn_mode;
|
||||||
float
|
float
|
||||||
pitchfactor; /* precomputed pitch bend factor to save some fdiv's */
|
pitchfactor; /* precomputed pitch bend factor to save some fdiv's */
|
||||||
float
|
|
||||||
left_offset, right_offset; /* precomputed panning values */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 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
|
||||||
|
|
||||||
|
struct MinEnvelope
|
||||||
|
{
|
||||||
|
int stage;
|
||||||
|
BYTE bUpdating;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GF1Envelope : public MinEnvelope
|
||||||
|
{
|
||||||
|
int volume, target, increment;
|
||||||
|
int rate[6], offset[6];
|
||||||
|
|
||||||
|
void Init(struct Renderer *song, Voice *v);
|
||||||
|
bool Update(struct Voice *v);
|
||||||
|
bool Recompute(struct Voice *v);
|
||||||
|
void ApplyToAmp(struct Voice *v);
|
||||||
|
void Release(struct Voice *v);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SF2Envelope : public MinEnvelope
|
||||||
|
{
|
||||||
|
float volume;
|
||||||
|
float DelayTime; // timecents
|
||||||
|
float AttackTime; // timecents
|
||||||
|
float HoldTime; // timecents
|
||||||
|
float DecayTime; // timecents
|
||||||
|
float SustainLevel; // -0.1%
|
||||||
|
float ReleaseTime; // timecents
|
||||||
|
float SampleRate;
|
||||||
|
int HoldStart;
|
||||||
|
float RateMul;
|
||||||
|
float RateMul_cB;
|
||||||
|
|
||||||
|
void Init(struct Renderer *song, Voice *v);
|
||||||
|
bool Update(struct Voice *v);
|
||||||
|
void ApplyToAmp(struct Voice *v);
|
||||||
|
void Release(struct Voice *v);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Envelope
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
MinEnvelope env;
|
||||||
|
GF1Envelope gf1;
|
||||||
|
SF2Envelope sf2;
|
||||||
|
};
|
||||||
|
|
||||||
|
BYTE Type;
|
||||||
|
|
||||||
|
void Init(struct Renderer *song, struct Voice *v);
|
||||||
|
bool Update(struct Voice *v)
|
||||||
|
{
|
||||||
|
if (Type == INST_GUS)
|
||||||
|
return gf1.Update(v);
|
||||||
|
return sf2.Update(v);
|
||||||
|
}
|
||||||
|
void ApplyToAmp(struct Voice *v)
|
||||||
|
{
|
||||||
|
if (Type == INST_GUS)
|
||||||
|
return gf1.ApplyToAmp(v);
|
||||||
|
return sf2.ApplyToAmp(v);
|
||||||
|
}
|
||||||
|
void Release(struct Voice *v)
|
||||||
|
{
|
||||||
|
if (Type == INST_GUS)
|
||||||
|
return gf1.Release(v);
|
||||||
|
return sf2.Release(v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct Voice
|
struct Voice
|
||||||
{
|
{
|
||||||
BYTE
|
BYTE
|
||||||
|
@ -472,11 +529,12 @@ struct Voice
|
||||||
orig_frequency, frequency;
|
orig_frequency, frequency;
|
||||||
int
|
int
|
||||||
sample_offset, sample_increment,
|
sample_offset, sample_increment,
|
||||||
envelope_volume, envelope_target, envelope_increment,
|
|
||||||
tremolo_sweep, tremolo_sweep_position,
|
tremolo_sweep, tremolo_sweep_position,
|
||||||
tremolo_phase, tremolo_phase_increment,
|
tremolo_phase, tremolo_phase_increment,
|
||||||
vibrato_sweep, vibrato_sweep_position;
|
vibrato_sweep, vibrato_sweep_position;
|
||||||
|
|
||||||
|
Envelope eg1, eg2;
|
||||||
|
|
||||||
final_volume_t left_mix, right_mix;
|
final_volume_t left_mix, right_mix;
|
||||||
|
|
||||||
float
|
float
|
||||||
|
@ -487,8 +545,10 @@ struct Voice
|
||||||
vibrato_sample_increment[VIBRATO_SAMPLE_INCREMENTS];
|
vibrato_sample_increment[VIBRATO_SAMPLE_INCREMENTS];
|
||||||
int
|
int
|
||||||
vibrato_phase, vibrato_control_ratio, vibrato_control_counter,
|
vibrato_phase, vibrato_control_ratio, vibrato_control_counter,
|
||||||
envelope_stage, control_counter;
|
control_counter;
|
||||||
|
|
||||||
|
int
|
||||||
|
sample_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Voice status options: */
|
/* Voice status options: */
|
||||||
|
@ -506,12 +566,23 @@ enum
|
||||||
/* Envelope stages: */
|
/* Envelope stages: */
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
ATTACK,
|
GF1_ATTACK,
|
||||||
HOLD,
|
GF1_HOLD,
|
||||||
DECAY,
|
GF1_DECAY,
|
||||||
RELEASE,
|
GF1_RELEASE,
|
||||||
RELEASEB,
|
GF1_RELEASEB,
|
||||||
RELEASEC
|
GF1_RELEASEC
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SF2_DELAY,
|
||||||
|
SF2_ATTACK,
|
||||||
|
SF2_HOLD,
|
||||||
|
SF2_DECAY,
|
||||||
|
SF2_SUSTAIN,
|
||||||
|
SF2_RELEASE,
|
||||||
|
SF2_FINISHED
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ISDRUMCHANNEL(c) ((drumchannels & (1<<(c))))
|
#define ISDRUMCHANNEL(c) ((drumchannels & (1<<(c))))
|
||||||
|
@ -527,10 +598,16 @@ extern void pre_resample(struct Renderer *song, Sample *sp);
|
||||||
tables.h
|
tables.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const double log_of_2 = 0.69314718055994529;
|
||||||
|
|
||||||
#define sine(x) (sin((2*PI/1024.0) * (x)))
|
#define sine(x) (sin((2*PI/1024.0) * (x)))
|
||||||
|
|
||||||
#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))) // Physically ideal equation
|
#define freq_to_note(x) (log((x) / 8175.7989473096690661233836992789) * (12.0 / log_of_2))
|
||||||
|
|
||||||
#define calc_gf1_amp(x) (pow(2.0,((x)*16.0 - 16.0))) // Actual GUS equation
|
#define calc_gf1_amp(x) (pow(2.0,((x)*16.0 - 16.0))) // Actual GUS equation
|
||||||
|
#define cb_to_amp(x) (pow(10.0, (x) * (1 / -200.0))) // centibels to amp
|
||||||
|
#define db_to_amp(x) (pow(10.0, (x) * (1 / -20.0))) // decibels to map
|
||||||
|
|
||||||
/*
|
/*
|
||||||
timidity.h
|
timidity.h
|
||||||
|
@ -582,7 +659,8 @@ struct Renderer
|
||||||
|
|
||||||
void kill_key_group(int voice);
|
void kill_key_group(int voice);
|
||||||
float calculate_scaled_frequency(Sample *sample, int note);
|
float calculate_scaled_frequency(Sample *sample, int note);
|
||||||
void start_note(int chan, int note, int vel, int voice);
|
void start_note(int chan, int note, int vel);
|
||||||
|
bool start_region(int chan, int note, int vel, Sample *sp, float freq);
|
||||||
|
|
||||||
void note_on(int chan, int note, int vel);
|
void note_on(int chan, int note, int vel);
|
||||||
void note_off(int chan, int note, int vel);
|
void note_off(int chan, int note, int vel);
|
||||||
|
@ -598,7 +676,7 @@ struct Renderer
|
||||||
void reset_controllers(int chan);
|
void reset_controllers(int chan);
|
||||||
void reset_midi();
|
void reset_midi();
|
||||||
|
|
||||||
void select_sample(int voice, Instrument *instr, int vel);
|
int allocate_voice();
|
||||||
|
|
||||||
void kill_note(int voice);
|
void kill_note(int voice);
|
||||||
void finish_note(int voice);
|
void finish_note(int voice);
|
||||||
|
@ -608,7 +686,7 @@ struct Renderer
|
||||||
void DataEntryCoarseNRPN(int chan, int nrpn, int val);
|
void DataEntryCoarseNRPN(int chan, int nrpn, int val);
|
||||||
void DataEntryFineNRPN(int chan, int nrpn, int val);
|
void DataEntryFineNRPN(int chan, int nrpn, int val);
|
||||||
|
|
||||||
static void compute_pan(int panning, float &left_offset, float &right_offset);
|
static void compute_pan(double panning, int type, float &left_offset, float &right_offset);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
560
zdoom.vcproj
560
zdoom.vcproj
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="Windows-1252"?>
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
<VisualStudioProject
|
<VisualStudioProject
|
||||||
ProjectType="Visual C++"
|
ProjectType="Visual C++"
|
||||||
Version="8,00"
|
Version="8.00"
|
||||||
Name="zdoom"
|
Name="zdoom"
|
||||||
ProjectGUID="{8049475B-5C87-46F9-9358-635218A4EF18}"
|
ProjectGUID="{8049475B-5C87-46F9-9358-635218A4EF18}"
|
||||||
RootNamespace=" zdoom"
|
RootNamespace=" zdoom"
|
||||||
|
@ -135,112 +135,6 @@
|
||||||
Name="VCPostBuildEventTool"
|
Name="VCPostBuildEventTool"
|
||||||
/>
|
/>
|
||||||
</Configuration>
|
</Configuration>
|
||||||
<Configuration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
OutputDirectory=".\Debug"
|
|
||||||
IntermediateDirectory=".\Debug"
|
|
||||||
ConfigurationType="1"
|
|
||||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
|
||||||
UseOfMFC="0"
|
|
||||||
ATLMinimizesCRunTimeLibraryUsage="false"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreBuildEventTool"
|
|
||||||
Description="Checking svnrevision.h..."
|
|
||||||
CommandLine="$(OutDir)\updaterevision.exe src src/svnrevision.h"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXMLDataGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebServiceProxyGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCMIDLTool"
|
|
||||||
PreprocessorDefinitions="_DEBUG"
|
|
||||||
MkTypLibCompatible="true"
|
|
||||||
SuppressStartupBanner="true"
|
|
||||||
TargetEnvironment="1"
|
|
||||||
TypeLibraryName=".\Debug/zdoom.tlb"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
Optimization="0"
|
|
||||||
AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;jpeg-6b;snes_spc\snes_spc"
|
|
||||||
PreprocessorDefinitions="WIN32,_DEBUG,_WIN32,_WINDOWS,USEASM,_CRTDBG_MAP_ALLOC,HAVE_STRUPR,HAVE_FILELENGTH"
|
|
||||||
MinimalRebuild="true"
|
|
||||||
RuntimeLibrary="1"
|
|
||||||
EnableFunctionLevelLinking="true"
|
|
||||||
ForceConformanceInForLoopScope="true"
|
|
||||||
PrecompiledHeaderFile=""
|
|
||||||
AssemblerOutput="0"
|
|
||||||
AssemblerListingLocation=".\Debug/"
|
|
||||||
ObjectFile=".\Debug/"
|
|
||||||
ProgramDataBaseFileName=".\Debug/"
|
|
||||||
WarningLevel="3"
|
|
||||||
SuppressStartupBanner="true"
|
|
||||||
Detect64BitPortabilityProblems="true"
|
|
||||||
DebugInformationFormat="4"
|
|
||||||
CompileAs="0"
|
|
||||||
DisableSpecificWarnings="4996"
|
|
||||||
ForcedIncludeFiles=""
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManagedResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCResourceCompilerTool"
|
|
||||||
PreprocessorDefinitions="_DEBUG"
|
|
||||||
Culture="1033"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreLinkEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCLinkerTool"
|
|
||||||
AdditionalOptions="/MACHINE:I386"
|
|
||||||
AdditionalDependencies="gdi32.lib user32.lib comctl32.lib shell32.lib advapi32.lib comdlg32.lib ole32.lib dxguid.lib dsound.lib dinput8.lib strmiids.lib wsock32.lib winmm.lib fmodex_vc.lib setupapi.lib ws2_32.lib"
|
|
||||||
OutputFile="../zdoomd.exe"
|
|
||||||
LinkIncremental="2"
|
|
||||||
SuppressStartupBanner="true"
|
|
||||||
AdditionalLibraryDirectories=""
|
|
||||||
IgnoreDefaultLibraryNames="libcmt;msvcrtd;msvcrt"
|
|
||||||
GenerateDebugInformation="true"
|
|
||||||
ProgramDatabaseFile=".\Debug/zdoomd.pdb"
|
|
||||||
SubSystem="2"
|
|
||||||
StackReserveSize="0"
|
|
||||||
TerminalServerAware="2"
|
|
||||||
SetChecksum="false"
|
|
||||||
TargetMachine="0"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCALinkTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManifestTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXDCMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCBscMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCFxCopTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCAppVerifierTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebDeploymentTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPostBuildEventTool"
|
|
||||||
/>
|
|
||||||
</Configuration>
|
|
||||||
<Configuration
|
<Configuration
|
||||||
Name="Release|x64"
|
Name="Release|x64"
|
||||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||||
|
@ -352,6 +246,112 @@
|
||||||
Name="VCPostBuildEventTool"
|
Name="VCPostBuildEventTool"
|
||||||
/>
|
/>
|
||||||
</Configuration>
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory=".\Debug"
|
||||||
|
IntermediateDirectory=".\Debug"
|
||||||
|
ConfigurationType="1"
|
||||||
|
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||||
|
UseOfMFC="0"
|
||||||
|
ATLMinimizesCRunTimeLibraryUsage="false"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
Description="Checking svnrevision.h..."
|
||||||
|
CommandLine="$(OutDir)\updaterevision.exe src src/svnrevision.h"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
PreprocessorDefinitions="_DEBUG"
|
||||||
|
MkTypLibCompatible="true"
|
||||||
|
SuppressStartupBanner="true"
|
||||||
|
TargetEnvironment="1"
|
||||||
|
TypeLibraryName=".\Debug/zdoom.tlb"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;jpeg-6b;snes_spc\snes_spc"
|
||||||
|
PreprocessorDefinitions="WIN32,_DEBUG,_WIN32,_WINDOWS,USEASM,_CRTDBG_MAP_ALLOC,HAVE_STRUPR,HAVE_FILELENGTH"
|
||||||
|
MinimalRebuild="true"
|
||||||
|
RuntimeLibrary="1"
|
||||||
|
EnableFunctionLevelLinking="true"
|
||||||
|
ForceConformanceInForLoopScope="true"
|
||||||
|
PrecompiledHeaderFile=""
|
||||||
|
AssemblerOutput="0"
|
||||||
|
AssemblerListingLocation=".\Debug/"
|
||||||
|
ObjectFile=".\Debug/"
|
||||||
|
ProgramDataBaseFileName=".\Debug/"
|
||||||
|
WarningLevel="3"
|
||||||
|
SuppressStartupBanner="true"
|
||||||
|
Detect64BitPortabilityProblems="true"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
CompileAs="0"
|
||||||
|
DisableSpecificWarnings="4996"
|
||||||
|
ForcedIncludeFiles=""
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
PreprocessorDefinitions="_DEBUG"
|
||||||
|
Culture="1033"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalOptions="/MACHINE:I386"
|
||||||
|
AdditionalDependencies="gdi32.lib user32.lib comctl32.lib shell32.lib advapi32.lib comdlg32.lib ole32.lib dxguid.lib dsound.lib dinput8.lib strmiids.lib wsock32.lib winmm.lib fmodex_vc.lib setupapi.lib ws2_32.lib"
|
||||||
|
OutputFile="../zdoomd.exe"
|
||||||
|
LinkIncremental="2"
|
||||||
|
SuppressStartupBanner="true"
|
||||||
|
AdditionalLibraryDirectories=""
|
||||||
|
IgnoreDefaultLibraryNames="libcmt;msvcrtd;msvcrt"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
ProgramDatabaseFile=".\Debug/zdoomd.pdb"
|
||||||
|
SubSystem="2"
|
||||||
|
StackReserveSize="0"
|
||||||
|
TerminalServerAware="2"
|
||||||
|
SetChecksum="false"
|
||||||
|
TargetMachine="0"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
<Configuration
|
<Configuration
|
||||||
Name="Debug|x64"
|
Name="Debug|x64"
|
||||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||||
|
@ -926,16 +926,6 @@
|
||||||
Outputs=""src/$(InputName).h""
|
Outputs=""src/$(InputName).h""
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
Description="Creating $(InputName).h from src/$(InputFileName)"
|
|
||||||
CommandLine="tools\re2c\re2c --no-generation-date -s -o "src/$(InputName).h" "src/$(InputFileName)"
"
|
|
||||||
Outputs=""src/$(InputName).h""
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Release|x64"
|
Name="Release|x64"
|
||||||
>
|
>
|
||||||
|
@ -946,6 +936,16 @@
|
||||||
Outputs=""src/$(InputName).h""
|
Outputs=""src/$(InputName).h""
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
Description="Creating $(InputName).h from src/$(InputFileName)"
|
||||||
|
CommandLine="tools\re2c\re2c --no-generation-date -s -o "src/$(InputName).h" "src/$(InputFileName)"
"
|
||||||
|
Outputs=""src/$(InputName).h""
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|x64"
|
Name="Debug|x64"
|
||||||
>
|
>
|
||||||
|
@ -1540,16 +1540,6 @@
|
||||||
Outputs="$(IntDir)\$(InputName).obj"
|
Outputs="$(IntDir)\$(InputName).obj"
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
Description="Assembling $(InputPath)..."
|
|
||||||
CommandLine="nasm -g -o "$(IntDir)\$(InputName).obj" -f win32 "$(InputPath)"
$(OutDir)\fixrtext "$(IntDir)\$(InputName).obj"
"
|
|
||||||
Outputs="$(IntDir)\$(InputName).obj"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Release|x64"
|
Name="Release|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
|
@ -1561,6 +1551,16 @@
|
||||||
Outputs="$(IntDir)/$(InputName).obj"
|
Outputs="$(IntDir)/$(InputName).obj"
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
Description="Assembling $(InputPath)..."
|
||||||
|
CommandLine="nasm -g -o "$(IntDir)\$(InputName).obj" -f win32 "$(InputPath)"
$(OutDir)\fixrtext "$(IntDir)\$(InputName).obj"
"
|
||||||
|
Outputs="$(IntDir)\$(InputName).obj"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|x64"
|
Name="Debug|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
|
@ -1586,16 +1586,6 @@
|
||||||
Outputs="$(IntDir)\$(InputName).obj"
|
Outputs="$(IntDir)\$(InputName).obj"
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
Description="Assembling $(InputPath)..."
|
|
||||||
CommandLine="nasm -g -o "$(IntDir)\$(InputName).obj" -f win32 "$(InputPath)"
$(OutDir)\fixrtext "$(IntDir)\$(InputName).obj"
"
|
|
||||||
Outputs="$(IntDir)\$(InputName).obj"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Release|x64"
|
Name="Release|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
|
@ -1607,6 +1597,16 @@
|
||||||
Outputs="$(IntDir)/$(InputName).obj"
|
Outputs="$(IntDir)/$(InputName).obj"
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
Description="Assembling $(InputPath)..."
|
||||||
|
CommandLine="nasm -g -o "$(IntDir)\$(InputName).obj" -f win32 "$(InputPath)"
$(OutDir)\fixrtext "$(IntDir)\$(InputName).obj"
"
|
||||||
|
Outputs="$(IntDir)\$(InputName).obj"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|x64"
|
Name="Debug|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
|
@ -1632,16 +1632,6 @@
|
||||||
Outputs="$(IntDir)\$(InputName).obj"
|
Outputs="$(IntDir)\$(InputName).obj"
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
Description="Assembling $(InputPath)..."
|
|
||||||
CommandLine="nasm -g -o "$(IntDir)\$(InputName).obj" -f win32 "$(InputPath)"
$(OutDir)\fixrtext "$(IntDir)\$(InputName).obj"
"
|
|
||||||
Outputs="$(IntDir)\$(InputName).obj"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Release|x64"
|
Name="Release|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
|
@ -1653,6 +1643,16 @@
|
||||||
Outputs="$(IntDir)\$(InputName).obj"
|
Outputs="$(IntDir)\$(InputName).obj"
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
Description="Assembling $(InputPath)..."
|
||||||
|
CommandLine="nasm -g -o "$(IntDir)\$(InputName).obj" -f win32 "$(InputPath)"
$(OutDir)\fixrtext "$(IntDir)\$(InputName).obj"
"
|
||||||
|
Outputs="$(IntDir)\$(InputName).obj"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|x64"
|
Name="Debug|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
|
@ -1678,16 +1678,6 @@
|
||||||
Outputs="$(IntDir)\$(InputName).obj"
|
Outputs="$(IntDir)\$(InputName).obj"
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
Description="Assembling $(InputPath)..."
|
|
||||||
CommandLine="nasm -g -o "$(IntDir)\$(InputName).obj" -f win32 "$(InputPath)"
$(OutDir)\fixrtext "$(IntDir)\$(InputName).obj"
"
|
|
||||||
Outputs="$(IntDir)\$(InputName).obj"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Release|x64"
|
Name="Release|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
|
@ -1699,6 +1689,16 @@
|
||||||
Outputs="$(IntDir)\$(InputName).obj"
|
Outputs="$(IntDir)\$(InputName).obj"
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
Description="Assembling $(InputPath)..."
|
||||||
|
CommandLine="nasm -g -o "$(IntDir)\$(InputName).obj" -f win32 "$(InputPath)"
$(OutDir)\fixrtext "$(IntDir)\$(InputName).obj"
"
|
||||||
|
Outputs="$(IntDir)\$(InputName).obj"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|x64"
|
Name="Debug|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
|
@ -1724,16 +1724,6 @@
|
||||||
Outputs="$(IntDir)\$(InputName).obj"
|
Outputs="$(IntDir)\$(InputName).obj"
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
Description="Assembling $(InputPath)..."
|
|
||||||
CommandLine="nasm -g -o "$(IntDir)\$(InputName).obj" -f win32 "$(InputPath)"
$(OutDir)\fixrtext "$(IntDir)\$(InputName).obj"
"
|
|
||||||
Outputs="$(IntDir)\$(InputName).obj"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Release|x64"
|
Name="Release|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
|
@ -1745,6 +1735,16 @@
|
||||||
Outputs="$(IntDir)\$(InputName).obj"
|
Outputs="$(IntDir)\$(InputName).obj"
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
Description="Assembling $(InputPath)..."
|
||||||
|
CommandLine="nasm -g -o "$(IntDir)\$(InputName).obj" -f win32 "$(InputPath)"
$(OutDir)\fixrtext "$(IntDir)\$(InputName).obj"
"
|
||||||
|
Outputs="$(IntDir)\$(InputName).obj"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|x64"
|
Name="Debug|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
|
@ -1910,6 +1910,14 @@
|
||||||
Outputs="$(IntDir)\$(InputName).obj"
|
Outputs="$(IntDir)\$(InputName).obj"
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release|x64"
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|Win32"
|
Name="Debug|Win32"
|
||||||
>
|
>
|
||||||
|
@ -1920,14 +1928,6 @@
|
||||||
Outputs="$(IntDir)\$(InputName).obj"
|
Outputs="$(IntDir)\$(InputName).obj"
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
|
||||||
Name="Release|x64"
|
|
||||||
ExcludedFromBuild="true"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|x64"
|
Name="Debug|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
|
@ -2785,6 +2785,14 @@
|
||||||
AdditionalIncludeDirectories="src\win32;$(NoInherit)"
|
AdditionalIncludeDirectories="src\win32;$(NoInherit)"
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release|x64"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
AdditionalIncludeDirectories="src\win32;$(NoInherit)"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|Win32"
|
Name="Debug|Win32"
|
||||||
>
|
>
|
||||||
|
@ -2794,14 +2802,6 @@
|
||||||
AdditionalIncludeDirectories="src\win32;$(NoInherit)"
|
AdditionalIncludeDirectories="src\win32;$(NoInherit)"
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
|
||||||
Name="Release|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCResourceCompilerTool"
|
|
||||||
AdditionalIncludeDirectories="src\win32;$(NoInherit)"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|x64"
|
Name="Debug|x64"
|
||||||
>
|
>
|
||||||
|
@ -2952,59 +2952,7 @@
|
||||||
Name="Timidity"
|
Name="Timidity"
|
||||||
>
|
>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\timidity\common.cpp"
|
RelativePath=".\src\timidity\instrum_font.cpp"
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\src\timidity\dls1.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\src\timidity\dls2.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\src\timidity\instrum.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\src\timidity\instrum_dls.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\src\timidity\mix.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\src\timidity\playmidi.cpp"
|
|
||||||
>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Release|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
EnableEnhancedInstructionSet="0"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\src\timidity\resample.cpp"
|
|
||||||
>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Release|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
EnableEnhancedInstructionSet="0"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\src\timidity\timidity.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\src\timidity\timidity.h"
|
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<Filter
|
<Filter
|
||||||
|
@ -3027,6 +2975,82 @@
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Headers"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\timidity\dls1.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\timidity\dls2.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\timidity\gf1patch.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\timidity\sf2.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\timidity\timidity.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Source"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\timidity\common.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\timidity\instrum.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\timidity\instrum_dls.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\timidity\instrum_sf2.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\timidity\mix.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\timidity\playmidi.cpp"
|
||||||
|
>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
EnableEnhancedInstructionSet="0"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\timidity\resample.cpp"
|
||||||
|
>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
EnableEnhancedInstructionSet="0"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\timidity\timidity.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
</Filter>
|
</Filter>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
|
@ -3044,7 +3068,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|Win32"
|
Name="Release|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3052,7 +3076,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Release|x64"
|
Name="Debug|Win32"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3084,7 +3108,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|Win32"
|
Name="Release|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3092,7 +3116,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Release|x64"
|
Name="Debug|Win32"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3121,7 +3145,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|Win32"
|
Name="Release|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3130,7 +3154,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Release|x64"
|
Name="Debug|Win32"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3160,7 +3184,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|Win32"
|
Name="Release|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3168,7 +3192,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Release|x64"
|
Name="Debug|Win32"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3197,7 +3221,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|Win32"
|
Name="Release|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3206,7 +3230,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Release|x64"
|
Name="Debug|Win32"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3237,7 +3261,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|Win32"
|
Name="Release|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3246,7 +3270,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Release|x64"
|
Name="Debug|Win32"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3276,7 +3300,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|Win32"
|
Name="Release|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3284,7 +3308,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Release|x64"
|
Name="Debug|Win32"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3313,7 +3337,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|Win32"
|
Name="Release|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3322,7 +3346,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Release|x64"
|
Name="Debug|Win32"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3353,7 +3377,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|Win32"
|
Name="Release|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3362,7 +3386,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Release|x64"
|
Name="Debug|Win32"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3393,7 +3417,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|Win32"
|
Name="Release|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3402,7 +3426,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Release|x64"
|
Name="Debug|Win32"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3432,7 +3456,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|Win32"
|
Name="Release|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3440,7 +3464,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Release|x64"
|
Name="Debug|Win32"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3468,7 +3492,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|Win32"
|
Name="Release|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3476,7 +3500,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Release|x64"
|
Name="Debug|Win32"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3504,7 +3528,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|Win32"
|
Name="Release|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3512,7 +3536,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Release|x64"
|
Name="Debug|Win32"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3540,7 +3564,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|Win32"
|
Name="Release|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3548,7 +3572,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Release|x64"
|
Name="Debug|Win32"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3578,7 +3602,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|Win32"
|
Name="Release|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3588,7 +3612,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Release|x64"
|
Name="Debug|Win32"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3632,7 +3656,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|Win32"
|
Name="Release|x64"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -3640,7 +3664,7 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Release|x64"
|
Name="Debug|Win32"
|
||||||
ExcludedFromBuild="true"
|
ExcludedFromBuild="true"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
|
|
Loading…
Reference in a new issue