mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-29 07:22:05 +00:00
Merge branch 'master' of https://github.com/rheit/zdoom
This commit is contained in:
commit
b27116cbbd
25 changed files with 6477 additions and 8 deletions
|
@ -188,6 +188,7 @@ else( WIN32 )
|
||||||
if( GTK2_FOUND )
|
if( GTK2_FOUND )
|
||||||
set( ZDOOM_LIBS ${ZDOOM_LIBS} ${GTK2_LIBRARIES} )
|
set( ZDOOM_LIBS ${ZDOOM_LIBS} ${GTK2_LIBRARIES} )
|
||||||
include_directories( ${GTK2_INCLUDE_DIRS} )
|
include_directories( ${GTK2_INCLUDE_DIRS} )
|
||||||
|
link_directories( ${GTK2_LIBRARY_DIRS} )
|
||||||
else( GTK2_FOUND )
|
else( GTK2_FOUND )
|
||||||
set( NO_GTK ON )
|
set( NO_GTK ON )
|
||||||
endif( GTK2_FOUND )
|
endif( GTK2_FOUND )
|
||||||
|
@ -1174,6 +1175,7 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE
|
||||||
sound/music_midistream.cpp
|
sound/music_midistream.cpp
|
||||||
sound/music_midi_base.cpp
|
sound/music_midi_base.cpp
|
||||||
sound/music_midi_timidity.cpp
|
sound/music_midi_timidity.cpp
|
||||||
|
sound/music_midi_wildmidi.cpp
|
||||||
sound/music_mus_opl.cpp
|
sound/music_mus_opl.cpp
|
||||||
sound/music_stream.cpp
|
sound/music_stream.cpp
|
||||||
sound/music_fluidsynth_mididevice.cpp
|
sound/music_fluidsynth_mididevice.cpp
|
||||||
|
@ -1222,6 +1224,12 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE
|
||||||
timidity/playmidi.cpp
|
timidity/playmidi.cpp
|
||||||
timidity/resample.cpp
|
timidity/resample.cpp
|
||||||
timidity/timidity.cpp
|
timidity/timidity.cpp
|
||||||
|
wildmidi/file_io.cpp
|
||||||
|
wildmidi/gus_pat.cpp
|
||||||
|
wildmidi/lock.cpp
|
||||||
|
wildmidi/reverb.cpp
|
||||||
|
wildmidi/wildmidi_lib.cpp
|
||||||
|
wildmidi/wm_error.cpp
|
||||||
xlat/parse_xlat.cpp
|
xlat/parse_xlat.cpp
|
||||||
fragglescript/t_fspic.cpp
|
fragglescript/t_fspic.cpp
|
||||||
fragglescript/t_func.cpp
|
fragglescript/t_func.cpp
|
||||||
|
@ -1359,6 +1367,8 @@ source_group("Audio Files\\OPL Synth" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURC
|
||||||
source_group("Audio Files\\OPL Synth\\DOSBox" FILES oplsynth/dosbox/opl.cpp oplsynth/dosbox/opl.h)
|
source_group("Audio Files\\OPL Synth\\DOSBox" FILES oplsynth/dosbox/opl.cpp oplsynth/dosbox/opl.h)
|
||||||
source_group("Audio Files\\Timidity\\Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/timidity/.+\\.h$")
|
source_group("Audio Files\\Timidity\\Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/timidity/.+\\.h$")
|
||||||
source_group("Audio Files\\Timidity\\Source" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/timidity/.+\\.cpp$")
|
source_group("Audio Files\\Timidity\\Source" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/timidity/.+\\.cpp$")
|
||||||
|
source_group("Audio Files\\WildMidi\\Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/wildmidi/.+\\.h$")
|
||||||
|
source_group("Audio Files\\WildMidi\\Source" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/wildmidi/.+\\.cpp$")
|
||||||
source_group("Decorate++" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/thingdef/.+")
|
source_group("Decorate++" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/thingdef/.+")
|
||||||
source_group("FraggleScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/fragglescript/.+")
|
source_group("FraggleScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/fragglescript/.+")
|
||||||
source_group("Games\\Doom Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_doom/.+")
|
source_group("Games\\Doom Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_doom/.+")
|
||||||
|
|
|
@ -1347,9 +1347,10 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply
|
||||||
int rootnode = npc->ConversationRoot;
|
int rootnode = npc->ConversationRoot;
|
||||||
if (reply->NextNode < 0)
|
if (reply->NextNode < 0)
|
||||||
{
|
{
|
||||||
npc->Conversation = StrifeDialogues[rootnode - reply->NextNode - 1];
|
unsigned next = (unsigned)(rootnode - reply->NextNode - 1);
|
||||||
if (gameaction != ga_slideshow)
|
if (gameaction != ga_slideshow && next < StrifeDialogues.Size())
|
||||||
{
|
{
|
||||||
|
npc->Conversation = StrifeDialogues[next];
|
||||||
P_StartConversation (npc, player->mo, player->ConversationFaceTalker, false);
|
P_StartConversation (npc, player->mo, player->ConversationFaceTalker, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -566,6 +566,10 @@ void APlayerPawn::Serialize (FArchive &arc)
|
||||||
{
|
{
|
||||||
arc << AirCapacity;
|
arc << AirCapacity;
|
||||||
}
|
}
|
||||||
|
if (SaveVersion >= 4526)
|
||||||
|
{
|
||||||
|
arc << ViewHeight;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
|
@ -1372,6 +1372,7 @@ static void S_AddSNDINFO (int lump)
|
||||||
else if (sc.Compare("default")) MidiDevices[nm] = MDEV_DEFAULT;
|
else if (sc.Compare("default")) MidiDevices[nm] = MDEV_DEFAULT;
|
||||||
else if (sc.Compare("fluidsynth")) MidiDevices[nm] = MDEV_FLUIDSYNTH;
|
else if (sc.Compare("fluidsynth")) MidiDevices[nm] = MDEV_FLUIDSYNTH;
|
||||||
else if (sc.Compare("gus")) MidiDevices[nm] = MDEV_GUS;
|
else if (sc.Compare("gus")) MidiDevices[nm] = MDEV_GUS;
|
||||||
|
else if (sc.Compare("wildmidi")) MidiDevices[nm] = MDEV_WILDMIDI;
|
||||||
else sc.ScriptError("Unknown MIDI device %s\n", sc.String);
|
else sc.ScriptError("Unknown MIDI device %s\n", sc.String);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -394,6 +394,7 @@ enum EMidiDevice
|
||||||
MDEV_TIMIDITY = 3,
|
MDEV_TIMIDITY = 3,
|
||||||
MDEV_FLUIDSYNTH = 4,
|
MDEV_FLUIDSYNTH = 4,
|
||||||
MDEV_GUS = 5,
|
MDEV_GUS = 5,
|
||||||
|
MDEV_WILDMIDI = 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef TMap<FName, FName> MusicAliasMap;
|
typedef TMap<FName, FName> MusicAliasMap;
|
||||||
|
|
|
@ -189,6 +189,7 @@ void I_ShutdownMusic(void)
|
||||||
assert (currSong == NULL);
|
assert (currSong == NULL);
|
||||||
}
|
}
|
||||||
Timidity::FreeAll();
|
Timidity::FreeAll();
|
||||||
|
WildMidi_Shutdown();
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
I_ShutdownMusicWin32();
|
I_ShutdownMusicWin32();
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "i_music.h"
|
#include "i_music.h"
|
||||||
#include "s_sound.h"
|
#include "s_sound.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
|
#include "wildmidi/wildmidi_lib.h"
|
||||||
|
|
||||||
void I_InitMusicWin32 ();
|
void I_InitMusicWin32 ();
|
||||||
void I_ShutdownMusicWin32 ();
|
void I_ShutdownMusicWin32 ();
|
||||||
|
@ -218,6 +219,24 @@ protected:
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class WildMidiMIDIDevice : public PseudoMIDIDevice
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WildMidiMIDIDevice();
|
||||||
|
~WildMidiMIDIDevice();
|
||||||
|
|
||||||
|
int Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata);
|
||||||
|
bool Preprocess(MIDIStreamer *song, bool looping);
|
||||||
|
bool IsOpen() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
midi *mMidi;
|
||||||
|
bool mLoop;
|
||||||
|
|
||||||
|
static bool FillStream(SoundStream *stream, void *buff, int len, void *userdata);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Base class for software synthesizer MIDI output devices ------------------
|
// Base class for software synthesizer MIDI output devices ------------------
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,9 @@ static DWORD nummididevices;
|
||||||
static bool nummididevicesset;
|
static bool nummididevicesset;
|
||||||
|
|
||||||
#ifdef HAVE_FLUIDSYNTH
|
#ifdef HAVE_FLUIDSYNTH
|
||||||
#define NUM_DEF_DEVICES 5
|
#define NUM_DEF_DEVICES 6
|
||||||
#else
|
#else
|
||||||
#define NUM_DEF_DEVICES 4
|
#define NUM_DEF_DEVICES 5
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void AddDefaultMidiDevices(FOptionValues *opt)
|
static void AddDefaultMidiDevices(FOptionValues *opt)
|
||||||
|
@ -33,8 +33,10 @@ static void AddDefaultMidiDevices(FOptionValues *opt)
|
||||||
pair[p+1].Value = -3.0;
|
pair[p+1].Value = -3.0;
|
||||||
pair[p+2].Text = "TiMidity++";
|
pair[p+2].Text = "TiMidity++";
|
||||||
pair[p+2].Value = -2.0;
|
pair[p+2].Value = -2.0;
|
||||||
pair[p+3].Text = "Sound System";
|
pair[p+3].Text = "WildMidi";
|
||||||
pair[p+3].Value = -1.0;
|
pair[p+3].Value = -6.0;
|
||||||
|
pair[p+4].Text = "Sound System";
|
||||||
|
pair[p+4].Value = -1.0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +72,7 @@ CUSTOM_CVAR (Int, snd_mididevice, -1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
if (!nummididevicesset)
|
if (!nummididevicesset)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((self >= (signed)nummididevices) || (self < -5))
|
if ((self >= (signed)nummididevices) || (self < -6))
|
||||||
{
|
{
|
||||||
Printf ("ID out of range. Using default device.\n");
|
Printf ("ID out of range. Using default device.\n");
|
||||||
self = 0;
|
self = 0;
|
||||||
|
@ -211,6 +213,7 @@ void I_BuildMIDIMenuList (FOptionValues *opt)
|
||||||
|
|
||||||
CCMD (snd_listmididevices)
|
CCMD (snd_listmididevices)
|
||||||
{
|
{
|
||||||
|
Printf("%s-6. WildMidi\n", -6 == snd_mididevice ? TEXTCOLOR_BOLD : "");
|
||||||
#ifdef HAVE_FLUIDSYNTH
|
#ifdef HAVE_FLUIDSYNTH
|
||||||
Printf("%s-5. FluidSynth\n", -5 == snd_mididevice ? TEXTCOLOR_BOLD : "");
|
Printf("%s-5. FluidSynth\n", -5 == snd_mididevice ? TEXTCOLOR_BOLD : "");
|
||||||
#endif
|
#endif
|
||||||
|
|
163
src/sound/music_midi_wildmidi.cpp
Normal file
163
src/sound/music_midi_wildmidi.cpp
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
#include "i_musicinterns.h"
|
||||||
|
#include "c_cvars.h"
|
||||||
|
#include "cmdlib.h"
|
||||||
|
#include "templates.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
|
||||||
|
CVAR(String, wildmidi_config, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
|
|
||||||
|
static FString currentConfig;
|
||||||
|
|
||||||
|
// added because Timidity's output is rather loud.
|
||||||
|
CUSTOM_CVAR (Float, wildmidi_mastervolume, 1.0f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
|
{
|
||||||
|
if (self < 0.f)
|
||||||
|
self = 0.f;
|
||||||
|
else if (self > 1.f)
|
||||||
|
self = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR (Int, wildmidi_frequency, 44100, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
|
{ // Clamp frequency to Timidity's limits
|
||||||
|
if (self < 11000)
|
||||||
|
self = 11000;
|
||||||
|
else if (self > 65000)
|
||||||
|
self = 65000;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// WildMidiMIDIDevice Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
WildMidiMIDIDevice::WildMidiMIDIDevice()
|
||||||
|
{
|
||||||
|
mMidi = NULL;
|
||||||
|
mLoop = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// WildMidiMIDIDevice Destructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
WildMidiMIDIDevice::~WildMidiMIDIDevice ()
|
||||||
|
{
|
||||||
|
if (mMidi != NULL) WildMidi_Close(mMidi);
|
||||||
|
// do not shut down the device so that it can be reused for the next song being played.
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// WildMidiMIDIDevice :: Preprocess
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool WildMidiMIDIDevice::Preprocess(MIDIStreamer *song, bool looping)
|
||||||
|
{
|
||||||
|
TArray<BYTE> midi;
|
||||||
|
|
||||||
|
// Write MIDI song to temporary file
|
||||||
|
song->CreateSMF(midi, looping ? 0 : 1);
|
||||||
|
|
||||||
|
mMidi = WildMidi_OpenBuffer(&midi[0], midi.Size());
|
||||||
|
if (mMidi == NULL)
|
||||||
|
{
|
||||||
|
Printf(PRINT_BOLD, "Could not open temp music file\n");
|
||||||
|
}
|
||||||
|
mLoop = looping;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// WildMidiMIDIDevice :: Open
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
int WildMidiMIDIDevice::Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata)
|
||||||
|
{
|
||||||
|
if (currentConfig.CompareNoCase(wildmidi_config) != 0)
|
||||||
|
{
|
||||||
|
if (currentConfig.IsNotEmpty()) WildMidi_Shutdown();
|
||||||
|
currentConfig = "";
|
||||||
|
if (!WildMidi_Init(wildmidi_config, wildmidi_frequency, WM_MO_ENHANCED_RESAMPLING))
|
||||||
|
{
|
||||||
|
currentConfig = wildmidi_config;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream = GSnd->CreateStream(FillStream, 32 * 1024, 0, wildmidi_frequency, this);
|
||||||
|
if (Stream == NULL)
|
||||||
|
{
|
||||||
|
Printf(PRINT_BOLD, "Could not create music stream.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// WildMidiMIDIDevice :: FillStream
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool WildMidiMIDIDevice::FillStream(SoundStream *stream, void *buff, int len, void *userdata)
|
||||||
|
{
|
||||||
|
char *buffer = (char*)buff;
|
||||||
|
WildMidiMIDIDevice *song = (WildMidiMIDIDevice *)userdata;
|
||||||
|
if (song->mMidi != NULL)
|
||||||
|
{
|
||||||
|
while (len > 0)
|
||||||
|
{
|
||||||
|
int written = WildMidi_GetOutput(song->mMidi, buffer, len);
|
||||||
|
if (written < 0)
|
||||||
|
{
|
||||||
|
// error
|
||||||
|
memset(buffer, 0, len);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
buffer += written;
|
||||||
|
len -= written;
|
||||||
|
|
||||||
|
if (len > 0)
|
||||||
|
{
|
||||||
|
if (!song->mLoop)
|
||||||
|
{
|
||||||
|
memset(buffer, 0, len);
|
||||||
|
return written > 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// loop the sound (i.e. go back to start.)
|
||||||
|
unsigned long spos = 0;
|
||||||
|
WildMidi_FastSeek(song->mMidi, &spos);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// WildMidiMIDIDevice :: IsOpen
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool WildMidiMIDIDevice::IsOpen() const
|
||||||
|
{
|
||||||
|
return mMidi != NULL;
|
||||||
|
}
|
||||||
|
|
|
@ -240,6 +240,7 @@ EMidiDevice MIDIStreamer::SelectMIDIDevice(EMidiDevice device)
|
||||||
#ifdef HAVE_FLUIDSYNTH
|
#ifdef HAVE_FLUIDSYNTH
|
||||||
case -5: return MDEV_FLUIDSYNTH;
|
case -5: return MDEV_FLUIDSYNTH;
|
||||||
#endif
|
#endif
|
||||||
|
case -6: return MDEV_WILDMIDI;
|
||||||
default:
|
default:
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return MDEV_MMAPI;
|
return MDEV_MMAPI;
|
||||||
|
@ -292,6 +293,9 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype) const
|
||||||
case MDEV_TIMIDITY:
|
case MDEV_TIMIDITY:
|
||||||
return new TimidityPPMIDIDevice;
|
return new TimidityPPMIDIDevice;
|
||||||
|
|
||||||
|
case MDEV_WILDMIDI:
|
||||||
|
return new WildMidiMIDIDevice;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ const char *GetVersionString();
|
||||||
|
|
||||||
// Use 4500 as the base git save version, since it's higher than the
|
// Use 4500 as the base git save version, since it's higher than the
|
||||||
// SVN revision ever got.
|
// SVN revision ever got.
|
||||||
#define SAVEVER 4525
|
#define SAVEVER 4526
|
||||||
|
|
||||||
#define SAVEVERSTRINGIFY2(x) #x
|
#define SAVEVERSTRINGIFY2(x) #x
|
||||||
#define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)
|
#define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)
|
||||||
|
|
94
src/wildmidi/common.h
Normal file
94
src/wildmidi/common.h
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
common.h
|
||||||
|
|
||||||
|
Midi Wavetable Processing library
|
||||||
|
|
||||||
|
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 __COMMON_H
|
||||||
|
#define __COMMON_H
|
||||||
|
|
||||||
|
#define SAMPLE_16BIT 0x01
|
||||||
|
#define SAMPLE_UNSIGNED 0x02
|
||||||
|
#define SAMPLE_LOOP 0x04
|
||||||
|
#define SAMPLE_PINGPONG 0x08
|
||||||
|
#define SAMPLE_REVERSE 0x10
|
||||||
|
#define SAMPLE_SUSTAIN 0x20
|
||||||
|
#define SAMPLE_ENVELOPE 0x40
|
||||||
|
#define SAMPLE_CLAMPED 0x80
|
||||||
|
|
||||||
|
#ifdef DEBUG_SAMPLES
|
||||||
|
#define SAMPLE_CONVERT_DEBUG(dx) printf("\r%s\n",dx)
|
||||||
|
#else
|
||||||
|
#define SAMPLE_CONVERT_DEBUG(dx)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern unsigned short int _WM_SampleRate;
|
||||||
|
|
||||||
|
struct _sample {
|
||||||
|
unsigned long int data_length;
|
||||||
|
unsigned long int loop_start;
|
||||||
|
unsigned long int loop_end;
|
||||||
|
unsigned long int loop_size;
|
||||||
|
unsigned char loop_fraction;
|
||||||
|
unsigned short int rate;
|
||||||
|
unsigned long int freq_low;
|
||||||
|
unsigned long int freq_high;
|
||||||
|
unsigned long int freq_root;
|
||||||
|
unsigned char modes;
|
||||||
|
signed long int env_rate[7];
|
||||||
|
signed long int env_target[7];
|
||||||
|
unsigned long int inc_div;
|
||||||
|
signed short *data;
|
||||||
|
struct _sample *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _env {
|
||||||
|
float time;
|
||||||
|
float level;
|
||||||
|
unsigned char set;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _patch {
|
||||||
|
unsigned short patchid;
|
||||||
|
unsigned char loaded;
|
||||||
|
char *filename;
|
||||||
|
signed short int amp;
|
||||||
|
unsigned char keep;
|
||||||
|
unsigned char remove;
|
||||||
|
struct _env env[6];
|
||||||
|
unsigned char note;
|
||||||
|
unsigned long int inuse_count;
|
||||||
|
struct _sample *first_sample;
|
||||||
|
struct _patch *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Set our global defines here */
|
||||||
|
#ifndef M_PI
|
||||||
|
#define M_PI 3.14159265358979323846
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_LN2
|
||||||
|
#define M_LN2 0.69314718055994530942
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __COMMON_H */
|
71
src/wildmidi/file_io.cpp
Normal file
71
src/wildmidi/file_io.cpp
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
** file_io.cpp
|
||||||
|
** ZDoom compatible file IO interface for WildMIDI
|
||||||
|
** (This file was completely redone to remove the low level IO code references)
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2010 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 "../files.h"
|
||||||
|
#include "wm_error.h"
|
||||||
|
#include "file_io.h"
|
||||||
|
|
||||||
|
unsigned char *_WM_BufferFile(const char *filename, unsigned long int *size)
|
||||||
|
{
|
||||||
|
FileReader file;
|
||||||
|
|
||||||
|
if (!file.Open(filename))
|
||||||
|
{
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, filename, errno);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
long fsize = file.GetLength();
|
||||||
|
|
||||||
|
if (fsize > WM_MAXFILESIZE)
|
||||||
|
{
|
||||||
|
/* don't bother loading suspiciously long files */
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LONGFIL, filename, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *data = (unsigned char*)malloc(fsize+1);
|
||||||
|
if (data == NULL)
|
||||||
|
{
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, NULL, errno);
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, filename, errno);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.Read(data, fsize);
|
||||||
|
data[fsize] = 0;
|
||||||
|
*size = fsize;
|
||||||
|
return data;
|
||||||
|
}
|
33
src/wildmidi/file_io.h
Normal file
33
src/wildmidi/file_io.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
file_io.c
|
||||||
|
|
||||||
|
file handling
|
||||||
|
|
||||||
|
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 __FILE_IO_H
|
||||||
|
#define __FILE_IO_H
|
||||||
|
|
||||||
|
#define WM_MAXFILESIZE 0x1fffffff
|
||||||
|
extern unsigned char *_WM_BufferFile (const char *filename, unsigned long int *size);
|
||||||
|
|
||||||
|
#endif /* __FILE_IO_H */
|
900
src/wildmidi/gus_pat.cpp
Normal file
900
src/wildmidi/gus_pat.cpp
Normal file
|
@ -0,0 +1,900 @@
|
||||||
|
/*
|
||||||
|
gus_pat.c
|
||||||
|
|
||||||
|
Midi Wavetable Processing library
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "gus_pat.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "wm_error.h"
|
||||||
|
#include "file_io.h"
|
||||||
|
|
||||||
|
#ifdef DEBUG_GUSPAT
|
||||||
|
#define GUSPAT_FILENAME_DEBUG(dx) fprintf(stderr,"\r%s\n",dx)
|
||||||
|
|
||||||
|
#define GUSPAT_INT_DEBUG(dx,dy) fprintf(stderr,"\r%s: %i\n",dx,dy)
|
||||||
|
#define GUSPAT_FLOAT_DEBUG(dx,dy) fprintf(stderr,"\r%s: %f\n",dx,dy)
|
||||||
|
#define GUSPAT_START_DEBUG() fprintf(stderr,"\r")
|
||||||
|
#define GUSPAT_MODE_DEBUG(dx,dy,dz) if (dx & dy) fprintf(stderr,"%s",dz)
|
||||||
|
#define GUSPAT_END_DEBUG() fprintf(stderr,"\n")
|
||||||
|
#else
|
||||||
|
#define GUSPAT_FILENAME_DEBUG(dx)
|
||||||
|
#define GUSPAT_INT_DEBUG(dx,dy)
|
||||||
|
#define GUSPAT_FLOAT_DEBUG(dx,dy)
|
||||||
|
#define GUSPAT_START_DEBUG()
|
||||||
|
#define GUSPAT_MODE_DEBUG(dx,dy,dz)
|
||||||
|
#define GUSPAT_END_DEBUG()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sample data conversion functions
|
||||||
|
* convert data to signed shorts
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* 8bit signed */
|
||||||
|
static int convert_8s(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->data_length;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc((gus_sample->data_length + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data++ = (*read_data++) << 8;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_WM_ERROR_NEW("(%s:%i) ERROR: calloc failed (%s)", __FUNCTION__, __LINE__,
|
||||||
|
strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 8bit signed ping pong */
|
||||||
|
static int convert_8sp(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned long int loop_length = gus_sample->loop_end
|
||||||
|
- gus_sample->loop_start;
|
||||||
|
unsigned long int dloop_length = loop_length * 2;
|
||||||
|
unsigned long int new_length = gus_sample->data_length + dloop_length;
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->loop_start;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
signed short int *write_data_a = NULL;
|
||||||
|
signed short int *write_data_b = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc((new_length + 2), sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data++ = (*read_data++) << 8;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
|
||||||
|
*write_data = (*read_data++ << 8);
|
||||||
|
write_data_a = write_data + dloop_length;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
write_data++;
|
||||||
|
write_data_b = write_data + dloop_length;
|
||||||
|
read_end = data + gus_sample->loop_end;
|
||||||
|
do {
|
||||||
|
*write_data = (*read_data++) << 8;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
write_data++;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
|
||||||
|
*write_data = (*read_data++ << 8);
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
read_end = data + gus_sample->data_length;
|
||||||
|
if (read_data != read_end) {
|
||||||
|
do {
|
||||||
|
*write_data_b++ = (*read_data++) << 8;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
}
|
||||||
|
gus_sample->loop_start += loop_length;
|
||||||
|
gus_sample->loop_end += dloop_length;
|
||||||
|
gus_sample->data_length = new_length;
|
||||||
|
gus_sample->modes ^= SAMPLE_PINGPONG;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 8bit signed reverse */
|
||||||
|
static int convert_8sr(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->data_length;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
unsigned long int tmp_loop = 0;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc((gus_sample->data_length + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data + gus_sample->data_length - 1;
|
||||||
|
do {
|
||||||
|
*write_data-- = (*read_data++) << 8;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
tmp_loop = gus_sample->loop_end;
|
||||||
|
gus_sample->loop_end = gus_sample->data_length - gus_sample->loop_start;
|
||||||
|
gus_sample->loop_start = gus_sample->data_length - tmp_loop;
|
||||||
|
gus_sample->loop_fraction = ((gus_sample->loop_fraction & 0x0f) << 4)
|
||||||
|
| ((gus_sample->loop_fraction & 0xf0) >> 4);
|
||||||
|
gus_sample->modes ^= SAMPLE_REVERSE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 8bit signed reverse ping pong */
|
||||||
|
static int convert_8srp(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned long int loop_length = gus_sample->loop_end
|
||||||
|
- gus_sample->loop_start;
|
||||||
|
unsigned long int dloop_length = loop_length * 2;
|
||||||
|
unsigned long int new_length = gus_sample->data_length + dloop_length;
|
||||||
|
unsigned char *read_data = data + gus_sample->data_length - 1;
|
||||||
|
unsigned char *read_end = data + gus_sample->loop_end;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
signed short int *write_data_a = NULL;
|
||||||
|
signed short int *write_data_b = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc((new_length + 2), sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data++ = (*read_data--) << 8;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
|
||||||
|
*write_data = (*read_data-- << 8);
|
||||||
|
write_data_a = write_data + dloop_length;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
write_data++;
|
||||||
|
write_data_b = write_data + dloop_length;
|
||||||
|
read_end = data + gus_sample->loop_start;
|
||||||
|
do {
|
||||||
|
*write_data = (*read_data--) << 8;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
write_data++;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
|
||||||
|
*write_data = (*read_data-- << 8);
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
read_end = data - 1;
|
||||||
|
do {
|
||||||
|
*write_data_b++ = (*read_data--) << 8;
|
||||||
|
write_data_b++;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
gus_sample->loop_start += loop_length;
|
||||||
|
gus_sample->loop_end += dloop_length;
|
||||||
|
gus_sample->data_length = new_length;
|
||||||
|
gus_sample->modes ^= SAMPLE_PINGPONG | SAMPLE_REVERSE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 8bit unsigned */
|
||||||
|
static int convert_8u(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->data_length;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc((gus_sample->data_length + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data++ = ((*read_data++) ^ 0x80) << 8;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
gus_sample->modes ^= SAMPLE_UNSIGNED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 8bit unsigned ping pong */
|
||||||
|
static int convert_8up(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned long int loop_length = gus_sample->loop_end
|
||||||
|
- gus_sample->loop_start;
|
||||||
|
unsigned long int dloop_length = loop_length * 2;
|
||||||
|
unsigned long int new_length = gus_sample->data_length + dloop_length;
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->loop_start;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
signed short int *write_data_a = NULL;
|
||||||
|
signed short int *write_data_b = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc((new_length + 2), sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data++ = ((*read_data++) ^ 0x80) << 8;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
|
||||||
|
*write_data = ((*read_data++) ^ 0x80) << 8;
|
||||||
|
write_data_a = write_data + dloop_length;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
write_data++;
|
||||||
|
write_data_b = write_data + dloop_length;
|
||||||
|
read_end = data + gus_sample->loop_end;
|
||||||
|
do {
|
||||||
|
*write_data = ((*read_data++) ^ 0x80) << 8;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
write_data++;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
|
||||||
|
*write_data = ((*read_data++) ^ 0x80) << 8;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
read_end = data + gus_sample->data_length;
|
||||||
|
if (read_data != read_end) {
|
||||||
|
do {
|
||||||
|
*write_data_b++ = ((*read_data++) ^ 0x80) << 8;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
}
|
||||||
|
gus_sample->loop_start += loop_length;
|
||||||
|
gus_sample->loop_end += dloop_length;
|
||||||
|
gus_sample->data_length = new_length;
|
||||||
|
gus_sample->modes ^= SAMPLE_PINGPONG | SAMPLE_UNSIGNED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 8bit unsigned reverse */
|
||||||
|
static int convert_8ur(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->data_length;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
unsigned long int tmp_loop = 0;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc((gus_sample->data_length + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data + gus_sample->data_length - 1;
|
||||||
|
do {
|
||||||
|
*write_data-- = ((*read_data++) ^ 0x80) << 8;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
tmp_loop = gus_sample->loop_end;
|
||||||
|
gus_sample->loop_end = gus_sample->data_length - gus_sample->loop_start;
|
||||||
|
gus_sample->loop_start = gus_sample->data_length - tmp_loop;
|
||||||
|
gus_sample->loop_fraction = ((gus_sample->loop_fraction & 0x0f) << 4)
|
||||||
|
| ((gus_sample->loop_fraction & 0xf0) >> 4);
|
||||||
|
gus_sample->modes ^= SAMPLE_REVERSE | SAMPLE_UNSIGNED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 8bit unsigned reverse ping pong */
|
||||||
|
static int convert_8urp(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned long int loop_length = gus_sample->loop_end
|
||||||
|
- gus_sample->loop_start;
|
||||||
|
unsigned long int dloop_length = loop_length * 2;
|
||||||
|
unsigned long int new_length = gus_sample->data_length + dloop_length;
|
||||||
|
unsigned char *read_data = data + gus_sample->data_length - 1;
|
||||||
|
unsigned char *read_end = data + gus_sample->loop_end;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
signed short int *write_data_a = NULL;
|
||||||
|
signed short int *write_data_b = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc((new_length + 2), sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data++ = ((*read_data--) ^ 0x80) << 8;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
|
||||||
|
*write_data = ((*read_data--) ^ 0x80) << 8;
|
||||||
|
write_data_a = write_data + dloop_length;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
write_data++;
|
||||||
|
write_data_b = write_data + dloop_length;
|
||||||
|
read_end = data + gus_sample->loop_start;
|
||||||
|
do {
|
||||||
|
*write_data = ((*read_data--) ^ 0x80) << 8;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
write_data++;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
|
||||||
|
*write_data = ((*read_data--) ^ 0x80) << 8;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
read_end = data - 1;
|
||||||
|
do {
|
||||||
|
*write_data_b++ = ((*read_data--) ^ 0x80) << 8;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
gus_sample->loop_start += loop_length;
|
||||||
|
gus_sample->loop_end += dloop_length;
|
||||||
|
gus_sample->data_length = new_length;
|
||||||
|
gus_sample->modes ^= SAMPLE_PINGPONG | SAMPLE_REVERSE | SAMPLE_UNSIGNED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 16bit signed */
|
||||||
|
static int convert_16s(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->data_length;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc(((gus_sample->data_length >> 1) + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data = *read_data++;
|
||||||
|
*write_data++ |= (*read_data++) << 8;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
|
||||||
|
gus_sample->loop_start >>= 1;
|
||||||
|
gus_sample->loop_end >>= 1;
|
||||||
|
gus_sample->data_length >>= 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 16bit signed ping pong */
|
||||||
|
static int convert_16sp(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned long int loop_length = gus_sample->loop_end
|
||||||
|
- gus_sample->loop_start;
|
||||||
|
unsigned long int dloop_length = loop_length * 2;
|
||||||
|
unsigned long int new_length = gus_sample->data_length + dloop_length;
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->loop_start;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
signed short int *write_data_a = NULL;
|
||||||
|
signed short int *write_data_b = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc(((new_length >> 1) + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data = (*read_data++);
|
||||||
|
*write_data++ |= (*read_data++) << 8;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
|
||||||
|
*write_data = (*read_data++);
|
||||||
|
*write_data |= (*read_data++) << 8;
|
||||||
|
write_data_a = write_data + (dloop_length >> 1);
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
write_data++;
|
||||||
|
write_data_b = write_data + (dloop_length >> 1);
|
||||||
|
read_end = data + gus_sample->loop_end;
|
||||||
|
do {
|
||||||
|
*write_data = (*read_data++);
|
||||||
|
*write_data |= (*read_data++) << 8;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
write_data++;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
|
||||||
|
*write_data = *(read_data++);
|
||||||
|
*write_data |= (*read_data++) << 8;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
read_end = data + gus_sample->data_length;
|
||||||
|
if (read_data != read_end) {
|
||||||
|
do {
|
||||||
|
*write_data_b = *(read_data++);
|
||||||
|
*write_data_b++ |= (*read_data++) << 8;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
}
|
||||||
|
gus_sample->loop_start += loop_length;
|
||||||
|
gus_sample->loop_end += dloop_length;
|
||||||
|
gus_sample->data_length = new_length;
|
||||||
|
gus_sample->modes ^= SAMPLE_PINGPONG;
|
||||||
|
gus_sample->loop_start >>= 1;
|
||||||
|
gus_sample->loop_end >>= 1;
|
||||||
|
gus_sample->data_length >>= 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 16bit signed reverse */
|
||||||
|
static int convert_16sr(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->data_length;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
unsigned long int tmp_loop = 0;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc(((gus_sample->data_length >> 1) + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data + (gus_sample->data_length >> 1) - 1;
|
||||||
|
do {
|
||||||
|
*write_data = *read_data++;
|
||||||
|
*write_data-- |= (*read_data++) << 8;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
tmp_loop = gus_sample->loop_end;
|
||||||
|
gus_sample->loop_end = gus_sample->data_length - gus_sample->loop_start;
|
||||||
|
gus_sample->loop_start = gus_sample->data_length - tmp_loop;
|
||||||
|
gus_sample->loop_fraction = ((gus_sample->loop_fraction & 0x0f) << 4)
|
||||||
|
| ((gus_sample->loop_fraction & 0xf0) >> 4);
|
||||||
|
gus_sample->loop_start >>= 1;
|
||||||
|
gus_sample->loop_end >>= 1;
|
||||||
|
gus_sample->data_length >>= 1;
|
||||||
|
gus_sample->modes ^= SAMPLE_REVERSE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 16bit signed reverse ping pong */
|
||||||
|
static int convert_16srp(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned long int loop_length = gus_sample->loop_end
|
||||||
|
- gus_sample->loop_start;
|
||||||
|
unsigned long int dloop_length = loop_length * 2;
|
||||||
|
unsigned long int new_length = gus_sample->data_length + dloop_length;
|
||||||
|
unsigned char *read_data = data + gus_sample->data_length - 1;
|
||||||
|
unsigned char *read_end = data + gus_sample->loop_end;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
signed short int *write_data_a = NULL;
|
||||||
|
signed short int *write_data_b = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc(((new_length >> 1) + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data = (*read_data--) << 8;
|
||||||
|
*write_data++ |= *read_data--;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
|
||||||
|
*write_data = (*read_data-- << 8);
|
||||||
|
*write_data |= *read_data--;
|
||||||
|
write_data_a = write_data + (dloop_length >> 1);
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
write_data++;
|
||||||
|
write_data_b = write_data + (dloop_length >> 1);
|
||||||
|
read_end = data + gus_sample->loop_start;
|
||||||
|
do {
|
||||||
|
*write_data = (*read_data--) << 8;
|
||||||
|
*write_data |= *read_data--;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
write_data++;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
|
||||||
|
*write_data = ((*read_data--) << 8);
|
||||||
|
*write_data |= *read_data--;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
read_end = data - 1;
|
||||||
|
do {
|
||||||
|
*write_data_b = (*read_data--) << 8;
|
||||||
|
*write_data_b++ |= *read_data--;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
gus_sample->loop_start += loop_length;
|
||||||
|
gus_sample->loop_end += dloop_length;
|
||||||
|
gus_sample->data_length = new_length;
|
||||||
|
gus_sample->modes ^= SAMPLE_PINGPONG | SAMPLE_REVERSE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 16bit unsigned */
|
||||||
|
static int convert_16u(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->data_length;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc(((gus_sample->data_length >> 1) + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data = *read_data++;
|
||||||
|
*write_data++ |= ((*read_data++) ^ 0x80) << 8;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
gus_sample->loop_start >>= 1;
|
||||||
|
gus_sample->loop_end >>= 1;
|
||||||
|
gus_sample->data_length >>= 1;
|
||||||
|
gus_sample->modes ^= SAMPLE_UNSIGNED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 16bit unsigned ping pong */
|
||||||
|
static int convert_16up(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned long int loop_length = gus_sample->loop_end
|
||||||
|
- gus_sample->loop_start;
|
||||||
|
unsigned long int dloop_length = loop_length * 2;
|
||||||
|
unsigned long int new_length = gus_sample->data_length + dloop_length;
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->loop_start;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
signed short int *write_data_a = NULL;
|
||||||
|
signed short int *write_data_b = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc(((new_length >> 1) + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data = (*read_data++);
|
||||||
|
*write_data++ |= ((*read_data++) ^ 0x80) << 8;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
|
||||||
|
*write_data = (*read_data++);
|
||||||
|
*write_data |= ((*read_data++) ^ 0x80) << 8;
|
||||||
|
write_data_a = write_data + (dloop_length >> 1);
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
write_data++;
|
||||||
|
write_data_b = write_data + (dloop_length >> 1);
|
||||||
|
read_end = data + gus_sample->loop_end;
|
||||||
|
do {
|
||||||
|
*write_data = (*read_data++);
|
||||||
|
*write_data |= ((*read_data++) ^ 0x80) << 8;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
write_data++;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
|
||||||
|
*write_data = (*read_data++);
|
||||||
|
*write_data |= ((*read_data++) ^ 0x80) << 8;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
read_end = data + gus_sample->data_length;
|
||||||
|
if (read_data != read_end) {
|
||||||
|
do {
|
||||||
|
*write_data_b = (*read_data++);
|
||||||
|
*write_data_b++ |= ((*read_data++) ^ 0x80) << 8;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
}
|
||||||
|
gus_sample->loop_start += loop_length;
|
||||||
|
gus_sample->loop_end += dloop_length;
|
||||||
|
gus_sample->data_length = new_length;
|
||||||
|
gus_sample->modes ^= SAMPLE_PINGPONG;
|
||||||
|
gus_sample->loop_start >>= 1;
|
||||||
|
gus_sample->loop_end >>= 1;
|
||||||
|
gus_sample->data_length >>= 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 16bit unsigned reverse */
|
||||||
|
static int convert_16ur(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->data_length;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
unsigned long int tmp_loop = 0;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc(((gus_sample->data_length >> 1) + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data + (gus_sample->data_length >> 1) - 1;
|
||||||
|
do {
|
||||||
|
*write_data = *read_data++;
|
||||||
|
*write_data-- |= ((*read_data++) ^ 0x80) << 8;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
tmp_loop = gus_sample->loop_end;
|
||||||
|
gus_sample->loop_end = gus_sample->data_length - gus_sample->loop_start;
|
||||||
|
gus_sample->loop_start = gus_sample->data_length - tmp_loop;
|
||||||
|
gus_sample->loop_fraction = ((gus_sample->loop_fraction & 0x0f) << 4)
|
||||||
|
| ((gus_sample->loop_fraction & 0xf0) >> 4);
|
||||||
|
gus_sample->loop_start >>= 1;
|
||||||
|
gus_sample->loop_end >>= 1;
|
||||||
|
gus_sample->data_length >>= 1;
|
||||||
|
gus_sample->modes ^= SAMPLE_REVERSE | SAMPLE_UNSIGNED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 16bit unsigned reverse ping pong */
|
||||||
|
static int convert_16urp(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned long int loop_length = gus_sample->loop_end
|
||||||
|
- gus_sample->loop_start;
|
||||||
|
unsigned long int dloop_length = loop_length * 2;
|
||||||
|
unsigned long int new_length = gus_sample->data_length + dloop_length;
|
||||||
|
unsigned char *read_data = data + gus_sample->data_length - 1;
|
||||||
|
unsigned char *read_end = data + gus_sample->loop_end;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
signed short int *write_data_a = NULL;
|
||||||
|
signed short int *write_data_b = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc(((new_length >> 1) + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data = ((*read_data--) ^ 0x80) << 8;
|
||||||
|
*write_data++ |= *read_data--;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
|
||||||
|
*write_data = ((*read_data--) ^ 0x80) << 8;
|
||||||
|
*write_data |= *read_data--;
|
||||||
|
write_data_a = write_data + (dloop_length >> 1);
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
write_data++;
|
||||||
|
write_data_b = write_data + (dloop_length >> 1);
|
||||||
|
read_end = data + gus_sample->loop_start;
|
||||||
|
do {
|
||||||
|
*write_data = ((*read_data--) ^ 0x80) << 8;
|
||||||
|
*write_data |= *read_data--;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
write_data++;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
|
||||||
|
*write_data = ((*read_data--) ^ 0x80) << 8;
|
||||||
|
*write_data |= *read_data--;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
read_end = data - 1;
|
||||||
|
do {
|
||||||
|
*write_data_b = ((*read_data--) ^ 0x80) << 8;
|
||||||
|
*write_data_b++ |= *read_data--;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
gus_sample->loop_start += loop_length;
|
||||||
|
gus_sample->loop_end += dloop_length;
|
||||||
|
gus_sample->data_length = new_length;
|
||||||
|
gus_sample->modes ^= SAMPLE_PINGPONG | SAMPLE_REVERSE | SAMPLE_UNSIGNED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sample loading */
|
||||||
|
|
||||||
|
struct _sample * _WM_load_gus_pat(const char *filename, int fix_release) {
|
||||||
|
unsigned char *gus_patch;
|
||||||
|
unsigned long int gus_size;
|
||||||
|
unsigned long int gus_ptr;
|
||||||
|
unsigned char no_of_samples;
|
||||||
|
struct _sample *gus_sample = NULL;
|
||||||
|
struct _sample *first_gus_sample = NULL;
|
||||||
|
unsigned long int i = 0;
|
||||||
|
|
||||||
|
int (*do_convert[])(unsigned char *data, struct _sample *gus_sample) = {
|
||||||
|
convert_8s,
|
||||||
|
convert_16s,
|
||||||
|
convert_8u,
|
||||||
|
convert_16u,
|
||||||
|
convert_8sp,
|
||||||
|
convert_16sp,
|
||||||
|
convert_8up,
|
||||||
|
convert_16up,
|
||||||
|
convert_8sr,
|
||||||
|
convert_16sr,
|
||||||
|
convert_8ur,
|
||||||
|
convert_16ur,
|
||||||
|
convert_8srp,
|
||||||
|
convert_16srp,
|
||||||
|
convert_8urp,
|
||||||
|
convert_16urp
|
||||||
|
};
|
||||||
|
unsigned long int tmp_loop;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__); SAMPLE_CONVERT_DEBUG(filename);
|
||||||
|
|
||||||
|
if ((gus_patch = _WM_BufferFile(filename, &gus_size)) == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (gus_size < 239) {
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT, "(too short)", 0);
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, filename, 0);
|
||||||
|
free(gus_patch);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (memcmp(gus_patch, "GF1PATCH110\0ID#000002", 22)
|
||||||
|
&& memcmp(gus_patch, "GF1PATCH100\0ID#000002", 22)) {
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(unsupported format)",
|
||||||
|
0);
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, filename, 0);
|
||||||
|
free(gus_patch);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (gus_patch[82] > 1) {
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(unsupported format)",
|
||||||
|
0);
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, filename, 0);
|
||||||
|
free(gus_patch);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (gus_patch[151] > 1) {
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(unsupported format)",
|
||||||
|
0);
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, filename, 0);
|
||||||
|
free(gus_patch);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
GUSPAT_FILENAME_DEBUG(filename); GUSPAT_INT_DEBUG("voices",gus_patch[83]);
|
||||||
|
|
||||||
|
no_of_samples = gus_patch[198];
|
||||||
|
gus_ptr = 239;
|
||||||
|
while (no_of_samples) {
|
||||||
|
unsigned long int tmp_cnt;
|
||||||
|
if (first_gus_sample == NULL) {
|
||||||
|
first_gus_sample = (struct _sample*)malloc(sizeof(struct _sample));
|
||||||
|
gus_sample = first_gus_sample;
|
||||||
|
} else {
|
||||||
|
gus_sample->next = (struct _sample*)malloc(sizeof(struct _sample));
|
||||||
|
gus_sample = gus_sample->next;
|
||||||
|
}
|
||||||
|
if (gus_sample == NULL) {
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, NULL, 0);
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, filename, 0);
|
||||||
|
free(gus_patch);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gus_sample->next = NULL;
|
||||||
|
gus_sample->loop_fraction = gus_patch[gus_ptr + 7];
|
||||||
|
gus_sample->data_length = (gus_patch[gus_ptr + 11] << 24)
|
||||||
|
| (gus_patch[gus_ptr + 10] << 16)
|
||||||
|
| (gus_patch[gus_ptr + 9] << 8) | gus_patch[gus_ptr + 8];
|
||||||
|
gus_sample->loop_start = (gus_patch[gus_ptr + 15] << 24)
|
||||||
|
| (gus_patch[gus_ptr + 14] << 16)
|
||||||
|
| (gus_patch[gus_ptr + 13] << 8) | gus_patch[gus_ptr + 12];
|
||||||
|
gus_sample->loop_end = (gus_patch[gus_ptr + 19] << 24)
|
||||||
|
| (gus_patch[gus_ptr + 18] << 16)
|
||||||
|
| (gus_patch[gus_ptr + 17] << 8) | gus_patch[gus_ptr + 16];
|
||||||
|
gus_sample->rate = (gus_patch[gus_ptr + 21] << 8)
|
||||||
|
| gus_patch[gus_ptr + 20];
|
||||||
|
gus_sample->freq_low = ((gus_patch[gus_ptr + 25] << 24)
|
||||||
|
| (gus_patch[gus_ptr + 24] << 16)
|
||||||
|
| (gus_patch[gus_ptr + 23] << 8) | gus_patch[gus_ptr + 22]);
|
||||||
|
gus_sample->freq_high = ((gus_patch[gus_ptr + 29] << 24)
|
||||||
|
| (gus_patch[gus_ptr + 28] << 16)
|
||||||
|
| (gus_patch[gus_ptr + 27] << 8) | gus_patch[gus_ptr + 26]);
|
||||||
|
gus_sample->freq_root = ((gus_patch[gus_ptr + 33] << 24)
|
||||||
|
| (gus_patch[gus_ptr + 32] << 16)
|
||||||
|
| (gus_patch[gus_ptr + 31] << 8) | gus_patch[gus_ptr + 30]);
|
||||||
|
|
||||||
|
/* This is done this way instead of ((freq * 1024) / rate) to avoid 32bit overflow. */
|
||||||
|
/* Result is 0.001% inacurate */
|
||||||
|
gus_sample->inc_div = ((gus_sample->freq_root * 512) / gus_sample->rate) * 2;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* We dont use this info at this time, kept in here for info */
|
||||||
|
printf("\rTremolo Sweep: %i, Rate: %i, Depth %i\n",
|
||||||
|
gus_patch[gus_ptr+49], gus_patch[gus_ptr+50], gus_patch[gus_ptr+51]);
|
||||||
|
printf("\rVibrato Sweep: %i, Rate: %i, Depth %i\n",
|
||||||
|
gus_patch[gus_ptr+52], gus_patch[gus_ptr+53], gus_patch[gus_ptr+54]);
|
||||||
|
#endif
|
||||||
|
gus_sample->modes = gus_patch[gus_ptr + 55];
|
||||||
|
GUSPAT_START_DEBUG(); GUSPAT_MODE_DEBUG(gus_patch[gus_ptr+55], SAMPLE_16BIT, "16bit "); GUSPAT_MODE_DEBUG(gus_patch[gus_ptr+55], SAMPLE_UNSIGNED, "Unsigned "); GUSPAT_MODE_DEBUG(gus_patch[gus_ptr+55], SAMPLE_LOOP, "Loop "); GUSPAT_MODE_DEBUG(gus_patch[gus_ptr+55], SAMPLE_PINGPONG, "PingPong "); GUSPAT_MODE_DEBUG(gus_patch[gus_ptr+55], SAMPLE_REVERSE, "Reverse "); GUSPAT_MODE_DEBUG(gus_patch[gus_ptr+55], SAMPLE_SUSTAIN, "Sustain "); GUSPAT_MODE_DEBUG(gus_patch[gus_ptr+55], SAMPLE_ENVELOPE, "Envelope "); GUSPAT_MODE_DEBUG(gus_patch[gus_ptr+55], SAMPLE_CLAMPED, "Clamped "); GUSPAT_END_DEBUG();
|
||||||
|
|
||||||
|
if (gus_sample->loop_start > gus_sample->loop_end) {
|
||||||
|
tmp_loop = gus_sample->loop_end;
|
||||||
|
gus_sample->loop_end = gus_sample->loop_start;
|
||||||
|
gus_sample->loop_start = tmp_loop;
|
||||||
|
gus_sample->loop_fraction =
|
||||||
|
((gus_sample->loop_fraction & 0x0f) << 4)
|
||||||
|
| ((gus_sample->loop_fraction & 0xf0) >> 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
FIXME: Experimental Hacky Fix
|
||||||
|
*/
|
||||||
|
if (fix_release) {
|
||||||
|
if (env_time_table[gus_patch[gus_ptr + 40]]
|
||||||
|
< env_time_table[gus_patch[gus_ptr + 41]]) {
|
||||||
|
unsigned char tmp_hack_rate = gus_patch[gus_ptr + 41];
|
||||||
|
gus_patch[gus_ptr + 41] = gus_patch[gus_ptr + 40];
|
||||||
|
gus_patch[gus_ptr + 40] = tmp_hack_rate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 6; i++) {
|
||||||
|
if (gus_sample->modes & SAMPLE_ENVELOPE) {
|
||||||
|
unsigned char env_rate = gus_patch[gus_ptr + 37 + i];
|
||||||
|
gus_sample->env_target[i] = 16448 * gus_patch[gus_ptr + 43 + i];
|
||||||
|
GUSPAT_INT_DEBUG("Envelope Level",gus_patch[gus_ptr+43+i]); GUSPAT_FLOAT_DEBUG("Envelope Time",env_time_table[env_rate]);
|
||||||
|
gus_sample->env_rate[i] = (signed long int) (4194303.0
|
||||||
|
/ ((float) _WM_SampleRate * env_time_table[env_rate]));
|
||||||
|
GUSPAT_INT_DEBUG("Envelope Rate",gus_sample->env_rate[i]); GUSPAT_INT_DEBUG("GUSPAT Rate",env_rate);
|
||||||
|
if (gus_sample->env_rate[i] == 0) {
|
||||||
|
_WM_ERROR_NEW("%s: Warning: found invalid envelope(%lu) rate setting in %s. Using %f instead.",
|
||||||
|
__FUNCTION__, i, filename, env_time_table[63]);
|
||||||
|
gus_sample->env_rate[i] = (signed long int) (4194303.0
|
||||||
|
/ ((float) _WM_SampleRate * env_time_table[63]));
|
||||||
|
GUSPAT_FLOAT_DEBUG("Envelope Time",env_time_table[63]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gus_sample->env_target[i] = 4194303;
|
||||||
|
gus_sample->env_rate[i] = (signed long int) (4194303.0
|
||||||
|
/ ((float) _WM_SampleRate * env_time_table[63]));
|
||||||
|
GUSPAT_FLOAT_DEBUG("Envelope Time",env_time_table[63]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gus_sample->env_target[6] = 0;
|
||||||
|
gus_sample->env_rate[6] = (signed long int) (4194303.0
|
||||||
|
/ ((float) _WM_SampleRate * env_time_table[63]));
|
||||||
|
|
||||||
|
gus_ptr += 96;
|
||||||
|
tmp_cnt = gus_sample->data_length;
|
||||||
|
|
||||||
|
if (do_convert[(((gus_sample->modes & 0x18) >> 1)
|
||||||
|
| (gus_sample->modes & 0x03))](&gus_patch[gus_ptr], gus_sample)
|
||||||
|
== -1) {
|
||||||
|
free(gus_patch);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gus_ptr += tmp_cnt;
|
||||||
|
gus_sample->loop_start = (gus_sample->loop_start << 10)
|
||||||
|
| (((gus_sample->loop_fraction & 0x0f) << 10) / 16);
|
||||||
|
gus_sample->loop_end = (gus_sample->loop_end << 10)
|
||||||
|
| (((gus_sample->loop_fraction & 0xf0) << 6) / 16);
|
||||||
|
gus_sample->loop_size = gus_sample->loop_end - gus_sample->loop_start;
|
||||||
|
gus_sample->data_length = gus_sample->data_length << 10;
|
||||||
|
no_of_samples--;
|
||||||
|
}
|
||||||
|
free(gus_patch);
|
||||||
|
return first_gus_sample;
|
||||||
|
}
|
77
src/wildmidi/gus_pat.h
Normal file
77
src/wildmidi/gus_pat.h
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
gus_pat.h
|
||||||
|
|
||||||
|
Midi Wavetable Processing library
|
||||||
|
|
||||||
|
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 __GUS_PAT_H
|
||||||
|
#define __GUS_PAT_H
|
||||||
|
|
||||||
|
/* Guspat Envelope Rate Timings */
|
||||||
|
|
||||||
|
static float env_time_table[] = {
|
||||||
|
/* Row 1 = (4095.0 / (x * ( 1.0 / (1.6 * 14.0) ))) / 1000000.0 */
|
||||||
|
0.0f, 0.091728000f, 0.045864000f, 0.030576000f, 0.022932000f, 0.018345600f, 0.015288000f, 0.013104000f,
|
||||||
|
0.011466000f, 0.010192000f, 0.009172800f, 0.008338909f, 0.007644000f, 0.007056000f, 0.006552000f, 0.006115200f,
|
||||||
|
0.005733000f, 0.005395765f, 0.005096000f, 0.004827789f, 0.004586400f, 0.004368000f, 0.004169455f, 0.003988174f,
|
||||||
|
0.003822000f, 0.003669120f, 0.003528000f, 0.003397333f, 0.003276000f, 0.003163034f, 0.003057600f, 0.002958968f,
|
||||||
|
0.002866500f, 0.002779636f, 0.002697882f, 0.002620800f, 0.002548000f, 0.002479135f, 0.002413895f, 0.002352000f,
|
||||||
|
0.002293200f, 0.002237268f, 0.002184000f, 0.002133209f, 0.002084727f, 0.002038400f, 0.001994087f, 0.001951660f,
|
||||||
|
0.001911000f, 0.001872000f, 0.001834560f, 0.001798588f, 0.001764000f, 0.001730717f, 0.001698667f, 0.001667782f,
|
||||||
|
0.001638000f, 0.001609263f, 0.001581517f, 0.001554712f, 0.001528800f, 0.001503738f, 0.001479484f, 0.001456000f,
|
||||||
|
|
||||||
|
/* Row 2 = (4095.0 / (x * ((1.0 / (1.6 * 14.0)) / 8.0 ))) / 1000000.0 */
|
||||||
|
0.0f, 0.733824000f, 0.366912000f, 0.244608000f, 0.183456000f, 0.146764800f, 0.122304000f, 0.104832000f,
|
||||||
|
0.091728000f, 0.081536000f, 0.073382400f, 0.066711273f, 0.061152000f, 0.056448000f, 0.052416000f, 0.048921600f,
|
||||||
|
0.045864000f, 0.043166118f, 0.040768000f, 0.038622316f, 0.036691200f, 0.034944000f, 0.033355636f, 0.031905391f,
|
||||||
|
0.030576000f, 0.029352960f, 0.028224000f, 0.027178667f, 0.026208000f, 0.025304276f, 0.024460800f, 0.023671742f,
|
||||||
|
0.022932000f, 0.022237091f, 0.021583059f, 0.020966400f, 0.020384000f, 0.019833081f, 0.019311158f, 0.018816000f,
|
||||||
|
0.018345600f, 0.017898146f, 0.017472000f, 0.017065674f, 0.016677818f, 0.016307200f, 0.015952696f, 0.015613277f,
|
||||||
|
0.015288000f, 0.014976000f, 0.014676480f, 0.014388706f, 0.014112000f, 0.013845736f, 0.013589333f, 0.013342255f,
|
||||||
|
0.013104000f, 0.012874105f, 0.012652138f, 0.012437695f, 0.012230400f, 0.012029902f, 0.011835871f, 0.011648000f,
|
||||||
|
|
||||||
|
/* Row 3 = (4095.0 / (x * ((1.0 / (1.6 * 14.0)) / 64.0 ))) / 1000000.0 */
|
||||||
|
0.0f, 5.870592000f, 2.935296000f, 1.956864000f, 1.467648000f, 1.174118400f, 0.978432000f, 0.838656000f,
|
||||||
|
0.733824000f, 0.652288000f, 0.587059200f, 0.533690182f, 0.489216000f, 0.451584000f, 0.419328000f, 0.391372800f,
|
||||||
|
0.366912000f, 0.345328941f, 0.326144000f, 0.308978526f, 0.293529600f, 0.279552000f, 0.266845091f, 0.255243130f,
|
||||||
|
0.244608000f, 0.234823680f, 0.225792000f, 0.217429333f, 0.209664000f, 0.202434207f, 0.195686400f, 0.189373935f,
|
||||||
|
0.183456000f, 0.177896727f, 0.172664471f, 0.167731200f, 0.163072000f, 0.158664649f, 0.154489263f, 0.150528000f,
|
||||||
|
0.146764800f, 0.143185171f, 0.139776000f, 0.136525395f, 0.133422545f, 0.130457600f, 0.127621565f, 0.124906213f,
|
||||||
|
0.122304000f, 0.119808000f, 0.117411840f, 0.115109647f, 0.112896000f, 0.110765887f, 0.108714667f, 0.106738036f,
|
||||||
|
0.104832000f, 0.102992842f, 0.101217103f, 0.099501559f, 0.097843200f, 0.096239213f, 0.094686968f, 0.093184000f,
|
||||||
|
|
||||||
|
/* Row 4 = (4095.0 / (x * ((1.0 / (1.6 * 14.0)) / 512.0))) / 1000000.0 */
|
||||||
|
0.0f, 46.964736000f,23.482368000f,15.654912000f,11.741184000f, 9.392947200f, 7.827456000f, 6.709248000f,
|
||||||
|
5.870592000f, 5.218304000f, 4.696473600f, 4.269521455f, 3.913728000f, 3.612672000f, 3.354624000f, 3.130982400f,
|
||||||
|
2.935296000f, 2.762631529f, 2.609152000f, 2.471828211f, 2.348236800f, 2.236416000f, 2.134760727f, 2.041945043f,
|
||||||
|
1.956864000f, 1.878589440f, 1.806336000f, 1.739434667f, 1.677312000f, 1.619473655f, 1.565491200f, 1.514991484f,
|
||||||
|
1.467648000f, 1.423173818f, 1.381315765f, 1.341849600f, 1.304576000f, 1.269317189f, 1.235914105f, 1.204224000f,
|
||||||
|
1.174118400f, 1.145481366f, 1.118208000f, 1.092203163f, 1.067380364f, 1.043660800f, 1.020972522f, 0.999249702f,
|
||||||
|
0.978432000f, 0.958464000f, 0.939294720f, 0.920877176f, 0.903168000f, 0.886127094f, 0.869717333f, 0.853904291f,
|
||||||
|
0.838656000f, 0.823942737f, 0.809736828f, 0.796012475f, 0.782745600f, 0.769913705f, 0.757495742f, 0.745472000f
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct _sample * _WM_load_gus_pat (const char *filename, int _fix_release);
|
||||||
|
|
||||||
|
#endif /* __GUS_PAT_H */
|
||||||
|
|
87
src/wildmidi/lock.cpp
Normal file
87
src/wildmidi/lock.cpp
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
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
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#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__ */
|
36
src/wildmidi/lock.h
Normal file
36
src/wildmidi/lock.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
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 */
|
398
src/wildmidi/reverb.cpp
Normal file
398
src/wildmidi/reverb.cpp
Normal file
|
@ -0,0 +1,398 @@
|
||||||
|
/*
|
||||||
|
reverb.c
|
||||||
|
|
||||||
|
Midi Wavetable Processing library
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "reverb.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
reverb function
|
||||||
|
*/
|
||||||
|
void _WM_reset_reverb(struct _rvb *rvb) {
|
||||||
|
int i, j, k;
|
||||||
|
for (i = 0; i < rvb->l_buf_size; i++) {
|
||||||
|
rvb->l_buf[i] = 0;
|
||||||
|
}
|
||||||
|
for (i = 0; i < rvb->r_buf_size; i++) {
|
||||||
|
rvb->r_buf[i] = 0;
|
||||||
|
}
|
||||||
|
for (k = 0; k < 8; k++) {
|
||||||
|
for (i = 0; i < 6; i++) {
|
||||||
|
for (j = 0; j < 2; j++) {
|
||||||
|
rvb->l_buf_flt_in[k][i][j] = 0;
|
||||||
|
rvb->l_buf_flt_out[k][i][j] = 0;
|
||||||
|
rvb->r_buf_flt_in[k][i][j] = 0;
|
||||||
|
rvb->r_buf_flt_out[k][i][j] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
_WM_init_reverb
|
||||||
|
|
||||||
|
=========================
|
||||||
|
Engine Description
|
||||||
|
|
||||||
|
8 reflective points around the room
|
||||||
|
2 speaker positions
|
||||||
|
1 listener position
|
||||||
|
|
||||||
|
Sounds come from the speakers to all points and to the listener.
|
||||||
|
Sound comes from the reflective points to the listener.
|
||||||
|
These sounds are combined, put through a filter that mimics surface absorbtion.
|
||||||
|
The combined sounds are also sent to the reflective points on the opposite side.
|
||||||
|
|
||||||
|
*/
|
||||||
|
struct _rvb *
|
||||||
|
_WM_init_reverb(int rate, float room_x, float room_y, float listen_x,
|
||||||
|
float listen_y) {
|
||||||
|
|
||||||
|
/* filters set at 125Hz, 250Hz, 500Hz, 1000Hz, 2000Hz, 4000Hz */
|
||||||
|
double Freq[] = {125.0, 250.0, 500.0, 1000.0, 2000.0, 4000.0};
|
||||||
|
|
||||||
|
/* numbers calculated from
|
||||||
|
* 101.325 kPa, 20 deg C, 50% relative humidity */
|
||||||
|
double dbAirAbs[] = {-0.00044, -0.00131, -0.002728, -0.004665, -0.009887, -0.029665};
|
||||||
|
|
||||||
|
/* modify these to adjust the absorption qualities of the surface.
|
||||||
|
* Remember that lower frequencies are less effected by surfaces
|
||||||
|
* Note: I am currently playing with the values and finding the ideal surfaces
|
||||||
|
* for nice default reverb.
|
||||||
|
*/
|
||||||
|
double dbAttn[8][6] = {
|
||||||
|
{-1.839, -6.205, -8.891, -12.059, -15.935, -20.942},
|
||||||
|
{-0.131, -6.205, -12.059, -20.933, -20.933, -15.944},
|
||||||
|
{-0.131, -6.205, -12.059, -20.933, -20.933, -15.944},
|
||||||
|
{-1.839, -6.205, -8.891, -12.059, -15.935, -20.942},
|
||||||
|
{-1.839, -6.205, -8.891, -12.059, -15.935, -20.942},
|
||||||
|
{-0.131, -6.205, -12.059, -20.933, -20.933, -15.944},
|
||||||
|
{-0.131, -6.205, -12.059, -20.933, -20.933, -15.944},
|
||||||
|
{-1.839, -6.205, -8.891, -12.059, -15.935, -20.942}
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
double dbAttn[6] = {
|
||||||
|
// concrete covered in carpet
|
||||||
|
// -0.175, -0.537, -1.412, -4.437, -7.959, -7.959
|
||||||
|
// pleated drapes
|
||||||
|
-0.630, -3.223, -5.849, -12.041, -10.458, -7.959
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* distance */
|
||||||
|
double SPL_DST[8] = {0.0};
|
||||||
|
double SPR_DST[8] = {0.0};
|
||||||
|
double RFN_DST[8] = {0.0};
|
||||||
|
|
||||||
|
double MAXL_DST = 0.0;
|
||||||
|
double MAXR_DST = 0.0;
|
||||||
|
|
||||||
|
double SPL_LSN_XOFS = 0.0;
|
||||||
|
double SPL_LSN_YOFS = 0.0;
|
||||||
|
double SPL_LSN_DST = 0.0;
|
||||||
|
|
||||||
|
double SPR_LSN_XOFS = 0.0;
|
||||||
|
double SPR_LSN_YOFS = 0.0;
|
||||||
|
double SPR_LSN_DST = 0.0;
|
||||||
|
|
||||||
|
|
||||||
|
struct _rvb *rtn_rvb = (struct _rvb*)malloc(sizeof(struct _rvb));
|
||||||
|
int j = 0;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
struct _coord {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
struct _coord SPL = {2.5, 5.0}; /* Left Speaker Position */
|
||||||
|
struct _coord SPR = {7.5, 5.0}; /* Right Speaker Position */
|
||||||
|
/* position of the reflective points */
|
||||||
|
struct _coord RFN[] = {
|
||||||
|
{ 5.0, 0.0},
|
||||||
|
{ 0.0, 6.66666},
|
||||||
|
{ 0.0, 13.3333},
|
||||||
|
{ 5.0, 20.0},
|
||||||
|
{ 10.0, 20.0},
|
||||||
|
{ 15.0, 13.3333},
|
||||||
|
{ 15.0, 6.66666},
|
||||||
|
{ 10.0, 0.0}
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
struct _coord SPL; /* Left Speaker Position */
|
||||||
|
struct _coord SPR; /* Right Speaker Position */
|
||||||
|
/* position of the reflective points */
|
||||||
|
struct _coord RFN[8];
|
||||||
|
|
||||||
|
SPL.x = room_x / 4.0;
|
||||||
|
SPR.x = room_x / 4.0 * 3.0;
|
||||||
|
SPL.y = room_y / 10.0;
|
||||||
|
SPR.y = room_y / 10.0;
|
||||||
|
|
||||||
|
RFN[0].x = room_x / 3.0;
|
||||||
|
RFN[0].y = 0.0;
|
||||||
|
RFN[1].x = 0.0;
|
||||||
|
RFN[1].y = room_y / 3.0;
|
||||||
|
RFN[2].x = 0.0;
|
||||||
|
RFN[2].y = room_y / 3.0 * 2.0;
|
||||||
|
RFN[3].x = room_x / 3.0;
|
||||||
|
RFN[3].y = room_y;
|
||||||
|
RFN[4].x = room_x / 3.0 * 2.0;
|
||||||
|
RFN[4].y = room_y;
|
||||||
|
RFN[5].x = room_x;
|
||||||
|
RFN[5].y = room_y / 3.0 * 2.0;
|
||||||
|
RFN[6].x = room_x;
|
||||||
|
RFN[6].y = room_y / 3.0;
|
||||||
|
RFN[7].x = room_x / 3.0 * 2.0;
|
||||||
|
RFN[7].y = 0.0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SPL_LSN_XOFS = SPL.x - listen_x;
|
||||||
|
SPL_LSN_YOFS = SPL.y - listen_y;
|
||||||
|
SPL_LSN_DST = sqrt((SPL_LSN_XOFS * SPL_LSN_XOFS) + (SPL_LSN_YOFS * SPL_LSN_YOFS));
|
||||||
|
|
||||||
|
if (SPL_LSN_DST > MAXL_DST)
|
||||||
|
MAXL_DST = SPL_LSN_DST;
|
||||||
|
|
||||||
|
SPR_LSN_XOFS = SPR.x - listen_x;
|
||||||
|
SPR_LSN_YOFS = SPR.y - listen_y;
|
||||||
|
SPR_LSN_DST = sqrt((SPR_LSN_XOFS * SPR_LSN_XOFS) + (SPR_LSN_YOFS * SPR_LSN_YOFS));
|
||||||
|
|
||||||
|
if (SPR_LSN_DST > MAXR_DST)
|
||||||
|
MAXR_DST = SPR_LSN_DST;
|
||||||
|
|
||||||
|
if (rtn_rvb == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < 8; j++) {
|
||||||
|
double SPL_RFL_XOFS = 0;
|
||||||
|
double SPL_RFL_YOFS = 0;
|
||||||
|
double SPR_RFL_XOFS = 0;
|
||||||
|
double SPR_RFL_YOFS = 0;
|
||||||
|
double RFN_XOFS = listen_x - RFN[j].x;
|
||||||
|
double RFN_YOFS = listen_y - RFN[j].y;
|
||||||
|
RFN_DST[j] = sqrt((RFN_XOFS * RFN_XOFS) + (RFN_YOFS * RFN_YOFS));
|
||||||
|
|
||||||
|
SPL_RFL_XOFS = SPL.x - RFN[i].x;
|
||||||
|
SPL_RFL_YOFS = SPL.y - RFN[i].y;
|
||||||
|
SPR_RFL_XOFS = SPR.x - RFN[i].x;
|
||||||
|
SPR_RFL_YOFS = SPR.y - RFN[i].y;
|
||||||
|
SPL_DST[i] = sqrt(
|
||||||
|
(SPL_RFL_XOFS * SPL_RFL_XOFS) + (SPL_RFL_YOFS * SPL_RFL_YOFS));
|
||||||
|
SPR_DST[i] = sqrt(
|
||||||
|
(SPR_RFL_XOFS * SPR_RFL_XOFS) + (SPR_RFL_YOFS * SPR_RFL_YOFS));
|
||||||
|
/*
|
||||||
|
add the 2 distances together and remove the speaker to listener distance
|
||||||
|
so we dont have to delay the initial output
|
||||||
|
*/
|
||||||
|
SPL_DST[i] += RFN_DST[i];
|
||||||
|
|
||||||
|
/* so i dont have to delay speaker output */
|
||||||
|
SPL_DST[i] -= SPL_LSN_DST;
|
||||||
|
|
||||||
|
if (i < 4) {
|
||||||
|
if (SPL_DST[i] > MAXL_DST)
|
||||||
|
MAXL_DST = SPL_DST[i];
|
||||||
|
} else {
|
||||||
|
if (SPL_DST[i] > MAXR_DST)
|
||||||
|
MAXR_DST = SPL_DST[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
SPR_DST[i] += RFN_DST[i];
|
||||||
|
|
||||||
|
/* so i dont have to delay speaker output */
|
||||||
|
SPR_DST[i] -= SPR_LSN_DST;
|
||||||
|
|
||||||
|
if (i < 4) {
|
||||||
|
if (SPR_DST[i] > MAXL_DST)
|
||||||
|
MAXL_DST = SPR_DST[i];
|
||||||
|
} else {
|
||||||
|
if (SPR_DST[i] > MAXR_DST)
|
||||||
|
MAXR_DST = SPR_DST[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
RFN_DST[j] *= 2.0;
|
||||||
|
|
||||||
|
if (j < 4) {
|
||||||
|
if (RFN_DST[j] > MAXL_DST)
|
||||||
|
MAXL_DST = RFN_DST[j];
|
||||||
|
} else {
|
||||||
|
if (RFN_DST[j] > MAXR_DST)
|
||||||
|
MAXR_DST = RFN_DST[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 6; i++) {
|
||||||
|
double srate = (double) rate;
|
||||||
|
double bandwidth = 2.0;
|
||||||
|
double omega = 2.0 * M_PI * Freq[i] / srate;
|
||||||
|
double sn = sin(omega);
|
||||||
|
double cs = cos(omega);
|
||||||
|
double alpha = sn * sinh(M_LN2 / 2 * bandwidth * omega / sn);
|
||||||
|
double A = pow(10.0, ((/*dbAttn[i]*/dbAttn[j][i] +
|
||||||
|
(dbAirAbs[i] * RFN_DST[j])) / 40.0) );
|
||||||
|
/*
|
||||||
|
Peaking band EQ filter
|
||||||
|
*/
|
||||||
|
double b0 = 1 + (alpha * A);
|
||||||
|
double b1 = -2 * cs;
|
||||||
|
double b2 = 1 - (alpha * A);
|
||||||
|
double a0 = 1 + (alpha / A);
|
||||||
|
double a1 = -2 * cs;
|
||||||
|
double a2 = 1 - (alpha / A);
|
||||||
|
|
||||||
|
rtn_rvb->coeff[j][i][0] = (signed long int) ((b0 / a0) * 1024.0);
|
||||||
|
rtn_rvb->coeff[j][i][1] = (signed long int) ((b1 / a0) * 1024.0);
|
||||||
|
rtn_rvb->coeff[j][i][2] = (signed long int) ((b2 / a0) * 1024.0);
|
||||||
|
rtn_rvb->coeff[j][i][3] = (signed long int) ((a1 / a0) * 1024.0);
|
||||||
|
rtn_rvb->coeff[j][i][4] = (signed long int) ((a2 / a0) * 1024.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* init the reverb buffers */
|
||||||
|
rtn_rvb->l_buf_size = (int) ((float) rate * (MAXL_DST / 340.29));
|
||||||
|
rtn_rvb->l_buf = (long*)malloc(
|
||||||
|
sizeof(signed long int) * (rtn_rvb->l_buf_size + 1));
|
||||||
|
rtn_rvb->l_out = 0;
|
||||||
|
|
||||||
|
rtn_rvb->r_buf_size = (int) ((float) rate * (MAXR_DST / 340.29));
|
||||||
|
rtn_rvb->r_buf = (long*)malloc(
|
||||||
|
sizeof(signed long int) * (rtn_rvb->r_buf_size + 1));
|
||||||
|
rtn_rvb->r_out = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
rtn_rvb->l_sp_in[i] = (int) ((float) rate * (SPL_DST[i] / 340.29));
|
||||||
|
rtn_rvb->l_sp_in[i + 4] = (int) ((float) rate
|
||||||
|
* (SPL_DST[i + 4] / 340.29));
|
||||||
|
rtn_rvb->r_sp_in[i] = (int) ((float) rate * (SPR_DST[i] / 340.29));
|
||||||
|
rtn_rvb->r_sp_in[i + 4] = (int) ((float) rate
|
||||||
|
* (SPR_DST[i + 4] / 340.29));
|
||||||
|
rtn_rvb->l_in[i] = (int) ((float) rate * (RFN_DST[i] / 340.29));
|
||||||
|
rtn_rvb->r_in[i] = (int) ((float) rate * (RFN_DST[i + 4] / 340.29));
|
||||||
|
}
|
||||||
|
|
||||||
|
rtn_rvb->gain = 4;
|
||||||
|
|
||||||
|
_WM_reset_reverb(rtn_rvb);
|
||||||
|
return rtn_rvb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* _WM_free_reverb - free up memory used for reverb */
|
||||||
|
void _WM_free_reverb(struct _rvb *rvb) {
|
||||||
|
if (!rvb) return;
|
||||||
|
free(rvb->l_buf);
|
||||||
|
free(rvb->r_buf);
|
||||||
|
free(rvb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _WM_do_reverb(struct _rvb *rvb, signed long int *buffer, int size) {
|
||||||
|
int i, j, k;
|
||||||
|
signed long int l_buf_flt = 0;
|
||||||
|
signed long int r_buf_flt = 0;
|
||||||
|
signed long int l_rfl = 0;
|
||||||
|
signed long int r_rfl = 0;
|
||||||
|
int vol_div = 64;
|
||||||
|
|
||||||
|
for (i = 0; i < size; i += 2) {
|
||||||
|
signed long int tmp_l_val = 0;
|
||||||
|
signed long int tmp_r_val = 0;
|
||||||
|
/*
|
||||||
|
add the initial reflections
|
||||||
|
from each speaker, 4 to go the left, 4 go to the right buffers
|
||||||
|
*/
|
||||||
|
tmp_l_val = buffer[i] / vol_div;
|
||||||
|
tmp_r_val = buffer[i + 1] / vol_div;
|
||||||
|
for (j = 0; j < 4; j++) {
|
||||||
|
rvb->l_buf[rvb->l_sp_in[j]] += tmp_l_val;
|
||||||
|
rvb->l_sp_in[j] = (rvb->l_sp_in[j] + 1) % rvb->l_buf_size;
|
||||||
|
rvb->l_buf[rvb->r_sp_in[j]] += tmp_r_val;
|
||||||
|
rvb->r_sp_in[j] = (rvb->r_sp_in[j] + 1) % rvb->l_buf_size;
|
||||||
|
|
||||||
|
rvb->r_buf[rvb->l_sp_in[j + 4]] += tmp_l_val;
|
||||||
|
rvb->l_sp_in[j + 4] = (rvb->l_sp_in[j + 4] + 1) % rvb->r_buf_size;
|
||||||
|
rvb->r_buf[rvb->r_sp_in[j + 4]] += tmp_r_val;
|
||||||
|
rvb->r_sp_in[j + 4] = (rvb->r_sp_in[j + 4] + 1) % rvb->r_buf_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
filter the reverb output and add to buffer
|
||||||
|
*/
|
||||||
|
l_rfl = rvb->l_buf[rvb->l_out];
|
||||||
|
rvb->l_buf[rvb->l_out] = 0;
|
||||||
|
rvb->l_out = (rvb->l_out + 1) % rvb->l_buf_size;
|
||||||
|
|
||||||
|
r_rfl = rvb->r_buf[rvb->r_out];
|
||||||
|
rvb->r_buf[rvb->r_out] = 0;
|
||||||
|
rvb->r_out = (rvb->r_out + 1) % rvb->r_buf_size;
|
||||||
|
|
||||||
|
for (k = 0; k < 8; k++) {
|
||||||
|
for (j = 0; j < 6; j++) {
|
||||||
|
l_buf_flt = ((l_rfl * rvb->coeff[k][j][0])
|
||||||
|
+ (rvb->l_buf_flt_in[k][j][0] * rvb->coeff[k][j][1])
|
||||||
|
+ (rvb->l_buf_flt_in[k][j][1] * rvb->coeff[k][j][2])
|
||||||
|
- (rvb->l_buf_flt_out[k][j][0] * rvb->coeff[k][j][3])
|
||||||
|
- (rvb->l_buf_flt_out[k][j][1] * rvb->coeff[k][j][4]))
|
||||||
|
/ 1024;
|
||||||
|
rvb->l_buf_flt_in[k][j][1] = rvb->l_buf_flt_in[k][j][0];
|
||||||
|
rvb->l_buf_flt_in[k][j][0] = l_rfl;
|
||||||
|
rvb->l_buf_flt_out[k][j][1] = rvb->l_buf_flt_out[k][j][0];
|
||||||
|
rvb->l_buf_flt_out[k][j][0] = l_buf_flt;
|
||||||
|
buffer[i] += l_buf_flt / 8;
|
||||||
|
|
||||||
|
r_buf_flt = ((r_rfl * rvb->coeff[k][j][0])
|
||||||
|
+ (rvb->r_buf_flt_in[k][j][0] * rvb->coeff[k][j][1])
|
||||||
|
+ (rvb->r_buf_flt_in[k][j][1] * rvb->coeff[k][j][2])
|
||||||
|
- (rvb->r_buf_flt_out[k][j][0] * rvb->coeff[k][j][3])
|
||||||
|
- (rvb->r_buf_flt_out[k][j][1] * rvb->coeff[k][j][4]))
|
||||||
|
/ 1024;
|
||||||
|
rvb->r_buf_flt_in[k][j][1] = rvb->r_buf_flt_in[k][j][0];
|
||||||
|
rvb->r_buf_flt_in[k][j][0] = r_rfl;
|
||||||
|
rvb->r_buf_flt_out[k][j][1] = rvb->r_buf_flt_out[k][j][0];
|
||||||
|
rvb->r_buf_flt_out[k][j][0] = r_buf_flt;
|
||||||
|
buffer[i + 1] += r_buf_flt / 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
add filtered result back into the buffers but on the opposite side
|
||||||
|
*/
|
||||||
|
tmp_l_val = buffer[i + 1] / vol_div;
|
||||||
|
tmp_r_val = buffer[i] / vol_div;
|
||||||
|
for (j = 0; j < 4; j++) {
|
||||||
|
rvb->l_buf[rvb->l_in[j]] += tmp_l_val;
|
||||||
|
rvb->l_in[j] = (rvb->l_in[j] + 1) % rvb->l_buf_size;
|
||||||
|
|
||||||
|
rvb->r_buf[rvb->r_in[j]] += tmp_r_val;
|
||||||
|
rvb->r_in[j] = (rvb->r_in[j] + 1) % rvb->r_buf_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
57
src/wildmidi/reverb.h
Normal file
57
src/wildmidi/reverb.h
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
reverb.h
|
||||||
|
|
||||||
|
Midi Wavetable Processing library
|
||||||
|
|
||||||
|
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 __REVERB_H
|
||||||
|
#define __REVERB_H
|
||||||
|
|
||||||
|
struct _rvb {
|
||||||
|
/* filter data */
|
||||||
|
signed long int l_buf_flt_in[8][6][2];
|
||||||
|
signed long int l_buf_flt_out[8][6][2];
|
||||||
|
signed long int r_buf_flt_in[8][6][2];
|
||||||
|
signed long int r_buf_flt_out[8][6][2];
|
||||||
|
signed long int coeff[8][6][5];
|
||||||
|
/* buffer data */
|
||||||
|
signed long int *l_buf;
|
||||||
|
signed long int *r_buf;
|
||||||
|
int l_buf_size;
|
||||||
|
int r_buf_size;
|
||||||
|
int l_out;
|
||||||
|
int r_out;
|
||||||
|
int l_sp_in[8];
|
||||||
|
int r_sp_in[8];
|
||||||
|
int l_in[4];
|
||||||
|
int r_in[4];
|
||||||
|
int gain;
|
||||||
|
unsigned long int max_reverb_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void _WM_reset_reverb (struct _rvb *rvb);
|
||||||
|
extern struct _rvb *_WM_init_reverb(int rate, float room_x, float room_y, float listen_x, float listen_y);
|
||||||
|
extern void _WM_free_reverb (struct _rvb *rvb);
|
||||||
|
extern void _WM_do_reverb (struct _rvb *rvb, signed long int *buffer, int size);
|
||||||
|
|
||||||
|
#endif /* __REVERB_H */
|
4288
src/wildmidi/wildmidi_lib.cpp
Normal file
4288
src/wildmidi/wildmidi_lib.cpp
Normal file
File diff suppressed because it is too large
Load diff
75
src/wildmidi/wildmidi_lib.h
Normal file
75
src/wildmidi/wildmidi_lib.h
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
wildmidi_lib.h
|
||||||
|
|
||||||
|
Midi Wavetable Processing library
|
||||||
|
|
||||||
|
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 WILDMIDI_LIB_H
|
||||||
|
#define WILDMIDI_LIB_H
|
||||||
|
|
||||||
|
#define WM_MO_LOG_VOLUME 0x0001
|
||||||
|
#define WM_MO_ENHANCED_RESAMPLING 0x0002
|
||||||
|
#define WM_MO_REVERB 0x0004
|
||||||
|
#define WM_MO_WHOLETEMPO 0x8000
|
||||||
|
#define WM_MO_ROUNDTEMPO 0x2000
|
||||||
|
|
||||||
|
#define WM_GS_VERSION 0x0001
|
||||||
|
|
||||||
|
#define WM_SYMBOL // we do not need this in ZDoom
|
||||||
|
|
||||||
|
/*
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct _WM_Info {
|
||||||
|
char *copyright;
|
||||||
|
unsigned long int current_sample;
|
||||||
|
unsigned long int approx_total_samples;
|
||||||
|
unsigned short int mixer_options;
|
||||||
|
unsigned long int total_midi_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void midi;
|
||||||
|
|
||||||
|
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_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 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_Shutdown (void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* WILDMIDI_LIB_H */
|
||||||
|
|
86
src/wildmidi/wm_error.cpp
Normal file
86
src/wildmidi/wm_error.cpp
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
wm_error.c
|
||||||
|
error reporting
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include "wm_error.h"
|
||||||
|
#include "doomtype.h"
|
||||||
|
#include "v_text.h"
|
||||||
|
|
||||||
|
void _WM_ERROR_NEW(const char * wmfmt, ...) {
|
||||||
|
va_list args;
|
||||||
|
fprintf(stderr, "\r");
|
||||||
|
va_start(args, wmfmt);
|
||||||
|
vfprintf(stderr, wmfmt, args);
|
||||||
|
va_end(args);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _WM_ERROR(const char * func, unsigned int lne, int wmerno,
|
||||||
|
const char * wmfor, int error) {
|
||||||
|
|
||||||
|
static const char *errors[WM_ERR_MAX+1] = {
|
||||||
|
"No error",
|
||||||
|
"Unable to obtain memory",
|
||||||
|
"Unable to stat",
|
||||||
|
"Unable to load",
|
||||||
|
"Unable to open",
|
||||||
|
"Unable to read",
|
||||||
|
"Invalid or Unsuported file format",
|
||||||
|
"File corrupt",
|
||||||
|
"Library not Initialized",
|
||||||
|
"Invalid argument",
|
||||||
|
"Library Already Initialized",
|
||||||
|
"Not a midi file",
|
||||||
|
"Refusing to load unusually long file",
|
||||||
|
|
||||||
|
"Invalid error code"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (wmerno < 0 || wmerno > WM_ERR_MAX)
|
||||||
|
wmerno = WM_ERR_MAX;
|
||||||
|
|
||||||
|
if (wmfor != NULL) {
|
||||||
|
if (error != 0) {
|
||||||
|
Printf(TEXTCOLOR_RED "\rlibWildMidi(%s:%u): ERROR %s %s (%s)\n", func,
|
||||||
|
lne, errors[wmerno], wmfor, strerror(error));
|
||||||
|
} else {
|
||||||
|
Printf(TEXTCOLOR_RED "\rlibWildMidi(%s:%u): ERROR %s %s\n", func, lne,
|
||||||
|
errors[wmerno], wmfor);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (error != 0) {
|
||||||
|
Printf(TEXTCOLOR_RED "\rlibWildMidi(%s:%u): ERROR %s (%s)\n", func, lne,
|
||||||
|
errors[wmerno], strerror(error));
|
||||||
|
} else {
|
||||||
|
Printf(TEXTCOLOR_RED "\rlibWildMidi(%s:%u): ERROR %s\n", func, lne,
|
||||||
|
errors[wmerno]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
56
src/wildmidi/wm_error.h
Normal file
56
src/wildmidi/wm_error.h
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
wm_error.h
|
||||||
|
|
||||||
|
error reporting
|
||||||
|
|
||||||
|
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 __WM_ERROR_H
|
||||||
|
#define __WM_ERROR_H
|
||||||
|
|
||||||
|
enum {
|
||||||
|
WM_ERR_NONE = 0,
|
||||||
|
WM_ERR_MEM,
|
||||||
|
WM_ERR_STAT,
|
||||||
|
WM_ERR_LOAD,
|
||||||
|
WM_ERR_OPEN,
|
||||||
|
WM_ERR_READ,
|
||||||
|
WM_ERR_INVALID,
|
||||||
|
WM_ERR_CORUPT,
|
||||||
|
WM_ERR_NOT_INIT,
|
||||||
|
WM_ERR_INVALID_ARG,
|
||||||
|
WM_ERR_ALR_INIT,
|
||||||
|
WM_ERR_NOT_MIDI,
|
||||||
|
WM_ERR_LONGFIL,
|
||||||
|
|
||||||
|
WM_ERR_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void _WM_ERROR_NEW(const char * wmfmt, ...)
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__attribute__((format(printf, 1, 2)))
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
extern void _WM_ERROR(const char * func, unsigned int lne, int wmerno,
|
||||||
|
const char * wmfor, int error);
|
||||||
|
|
||||||
|
#endif /* __WM_ERROR_H */
|
|
@ -106,6 +106,7 @@
|
||||||
MapExports="true"
|
MapExports="true"
|
||||||
SubSystem="2"
|
SubSystem="2"
|
||||||
StackReserveSize="0"
|
StackReserveSize="0"
|
||||||
|
LargeAddressAware="2"
|
||||||
TerminalServerAware="2"
|
TerminalServerAware="2"
|
||||||
OptimizeReferences="2"
|
OptimizeReferences="2"
|
||||||
EnableCOMDATFolding="2"
|
EnableCOMDATFolding="2"
|
||||||
|
@ -223,6 +224,7 @@
|
||||||
MapExports="true"
|
MapExports="true"
|
||||||
SubSystem="2"
|
SubSystem="2"
|
||||||
StackReserveSize="0"
|
StackReserveSize="0"
|
||||||
|
LargeAddressAware="2"
|
||||||
TerminalServerAware="2"
|
TerminalServerAware="2"
|
||||||
OptimizeReferences="2"
|
OptimizeReferences="2"
|
||||||
EnableCOMDATFolding="2"
|
EnableCOMDATFolding="2"
|
||||||
|
@ -332,6 +334,7 @@
|
||||||
ProgramDatabaseFile=".\Debug/zdoomd.pdb"
|
ProgramDatabaseFile=".\Debug/zdoomd.pdb"
|
||||||
SubSystem="2"
|
SubSystem="2"
|
||||||
StackReserveSize="0"
|
StackReserveSize="0"
|
||||||
|
LargeAddressAware="2"
|
||||||
TerminalServerAware="2"
|
TerminalServerAware="2"
|
||||||
SetChecksum="false"
|
SetChecksum="false"
|
||||||
TargetMachine="0"
|
TargetMachine="0"
|
||||||
|
@ -440,6 +443,7 @@
|
||||||
ProgramDatabaseFile=".\Debug/zdoomd.pdb"
|
ProgramDatabaseFile=".\Debug/zdoomd.pdb"
|
||||||
SubSystem="2"
|
SubSystem="2"
|
||||||
StackReserveSize="0"
|
StackReserveSize="0"
|
||||||
|
LargeAddressAware="2"
|
||||||
TerminalServerAware="2"
|
TerminalServerAware="2"
|
||||||
SetChecksum="false"
|
SetChecksum="false"
|
||||||
TargetMachine="17"
|
TargetMachine="17"
|
||||||
|
|
Loading…
Reference in a new issue