This commit is contained in:
Christoph Oelckers 2015-12-30 12:28:55 +01:00
commit 86797b419f
28 changed files with 518 additions and 1864 deletions

View file

@ -978,6 +978,7 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE
nodebuild_extract.cpp nodebuild_extract.cpp
nodebuild_gl.cpp nodebuild_gl.cpp
nodebuild_utility.cpp nodebuild_utility.cpp
pathexpander.cpp
p_3dfloors.cpp p_3dfloors.cpp
p_3dmidtex.cpp p_3dmidtex.cpp
p_acs.cpp p_acs.cpp
@ -1257,7 +1258,6 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE
timidity/timidity.cpp timidity/timidity.cpp
wildmidi/file_io.cpp wildmidi/file_io.cpp
wildmidi/gus_pat.cpp wildmidi/gus_pat.cpp
wildmidi/lock.cpp
wildmidi/reverb.cpp wildmidi/reverb.cpp
wildmidi/wildmidi_lib.cpp wildmidi/wildmidi_lib.cpp
wildmidi/wm_error.cpp wildmidi/wm_error.cpp

134
src/pathexpander.cpp Normal file
View file

@ -0,0 +1,134 @@
/*
** pathexpander.cpp
** Utility class for expanding a given path with a range of directories
**
**---------------------------------------------------------------------------
** Copyright 2015 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include "pathexpander.h"
#include "cmdlib.h"
#include "w_wad.h"
//============================================================================
//
//
//
//============================================================================
static FString BuildPath(const FString &base, const char *name)
{
FString current;
if (base.IsNotEmpty())
{
current = base;
if (current[current.Len() - 1] != '/') current += '/';
}
current += name;
return current;
}
//============================================================================
//
// This is meant to find and open files for reading.
//
//============================================================================
FileReader *PathExpander::openFileReader(const char *name, int *plumpnum)
{
FileReader *fp;
FString current_filename;
if (!name || !(*name))
{
return 0;
}
/* First try the given name */
current_filename = name;
FixPathSeperator(current_filename);
if (openmode != OM_FILE)
{
int lumpnum = Wads.CheckNumForFullName(current_filename);
if (lumpnum >= 0)
{
fp = Wads.ReopenLumpNum(lumpnum);
if (plumpnum) *plumpnum = lumpnum;
return fp;
}
if (openmode == OM_LUMP) // search the path list when not loading the main config
{
for (unsigned int plp = PathList.Size(); plp-- != 0; )
{ /* Try along the path then */
current_filename = BuildPath(PathList[plp], name);
lumpnum = Wads.CheckNumForFullName(current_filename);
if (lumpnum >= 0)
{
fp = Wads.ReopenLumpNum(lumpnum);
if (plumpnum) *plumpnum = lumpnum;
return fp;
}
}
return NULL;
}
}
if (plumpnum) *plumpnum = -1;
fp = new FileReader;
if (fp->Open(current_filename)) return fp;
if (name[0] != '/')
{
for (unsigned int plp = PathList.Size(); plp-- != 0; )
{ /* Try along the path then */
current_filename = BuildPath(PathList[plp], name);
if (fp->Open(current_filename)) return fp;
}
}
delete fp;
/* Nothing could be opened. */
return NULL;
}
/* This adds a directory to the path list */
void PathExpander::addToPathlist(const char *s)
{
FString copy = s;
FixPathSeperator(copy);
PathList.Push(copy);
}
void PathExpander::clearPathlist()
{
PathList.Clear();
}

31
src/pathexpander.h Normal file
View file

@ -0,0 +1,31 @@
#ifndef __PATHEXPANDER_H
#define __PATHEXPANDER_H
#include "tarray.h"
#include "zstring.h"
#include "files.h"
class PathExpander
{
TArray<FString> PathList;
public:
int openmode;
enum
{
OM_FILEORLUMP = 0,
OM_LUMP,
OM_FILE
};
PathExpander(int om = OM_FILEORLUMP)
{
openmode = om;
}
void addToPathlist(const char *s);
void clearPathlist();
FileReader *openFileReader(const char *name, int *plumpnum);
};
#endif

View file

@ -162,7 +162,7 @@ void I_InitMusic (void)
if (!setatterm) if (!setatterm)
{ {
setatterm = true; setatterm = true;
atterm (I_ShutdownMusic); atterm (I_ShutdownMusicExit);
#ifndef _WIN32 #ifndef _WIN32
signal (SIGCHLD, ChildSigHandler); signal (SIGCHLD, ChildSigHandler);
@ -178,7 +178,7 @@ void I_InitMusic (void)
// //
//========================================================================== //==========================================================================
void I_ShutdownMusic(void) void I_ShutdownMusic(bool onexit)
{ {
if (MusicDown) if (MusicDown)
return; return;
@ -189,12 +189,17 @@ void I_ShutdownMusic(void)
assert (currSong == NULL); assert (currSong == NULL);
} }
Timidity::FreeAll(); Timidity::FreeAll();
WildMidi_Shutdown(); if (onexit) WildMidi_Shutdown();
#ifdef _WIN32 #ifdef _WIN32
I_ShutdownMusicWin32(); I_ShutdownMusicWin32();
#endif // _WIN32 #endif // _WIN32
} }
void I_ShutdownMusicExit()
{
I_ShutdownMusic(true);
}
//========================================================================== //==========================================================================
// //
@ -281,6 +286,10 @@ void MusInfo::FluidSettingStr(const char *, const char *)
{ {
} }
void MusInfo::WildMidiSetOption(int opt, int set)
{
}
FString MusInfo::GetStats() FString MusInfo::GetStats()
{ {
return "No stats available for this song"; return "No stats available for this song";

View file

@ -43,7 +43,8 @@ struct FOptionValues;
// MUSIC I/O // MUSIC I/O
// //
void I_InitMusic (); void I_InitMusic ();
void I_ShutdownMusic (); void I_ShutdownMusic (bool onexit = false);
void I_ShutdownMusicExit ();
void I_BuildMIDIMenuList (FOptionValues *); void I_BuildMIDIMenuList (FOptionValues *);
void I_UpdateMusic (); void I_UpdateMusic ();
@ -81,6 +82,7 @@ public:
virtual void FluidSettingInt(const char *setting, int value); // FluidSynth settings virtual void FluidSettingInt(const char *setting, int value); // FluidSynth settings
virtual void FluidSettingNum(const char *setting, double value); // " virtual void FluidSettingNum(const char *setting, double value); // "
virtual void FluidSettingStr(const char *setting, const char *value); // " virtual void FluidSettingStr(const char *setting, const char *value); // "
virtual void WildMidiSetOption(int opt, int set);
void Start(bool loop, float rel_vol = -1.f, int subsong = 0); void Start(bool loop, float rel_vol = -1.f, int subsong = 0);

View file

@ -102,6 +102,7 @@ public:
virtual void FluidSettingInt(const char *setting, int value); virtual void FluidSettingInt(const char *setting, int value);
virtual void FluidSettingNum(const char *setting, double value); virtual void FluidSettingNum(const char *setting, double value);
virtual void FluidSettingStr(const char *setting, const char *value); virtual void FluidSettingStr(const char *setting, const char *value);
virtual void WildMidiSetOption(int opt, int set);
virtual bool Preprocess(MIDIStreamer *song, bool looping); virtual bool Preprocess(MIDIStreamer *song, bool looping);
virtual FString GetStats(); virtual FString GetStats();
}; };
@ -349,6 +350,7 @@ protected:
void HandleEvent(int status, int parm1, int parm2); void HandleEvent(int status, int parm1, int parm2);
void HandleLongEvent(const BYTE *data, int len); void HandleLongEvent(const BYTE *data, int len);
void ComputeOutput(float *buffer, int len); void ComputeOutput(float *buffer, int len);
void WildMidiSetOption(int opt, int set);
}; };
// FluidSynth implementation of a MIDI device ------------------------------- // FluidSynth implementation of a MIDI device -------------------------------
@ -447,6 +449,7 @@ public:
void FluidSettingInt(const char *setting, int value); void FluidSettingInt(const char *setting, int value);
void FluidSettingNum(const char *setting, double value); void FluidSettingNum(const char *setting, double value);
void FluidSettingStr(const char *setting, const char *value); void FluidSettingStr(const char *setting, const char *value);
void WildMidiSetOption(int opt, int set);
void CreateSMF(TArray<BYTE> &file, int looplimit=0); void CreateSMF(TArray<BYTE> &file, int looplimit=0);
protected: protected:
@ -566,7 +569,7 @@ protected:
struct TrackInfo; struct TrackInfo;
void ProcessInitialMetaEvents (); void ProcessInitialMetaEvents ();
DWORD *SendCommand (DWORD *event, TrackInfo *track, DWORD delay); DWORD *SendCommand (DWORD *event, TrackInfo *track, DWORD delay, ptrdiff_t room, bool &sysex_noroom);
TrackInfo *FindNextDue (); TrackInfo *FindNextDue ();
BYTE *MusHeader; BYTE *MusHeader;

View file

@ -168,6 +168,7 @@ CCMD (snd_listmididevices)
MIDIOUTCAPS caps; MIDIOUTCAPS caps;
MMRESULT res; MMRESULT res;
PrintMidiDevice (-6, "WildMidi", MOD_SWSYNTH, 0);
#ifdef HAVE_FLUIDSYNTH #ifdef HAVE_FLUIDSYNTH
PrintMidiDevice (-5, "FluidSynth", MOD_SWSYNTH, 0); PrintMidiDevice (-5, "FluidSynth", MOD_SWSYNTH, 0);
#endif #endif

View file

@ -626,6 +626,21 @@ void MIDIStreamer::FluidSettingStr(const char *setting, const char *value)
} }
//==========================================================================
//
// MIDIDeviceStreamer :: WildMidiSetOption
//
//==========================================================================
void MIDIStreamer::WildMidiSetOption(int opt, int set)
{
if (MIDI != NULL)
{
MIDI->WildMidiSetOption(opt, set);
}
}
//========================================================================== //==========================================================================
// //
// MIDIStreamer :: OutputVolume // MIDIStreamer :: OutputVolume
@ -1196,9 +1211,15 @@ void MIDIStreamer::CreateSMF(TArray<BYTE> &file, int looplimit)
len--; len--;
file.Push(MIDI_SYSEX); file.Push(MIDI_SYSEX);
WriteVarLen(file, len); WriteVarLen(file, len);
memcpy(&file[file.Reserve(len - 1)], bytes, len); memcpy(&file[file.Reserve(len)], bytes + 1, len);
running_status = 255;
} }
else
{
file.Push(MIDI_SYSEXEND);
WriteVarLen(file, len);
memcpy(&file[file.Reserve(len)], bytes, len);
}
running_status = 255;
} }
else if (MEVT_EVENTTYPE(event[2]) == 0) else if (MEVT_EVENTTYPE(event[2]) == 0)
{ {
@ -1516,6 +1537,16 @@ void MIDIDevice::FluidSettingStr(const char *setting, const char *value)
{ {
} }
//==========================================================================
//
// MIDIDevice :: WildMidiSetOption
//
//==========================================================================
void MIDIDevice::WildMidiSetOption(int opt, int set)
{
}
//========================================================================== //==========================================================================
// //
// MIDIDevice :: GetStats // MIDIDevice :: GetStats

View file

@ -322,7 +322,12 @@ DWORD *MIDISong2::MakeEvents(DWORD *events, DWORD *max_event_p, DWORD max_time)
// Play all events for this tick. // Play all events for this tick.
do do
{ {
DWORD *new_events = SendCommand(events, TrackDue, time); bool sysex_noroom = false;
DWORD *new_events = SendCommand(events, TrackDue, time, max_event_p - events, sysex_noroom);
if (sysex_noroom)
{
return events;
}
TrackDue = FindNextDue(); TrackDue = FindNextDue();
if (new_events != events) if (new_events != events)
{ {
@ -366,12 +371,15 @@ void MIDISong2::AdvanceTracks(DWORD time)
// //
//========================================================================== //==========================================================================
DWORD *MIDISong2::SendCommand (DWORD *events, TrackInfo *track, DWORD delay) DWORD *MIDISong2::SendCommand (DWORD *events, TrackInfo *track, DWORD delay, ptrdiff_t room, bool &sysex_noroom)
{ {
DWORD len; DWORD len;
BYTE event, data1 = 0, data2 = 0; BYTE event, data1 = 0, data2 = 0;
int i; int i;
sysex_noroom = false;
size_t start_p = track->TrackP;
CHECK_FINISHED CHECK_FINISHED
event = track->TrackBegin[track->TrackP++]; event = track->TrackBegin[track->TrackP++];
CHECK_FINISHED CHECK_FINISHED
@ -588,14 +596,45 @@ DWORD *MIDISong2::SendCommand (DWORD *events, TrackInfo *track, DWORD delay)
} }
else else
{ {
// Skip SysEx events just because I don't want to bother with them. // SysEx events could potentially not have enough room in the buffer...
// The old MIDI player ignored them too, so this won't break
// anything that played before.
if (event == MIDI_SYSEX || event == MIDI_SYSEXEND) if (event == MIDI_SYSEX || event == MIDI_SYSEXEND)
{ {
len = track->ReadVarLen (); len = track->ReadVarLen();
if (len >= (MAX_EVENTS-1)*3*4)
{ // This message will never fit. Throw it away.
track->TrackP += len; track->TrackP += len;
} }
else if (len + 12 >= (size_t)room * 4)
{ // Not enough room left in this buffer. Backup and wait for the next one.
track->TrackP = start_p;
sysex_noroom = true;
return events;
}
else
{
events[0] = delay;
events[1] = 0;
BYTE *msg = (BYTE *)&events[3];
if (event == MIDI_SYSEX)
{ // Need to add the SysEx marker to the message.
events[2] = (MEVT_LONGMSG << 24) | (len + 1);
*msg++ = MIDI_SYSEX;
}
else
{
events[2] = (MEVT_LONGMSG << 24) | len;
}
memcpy(msg, &track->TrackBegin[track->TrackP], len);
msg += len;
// Must pad with 0
while ((size_t)msg & 3)
{
*msg++ = 0;
}
events = (DWORD *)msg;
track->TrackP += len;
}
}
else if (event == MIDI_META) else if (event == MIDI_META)
{ {
// It's a meta-event // It's a meta-event

View file

@ -61,6 +61,17 @@ static FString CurrentConfig;
CVAR(String, wildmidi_config, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(String, wildmidi_config, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Int, wildmidi_frequency, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(Int, wildmidi_frequency, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CUSTOM_CVAR(Bool, wildmidi_reverb, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
if (currSong != NULL)
currSong->WildMidiSetOption(WM_MO_REVERB, *self? WM_MO_REVERB:0);
}
CUSTOM_CVAR(Bool, wildmidi_enhanced_resampling, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
if (currSong != NULL)
currSong->WildMidiSetOption(WM_MO_ENHANCED_RESAMPLING, *self? WM_MO_ENHANCED_RESAMPLING:0);
}
// CODE -------------------------------------------------------------------- // CODE --------------------------------------------------------------------
@ -90,7 +101,7 @@ WildMIDIDevice::WildMIDIDevice()
WildMidi_Shutdown(); WildMidi_Shutdown();
CurrentConfig = ""; CurrentConfig = "";
} }
if (!WildMidi_Init(wildmidi_config, SampleRate, WM_MO_ENHANCED_RESAMPLING)) if (!WildMidi_Init(wildmidi_config, SampleRate, 0))
{ {
CurrentConfig = wildmidi_config; CurrentConfig = wildmidi_config;
} }
@ -98,6 +109,10 @@ WildMIDIDevice::WildMIDIDevice()
if (CurrentConfig.IsNotEmpty()) if (CurrentConfig.IsNotEmpty())
{ {
Renderer = new WildMidi_Renderer(); Renderer = new WildMidi_Renderer();
int flags = 0;
if (wildmidi_enhanced_resampling) flags |= WM_MO_ENHANCED_RESAMPLING;
if (wildmidi_reverb) flags |= WM_MO_REVERB;
Renderer->SetOption(WM_MO_ENHANCED_RESAMPLING | WM_MO_REVERB, flags);
} }
} }
@ -178,7 +193,7 @@ void WildMIDIDevice::HandleEvent(int status, int parm1, int parm2)
void WildMIDIDevice::HandleLongEvent(const BYTE *data, int len) void WildMIDIDevice::HandleLongEvent(const BYTE *data, int len)
{ {
Renderer->LongEvent((const char *)data, len); Renderer->LongEvent(data, len);
} }
//========================================================================== //==========================================================================
@ -204,3 +219,14 @@ FString WildMIDIDevice::GetStats()
out.Format("%3d voices", Renderer->GetVoiceCount()); out.Format("%3d voices", Renderer->GetVoiceCount());
return out; return out;
} }
//==========================================================================
//
// WildMIDIDevice :: GetStats
//
//==========================================================================
void WildMIDIDevice::WildMidiSetOption(int opt, int set)
{
Renderer->SetOption(opt, set);
}

View file

@ -35,82 +35,6 @@
namespace Timidity namespace Timidity
{ {
static TArray<FString> PathList;
FString BuildPath(FString base, const char *name)
{
FString current;
if (base.IsNotEmpty())
{
current = base;
if (current[current.Len() - 1] != '/') current += '/';
}
current += name;
return current;
}
/* This is meant to find and open files for reading. */
FileReader *open_filereader(const char *name, int open, int *plumpnum)
{
FileReader *fp;
FString current_filename;
if (!name || !(*name))
{
return 0;
}
/* First try the given name */
current_filename = name;
FixPathSeperator(current_filename);
int lumpnum = Wads.CheckNumForFullName(current_filename);
if (open != OM_FILE)
{
if (lumpnum >= 0)
{
fp = Wads.ReopenLumpNum(lumpnum);
if (plumpnum) *plumpnum = lumpnum;
return fp;
}
if (open == OM_LUMP) // search the path list when not loading the main config
{
for (unsigned int plp = PathList.Size(); plp-- != 0; )
{ /* Try along the path then */
current_filename = BuildPath(PathList[plp], name);
lumpnum = Wads.CheckNumForFullName(current_filename);
if (lumpnum >= 0)
{
fp = Wads.ReopenLumpNum(lumpnum);
if (plumpnum) *plumpnum = lumpnum;
return fp;
}
}
return NULL;
}
}
if (plumpnum) *plumpnum = -1;
fp = new FileReader;
if (fp->Open(current_filename)) return fp;
if (name[0] != '/')
{
for (unsigned int plp = PathList.Size(); plp-- != 0; )
{ /* Try along the path then */
current_filename = BuildPath(PathList[plp], name);
if (fp->Open(current_filename)) return fp;
}
}
delete fp;
/* Nothing could be opened. */
current_filename = "";
return NULL;
}
/* This'll allocate memory or die. */ /* This'll allocate memory or die. */
@ -132,17 +56,5 @@ void *safe_malloc(size_t count)
return 0; // Unreachable. return 0; // Unreachable.
} }
/* This adds a directory to the path list */
void add_to_pathlist(const char *s)
{
FString copy = s;
FixPathSeperator(copy);
PathList.Push(copy);
}
void clear_pathlist()
{
PathList.Clear();
}
} }

View file

@ -142,7 +142,7 @@ static void reverse_data(sample_t *sp, int ls, int le)
TODO: do reverse loops right */ TODO: do reverse loops right */
static Instrument *load_instrument(Renderer *song, const char *name, int percussion, static Instrument *load_instrument(Renderer *song, const char *name, int percussion,
int panning, int amp, int note_to_use, int panning, int note_to_use,
int strip_loop, int strip_envelope, int strip_loop, int strip_envelope,
int strip_tail) int strip_tail)
{ {
@ -159,16 +159,16 @@ static Instrument *load_instrument(Renderer *song, const char *name, int percuss
if (!name) return 0; if (!name) return 0;
/* Open patch file */ /* Open patch file */
if ((fp = open_filereader(name, openmode, NULL)) == NULL) if ((fp = pathExpander.openFileReader(name, NULL)) == NULL)
{ {
/* Try with various extensions */ /* Try with various extensions */
FString tmp = name; FString tmp = name;
tmp += ".pat"; tmp += ".pat";
if ((fp = open_filereader(tmp, openmode, NULL)) == NULL) if ((fp = pathExpander.openFileReader(tmp, NULL)) == NULL)
{ {
#ifdef __unix__ // Windows isn't case-sensitive. #ifdef __unix__ // Windows isn't case-sensitive.
tmp.ToUpper(); tmp.ToUpper();
if ((fp = open_filereader(tmp, openmode, NULL)) == NULL) if ((fp = pathExpander.openFileReader(tmp, NULL)) == NULL)
#endif #endif
{ {
noluck = true; noluck = true;
@ -372,7 +372,6 @@ fail:
{ {
sp->modes &= ~(PATCH_SUSTAIN | PATCH_LOOPEN | PATCH_BIDIR | PATCH_BACKWARD); sp->modes &= ~(PATCH_SUSTAIN | PATCH_LOOPEN | PATCH_BIDIR | PATCH_BACKWARD);
} }
sp->modes |= PATCH_T_NO_LOOP;
} }
if (strip_envelope == 1) if (strip_envelope == 1)
@ -398,37 +397,6 @@ fail:
patch_data.EnvelopeOffset[k] = patch_data.EnvelopeOffset[0]; patch_data.EnvelopeOffset[k] = patch_data.EnvelopeOffset[0];
} }
} }
sp->modes |= PATCH_T_NO_ENVELOPE;
}
else if (strip_envelope != 0)
{
/* Have to make a guess. */
if (!(sp->modes & (PATCH_LOOPEN | PATCH_BIDIR | PATCH_BACKWARD)))
{
/* No loop? Then what's there to sustain? No envelope needed either... */
sp->modes |= PATCH_T_NO_ENVELOPE;
cmsg(CMSG_INFO, VERB_DEBUG, " - No loop, removing sustain and envelope\n");
}
else if (memcmp(patch_data.EnvelopeRate, "??????", 6) == 0 || patch_data.EnvelopeOffset[GF1_RELEASEC] >= 100)
{
/* Envelope rates all maxed out? Envelope end at a high "offset"?
That's a weird envelope. Take it out. */
sp->modes |= PATCH_T_NO_ENVELOPE;
cmsg(CMSG_INFO, VERB_DEBUG, " - Weirdness, removing envelope\n");
}
else if (!(sp->modes & PATCH_SUSTAIN))
{
/* No sustain? Then no envelope. I don't know if this is
justified, but patches without sustain usually don't need the
envelope either... at least the Gravis ones. They're mostly
drums. I think. */
sp->modes |= PATCH_T_NO_ENVELOPE;
cmsg(CMSG_INFO, VERB_DEBUG, " - No sustain, removing envelope\n");
}
}
if (!(sp->modes & PATCH_NO_SRELEASE))
{ // TiMidity thinks that this is an envelope enable flag.
sp->modes |= PATCH_T_NO_ENVELOPE;
} }
for (j = 0; j < 6; j++) for (j = 0; j < 6; j++)
@ -470,29 +438,6 @@ fail:
sp->modes |= PATCH_LOOPEN; /* just in case */ sp->modes |= PATCH_LOOPEN; /* just in case */
} }
if (amp != -1)
{
sp->volume = (amp) / 100.f;
}
else
{
/* Try to determine a volume scaling factor for the sample.
This is a very crude adjustment, but things sound more
balanced with it. Still, this should be a runtime option.
(This is ignored unless midi_timiditylike is turned on.) */
int i;
sample_t maxamp = 0, a;
sample_t *tmp;
for (i = sp->data_length, tmp = sp->data; i; --i)
{
a = fabsf(*tmp++);
if (a > maxamp)
maxamp = a;
}
sp->volume = 1 / maxamp;
cmsg(CMSG_INFO, VERB_DEBUG, " * volume comp: %f\n", sp->volume);
}
/* Then fractional samples */ /* Then fractional samples */
sp->data_length <<= FRACTION_BITS; sp->data_length <<= FRACTION_BITS;
sp->loop_start <<= FRACTION_BITS; sp->loop_start <<= FRACTION_BITS;
@ -653,7 +598,6 @@ static int fill_bank(Renderer *song, int dr, int b)
ip = load_instrument(song, bank->tone[i].name, ip = load_instrument(song, bank->tone[i].name,
(dr) ? 1 : 0, (dr) ? 1 : 0,
bank->tone[i].pan, bank->tone[i].pan,
bank->tone[i].amp,
(bank->tone[i].note != -1) ? bank->tone[i].note : ((dr) ? i : -1), (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_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_envelope != -1) ? bank->tone[i].strip_envelope : ((dr) ? 1 : -1),
@ -731,7 +675,7 @@ void free_instruments()
int Renderer::set_default_instrument(const char *name) int Renderer::set_default_instrument(const char *name)
{ {
Instrument *ip; Instrument *ip;
if ((ip = load_instrument(this, name, 0, -1, -1, -1, 0, 0, 0)) == NULL) if ((ip = load_instrument(this, name, 0, -1, -1, 0, 0, 0)) == NULL)
{ {
return -1; return -1;
} }

View file

@ -1141,7 +1141,6 @@ static void load_region_dls(Renderer *song, Sample *sample, DLS_Instrument *ins,
sample->loop_start = rgn->wsmp_loop->ulStart / 2; sample->loop_start = rgn->wsmp_loop->ulStart / 2;
sample->loop_end = sample->loop_start + (rgn->wsmp_loop->ulLength / 2); sample->loop_end = sample->loop_start + (rgn->wsmp_loop->ulLength / 2);
} }
sample->volume = 1.0f;
if (sample->modes & PATCH_SUSTAIN) if (sample->modes & PATCH_SUSTAIN)
{ {

View file

@ -54,7 +54,7 @@ void font_add(const char *filename, int load_order)
} }
else else
{ {
FileReader *fp = open_filereader(filename, openmode, NULL); FileReader *fp = pathExpander.openFileReader(filename, NULL);
if (fp != NULL) if (fp != NULL)
{ {

View file

@ -1441,7 +1441,6 @@ void SFFile::ApplyGeneratorsToRegion(SFGenComposite *gen, SFSample *sfsamp, Rend
sp->root_freq = note_to_freq(sp->scale_note); sp->root_freq = note_to_freq(sp->scale_note);
sp->sample_rate = sfsamp->SampleRate; sp->sample_rate = sfsamp->SampleRate;
sp->key_group = gen->exclusiveClass; sp->key_group = gen->exclusiveClass;
sp->volume = 1;
// Set key scaling // Set key scaling
if (gen->keynum >= 0 && gen->keynum <= 127) if (gen->keynum >= 0 && gen->keynum <= 127)
@ -1502,7 +1501,7 @@ void SFFile::ApplyGeneratorsToRegion(SFGenComposite *gen, SFSample *sfsamp, Rend
void SFFile::LoadSample(SFSample *sample) void SFFile::LoadSample(SFSample *sample)
{ {
FileReader *fp = open_filereader(Filename, openmode, NULL); FileReader *fp = pathExpander.openFileReader(Filename, NULL);
DWORD i; DWORD i;
if (fp == NULL) if (fp == NULL)

View file

@ -29,8 +29,6 @@
#include "templates.h" #include "templates.h"
#include "c_cvars.h" #include "c_cvars.h"
EXTERN_CVAR(Bool, midi_timiditylike)
namespace Timidity namespace Timidity
{ {
@ -78,16 +76,7 @@ void GF1Envelope::Init(Renderer *song, Voice *v)
void GF1Envelope::Release(Voice *v) void GF1Envelope::Release(Voice *v)
{ {
if (midi_timiditylike) if (!(v->sample->modes & PATCH_NO_SRELEASE) || (v->sample->modes & PATCH_FAST_REL))
{
if (!(v->sample->modes & PATCH_T_NO_ENVELOPE))
{
stage = GF1_RELEASE;
Recompute(v);
}
// else ... loop was already turned off by the caller
}
else if (!(v->sample->modes & PATCH_NO_SRELEASE) || (v->sample->modes & PATCH_FAST_REL))
{ {
/* ramp out to minimum volume with rate from final release stage */ /* ramp out to minimum volume with rate from final release stage */
stage = GF1_RELEASEC+1; stage = GF1_RELEASEC+1;
@ -119,23 +108,11 @@ bool GF1Envelope::Recompute(Voice *v)
bUpdating = false; bUpdating = false;
v->status &= ~(VOICE_SUSTAINING | VOICE_LPE); v->status &= ~(VOICE_SUSTAINING | VOICE_LPE);
v->status |= VOICE_RELEASING; v->status |= VOICE_RELEASING;
if (midi_timiditylike) /* play sampled release */
{ /* kill the voice ... or not */
if (volume <= 0)
{
v->status |= VOICE_STOPPING;
}
return 1;
}
else
{ /* play sampled release */
}
return 0; return 0;
} }
if (newstage == GF1_RELEASE && !(v->status & VOICE_RELEASING) && if (newstage == GF1_RELEASE && !(v->status & VOICE_RELEASING) && (v->sample->modes & PATCH_SUSTAIN))
((!midi_timiditylike && (v->sample->modes & PATCH_SUSTAIN)) ||
(midi_timiditylike && !(v->sample->modes & PATCH_T_NO_ENVELOPE))))
{ {
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. */
@ -161,10 +138,6 @@ bool GF1Envelope::Recompute(Voice *v)
bool GF1Envelope::Update(Voice *v) bool GF1Envelope::Update(Voice *v)
{ {
if (midi_timiditylike && (v->sample->modes & PATCH_T_NO_ENVELOPE))
{
return 0;
}
volume += increment; volume += increment;
if (((increment < 0) && (volume <= target)) || ((increment > 0) && (volume >= target))) if (((increment < 0) && (volume <= target)) || ((increment > 0) && (volume >= target)))
{ {
@ -182,27 +155,6 @@ void GF1Envelope::ApplyToAmp(Voice *v)
double env_vol = v->attenuation; double env_vol = v->attenuation;
double final_amp; double final_amp;
if (midi_timiditylike)
{
final_amp = v->sample->volume * FINAL_MIX_TIMIDITY_SCALE;
if (v->tremolo_phase_increment != 0)
{
env_vol *= v->tremolo_volume;
}
if (!(v->sample->modes & PATCH_T_NO_ENVELOPE))
{
if (stage > GF1_ATTACK)
{
env_vol *= pow(2.0, volume * (6.0 / (1 << 30)) - 6.0);
}
else
{
env_vol *= volume / float(1 << 30);
}
}
}
else
{
final_amp = FINAL_MIX_SCALE; final_amp = FINAL_MIX_SCALE;
if (v->tremolo_phase_increment != 0) if (v->tremolo_phase_increment != 0)
{ // [RH] FIXME: This is wrong. Tremolo should offset the { // [RH] FIXME: This is wrong. Tremolo should offset the
@ -211,7 +163,6 @@ void GF1Envelope::ApplyToAmp(Voice *v)
} }
env_vol *= volume / float(1 << 30); env_vol *= volume / float(1 << 30);
env_vol = calc_gf1_amp(env_vol); env_vol = calc_gf1_amp(env_vol);
}
env_vol *= final_amp; env_vol *= final_amp;
v->left_mix = float(env_vol * v->left_offset); v->left_mix = float(env_vol * v->left_offset);
v->right_mix = float(env_vol * v->right_offset); v->right_mix = float(env_vol * v->right_offset);

View file

@ -29,8 +29,6 @@
#include "timidity.h" #include "timidity.h"
#include "c_cvars.h" #include "c_cvars.h"
EXTERN_CVAR(Bool, midi_timiditylike)
namespace Timidity namespace Timidity
{ {
@ -118,7 +116,7 @@ void Renderer::recompute_freq(int v)
voice[v].sample_increment = (int)(a); voice[v].sample_increment = (int)(a);
} }
static BYTE vol_table[] = { static const BYTE vol_table[] = {
000 /* 000 */, 129 /* 001 */, 145 /* 002 */, 155 /* 003 */, 000 /* 000 */, 129 /* 001 */, 145 /* 002 */, 155 /* 003 */,
161 /* 004 */, 166 /* 005 */, 171 /* 006 */, 174 /* 007 */, 161 /* 004 */, 166 /* 005 */, 171 /* 006 */, 174 /* 007 */,
177 /* 008 */, 180 /* 009 */, 182 /* 010 */, 185 /* 011 */, 177 /* 008 */, 180 /* 009 */, 182 /* 010 */, 185 /* 011 */,
@ -160,18 +158,9 @@ void Renderer::recompute_amp(Voice *v)
int chanexpr = chan->expression; int chanexpr = chan->expression;
if (v->sample->type == INST_GUS) if (v->sample->type == INST_GUS)
{
if (midi_timiditylike)
{
v->attenuation = float(timidityxx_perceived_vol(v->velocity / 127.0) *
timidityxx_perceived_vol(chanvol / 127.0) *
timidityxx_perceived_vol(chanexpr / 127.0));
}
else
{ {
v->attenuation = (vol_table[(chanvol * chanexpr) / 127] * vol_table[v->velocity]) * ((127 + 64) / 12419775.f); v->attenuation = (vol_table[(chanvol * chanexpr) / 127] * vol_table[v->velocity]) * ((127 + 64) / 12419775.f);
} }
}
else else
{ {
// Implicit modulators from SF2 spec // Implicit modulators from SF2 spec
@ -199,7 +188,7 @@ void Renderer::compute_pan(double pan, int type, float &left_offset, float &righ
} }
else else
{ {
if (type == INST_GUS && !midi_timiditylike) if (type == INST_GUS)
{ {
/* Original amp equation looks like this: /* Original amp equation looks like this:
* calc_gf1_amp(atten + offset) * calc_gf1_amp(atten + offset)
@ -218,9 +207,7 @@ void Renderer::compute_pan(double pan, int type, float &left_offset, float &righ
} }
else else
{ {
/* I have no idea what equation, if any, will reproduce the sc_pan_table /* Equal Power Panning for SF2/DLS.
* that TiMidity++ uses, so midi_timiditylike gets the same Equal Power
* Panning as SF2/DLS.
*/ */
left_offset = (float)sqrt(1 - pan); left_offset = (float)sqrt(1 - pan);
right_offset = (float)sqrt(pan); right_offset = (float)sqrt(pan);
@ -561,7 +548,7 @@ void Renderer::finish_note(int i)
v->status &= ~VOICE_SUSTAINING; v->status &= ~VOICE_SUSTAINING;
v->status |= VOICE_RELEASING; v->status |= VOICE_RELEASING;
if (!(v->sample->modes & PATCH_NO_SRELEASE) || midi_timiditylike) if (!(v->sample->modes & PATCH_NO_SRELEASE))
{ {
v->status &= ~VOICE_LPE; /* sampled release */ v->status &= ~VOICE_LPE; /* sampled release */
} }

View file

@ -28,8 +28,6 @@
#include "timidity.h" #include "timidity.h"
#include "c_cvars.h" #include "c_cvars.h"
EXTERN_CVAR(Bool, midi_timiditylike)
namespace Timidity namespace Timidity
{ {
@ -522,7 +520,7 @@ sample_t *resample_voice(Renderer *song, Voice *vp, int *countptr)
if (vp->vibrato_control_ratio) if (vp->vibrato_control_ratio)
{ {
if (vp->status & VOICE_LPE && !(midi_timiditylike && vp->sample->modes & PATCH_T_NO_LOOP)) if (vp->status & VOICE_LPE)
{ {
if (modes & PATCH_BIDIR) if (modes & PATCH_BIDIR)
return rs_vib_bidir(song->resample_buffer, song->rate, vp, *countptr); return rs_vib_bidir(song->resample_buffer, song->rate, vp, *countptr);
@ -536,7 +534,7 @@ sample_t *resample_voice(Renderer *song, Voice *vp, int *countptr)
} }
else else
{ {
if (vp->status & VOICE_LPE && !(midi_timiditylike && vp->sample->modes & PATCH_T_NO_LOOP)) if (vp->status & VOICE_LPE)
{ {
if (modes & PATCH_BIDIR) if (modes & PATCH_BIDIR)
return rs_bidir(song->resample_buffer, vp, *countptr); return rs_bidir(song->resample_buffer, vp, *countptr);

View file

@ -34,7 +34,6 @@
CVAR(String, midi_config, CONFIG_FILE, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(String, midi_config, CONFIG_FILE, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR(Int, midi_voices, 32, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(Int, midi_voices, 32, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR(Bool, midi_timiditylike, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR(String, gus_patchdir, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(String, gus_patchdir, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR(Bool, midi_dmxgus, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(Bool, midi_dmxgus, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR(Int, gus_memsize, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(Int, gus_memsize, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
@ -42,10 +41,10 @@ CVAR(Int, gus_memsize, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
namespace Timidity namespace Timidity
{ {
PathExpander pathExpander;
ToneBank *tonebank[MAXBANK], *drumset[MAXBANK]; ToneBank *tonebank[MAXBANK], *drumset[MAXBANK];
static FString def_instr_name; static FString def_instr_name;
int openmode = OM_FILEORLUMP;
static int read_config_file(const char *name, bool ismain) static int read_config_file(const char *name, bool ismain)
{ {
@ -62,21 +61,21 @@ static int read_config_file(const char *name, bool ismain)
return (-1); return (-1);
} }
if (ismain) openmode = OM_FILEORLUMP; if (ismain) pathExpander.openmode = PathExpander::OM_FILEORLUMP;
if (!(fp = open_filereader(name, openmode, &lumpnum))) if (!(fp = pathExpander.openFileReader(name, &lumpnum)))
return -1; return -1;
if (ismain) if (ismain)
{ {
if (lumpnum > 0) if (lumpnum > 0)
{ {
openmode = OM_LUMP; pathExpander.openmode = PathExpander::OM_LUMP;
clear_pathlist(); // when reading from a PK3 we won't want to use any external path pathExpander.clearPathlist(); // when reading from a PK3 we don't want to use any external path
} }
else else
{ {
openmode = OM_FILE; pathExpander.openmode = PathExpander::OM_FILE;
} }
} }
@ -288,7 +287,7 @@ static int read_config_file(const char *name, bool ismain)
return -2; return -2;
} }
for (i = 1; i < words; i++) for (i = 1; i < words; i++)
add_to_pathlist(w[i]); pathExpander.addToPathlist(w[i]);
} }
else if (!strcmp(w[0], "source")) else if (!strcmp(w[0], "source"))
{ {
@ -377,7 +376,7 @@ static int read_config_file(const char *name, bool ismain)
delete fp; delete fp;
return -2; return -2;
} }
bank->tone[i].note = bank->tone[i].amp = bank->tone[i].pan = bank->tone[i].note = bank->tone[i].pan =
bank->tone[i].fontbank = bank->tone[i].fontpreset = bank->tone[i].fontbank = bank->tone[i].fontpreset =
bank->tone[i].fontnote = bank->tone[i].strip_loop = bank->tone[i].fontnote = bank->tone[i].strip_loop =
bank->tone[i].strip_envelope = bank->tone[i].strip_tail = -1; bank->tone[i].strip_envelope = bank->tone[i].strip_tail = -1;
@ -415,14 +414,7 @@ static int read_config_file(const char *name, bool ismain)
*cp++ = 0; *cp++ = 0;
if (!strcmp(w[j], "amp")) if (!strcmp(w[j], "amp"))
{ {
k = atoi(cp); /* Ignored */
if ((k < 0 || k > MAX_AMPLIFICATION) || (*cp < '0' || *cp > '9'))
{
Printf("%s: line %d: amplification must be between 0 and %d\n", name, line, MAX_AMPLIFICATION);
delete fp;
return -2;
}
bank->tone[i].amp = k;
} }
else if (!strcmp(w[j], "note")) else if (!strcmp(w[j], "note"))
{ {
@ -532,15 +524,15 @@ int LoadConfig(const char *filename)
* file itself since that file should contain any other directory * file itself since that file should contain any other directory
* that needs to be added to the search path. * that needs to be added to the search path.
*/ */
clear_pathlist(); pathExpander.clearPathlist();
#ifdef _WIN32 #ifdef _WIN32
add_to_pathlist("C:\\TIMIDITY"); pathExpander.addToPathlist("C:\\TIMIDITY");
add_to_pathlist("\\TIMIDITY"); pathExpander.addToPathlist("\\TIMIDITY");
add_to_pathlist(progdir); pathExpander.addToPathlist(progdir);
#else #else
add_to_pathlist("/usr/local/lib/timidity"); pathExpander.addToPathlist("/usr/local/lib/timidity");
add_to_pathlist("/etc/timidity"); pathExpander.addToPathlist("/etc/timidity");
add_to_pathlist("/etc"); pathExpander.addToPathlist("/etc");
#endif #endif
/* Some functions get aggravated if not even the standard banks are available. */ /* Some functions get aggravated if not even the standard banks are available. */
@ -579,10 +571,10 @@ int LoadDMXGUS()
if (ultradir.IsNotEmpty()) if (ultradir.IsNotEmpty())
{ {
ultradir += "/midi"; ultradir += "/midi";
add_to_pathlist(ultradir.GetChars()); pathExpander.addToPathlist(ultradir.GetChars());
} }
// Load DMXGUS lump and patches from gus_patchdir // Load DMXGUS lump and patches from gus_patchdir
add_to_pathlist(gus_patchdir); pathExpander.addToPathlist(gus_patchdir);
char readbuffer[1024]; char readbuffer[1024];
long size = data.GetLength(); long size = data.GetLength();
@ -676,7 +668,7 @@ int LoadDMXGUS()
continue; continue;
int val = k % 128; int val = k % 128;
bank->tone[val].note = bank->tone[val].amp = bank->tone[val].pan = bank->tone[val].note = bank->tone[val].pan =
bank->tone[val].fontbank = bank->tone[val].fontpreset = bank->tone[val].fontbank = bank->tone[val].fontpreset =
bank->tone[val].fontnote = bank->tone[val].strip_loop = bank->tone[val].fontnote = bank->tone[val].strip_loop =
bank->tone[val].strip_envelope = bank->tone[val].strip_tail = -1; bank->tone[val].strip_envelope = bank->tone[val].strip_tail = -1;

View file

@ -21,6 +21,7 @@
#define TIMIDITY_H #define TIMIDITY_H
#include "doomtype.h" #include "doomtype.h"
#include "pathexpander.h"
class FileReader; class FileReader;
@ -54,10 +55,6 @@ config.h
volume level of FMOD's built-in MIDI player. */ volume level of FMOD's built-in MIDI player. */
#define FINAL_MIX_SCALE 0.5 #define FINAL_MIX_SCALE 0.5
/* This value is used instead when midi_timiditylike is turned on,
because TiMidity++ is louder than a GUS. */
#define FINAL_MIX_TIMIDITY_SCALE 0.3
/* How many bits to use for the fractional part of sample positions. /* How many bits to use for the fractional part of sample positions.
This affects tonal accuracy. The entire position counter must fit This affects tonal accuracy. The entire position counter must fit
in 32 bits, so with FRACTION_BITS equal to 12, the maximum size of in 32 bits, so with FRACTION_BITS equal to 12, the maximum size of
@ -172,17 +169,8 @@ extern __inline__ double pow_x87_inline(double x,double y)
common.h common.h
*/ */
#define OM_FILEORLUMP 0
#define OM_LUMP 1
#define OM_FILE 2
extern void add_to_pathlist(const char *s);
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);
extern int openmode;
/* /*
controls.h controls.h
*/ */
@ -219,9 +207,6 @@ enum
PATCH_SUSTAIN = (1<<5), PATCH_SUSTAIN = (1<<5),
PATCH_NO_SRELEASE = (1<<6), PATCH_NO_SRELEASE = (1<<6),
PATCH_FAST_REL = (1<<7), PATCH_FAST_REL = (1<<7),
PATCH_T_NO_ENVELOPE = (1<<8),
PATCH_T_NO_LOOP = (1<<9)
}; };
struct Sample struct Sample
@ -247,8 +232,6 @@ struct Sample
short release_vol; short release_vol;
} sf2; } sf2;
} envelope; } envelope;
float
volume;
sample_t *data; sample_t *data;
SDWORD SDWORD
tremolo_sweep_increment, tremolo_phase_increment, tremolo_sweep_increment, tremolo_phase_increment,
@ -324,11 +307,12 @@ struct Instrument
struct ToneBankElement struct ToneBankElement
{ {
ToneBankElement() : ToneBankElement() :
note(0), amp(0), pan(0), strip_loop(0), strip_envelope(0), strip_tail(0) note(0), pan(0), strip_loop(0), strip_envelope(0), strip_tail(0)
{} {}
FString name; FString name;
int note, amp, pan, fontbank, fontpreset, fontnote, strip_loop, strip_envelope, strip_tail; int note, pan, fontbank, fontpreset, fontnote;
SBYTE strip_loop, strip_envelope, strip_tail;
}; };
/* A hack to delay instrument loading until after reading the entire MIDI file. */ /* A hack to delay instrument loading until after reading the entire MIDI file. */
@ -616,8 +600,6 @@ const double log_of_2 = 0.69314718055994529;
#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 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
#define timidityxx_perceived_vol(x) (pow((x), 1.66096404744))
/* /*
timidity.h timidity.h
@ -627,6 +609,7 @@ int LoadConfig(const char *filename);
int LoadDMXGUS(); int LoadDMXGUS();
extern int LoadConfig(); extern int LoadConfig();
extern void FreeAll(); extern void FreeAll();
extern PathExpander pathExpander;
extern ToneBank *tonebank[MAXBANK]; extern ToneBank *tonebank[MAXBANK];
extern ToneBank *drumset[MAXBANK]; extern ToneBank *drumset[MAXBANK];

View file

@ -38,18 +38,56 @@
#include "../files.h" #include "../files.h"
#include "wm_error.h" #include "wm_error.h"
#include "file_io.h" #include "file_io.h"
#include "pathexpander.h"
#include "cmdlib.h"
unsigned char *_WM_BufferFile(const char *filename, unsigned long int *size) static PathExpander wmPathExpander;
unsigned char *_WM_BufferFile(const char *filename, unsigned long int *size, bool ismain)
{ {
FileReader file; FileReader *fp;
int lumpnum;
if (!file.Open(filename)) if (ismain)
{
wmPathExpander.openmode = PathExpander::OM_FILEORLUMP;
wmPathExpander.clearPathlist();
#ifdef _WIN32
wmPathExpander.addToPathlist("C:\\TIMIDITY");
wmPathExpander.addToPathlist("\\TIMIDITY");
wmPathExpander.addToPathlist(progdir);
#else
wmPathExpander.addToPathlist("/usr/local/lib/timidity");
wmPathExpander.addToPathlist("/etc/timidity");
wmPathExpander.addToPathlist("/etc");
#endif
}
if (!(fp = wmPathExpander.openFileReader(filename, &lumpnum)))
return NULL;
if (ismain)
{
if (lumpnum > 0)
{
wmPathExpander.openmode = PathExpander::OM_LUMP;
wmPathExpander.clearPathlist(); // when reading from a PK3 we don't want to use any external path
}
else
{
wmPathExpander.openmode = PathExpander::OM_FILE;
}
}
if (fp == NULL)
{ {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, filename, errno); _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, filename, errno);
return NULL; return NULL;
} }
long fsize = file.GetLength(); long fsize = fp->GetLength();
if (fsize > WM_MAXFILESIZE) if (fsize > WM_MAXFILESIZE)
{ {
@ -66,7 +104,8 @@ unsigned char *_WM_BufferFile(const char *filename, unsigned long int *size)
return NULL; return NULL;
} }
file.Read(data, fsize); fp->Read(data, fsize);
delete fp;
data[fsize] = 0; data[fsize] = 0;
*size = fsize; *size = fsize;
return data; return data;

View file

@ -28,6 +28,6 @@
#define __FILE_IO_H #define __FILE_IO_H
#define WM_MAXFILESIZE 0x1fffffff #define WM_MAXFILESIZE 0x1fffffff
extern unsigned char *_WM_BufferFile (const char *filename, unsigned long int *size); extern unsigned char *_WM_BufferFile (const char *filename, unsigned long int *size, bool mainfile = false);
#endif /* __FILE_IO_H */ #endif /* __FILE_IO_H */

View file

@ -1,86 +0,0 @@
/*
lock.c - data locking code for lib
Copyright (C) Chris Ison 2001-2011
Copyright (C) Bret Curtis 2013-2014
This file is part of WildMIDI.
WildMIDI is free software: you can redistribute and/or modify the player
under the terms of the GNU General Public License and you can redistribute
and/or modify the library under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation, either version 3 of
the licenses, or(at your option) any later version.
WildMIDI is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License and
the GNU Lesser General Public License for more details.
You should have received a copy of the GNU General Public License and the
GNU Lesser General Public License along with WildMIDI. If not, see
<http://www.gnu.org/licenses/>.
*/
//#include "config.h"
#ifndef __DJGPP__
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
#include "lock.h"
#include "common.h"
/*
_WM_Lock(wmlock)
wmlock = a pointer to a value
returns nothing
Attempts to set a lock on the MDI tree so that
only 1 library command may access it at any time.
If lock fails the process retries until successful.
*/
void _WM_Lock(int * wmlock) {
LOCK_START:
/* Check if lock is clear, if so set it */
if (*wmlock == 0) {
(*wmlock)++;
/* Now that the lock is set, make sure we
* don't have a race condition. If so,
* decrement the lock by one and retry. */
if (*wmlock == 1) {
return; /* Lock cleanly set */
}
(*wmlock)--;
}
#ifdef _WIN32
Sleep(10);
#else
usleep(500);
#endif
goto LOCK_START;
}
/*
_WM_Unlock(wmlock)
wmlock = a pointer to a value
returns nothing
Removes a lock previously placed on the MDI tree.
*/
void _WM_Unlock(int *wmlock) {
/* We don't want a -1 lock, so just to make sure */
if ((*wmlock) != 0) {
(*wmlock)--;
}
}
#endif /* __DJGPP__ */

View file

@ -1,36 +0,0 @@
/*
lock.h - data locking code for lib
Copyright (C) Chris Ison 2001-2011
Copyright (C) Bret Curtis 2013-2014
This file is part of WildMIDI.
WildMIDI is free software: you can redistribute and/or modify the player
under the terms of the GNU General Public License and you can redistribute
and/or modify the library under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation, either version 3 of
the licenses, or(at your option) any later version.
WildMIDI is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License and
the GNU Lesser General Public License for more details.
You should have received a copy of the GNU General Public License and the
GNU Lesser General Public License along with WildMIDI. If not, see
<http://www.gnu.org/licenses/>.
*/
#ifndef __LOCK_H
#define __LOCK_H
extern void _WM_Lock (int * wmlock);
extern void _WM_Unlock (int *wmlock);
#ifdef __DJGPP__
#define _WM_Lock(p) do {} while (0)
#define _WM_Unlock(p) do {} while (0)
#endif
#endif /* __LOCK_H */

File diff suppressed because it is too large Load diff

View file

@ -56,12 +56,7 @@ typedef void midi;
WM_SYMBOL const char * WildMidi_GetString (unsigned short int info); WM_SYMBOL const char * WildMidi_GetString (unsigned short int info);
WM_SYMBOL int WildMidi_Init (const char * config_file, unsigned short int rate, unsigned short int options); WM_SYMBOL int WildMidi_Init (const char * config_file, unsigned short int rate, unsigned short int options);
WM_SYMBOL int WildMidi_MasterVolume (unsigned char master_volume); WM_SYMBOL int WildMidi_MasterVolume (unsigned char master_volume);
WM_SYMBOL midi * WildMidi_Open (const char *midifile);
WM_SYMBOL midi * WildMidi_OpenBuffer (unsigned char *midibuffer, unsigned long int size);
WM_SYMBOL int WildMidi_GetOutput (midi * handle, char * buffer, unsigned long int size);
WM_SYMBOL int WildMidi_SetOption (midi * handle, unsigned short int options, unsigned short int setting); WM_SYMBOL int WildMidi_SetOption (midi * handle, unsigned short int options, unsigned short int setting);
WM_SYMBOL struct _WM_Info * WildMidi_GetInfo (midi * handle);
WM_SYMBOL int WildMidi_FastSeek (midi * handle, unsigned long int *sample_pos);
WM_SYMBOL int WildMidi_Close (midi * handle); WM_SYMBOL int WildMidi_Close (midi * handle);
WM_SYMBOL int WildMidi_Shutdown (void); WM_SYMBOL int WildMidi_Shutdown (void);
WM_SYMBOL int WildMidi_GetSampleRate (void); WM_SYMBOL int WildMidi_GetSampleRate (void);
@ -79,10 +74,11 @@ public:
~WildMidi_Renderer(); ~WildMidi_Renderer();
void ShortEvent(int status, int parm1, int parm2); void ShortEvent(int status, int parm1, int parm2);
void LongEvent(const char *data, int len); void LongEvent(const unsigned char *data, int len);
void ComputeOutput(float *buffer, int len); void ComputeOutput(float *buffer, int len);
void LoadInstrument(int bank, int percussion, int instr); void LoadInstrument(int bank, int percussion, int instr);
int GetVoiceCount(); int GetVoiceCount();
void SetOption(int opt, int set);
private: private:
void *handle; void *handle;
}; };

View file

@ -1604,7 +1604,6 @@ OptionMenu AdvSoundOptions
StaticText "GUS Emulation", 1 StaticText "GUS Emulation", 1
TextField "GUS config file", "midi_config" TextField "GUS config file", "midi_config"
Slider "MIDI voices", "midi_voices", 16, 256, 4, 0 Slider "MIDI voices", "midi_voices", 16, 256, 4, 0
Option "Emulate TiMidity", "midi_timiditylike", "OnOff"
Option "Read DMXGUS lumps", "midi_dmxgus", "OnOff" Option "Read DMXGUS lumps", "midi_dmxgus", "OnOff"
Option "GUS memory size", "gus_memsize", "GusMemory" Option "GUS memory size", "gus_memsize", "GusMemory"
StaticText " " StaticText " "
@ -1620,6 +1619,10 @@ OptionMenu AdvSoundOptions
Option "Reverb", "timidity_reverb", "OnOff" Option "Reverb", "timidity_reverb", "OnOff"
Option "Chorus", "timidity_chorus", "OnOff" Option "Chorus", "timidity_chorus", "OnOff"
Slider "Relative volume", "timidity_mastervolume", 0, 4, 0.2, 1 Slider "Relative volume", "timidity_mastervolume", 0, 4, 0.2, 1
StaticText " "
StaticText "WildMidi", 1
TextField "WildMidi config file", "wildmidi_config"
Option "Reverb", "wildmidi_reverb", "OnOff"
} }
/*======================================= /*=======================================

View file

@ -942,6 +942,10 @@
RelativePath=".\src\parsecontext.cpp" RelativePath=".\src\parsecontext.cpp"
> >
</File> </File>
<File
RelativePath=".\src\pathexpander.cpp"
>
</File>
<File <File
RelativePath=".\src\po_man.cpp" RelativePath=".\src\po_man.cpp"
> >
@ -1479,6 +1483,10 @@
RelativePath=".\src\parsecontext.h" RelativePath=".\src\parsecontext.h"
> >
</File> </File>
<File
RelativePath=".\src\pathexpander.h"
>
</File>
<File <File
RelativePath=".\src\po_man.h" RelativePath=".\src\po_man.h"
> >
@ -2811,10 +2819,6 @@
RelativePath=".\src\wildmidi\gus_pat.h" RelativePath=".\src\wildmidi\gus_pat.h"
> >
</File> </File>
<File
RelativePath=".\src\wildmidi\lock.h"
>
</File>
<File <File
RelativePath=".\src\wildmidi\reverb.h" RelativePath=".\src\wildmidi\reverb.h"
> >
@ -2839,10 +2843,6 @@
RelativePath=".\src\wildmidi\gus_pat.cpp" RelativePath=".\src\wildmidi\gus_pat.cpp"
> >
</File> </File>
<File
RelativePath=".\src\wildmidi\lock.cpp"
>
</File>
<File <File
RelativePath=".\src\wildmidi\reverb.cpp" RelativePath=".\src\wildmidi\reverb.cpp"
> >