mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-02-22 11:52:10 +00:00
- Fixed: Timidity::Channel::mono, rpn, and nrpn were not initialized. In
particular, this meant that every channel was almost certainly in mono mode, which can sound pretty bad if the song isn't meant to be played that way. - Added bank numbers to the MIDI precaching for Timidity, since I guess I do need to care about banks, if even the Duke MIDIs use various banks. - Fixed: snd_midiprecache only exists in Win32 builds, so gameconfigfile.cpp shouldn't unconditionally link against it. - Fixed: pre_resample() was still disabled, and it left two samples at the end of the new wave data uninitialized. SVN r903 (trunk)
This commit is contained in:
parent
1809870824
commit
0d18580ff0
14 changed files with 181 additions and 102 deletions
|
@ -1,4 +1,13 @@
|
||||||
April 11, 2008
|
April 11, 2008
|
||||||
|
- Fixed: Timidity::Channel::mono, rpn, and nrpn were not initialized. In
|
||||||
|
particular, this meant that every channel was almost certainly in mono mode,
|
||||||
|
which can sound pretty bad if the song isn't meant to be played that way.
|
||||||
|
- Added bank numbers to the MIDI precaching for Timidity, since I guess I do
|
||||||
|
need to care about banks, if even the Duke MIDIs use various banks.
|
||||||
|
- Fixed: snd_midiprecache only exists in Win32 builds, so gameconfigfile.cpp
|
||||||
|
shouldn't unconditionally link against it.
|
||||||
|
- Fixed: pre_resample() was still disabled, and it left two samples at the end
|
||||||
|
of the new wave data uninitialized.
|
||||||
- Moved the xmap table from timidity/tables.cpp to playmidi.cpp. Now I can get
|
- Moved the xmap table from timidity/tables.cpp to playmidi.cpp. Now I can get
|
||||||
rid of timidity/tables.cpp, which conflicts in name with the main Doom
|
rid of timidity/tables.cpp, which conflicts in name with the main Doom
|
||||||
tables.cpp. (And interestingly, VC++ automatically renamed the object file,
|
tables.cpp. (And interestingly, VC++ automatically renamed the object file,
|
||||||
|
|
|
@ -71,7 +71,6 @@ EXTERN_CVAR (Color, am_wallcolor)
|
||||||
EXTERN_CVAR (Color, am_fdwallcolor)
|
EXTERN_CVAR (Color, am_fdwallcolor)
|
||||||
EXTERN_CVAR (Color, am_cdwallcolor)
|
EXTERN_CVAR (Color, am_cdwallcolor)
|
||||||
EXTERN_CVAR (Float, spc_amp)
|
EXTERN_CVAR (Float, spc_amp)
|
||||||
EXTERN_CVAR (Bool, snd_midiprecache)
|
|
||||||
|
|
||||||
FString WeaponSection;
|
FString WeaponSection;
|
||||||
|
|
||||||
|
@ -306,7 +305,11 @@ void FGameConfigFile::DoGlobalSetup ()
|
||||||
}
|
}
|
||||||
if (last < 207)
|
if (last < 207)
|
||||||
{ // Now that snd_midiprecache works again, you probably don't want it on.
|
{ // Now that snd_midiprecache works again, you probably don't want it on.
|
||||||
snd_midiprecache = false;
|
FBaseCVar *precache = FindCVar ("snd_midiprecache", NULL);
|
||||||
|
if (precache != NULL)
|
||||||
|
{
|
||||||
|
precache->ResetToDefault();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,7 +112,7 @@ public:
|
||||||
virtual bool FakeVolume() = 0;
|
virtual bool FakeVolume() = 0;
|
||||||
virtual bool Pause(bool paused) = 0;
|
virtual bool Pause(bool paused) = 0;
|
||||||
virtual bool NeedThreadedCallback() = 0;
|
virtual bool NeedThreadedCallback() = 0;
|
||||||
virtual void PrecacheInstruments(const BYTE *instruments, int count);
|
virtual void PrecacheInstruments(const WORD *instruments, int count);
|
||||||
};
|
};
|
||||||
|
|
||||||
// WinMM implementation of a MIDI output device -----------------------------
|
// WinMM implementation of a MIDI output device -----------------------------
|
||||||
|
@ -138,7 +138,7 @@ public:
|
||||||
bool FakeVolume();
|
bool FakeVolume();
|
||||||
bool NeedThreadedCallback();
|
bool NeedThreadedCallback();
|
||||||
bool Pause(bool paused);
|
bool Pause(bool paused);
|
||||||
void PrecacheInstruments(const BYTE *instruments, int count);
|
void PrecacheInstruments(const WORD *instruments, int count);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void CALLBACK CallbackFunc(HMIDIOUT, UINT, DWORD_PTR, DWORD, DWORD);
|
static void CALLBACK CallbackFunc(HMIDIOUT, UINT, DWORD_PTR, DWORD, DWORD);
|
||||||
|
@ -230,7 +230,7 @@ public:
|
||||||
bool FakeVolume();
|
bool FakeVolume();
|
||||||
bool Pause(bool paused);
|
bool Pause(bool paused);
|
||||||
bool NeedThreadedCallback();
|
bool NeedThreadedCallback();
|
||||||
void PrecacheInstruments(const BYTE *instruments, int count);
|
void PrecacheInstruments(const WORD *instruments, int count);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static bool FillStream(SoundStream *stream, void *buff, int len, void *userdata);
|
static bool FillStream(SoundStream *stream, void *buff, int len, void *userdata);
|
||||||
|
|
|
@ -766,14 +766,17 @@ void MIDISong2::SetTempo(int new_tempo)
|
||||||
|
|
||||||
void MIDISong2::Precache()
|
void MIDISong2::Precache()
|
||||||
{
|
{
|
||||||
int i, j;
|
|
||||||
|
|
||||||
// This array keeps track of instruments that are used. The first 128
|
// This array keeps track of instruments that are used. The first 128
|
||||||
// entries are for melodic instruments. The second 128 are for
|
// entries are for melodic instruments. The second 128 are for
|
||||||
// percussion.
|
// percussion.
|
||||||
BYTE found_instruments[256] = { 0, };
|
BYTE found_instruments[256] = { 0, };
|
||||||
|
BYTE found_banks[256] = { 0, };
|
||||||
|
bool multiple_banks = false;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
DoRestart();
|
DoRestart();
|
||||||
|
found_banks[0] = true; // Bank 0 is always used.
|
||||||
|
found_banks[128] = true;
|
||||||
for (i = 0; i < NumTracks; ++i)
|
for (i = 0; i < NumTracks; ++i)
|
||||||
{
|
{
|
||||||
TrackInfo *track = &Tracks[i];
|
TrackInfo *track = &Tracks[i];
|
||||||
|
@ -786,20 +789,20 @@ void MIDISong2::Precache()
|
||||||
ev = track->TrackBegin[track->TrackP++];
|
ev = track->TrackBegin[track->TrackP++];
|
||||||
command = ev & 0xF0;
|
command = ev & 0xF0;
|
||||||
|
|
||||||
if (command == MIDI_SYSEX || command == MIDI_SYSEXEND)
|
if (ev == MIDI_META)
|
||||||
{
|
|
||||||
len = track->ReadVarLen();
|
|
||||||
track->TrackP += len;
|
|
||||||
}
|
|
||||||
else if (command == MIDI_META)
|
|
||||||
{
|
{
|
||||||
track->TrackP++;
|
track->TrackP++;
|
||||||
len = track->ReadVarLen();
|
len = track->ReadVarLen();
|
||||||
track->TrackP += len;
|
track->TrackP += len;
|
||||||
}
|
}
|
||||||
else if ((command & 0xF0) == 0xF0)
|
else if (ev == MIDI_SYSEX || ev == MIDI_SYSEXEND)
|
||||||
{
|
{
|
||||||
track->TrackP += CommonLengths[ev & 0xF];
|
len = track->ReadVarLen();
|
||||||
|
track->TrackP += len;
|
||||||
|
}
|
||||||
|
else if (command == 0xF0)
|
||||||
|
{
|
||||||
|
track->TrackP += CommonLengths[ev & 0x0F];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -821,27 +824,62 @@ void MIDISong2::Precache()
|
||||||
}
|
}
|
||||||
if (channel != 9 && command == (MIDI_PRGMCHANGE & 0x70))
|
if (channel != 9 && command == (MIDI_PRGMCHANGE & 0x70))
|
||||||
{
|
{
|
||||||
found_instruments[data1 & 127] = 1;
|
found_instruments[data1 & 127] = true;
|
||||||
|
}
|
||||||
|
else if (channel == 9 && command == (MIDI_PRGMCHANGE & 0x70) && data1 != 0)
|
||||||
|
{ // On a percussion channel, program change also serves as bank select.
|
||||||
|
multiple_banks = true;
|
||||||
|
found_banks[data1 | 128] = true;
|
||||||
}
|
}
|
||||||
else if (channel == 9 && command == (MIDI_NOTEON & 0x70) && data2 != 0)
|
else if (channel == 9 && command == (MIDI_NOTEON & 0x70) && data2 != 0)
|
||||||
{
|
{
|
||||||
found_instruments[data1 | 128] = 1;
|
found_instruments[data1 | 128] = true;
|
||||||
|
}
|
||||||
|
else if (command == (MIDI_CTRLCHANGE & 0x70) && data1 == 0 && data2 != 0)
|
||||||
|
{
|
||||||
|
multiple_banks = true;
|
||||||
|
if (channel == 9)
|
||||||
|
{
|
||||||
|
found_banks[data2 | 128] = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
found_banks[data2 & 127] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
track->ReadVarLen(); // Skip delay.
|
track->ReadVarLen(); // Skip delay.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
DoRestart();
|
DoRestart();
|
||||||
|
|
||||||
// Now pack everything into a contiguous region for the PrecacheInstruments call().
|
// Now pack everything into a contiguous region for the PrecacheInstruments call().
|
||||||
for (i = j = 0; i < 256; ++i)
|
TArray<WORD> packed;
|
||||||
|
|
||||||
|
for (i = 0; i < 256; ++i)
|
||||||
{
|
{
|
||||||
if (found_instruments[i])
|
if (found_instruments[i])
|
||||||
{
|
{
|
||||||
found_instruments[j++] = i;
|
WORD packnum = (i & 127) | ((i & 128) << 7);
|
||||||
|
if (!multiple_banks)
|
||||||
|
{
|
||||||
|
packed.Push(packnum);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // In order to avoid having to multiplex tracks in a type 1 file,
|
||||||
|
// precache every used instrument in every used bank, even if not
|
||||||
|
// all combinations are actually used.
|
||||||
|
for (j = 0; j < 128; ++j)
|
||||||
|
{
|
||||||
|
if (found_banks[j + (i & 128)])
|
||||||
|
{
|
||||||
|
packed.Push(packnum | (j << 7));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MIDI->PrecacheInstruments(found_instruments, j);
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MIDI->PrecacheInstruments(&packed[0], packed.Size());
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -733,12 +733,13 @@ MIDIDevice::~MIDIDevice()
|
||||||
// If the device can benefit from preloading the instruments, it can do so
|
// If the device can benefit from preloading the instruments, it can do so
|
||||||
// now.
|
// now.
|
||||||
//
|
//
|
||||||
// For each entry, bit 7 set indicates that the instrument is percussion and
|
// Each entry is packed as follows:
|
||||||
// the lower 7 bits contain the note number to use on MIDI channel 10,
|
// Bits 0- 6: Instrument number
|
||||||
// otherwise it is melodic and the lower 7 bits are the program number.
|
// Bits 7-13: Bank number
|
||||||
|
// Bit 14: Select drum set if 1, tone bank if 0
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void MIDIDevice::PrecacheInstruments(const BYTE *instruments, int count)
|
void MIDIDevice::PrecacheInstruments(const WORD *instruments, int count)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,19 +189,20 @@ bool MUSSong2::CheckDone()
|
||||||
|
|
||||||
void MUSSong2::Precache()
|
void MUSSong2::Precache()
|
||||||
{
|
{
|
||||||
BYTE *work = (BYTE *)alloca(MusHeader->NumInstruments);
|
WORD *work = (WORD *)alloca(MusHeader->NumInstruments * sizeof(WORD));
|
||||||
const WORD *used = (WORD *)MusHeader + sizeof(MUSHeader) / 2;
|
const WORD *used = (WORD *)MusHeader + sizeof(MUSHeader) / sizeof(WORD);
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
for (i = j = 0; i < MusHeader->NumInstruments; ++i)
|
for (i = j = 0; i < MusHeader->NumInstruments; ++i)
|
||||||
{
|
{
|
||||||
if (used[i] < 128)
|
WORD instr = LittleShort(used[i]);
|
||||||
|
if (instr < 128)
|
||||||
{
|
{
|
||||||
work[j++] = (BYTE)used[i];
|
work[j++] = instr;
|
||||||
}
|
}
|
||||||
else if (used[i] >= 135 && used[i] <= 181)
|
else if (used[i] >= 135 && used[i] <= 181)
|
||||||
{ // Percussions are 100-based, not 128-based, eh?
|
{ // Percussions are 100-based, not 128-based, eh?
|
||||||
work[j++] = used[i] - 100 + 128;
|
work[j++] = instr - 100 + (1 << 14);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MIDI->PrecacheInstruments(&work[0], j);
|
MIDI->PrecacheInstruments(&work[0], j);
|
||||||
|
|
|
@ -345,17 +345,18 @@ bool TimidityMIDIDevice::Pause(bool paused)
|
||||||
//
|
//
|
||||||
// TimidityMIDIDevice :: PrecacheInstruments
|
// TimidityMIDIDevice :: PrecacheInstruments
|
||||||
//
|
//
|
||||||
// For each entry, bit 7 set indicates that the instrument is percussion and
|
// Each entry is packed as follows:
|
||||||
// the lower 7 bits contain the note number to use on MIDI channel 10,
|
// Bits 0- 6: Instrument number
|
||||||
// otherwise it is melodic and the lower 7 bits are the program number.
|
// Bits 7-13: Bank number
|
||||||
|
// Bit 14: Select drum set if 1, tone bank if 0
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void TimidityMIDIDevice::PrecacheInstruments(const BYTE *instruments, int count)
|
void TimidityMIDIDevice::PrecacheInstruments(const WORD *instruments, int count)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < count; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
Renderer->MarkInstrument(0, instruments[i] >> 7, instruments[i] & 127);
|
Renderer->MarkInstrument((instruments[i] >> 7) & 127, instruments[i] >> 14, instruments[i] & 127);
|
||||||
}
|
}
|
||||||
Renderer->load_missing_instruments();
|
Renderer->load_missing_instruments();
|
||||||
}
|
}
|
||||||
|
|
|
@ -209,9 +209,10 @@ void WinMIDIDevice::Stop()
|
||||||
//
|
//
|
||||||
// WinMIDIDevice :: PrecacheInstruments
|
// WinMIDIDevice :: PrecacheInstruments
|
||||||
//
|
//
|
||||||
// For each entry, bit 7 set indicates that the instrument is percussion and
|
// Each entry is packed as follows:
|
||||||
// the lower 7 bits contain the note number to use on MIDI channel 10,
|
// Bits 0- 6: Instrument number
|
||||||
// otherwise it is melodic and the lower 7 bits are the program number.
|
// Bits 7-13: Bank number
|
||||||
|
// Bit 14: Select drum set if 1, tone bank if 0
|
||||||
//
|
//
|
||||||
// My old GUS PnP needed the instruments to be preloaded, or it would miss
|
// My old GUS PnP needed the instruments to be preloaded, or it would miss
|
||||||
// some notes the first time through the song. I doubt any modern
|
// some notes the first time through the song. I doubt any modern
|
||||||
|
@ -221,7 +222,7 @@ void WinMIDIDevice::Stop()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void WinMIDIDevice::PrecacheInstruments(const BYTE *instruments, int count)
|
void WinMIDIDevice::PrecacheInstruments(const WORD *instruments, int count)
|
||||||
{
|
{
|
||||||
// Setting snd_midiprecache to false disables this precaching, since it
|
// Setting snd_midiprecache to false disables this precaching, since it
|
||||||
// does involve sleeping for more than a miniscule amount of time.
|
// does involve sleeping for more than a miniscule amount of time.
|
||||||
|
@ -229,14 +230,31 @@ void WinMIDIDevice::PrecacheInstruments(const BYTE *instruments, int count)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int i = 0, chan = 0; i < count; ++i)
|
BYTE bank[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
|
int i, chan;
|
||||||
|
|
||||||
|
for (i = 0, chan = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
if (instruments[i] & 0x80)
|
int instr = instruments[i] & 127;
|
||||||
{ // Percussion
|
int banknum = (instruments[i] >> 7) & 127;
|
||||||
|
int percussion = instruments[i] >> 14;
|
||||||
|
|
||||||
|
if (percussion)
|
||||||
|
{
|
||||||
|
if (bank[9] != banknum)
|
||||||
|
{
|
||||||
|
midiOutShortMsg((HMIDIOUT)MidiOut, MIDI_CTRLCHANGE | 9 | (0 << 8) | (banknum << 16));
|
||||||
|
bank[9] = banknum;
|
||||||
|
}
|
||||||
midiOutShortMsg((HMIDIOUT)MidiOut, MIDI_NOTEON | 9 | ((instruments[i] & 0x7f) << 8) | (1 << 16));
|
midiOutShortMsg((HMIDIOUT)MidiOut, MIDI_NOTEON | 9 | ((instruments[i] & 0x7f) << 8) | (1 << 16));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // Melodic
|
{ // Melodic
|
||||||
|
if (bank[chan] != banknum)
|
||||||
|
{
|
||||||
|
midiOutShortMsg((HMIDIOUT)MidiOut, MIDI_CTRLCHANGE | 9 | (0 << 8) | (banknum << 16));
|
||||||
|
bank[chan] = banknum;
|
||||||
|
}
|
||||||
midiOutShortMsg((HMIDIOUT)MidiOut, MIDI_PRGMCHANGE | chan | (instruments[i] << 8));
|
midiOutShortMsg((HMIDIOUT)MidiOut, MIDI_PRGMCHANGE | chan | (instruments[i] << 8));
|
||||||
midiOutShortMsg((HMIDIOUT)MidiOut, MIDI_NOTEON | chan | (60 << 8) | (1 << 16));
|
midiOutShortMsg((HMIDIOUT)MidiOut, MIDI_NOTEON | chan | (60 << 8) | (1 << 16));
|
||||||
if (++chan == 9)
|
if (++chan == 9)
|
||||||
|
@ -258,6 +276,14 @@ void WinMIDIDevice::PrecacheInstruments(const BYTE *instruments, int count)
|
||||||
// And now chan is back at 0, ready to start the cycle over.
|
// And now chan is back at 0, ready to start the cycle over.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Make sure all channels are set back to bank 0.
|
||||||
|
for (i = 0; i < 16; ++i)
|
||||||
|
{
|
||||||
|
if (bank[i] != 0)
|
||||||
|
{
|
||||||
|
midiOutShortMsg((HMIDIOUT)MidiOut, MIDI_CTRLCHANGE | 9 | (0 << 8) | (0 << 16));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -106,20 +106,9 @@ static void free_bank(int dr, int b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int convert_envelope_rate_attack(Renderer *song, BYTE rate, BYTE fastness)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
|
|
||||||
r = 3 - ((rate>>6) & 0x3);
|
|
||||||
r *= 3;
|
|
||||||
r = (int)(rate & 0x3f) << r; /* 6.9 fixed point */
|
|
||||||
|
|
||||||
/* 15.15 fixed point. */
|
|
||||||
return int(((r * 44100) / song->rate) * song->control_ratio) << 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
int convert_envelope_rate(Renderer *song, BYTE rate)
|
int convert_envelope_rate(Renderer *song, BYTE rate)
|
||||||
{
|
{
|
||||||
|
#if 1
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = 3 - ((rate>>6) & 0x3);
|
r = 3 - ((rate>>6) & 0x3);
|
||||||
|
@ -127,8 +116,12 @@ int convert_envelope_rate(Renderer *song, BYTE rate)
|
||||||
r = (int)(rate & 0x3f) << r; /* 6.9 fixed point */
|
r = (int)(rate & 0x3f) << r; /* 6.9 fixed point */
|
||||||
|
|
||||||
/* 15.15 fixed point. */
|
/* 15.15 fixed point. */
|
||||||
return int(((r * 44100) / song->rate) * song->control_ratio)
|
return int(((r * 44100) / song->rate) * song->control_ratio) << ((song->fast_decay) ? 10 : 9);
|
||||||
<< ((song->fast_decay) ? 10 : 9);
|
#else
|
||||||
|
double frameadd = (double)(rate & 63) / (double)(1 << (3 * (rate >> 6)));
|
||||||
|
double realadd = (frameadd * 19293 / song->rate) * (1 << 15) * song->control_ratio;
|
||||||
|
return (int)realadd;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int convert_envelope_offset(BYTE offset)
|
int convert_envelope_offset(BYTE offset)
|
||||||
|
@ -238,11 +231,11 @@ static InstrumentLayer *load_instrument(Renderer *song, const char *name, int fo
|
||||||
|
|
||||||
if (noluck)
|
if (noluck)
|
||||||
{
|
{
|
||||||
song->ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Instrument `%s' can't be found.", name);
|
cmsg(CMSG_ERROR, VERB_NORMAL, "Instrument `%s' can't be found.", name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*song->ctl->cmsg(CMSG_INFO, VERB_NOISY, "Loading instrument %s", current_filename);*/
|
/*cmsg(CMSG_INFO, VERB_NOISY, "Loading instrument %s", current_filename);*/
|
||||||
|
|
||||||
/* Read some headers and do cursory sanity checks. There are loads
|
/* Read some headers and do cursory sanity checks. There are loads
|
||||||
of magic offsets. This could be rewritten... */
|
of magic offsets. This could be rewritten... */
|
||||||
|
@ -252,7 +245,7 @@ static InstrumentLayer *load_instrument(Renderer *song, const char *name, int fo
|
||||||
memcmp(tmp, "GF1PATCH100\0ID#000002", 22))) /* don't know what the
|
memcmp(tmp, "GF1PATCH100\0ID#000002", 22))) /* don't know what the
|
||||||
differences are */
|
differences are */
|
||||||
{
|
{
|
||||||
song->ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: not an instrument", name);
|
cmsg(CMSG_ERROR, VERB_NORMAL, "%s: not an instrument", name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,13 +286,13 @@ static InstrumentLayer *load_instrument(Renderer *song, const char *name, int fo
|
||||||
|
|
||||||
if (tmp[82] != 1 && tmp[82] != 0) /* instruments. To some patch makers, 0 means 1 */
|
if (tmp[82] != 1 && tmp[82] != 0) /* instruments. To some patch makers, 0 means 1 */
|
||||||
{
|
{
|
||||||
song->ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle patches with %d instruments", tmp[82]);
|
cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle patches with %d instruments", tmp[82]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmp[151] != 1 && tmp[151] != 0) /* layers. What's a layer? */
|
if (tmp[151] != 1 && tmp[151] != 0) /* layers. What's a layer? */
|
||||||
{
|
{
|
||||||
song->ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle instruments with %d layers", tmp[151]);
|
cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle instruments with %d layers", tmp[151]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,7 +357,7 @@ static InstrumentLayer *load_instrument(Renderer *song, const char *name, int fo
|
||||||
ip->right_sample = NULL;
|
ip->right_sample = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
song->ctl->cmsg(CMSG_INFO, VERB_NOISY, "%s%s[%d,%d] %s(%d-%d layer %d of %d)",
|
cmsg(CMSG_INFO, VERB_NOISY, "%s%s[%d,%d] %s(%d-%d layer %d of %d)",
|
||||||
(percussion)? " ":"", name,
|
(percussion)? " ":"", name,
|
||||||
(percussion)? note_to_use : gm_num, bank,
|
(percussion)? note_to_use : gm_num, bank,
|
||||||
(right_samples)? "(2) " : "",
|
(right_samples)? "(2) " : "",
|
||||||
|
@ -432,7 +425,7 @@ static InstrumentLayer *load_instrument(Renderer *song, const char *name, int fo
|
||||||
if (1 != fread(&fractions, 1, 1, fp))
|
if (1 != fread(&fractions, 1, 1, fp))
|
||||||
{
|
{
|
||||||
fail:
|
fail:
|
||||||
song->ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Error reading sample %d", i);
|
cmsg(CMSG_ERROR, VERB_NORMAL, "Error reading sample %d", i);
|
||||||
if (stereo_layer == 1)
|
if (stereo_layer == 1)
|
||||||
{
|
{
|
||||||
for (j = 0; j < i; j++)
|
for (j = 0; j < i; j++)
|
||||||
|
@ -505,14 +498,14 @@ fail:
|
||||||
sp->tremolo_sweep_increment = 0;
|
sp->tremolo_sweep_increment = 0;
|
||||||
sp->tremolo_phase_increment = 0;
|
sp->tremolo_phase_increment = 0;
|
||||||
sp->tremolo_depth = 0;
|
sp->tremolo_depth = 0;
|
||||||
song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " * no tremolo");
|
cmsg(CMSG_INFO, VERB_DEBUG, " * no tremolo");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sp->tremolo_sweep_increment = convert_tremolo_sweep(song, tmp[12]);
|
sp->tremolo_sweep_increment = convert_tremolo_sweep(song, tmp[12]);
|
||||||
sp->tremolo_phase_increment = convert_tremolo_rate(song, tmp[13]);
|
sp->tremolo_phase_increment = convert_tremolo_rate(song, tmp[13]);
|
||||||
sp->tremolo_depth = tmp[14];
|
sp->tremolo_depth = tmp[14];
|
||||||
song->ctl->cmsg(CMSG_INFO, VERB_DEBUG,
|
cmsg(CMSG_INFO, VERB_DEBUG,
|
||||||
" * tremolo: sweep %d, phase %d, depth %d",
|
" * tremolo: sweep %d, phase %d, depth %d",
|
||||||
sp->tremolo_sweep_increment, sp->tremolo_phase_increment,
|
sp->tremolo_sweep_increment, sp->tremolo_phase_increment,
|
||||||
sp->tremolo_depth);
|
sp->tremolo_depth);
|
||||||
|
@ -523,14 +516,14 @@ fail:
|
||||||
sp->vibrato_sweep_increment = 0;
|
sp->vibrato_sweep_increment = 0;
|
||||||
sp->vibrato_control_ratio = 0;
|
sp->vibrato_control_ratio = 0;
|
||||||
sp->vibrato_depth = 0;
|
sp->vibrato_depth = 0;
|
||||||
song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " * no vibrato");
|
cmsg(CMSG_INFO, VERB_DEBUG, " * no vibrato");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sp->vibrato_control_ratio = convert_vibrato_rate(song, tmp[16]);
|
sp->vibrato_control_ratio = convert_vibrato_rate(song, tmp[16]);
|
||||||
sp->vibrato_sweep_increment= convert_vibrato_sweep(song, tmp[15], sp->vibrato_control_ratio);
|
sp->vibrato_sweep_increment= convert_vibrato_sweep(song, tmp[15], sp->vibrato_control_ratio);
|
||||||
sp->vibrato_depth = tmp[17];
|
sp->vibrato_depth = tmp[17];
|
||||||
song->ctl->cmsg(CMSG_INFO, VERB_DEBUG,
|
cmsg(CMSG_INFO, VERB_DEBUG,
|
||||||
" * vibrato: sweep %d, ctl %d, depth %d",
|
" * vibrato: sweep %d, ctl %d, depth %d",
|
||||||
sp->vibrato_sweep_increment, sp->vibrato_control_ratio,
|
sp->vibrato_sweep_increment, sp->vibrato_control_ratio,
|
||||||
sp->vibrato_depth);
|
sp->vibrato_depth);
|
||||||
|
@ -571,14 +564,14 @@ fail:
|
||||||
if ((strip_loop == 1) &&
|
if ((strip_loop == 1) &&
|
||||||
(sp->modes & (MODES_SUSTAIN | MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE)))
|
(sp->modes & (MODES_SUSTAIN | MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE)))
|
||||||
{
|
{
|
||||||
song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - Removing loop and/or sustain");
|
cmsg(CMSG_INFO, VERB_DEBUG, " - Removing loop and/or sustain");
|
||||||
sp->modes &=~(MODES_SUSTAIN | MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE);
|
sp->modes &=~(MODES_SUSTAIN | MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strip_envelope == 1)
|
if (strip_envelope == 1)
|
||||||
{
|
{
|
||||||
if (sp->modes & MODES_ENVELOPE)
|
if (sp->modes & MODES_ENVELOPE)
|
||||||
song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - Removing envelope");
|
cmsg(CMSG_INFO, VERB_DEBUG, " - Removing envelope");
|
||||||
sp->modes &= ~MODES_ENVELOPE;
|
sp->modes &= ~MODES_ENVELOPE;
|
||||||
}
|
}
|
||||||
else if (strip_envelope != 0)
|
else if (strip_envelope != 0)
|
||||||
|
@ -588,7 +581,7 @@ fail:
|
||||||
{
|
{
|
||||||
/* No loop? Then what's there to sustain? No envelope needed either... */
|
/* No loop? Then what's there to sustain? No envelope needed either... */
|
||||||
sp->modes &= ~(MODES_SUSTAIN|MODES_ENVELOPE);
|
sp->modes &= ~(MODES_SUSTAIN|MODES_ENVELOPE);
|
||||||
song->ctl->cmsg(CMSG_INFO, VERB_DEBUG,
|
cmsg(CMSG_INFO, VERB_DEBUG,
|
||||||
" - No loop, removing sustain and envelope");
|
" - No loop, removing sustain and envelope");
|
||||||
}
|
}
|
||||||
else if (!memcmp(tmp, "??????", 6) || tmp[11] >= 100)
|
else if (!memcmp(tmp, "??????", 6) || tmp[11] >= 100)
|
||||||
|
@ -596,7 +589,7 @@ fail:
|
||||||
/* Envelope rates all maxed out? Envelope end at a high "offset"?
|
/* Envelope rates all maxed out? Envelope end at a high "offset"?
|
||||||
That's a weird envelope. Take it out. */
|
That's a weird envelope. Take it out. */
|
||||||
sp->modes &= ~MODES_ENVELOPE;
|
sp->modes &= ~MODES_ENVELOPE;
|
||||||
song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - Weirdness, removing envelope");
|
cmsg(CMSG_INFO, VERB_DEBUG, " - Weirdness, removing envelope");
|
||||||
}
|
}
|
||||||
else if (!(sp->modes & MODES_SUSTAIN))
|
else if (!(sp->modes & MODES_SUSTAIN))
|
||||||
{
|
{
|
||||||
|
@ -605,7 +598,7 @@ fail:
|
||||||
envelope either... at least the Gravis ones. They're mostly
|
envelope either... at least the Gravis ones. They're mostly
|
||||||
drums. I think. */
|
drums. I think. */
|
||||||
sp->modes &= ~MODES_ENVELOPE;
|
sp->modes &= ~MODES_ENVELOPE;
|
||||||
song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - No sustain, removing envelope");
|
cmsg(CMSG_INFO, VERB_DEBUG, " - No sustain, removing envelope");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,8 +606,7 @@ fail:
|
||||||
|
|
||||||
for (j = ATTACK; j < DELAY; j++)
|
for (j = ATTACK; j < DELAY; j++)
|
||||||
{
|
{
|
||||||
sp->envelope_rate[j] =
|
sp->envelope_rate[j] = convert_envelope_rate(song, tmp[j]);
|
||||||
(j < 3) ? convert_envelope_rate_attack(song, tmp[j], 11) : convert_envelope_rate(song, tmp[j]);
|
|
||||||
sp->envelope_offset[j] = convert_envelope_offset(tmp[6+j]);
|
sp->envelope_offset[j] = convert_envelope_offset(tmp[6+j]);
|
||||||
}
|
}
|
||||||
if (sf2flag)
|
if (sf2flag)
|
||||||
|
@ -663,7 +655,7 @@ fail:
|
||||||
/* The GUS apparently plays reverse loops by reversing the
|
/* The GUS apparently plays reverse loops by reversing the
|
||||||
whole sample. We do the same because the GUS does not SUCK. */
|
whole sample. We do the same because the GUS does not SUCK. */
|
||||||
|
|
||||||
song->ctl->cmsg(CMSG_WARNING, VERB_NORMAL, "Reverse loop in %s", name);
|
cmsg(CMSG_WARNING, VERB_NORMAL, "Reverse loop in %s", name);
|
||||||
reverse_data((sample_t *)sp->data, 0, sp->data_length);
|
reverse_data((sample_t *)sp->data, 0, sp->data_length);
|
||||||
sp->data[sp->data_length] = sp->data[sp->data_length - 1];
|
sp->data[sp->data_length] = sp->data[sp->data_length - 1];
|
||||||
|
|
||||||
|
@ -699,7 +691,7 @@ fail:
|
||||||
maxamp = a;
|
maxamp = a;
|
||||||
}
|
}
|
||||||
sp->volume = 1 / maxamp;
|
sp->volume = 1 / maxamp;
|
||||||
song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " * volume comp: %f", sp->volume);
|
cmsg(CMSG_INFO, VERB_DEBUG, " * volume comp: %f", sp->volume);
|
||||||
#else
|
#else
|
||||||
sp->volume = 1;
|
sp->volume = 1;
|
||||||
#endif
|
#endif
|
||||||
|
@ -722,7 +714,7 @@ fail:
|
||||||
if (strip_tail == 1)
|
if (strip_tail == 1)
|
||||||
{
|
{
|
||||||
/* Let's not really, just say we did. */
|
/* Let's not really, just say we did. */
|
||||||
song->ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - Stripping tail");
|
cmsg(CMSG_INFO, VERB_DEBUG, " - Stripping tail");
|
||||||
sp->data_length = sp->loop_end;
|
sp->data_length = sp->loop_end;
|
||||||
}
|
}
|
||||||
} /* end of sample loop */
|
} /* end of sample loop */
|
||||||
|
@ -839,7 +831,7 @@ static int fill_bank(Renderer *song, int dr, int b)
|
||||||
ToneBank *bank = ((dr) ? drumset[b] : tonebank[b]);
|
ToneBank *bank = ((dr) ? drumset[b] : tonebank[b]);
|
||||||
if (bank == NULL)
|
if (bank == NULL)
|
||||||
{
|
{
|
||||||
song->ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
|
cmsg(CMSG_ERROR, VERB_NORMAL,
|
||||||
"Huh. Tried to load instruments in non-existent %s %d",
|
"Huh. Tried to load instruments in non-existent %s %d",
|
||||||
(dr) ? "drumset" : "tone bank", b);
|
(dr) ? "drumset" : "tone bank", b);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -855,7 +847,7 @@ static int fill_bank(Renderer *song, int dr, int b)
|
||||||
}
|
}
|
||||||
if (bank->tone[i].name.IsEmpty())
|
if (bank->tone[i].name.IsEmpty())
|
||||||
{
|
{
|
||||||
song->ctl->cmsg(CMSG_WARNING, (b!=0) ? VERB_VERBOSE : VERB_NORMAL,
|
cmsg(CMSG_WARNING, (b!=0) ? VERB_VERBOSE : VERB_NORMAL,
|
||||||
"No instrument mapped to %s %d, program %d%s",
|
"No instrument mapped to %s %d, program %d%s",
|
||||||
(dr)? "drum set" : "tone bank", b, i,
|
(dr)? "drum set" : "tone bank", b, i,
|
||||||
(b!=0) ? "" : " - this instrument will not be heard");
|
(b!=0) ? "" : " - this instrument will not be heard");
|
||||||
|
@ -901,7 +893,7 @@ static int fill_bank(Renderer *song, int dr, int b)
|
||||||
bank->tone[i].sf_ix
|
bank->tone[i].sf_ix
|
||||||
)))
|
)))
|
||||||
{
|
{
|
||||||
song->ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
|
cmsg(CMSG_ERROR, VERB_NORMAL,
|
||||||
"Couldn't load instrument %s (%s %d, program %d)",
|
"Couldn't load instrument %s (%s %d, program %d)",
|
||||||
bank->tone[i].name,
|
bank->tone[i].name,
|
||||||
(dr)? "drum set" : "tone bank", b, i);
|
(dr)? "drum set" : "tone bank", b, i);
|
||||||
|
|
|
@ -105,10 +105,8 @@ static int update_envelope(Voice *v)
|
||||||
{
|
{
|
||||||
v->envelope_volume += v->envelope_increment;
|
v->envelope_volume += v->envelope_increment;
|
||||||
/* Why is there no ^^ operator?? */
|
/* Why is there no ^^ operator?? */
|
||||||
if (((v->envelope_increment < 0) &&
|
if (((v->envelope_increment < 0) && (v->envelope_volume <= v->envelope_target)) ||
|
||||||
(v->envelope_volume <= v->envelope_target)) ||
|
((v->envelope_increment > 0) && (v->envelope_volume >= v->envelope_target)))
|
||||||
((v->envelope_increment > 0) &&
|
|
||||||
(v->envelope_volume >= v->envelope_target)))
|
|
||||||
{
|
{
|
||||||
v->envelope_volume = v->envelope_target;
|
v->envelope_volume = v->envelope_target;
|
||||||
if (recompute_envelope(v))
|
if (recompute_envelope(v))
|
||||||
|
|
|
@ -247,6 +247,9 @@ void Renderer::reset_controllers(int c)
|
||||||
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 */
|
||||||
|
channel[c].mono = 0;
|
||||||
|
channel[c].rpn = RPN_RESET;
|
||||||
|
channel[c].nrpn = RPN_RESET;
|
||||||
|
|
||||||
channel[c].reverberation = 0;
|
channel[c].reverberation = 0;
|
||||||
channel[c].chorusdepth = 0;
|
channel[c].chorusdepth = 0;
|
||||||
|
@ -880,7 +883,7 @@ void Renderer::start_note(int ch, int this_note, int this_velocity, int i)
|
||||||
ip = lp->instrument;
|
ip = lp->instrument;
|
||||||
if (ip->type == INST_GUS && ip->samples != 1)
|
if (ip->type == INST_GUS && ip->samples != 1)
|
||||||
{
|
{
|
||||||
ctl->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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1257,7 +1260,7 @@ void Renderer::note_off(int chan, int note, int vel)
|
||||||
void Renderer::all_notes_off(int c)
|
void Renderer::all_notes_off(int c)
|
||||||
{
|
{
|
||||||
int i = voices;
|
int i = voices;
|
||||||
ctl->cmsg(CMSG_INFO, VERB_DEBUG, "All notes off on channel %d", c);
|
cmsg(CMSG_INFO, VERB_DEBUG, "All notes off on channel %d", c);
|
||||||
while (i--)
|
while (i--)
|
||||||
{
|
{
|
||||||
if (voice[i].status == VOICE_ON && voice[i].channel == c)
|
if (voice[i].status == VOICE_ON && voice[i].channel == c)
|
||||||
|
|
|
@ -553,8 +553,8 @@ void pre_resample(Renderer *song, Sample *sp)
|
||||||
{
|
{
|
||||||
"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"
|
"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"
|
||||||
};
|
};
|
||||||
return;
|
|
||||||
song->ctl->cmsg(CMSG_INFO, VERB_NOISY, " * pre-resampling for note %d (%s%d)",
|
cmsg(CMSG_INFO, VERB_NOISY, " * pre-resampling for note %d (%s%d)",
|
||||||
sp->note_to_use,
|
sp->note_to_use,
|
||||||
note_name[sp->note_to_use % 12], (sp->note_to_use & 0x7F) / 12);
|
note_name[sp->note_to_use % 12], (sp->note_to_use & 0x7F) / 12);
|
||||||
|
|
||||||
|
@ -565,9 +565,9 @@ return;
|
||||||
if (newlen < 0 || (newlen >> FRACTION_BITS) > MAX_SAMPLE_SIZE)
|
if (newlen < 0 || (newlen >> FRACTION_BITS) > MAX_SAMPLE_SIZE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dest = newdata = (sample_t *)safe_malloc(newlen >> (FRACTION_BITS - 2));
|
count = newlen >> FRACTION_BITS;
|
||||||
|
dest = newdata = (sample_t *)safe_malloc(count * sizeof(float));
|
||||||
|
|
||||||
count = (newlen >> FRACTION_BITS) - 1;
|
|
||||||
ofs = incr = (sp->data_length - (1 << FRACTION_BITS)) / count;
|
ofs = incr = (sp->data_length - (1 << FRACTION_BITS)) / count;
|
||||||
|
|
||||||
if (--count)
|
if (--count)
|
||||||
|
|
|
@ -404,7 +404,6 @@ int LoadConfig()
|
||||||
|
|
||||||
Renderer::Renderer(float sample_rate)
|
Renderer::Renderer(float sample_rate)
|
||||||
{
|
{
|
||||||
ctl = new ControlMode;
|
|
||||||
rate = sample_rate;
|
rate = sample_rate;
|
||||||
patches = NULL;
|
patches = NULL;
|
||||||
default_instrument = NULL;
|
default_instrument = NULL;
|
||||||
|
@ -420,7 +419,7 @@ Renderer::Renderer(float sample_rate)
|
||||||
if (def_instr_name.IsNotEmpty())
|
if (def_instr_name.IsNotEmpty())
|
||||||
set_default_instrument(def_instr_name);
|
set_default_instrument(def_instr_name);
|
||||||
|
|
||||||
voices = DEFAULT_VOICES;
|
voices = MAX_VOICES;//DEFAULT_VOICES;
|
||||||
memset(voice, 0, sizeof(voice));
|
memset(voice, 0, sizeof(voice));
|
||||||
memset(drumvolume, 0, sizeof(drumvolume));
|
memset(drumvolume, 0, sizeof(drumvolume));
|
||||||
memset(drumpanpot, 0, sizeof(drumpanpot));
|
memset(drumpanpot, 0, sizeof(drumpanpot));
|
||||||
|
@ -502,12 +501,25 @@ void Renderer::MarkInstrument(int banknum, int percussion, int instr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ControlMode::~ControlMode()
|
#ifdef _WIN32
|
||||||
{
|
#define WIN32_LEAN_AND_MEAN
|
||||||
}
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
void ControlMode::cmsg(int type, int verbosity_level, const char *fmt, ...)
|
void cmsg(int type, int verbosity_level, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
char buf[1024];
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
vsprintf(buf, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
size_t l = strlen(buf);
|
||||||
|
buf[l] = '\n';
|
||||||
|
buf[l+1] = '\0';
|
||||||
|
OutputDebugString(buf);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,11 +205,7 @@ controls.h
|
||||||
#define VERB_DEBUG 3
|
#define VERB_DEBUG 3
|
||||||
#define VERB_DEBUG_SILLY 4
|
#define VERB_DEBUG_SILLY 4
|
||||||
|
|
||||||
struct ControlMode
|
|
||||||
{
|
|
||||||
virtual ~ControlMode();
|
|
||||||
void cmsg(int type, int verbosity_level, const char *fmt, ...);
|
void cmsg(int type, int verbosity_level, const char *fmt, ...);
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -522,7 +518,6 @@ extern ToneBank *drumset[MAXBANK];
|
||||||
|
|
||||||
struct Renderer
|
struct Renderer
|
||||||
{
|
{
|
||||||
ControlMode *ctl;
|
|
||||||
float rate;
|
float rate;
|
||||||
DLS_Data *patches;
|
DLS_Data *patches;
|
||||||
InstrumentLayer *default_instrument;
|
InstrumentLayer *default_instrument;
|
||||||
|
|
Loading…
Reference in a new issue