SVN r44 (trunk)

This commit is contained in:
Christoph Oelckers 2006-04-14 12:58:52 +00:00
parent 4dd936e438
commit 07f35a7008
22 changed files with 423 additions and 119 deletions

97
FLAC/private/float.h Normal file
View file

@ -0,0 +1,97 @@
/* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2004,2005 Josh Coalson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - 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.
*
* - Neither the name of the Xiph.org Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``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 FOUNDATION OR
* CONTRIBUTORS 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.
*/
#ifndef FLAC__PRIVATE__FLOAT_H
#define FLAC__PRIVATE__FLOAT_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "FLAC/ordinals.h"
/*
* These typedefs make it easier to ensure that integer versions of
* the library really only contain integer operations. All the code
* in libFLAC should use FLAC__float and FLAC__double in place of
* float and double, and be protected by checks of the macro
* FLAC__INTEGER_ONLY_LIBRARY.
*
* FLAC__real is the basic floating point type used in LPC analysis.
*/
#ifndef FLAC__INTEGER_ONLY_LIBRARY
typedef double FLAC__double;
typedef float FLAC__float;
/*
* WATCHOUT: changing FLAC__real will change the signatures of many
* functions that have assembly language equivalents and break them.
*/
typedef float FLAC__real;
#else
/*
* The convention for FLAC__fixedpoint is to use the upper 16 bits
* for the integer part and lower 16 bits for the fractional part.
*/
typedef FLAC__int32 FLAC__fixedpoint;
extern const FLAC__fixedpoint FLAC__FP_ZERO;
extern const FLAC__fixedpoint FLAC__FP_ONE_HALF;
extern const FLAC__fixedpoint FLAC__FP_ONE;
extern const FLAC__fixedpoint FLAC__FP_LN2;
extern const FLAC__fixedpoint FLAC__FP_E;
#define FLAC__fixedpoint_trunc(x) ((x)>>16)
#define FLAC__fixedpoint_mul(x, y) ( (FLAC__fixedpoint) ( ((FLAC__int64)(x)*(FLAC__int64)(y)) >> 16 ) )
#define FLAC__fixedpoint_div(x, y) ( (FLAC__fixedpoint) ( ( ((FLAC__int64)(x)<<32) / (FLAC__int64)(y) ) >> 16 ) )
/*
* FLAC__fixedpoint_log2()
* --------------------------------------------------------------------
* Returns the base-2 logarithm of the fixed-point number 'x' using an
* algorithm by Knuth for x >= 1.0
*
* 'fracbits' is the number of fractional bits of 'x'. 'fracbits' must
* be < 32 and evenly divisible by 4 (0 is OK but not very precise).
*
* 'precision' roughly limits the number of iterations that are done;
* use (unsigned)(-1) for maximum precision.
*
* If 'x' is less than one -- that is, x < (1<<fracbits) -- then this
* function will punt and return 0.
*
* The return value will also have 'fracbits' fractional bits.
*/
FLAC__uint32 FLAC__fixedpoint_log2(FLAC__uint32 x, unsigned fracbits, unsigned precision);
#endif
#endif

View file

@ -1,3 +1,12 @@
April 14, 2006 (Changes by Graf Zahl)
- Added the missing file 'flac/private/float.h' to the repository.
- Added: In preparation for Zip-support the sound code has to be able to
load music data from memory, not just from files.
- Re-added I_SetMusicVolume to optionally reduce the music volume in Strife
conversations.
- Fixed: The total game time must not be restored when loading a snapshot
during a hub transition.
April 13, 2006 April 13, 2006
- Fix farchive.cpp swappers for GCC again. Now that they use entirely integer - Fix farchive.cpp swappers for GCC again. Now that they use entirely integer
math, they should work with all GCC versions. math, they should work with all GCC versions.

View file

@ -2290,7 +2290,7 @@ void G_AirControlChanged ()
void G_SerializeLevel (FArchive &arc, bool hubLoad) void G_SerializeLevel (FArchive &arc, bool hubLoad)
{ {
int i; int i = level.totaltime;
arc << level.flags arc << level.flags
<< level.fadeto << level.fadeto
@ -2300,7 +2300,11 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad)
<< level.gravity << level.gravity
<< level.aircontrol << level.aircontrol
<< level.maptime << level.maptime
<< level.totaltime; << i;
// Hub transitions must keep the current total time
if (!hubLoad)
level.totaltime=i;
if (arc.IsStoring ()) if (arc.IsStoring ())
{ {

View file

@ -21,7 +21,7 @@ EXTERN_CVAR (Bool, opl_onechip)
static OPLmusicBlock *BlockForStats; static OPLmusicBlock *BlockForStats;
OPLmusicBlock::OPLmusicBlock (FILE *file, int len, int rate, int maxSamples) OPLmusicBlock::OPLmusicBlock (FILE *file, char * musiccache, int len, int rate, int maxSamples)
: SampleRate (rate), NextTickIn (0), Looping (false), ScoreLen (len) : SampleRate (rate), NextTickIn (0), Looping (false), ScoreLen (len)
{ {
scoredata = NULL; scoredata = NULL;
@ -40,7 +40,22 @@ OPLmusicBlock::OPLmusicBlock (FILE *file, int len, int rate, int maxSamples)
#endif #endif
scoredata = new BYTE[len]; scoredata = new BYTE[len];
if (fread (scoredata, 1, len, file) != (size_t)len || io->OPLinit (TwoChips + 1, rate))
if (file)
{
if (fread (scoredata, 1, len, file) != (size_t)len)
{
delete[] scoredata;
scoredata = NULL;
return;
}
}
else
{
memcpy(scoredata, &musiccache[0], len);
}
if (io->OPLinit (TwoChips + 1, rate))
{ {
delete[] scoredata; delete[] scoredata;
scoredata = NULL; scoredata = NULL;

View file

@ -11,7 +11,7 @@
class OPLmusicBlock : public musicBlock class OPLmusicBlock : public musicBlock
{ {
public: public:
OPLmusicBlock (FILE *file, int len, int rate, int maxSamples); OPLmusicBlock (FILE *file, char * musiccache, int len, int rate, int maxSamples);
~OPLmusicBlock (); ~OPLmusicBlock ();
bool IsValid () const; bool IsValid () const;

View file

@ -15,6 +15,7 @@
#include "a_strifeglobal.h" #include "a_strifeglobal.h"
#include "a_keys.h" #include "a_keys.h"
#include "p_enemy.h" #include "p_enemy.h"
#include "sound/i_music.h"
// The conversations as they exist inside a SCRIPTxx lump. // The conversations as they exist inside a SCRIPTxx lump.
struct Response struct Response
@ -664,6 +665,12 @@ static void TakeStrifeItem (const TypeInfo *itemtype, int amount)
} }
} }
CUSTOM_CVAR(Float, dlg_musicvolume, 1.0f, CVAR_ARCHIVE)
{
if (self < 0.f) self = 0.f;
else if (self > 1.f) self = 1.f;
}
//============================================================================ //============================================================================
// //
// P_StartConversation // P_StartConversation
@ -723,6 +730,7 @@ void P_StartConversation (AActor *npc, AActor *pc)
if (CurNode->SpeakerVoice != 0) if (CurNode->SpeakerVoice != 0)
{ {
I_SetMusicVolume(dlg_musicvolume);
S_SoundID (npc, CHAN_VOICE, CurNode->SpeakerVoice, 1, ATTN_NORM); S_SoundID (npc, CHAN_VOICE, CurNode->SpeakerVoice, 1, ATTN_NORM);
} }
@ -1043,6 +1051,7 @@ static void PickConversationReply ()
} }
ConversationNPC->angle = ConversationNPCAngle; ConversationNPC->angle = ConversationNPCAngle;
I_SetMusicVolume(1.f);
} }
//============================================================================ //============================================================================
@ -1075,5 +1084,6 @@ void CleanupConversationMenu ()
DialogueLines = NULL; DialogueLines = NULL;
} }
ConversationItems.Clear (); ConversationItems.Clear ();
I_SetMusicVolume(1.f);
} }

View file

@ -265,8 +265,8 @@ void S_NoiseDebug (void)
BorderNeedRefresh = screen->GetPageCount (); BorderNeedRefresh = screen->GetPageCount ();
} }
static string LastLocalSndInfo = ""; static string LastLocalSndInfo;
static string LastLocalSndSeq = ""; static string LastLocalSndSeq;
void S_AddLocalSndInfo(int lump); void S_AddLocalSndInfo(int lump);
//========================================================================== //==========================================================================
@ -1414,6 +1414,8 @@ bool S_StartMusic (const char *m_id)
// specified, it will only be played if the specified CD is in a drive. // specified, it will only be played if the specified CD is in a drive.
//========================================================================== //==========================================================================
TArray<char> musiccache;
bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force) bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
{ {
if (!force && PlayList) if (!force && PlayList)
@ -1467,8 +1469,24 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
Printf ("Music \"%s\" not found\n", musicname); Printf ("Music \"%s\" not found\n", musicname);
return false; return false;
} }
offset = Wads.GetLumpOffset (lumpnum); if (!Wads.IsUncompressedFile(lumpnum))
length = Wads.LumpLength (lumpnum); {
// We must cache the music data and use it from memory.
// shut down old music before reallocating and overwriting the cache!
S_StopMusic (true);
offset = -1; // this tells the low level code that the music
// is being used from memory
length = Wads.LumpLength (lumpnum);
musiccache.Resize(length);
Wads.ReadLump(lumpnum, &musiccache[0]);
}
else
{
offset = Wads.GetLumpOffset (lumpnum);
length = Wads.LumpLength (lumpnum);
}
} }
else else
{ {
@ -1480,13 +1498,27 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
S_StopMusic (true); S_StopMusic (true);
// load & register it // load & register it
// Note by Graf Zahl: S_StopMusic NULLs this variable so there's nothing to delete anymore!
/*
if (mus_playing.name) if (mus_playing.name)
{ {
delete[] mus_playing.name; delete[] mus_playing.name;
} }
mus_playing.handle = I_RegisterSong (lumpnum != -1 ? */
Wads.GetWadFullName (Wads.GetLumpFile (lumpnum)) :
musicname, offset, length); if (offset!=-1)
{
mus_playing.handle = I_RegisterSong (lumpnum != -1 ?
Wads.GetWadFullName (Wads.GetLumpFile (lumpnum)) :
musicname, NULL, offset, length);
}
else
{
// musiccache is used globally because otherwise I'd have to pass
// it as a parameter through several layers of code.
mus_playing.handle = I_RegisterSong (NULL, &musiccache[0], -1, length);
}
} }
mus_playing.loop = looping; mus_playing.loop = looping;

View file

@ -611,11 +611,19 @@ SoundStream *FMODSoundRenderer::CreateStream (SoundStreamCallback callback, int
return NULL; return NULL;
} }
SoundStream *FMODSoundRenderer::OpenStream (const char *filename, int flags, int offset, int length) SoundStream *FMODSoundRenderer::OpenStream (const char *filename_or_data, int flags, int offset, int length)
{ {
unsigned int mode = FSOUND_NORMAL | FSOUND_2D; unsigned int mode = FSOUND_NORMAL | FSOUND_2D;
if (flags & SoundStream::Loop) mode |= FSOUND_LOOP_NORMAL; if (flags & SoundStream::Loop) mode |= FSOUND_LOOP_NORMAL;
FSOUND_STREAM *stream = FSOUND_Stream_Open (filename, mode, offset, length); FSOUND_STREAM *stream;
if (offset==-1)
{
mode |= FSOUND_LOADMEMORY;
offset=0;
}
stream = FSOUND_Stream_Open (filename_or_data, mode, offset, length);
if (stream != NULL) if (stream != NULL)
{ {
return new FMODStreamCapsule (stream); return new FMODStreamCapsule (stream);
@ -623,9 +631,19 @@ SoundStream *FMODSoundRenderer::OpenStream (const char *filename, int flags, int
return NULL; return NULL;
} }
SoundTrackerModule *FMODSoundRenderer::OpenModule (const char *filename, int offset, int length) SoundTrackerModule *FMODSoundRenderer::OpenModule (const char *filename_or_data, int offset, int length)
{ {
FMUSIC_MODULE *mod = FMUSIC_LoadSongEx (filename, offset, length, FSOUND_LOOP_NORMAL, NULL, 0); FMUSIC_MODULE *mod;
int mode = FSOUND_LOOP_NORMAL;
if (offset==-1)
{
mode |= FSOUND_LOADMEMORY;
offset=0;
}
mod = FMUSIC_LoadSongEx (filename_or_data, offset, length, mode, NULL, 0);
if (mod != NULL) if (mod != NULL)
{ {
return new FMUSICCapsule (mod); return new FMUSICCapsule (mod);

View file

@ -84,6 +84,7 @@ static bool MusicDown = true;
MusInfo *currSong; MusInfo *currSong;
int nomusic = 0; int nomusic = 0;
float relative_volume = 1.f; float relative_volume = 1.f;
float saved_relative_volume = 1.0f; // this could be used to implement an ACS FadeMusic function
//========================================================================== //==========================================================================
// //
@ -159,7 +160,7 @@ void I_PlaySong (void *handle, int _looping, float rel_vol)
if (!info || nomusic) if (!info || nomusic)
return; return;
relative_volume = rel_vol; saved_relative_volume = relative_volume = rel_vol;
info->Stop (); info->Stop ();
info->Play (_looping ? true : false); info->Play (_looping ? true : false);
@ -207,7 +208,7 @@ void I_UnRegisterSong (void *handle)
} }
} }
void *I_RegisterSong (const char *filename, int offset, int len) void *I_RegisterSong (const char *filename, char * musiccache, int offset, int len)
{ {
FILE *file; FILE *file;
MusInfo *info = NULL; MusInfo *info = NULL;
@ -218,63 +219,72 @@ void *I_RegisterSong (const char *filename, int offset, int len)
return 0; return 0;
} }
file = fopen (filename, "rb"); if (offset!=-1)
if (file == NULL)
{ {
return 0; file = fopen (filename, "rb");
} if (file == NULL)
{
return 0;
}
if (len == 0 && offset == 0) if (len == 0 && offset == 0)
{ {
fseek (file, 0, SEEK_END); fseek (file, 0, SEEK_END);
len = ftell (file); len = ftell (file);
fseek (file, 0, SEEK_SET); fseek (file, 0, SEEK_SET);
} }
else else
{ {
fseek (file, offset, SEEK_SET); fseek (file, offset, SEEK_SET);
} }
if (fread (&id, 4, 1, file) != 1) if (fread (&id, 4, 1, file) != 1)
{ {
fclose (file); fclose (file);
return 0; return 0;
}
fseek (file, -4, SEEK_CUR);
}
else
{
file = NULL;
memcpy(&id, &musiccache[0], 4);
} }
fseek (file, -4, SEEK_CUR);
// Check for MUS format // Check for MUS format
if (id == MAKE_ID('M','U','S',0x1a)) if (id == MAKE_ID('M','U','S',0x1a))
{ {
if (GSnd != NULL && opl_enable) if (GSnd != NULL && opl_enable)
{ {
info = new OPLMUSSong (file, len); info = new OPLMUSSong (file, musiccache, len);
} }
if (info == NULL) if (info == NULL)
{ {
#ifdef _WIN32 #ifdef _WIN32
if (snd_mididevice != -2) if (snd_mididevice != -2)
{ {
info = new MUSSong2 (file, len); info = new MUSSong2 (file, musiccache, len);
} }
else if (GSnd != NULL) else if (GSnd != NULL)
#endif // _WIN32 #endif // _WIN32
{ {
info = new TimiditySong (file, len); info = new TimiditySong (file, musiccache, len);
} }
} }
} }
// Check for MIDI format // Check for MIDI format
else if (id == MAKE_ID('M','T','h','d')) else if (id == MAKE_ID('M','T','h','d'))
{ {
// This is a midi file
#ifdef _WIN32 #ifdef _WIN32
if (snd_mididevice != -2) if (snd_mididevice != -2)
{ {
info = new MIDISong2 (file, len); info = new MIDISong2 (file, musiccache, len);
} }
else if (GSnd != NULL) else if (GSnd != NULL)
#endif // _WIN32 #endif // _WIN32
{ {
info = new TimiditySong (file, len); info = new TimiditySong (file, musiccache, len);
} }
} }
// Check for SPC format // Check for SPC format
@ -283,22 +293,32 @@ void *I_RegisterSong (const char *filename, int offset, int len)
{ {
char header[0x23]; char header[0x23];
if (fread (header, 1, 0x23, file) != 0x23) if (file != NULL)
{ {
fclose (file); if (fread (header, 1, 0x23, file) != 0x23)
return 0; {
fclose (file);
return 0;
}
fseek (file, -0x23, SEEK_CUR);
} }
fseek (file, -0x23, SEEK_CUR); else
if (strncmp (header+4, "-SPC700 Sound File Data", 23) == 0)
{ {
info = new SPCSong (file, len); memcpy(header, musiccache, 0x23);
}
if (strncmp (header+4, "-SPC700 Sound File Data", 23) == 0 &&
header[0x21] == '\x1a' &&
header[0x22] == '\x1a')
{
info = new SPCSong (file, musiccache, len);
} }
} }
#endif #endif
// Check for FLAC format // Check for FLAC format
else if (id == MAKE_ID('f','L','a','C')) else if (id == MAKE_ID('f','L','a','C'))
{ {
info = new FLACSong (file, len); info = new FLACSong (file, musiccache, len);
file = NULL; file = NULL;
} }
// Check for RDosPlay raw OPL format // Check for RDosPlay raw OPL format
@ -306,15 +326,23 @@ void *I_RegisterSong (const char *filename, int offset, int len)
{ {
DWORD fullsig[2]; DWORD fullsig[2];
if (fread (fullsig, 4, 2, file) != 2) if (file != NULL)
{ {
fclose (file); if (fread (fullsig, 4, 2, file) != 2)
return 0; {
fclose (file);
return 0;
}
fseek (file, -8, SEEK_CUR);
} }
fseek (file, -8, SEEK_CUR); else
{
memcpy(fullsig, musiccache, 8);
}
if (fullsig[1] == MAKE_ID('D','A','T','A')) if (fullsig[1] == MAKE_ID('D','A','T','A'))
{ {
info = new OPLMUSSong (file, len); info = new OPLMUSSong (file, musiccache, len);
} }
} }
// Check for Martin Fernandez's modified IMF format // Check for Martin Fernandez's modified IMF format
@ -322,15 +350,22 @@ void *I_RegisterSong (const char *filename, int offset, int len)
{ {
char fullhead[6]; char fullhead[6];
if (fread (fullhead, 1, 6, file) != 6) if (file != NULL)
{ {
fclose (file); if (fread (fullhead, 1, 6, file) != 6)
return 0; {
fclose (file);
return 0;
}
fseek (file, -6, SEEK_CUR);
}
else
{
memcpy(fullhead, musiccache, 6);
} }
fseek (file, -6, SEEK_CUR);
if (fullhead[4] == 'B' && fullhead[5] == 1) if (fullhead[4] == 'B' && fullhead[5] == 1)
{ {
info = new OPLMUSSong (file, len); info = new OPLMUSSong (file, musiccache, len);
} }
} }
@ -339,20 +374,23 @@ void *I_RegisterSong (const char *filename, int offset, int len)
// Check for CDDA "format" // Check for CDDA "format"
if (id == (('R')|(('I')<<8)|(('F')<<16)|(('F')<<24))) if (id == (('R')|(('I')<<8)|(('F')<<16)|(('F')<<24)))
{ {
DWORD subid; if (file != NULL)
fseek (file, 8, SEEK_CUR);
if (fread (&subid, 4, 1, file) != 1)
{ {
fclose (file); DWORD subid;
return 0;
}
fseek (file, -12, SEEK_CUR);
if (subid == (('C')|(('D')<<8)|(('D')<<16)|(('A')<<24))) fseek (file, 8, SEEK_CUR);
{ if (fread (&subid, 4, 1, file) != 1)
// This is a CDDA file {
info = new CDDAFile (file, len); fclose (file);
return 0;
}
fseek (file, -12, SEEK_CUR);
if (subid == (('C')|(('D')<<8)|(('D')<<16)|(('A')<<24)))
{
// This is a CDDA file
info = new CDDAFile (file, len);
}
} }
} }
@ -363,13 +401,13 @@ void *I_RegisterSong (const char *filename, int offset, int len)
if (info == NULL && GSnd != NULL && len >= 1024) if (info == NULL && GSnd != NULL && len >= 1024)
{ {
// First try loading it as MOD, then as a stream // First try loading it as MOD, then as a stream
fclose (file); if (file != NULL) fclose (file);
file = NULL; file = NULL;
info = new MODSong (filename, offset, len); info = new MODSong (offset>=0? filename : musiccache, offset, len);
if (!info->IsValid ()) if (!info->IsValid ())
{ {
delete info; delete info;
info = new StreamSong (filename, offset, len); info = new StreamSong (offset>=0? filename : musiccache, offset, len);
} }
} }
} }
@ -416,6 +454,17 @@ bool I_SetSongPosition (void *handle, int order)
return info ? info->SetPosition (order) : false; return info ? info->SetPosition (order) : false;
} }
// Sets relative music volume. Takes $musicvolume in SNDINFO into consideration
void I_SetMusicVolume (float factor)
{
factor = clamp<float>(factor, 0, 2.0f);
relative_volume = saved_relative_volume * factor;
#ifdef _WIN32
snd_midivolume.Callback();
#endif
snd_musicvolume.Callback();
}
CCMD(testmusicvol) CCMD(testmusicvol)
{ {
if (argv.argc() > 1) if (argv.argc() > 1)

View file

@ -53,7 +53,7 @@ void I_PauseSong (void *handle);
void I_ResumeSong (void *handle); void I_ResumeSong (void *handle);
// Registers a song handle to song data. // Registers a song handle to song data.
void *I_RegisterSong (const char *file, int offset, int length); void *I_RegisterSong (const char *file, char * musiccache, int offset, int length);
void *I_RegisterCDSong (int track, int cdid = 0); void *I_RegisterCDSong (int track, int cdid = 0);
// Called by anything that wishes to start music. // Called by anything that wishes to start music.

View file

@ -57,7 +57,7 @@ public:
class MUSSong2 : public MusInfo class MUSSong2 : public MusInfo
{ {
public: public:
MUSSong2 (FILE *file, int length); MUSSong2 (FILE *file, char * musiccache, int length);
~MUSSong2 (); ~MUSSong2 ();
void SetVolume (float volume); void SetVolume (float volume);
@ -102,7 +102,7 @@ protected:
class MIDISong2 : public MusInfo class MIDISong2 : public MusInfo
{ {
public: public:
MIDISong2 (FILE *file, int length); MIDISong2 (FILE *file, char * musiccache, int length);
~MIDISong2 (); ~MIDISong2 ();
void SetVolume (float volume); void SetVolume (float volume);
@ -204,7 +204,7 @@ typedef void *(__stdcall *EmuAPU_TYPE) (void *, DWORD, BYTE);
class SPCSong : public StreamSong class SPCSong : public StreamSong
{ {
public: public:
SPCSong (FILE *file, int length); SPCSong (FILE *file, char * musiccache, int length);
~SPCSong (); ~SPCSong ();
void Play (bool looping); void Play (bool looping);
bool IsPlaying (); bool IsPlaying ();
@ -241,7 +241,7 @@ protected:
class TimiditySong : public StreamSong class TimiditySong : public StreamSong
{ {
public: public:
TimiditySong (FILE *file, int length); TimiditySong (FILE *file, char * musiccache, int length);
~TimiditySong (); ~TimiditySong ();
void Play (bool looping); void Play (bool looping);
void Stop (); void Stop ();
@ -278,7 +278,7 @@ protected:
class OPLMUSSong : public StreamSong class OPLMUSSong : public StreamSong
{ {
public: public:
OPLMUSSong (FILE *file, int length); OPLMUSSong (FILE *file, char * musiccache, int length);
~OPLMUSSong (); ~OPLMUSSong ();
void Play (bool looping); void Play (bool looping);
bool IsPlaying (); bool IsPlaying ();
@ -296,7 +296,7 @@ protected:
class FLACSong : public StreamSong class FLACSong : public StreamSong
{ {
public: public:
FLACSong (FILE *file, int length); FLACSong (FILE *file, char * musiccache, int length);
~FLACSong (); ~FLACSong ();
void Play (bool looping); void Play (bool looping);
bool IsPlaying (); bool IsPlaying ();

View file

@ -9,7 +9,7 @@
class FLACSong::FLACStreamer : protected FLAC::Decoder::Stream class FLACSong::FLACStreamer : protected FLAC::Decoder::Stream
{ {
public: public:
FLACStreamer (FILE *file, int length); FLACStreamer (FILE *file, char * musiccache, int length);
~FLACStreamer (); ~FLACStreamer ();
bool ServiceStream (void *buff, int len, bool loop); bool ServiceStream (void *buff, int len, bool loop);
@ -24,7 +24,7 @@ protected:
void CopyToStream (void *&sbuff, FLAC__int32 **buffer, size_t ofs, size_t samples); void CopyToStream (void *&sbuff, FLAC__int32 **buffer, size_t ofs, size_t samples);
FileReader File; FileReader *File;
long StartPos, EndPos; long StartPos, EndPos;
FLAC__int32 *SamplePool[2]; FLAC__int32 *SamplePool[2];
@ -36,10 +36,10 @@ protected:
size_t SLen; size_t SLen;
}; };
FLACSong::FLACSong (FILE *file, int length) FLACSong::FLACSong (FILE *file, char * musiccache, int length)
: State (NULL) : State (NULL)
{ {
State = new FLACStreamer (file, length); State = new FLACStreamer (file, musiccache, length);
if (State->NumChannels > 0 && State->SampleBits > 0 && State->SampleRate > 0) if (State->NumChannels > 0 && State->SampleBits > 0 && State->SampleRate > 0)
{ {
@ -107,17 +107,25 @@ bool FLACSong::FillStream (SoundStream *stream, void *buff, int len, void *userd
return song->State->ServiceStream (buff, len, song->m_Looping); return song->State->ServiceStream (buff, len, song->m_Looping);
} }
FLACSong::FLACStreamer::FLACStreamer (FILE *iofile, int length) FLACSong::FLACStreamer::FLACStreamer (FILE *iofile, char * musiccache, int length)
: NumChannels (0), : NumChannels (0),
SampleBits (0), SampleBits (0),
SampleRate (0), SampleRate (0),
File (iofile, length),
PoolSize (0), PoolSize (0),
PoolUsed (0), PoolUsed (0),
PoolPos (0) PoolPos (0)
{ {
StartPos = File.Tell(); if (iofile != NULL)
EndPos = StartPos + File.GetLength(); {
File = new FileReader (iofile, length);
}
else
{
File = new MemoryReader(musiccache, length);
}
StartPos = File->Tell();
EndPos = StartPos + File->GetLength();
init (); init ();
process_until_end_of_metadata (); process_until_end_of_metadata ();
} }
@ -129,7 +137,8 @@ FLACSong::FLACStreamer::~FLACStreamer ()
delete[] SamplePool[0]; delete[] SamplePool[0];
SamplePool[0] = NULL; SamplePool[0] = NULL;
} }
fclose (File.GetFile()); if (File->GetFile()!=NULL) fclose (File->GetFile());
delete File;
} }
bool FLACSong::FLACStreamer::ServiceStream (void *buff1, int len, bool loop) bool FLACSong::FLACStreamer::ServiceStream (void *buff1, int len, bool loop)
@ -172,7 +181,7 @@ bool FLACSong::FLACStreamer::ServiceStream (void *buff1, int len, bool loop)
{ {
return FALSE; return FALSE;
} }
File.Seek (StartPos, SEEK_SET); File->Seek (StartPos, SEEK_SET);
reset (); reset ();
} }
@ -237,7 +246,7 @@ void FLACSong::FLACStreamer::CopyToStream (void *&sbuff, FLAC__int32 **buffer, s
{ {
if (*bytes > 0) if (*bytes > 0)
{ {
long here = File.Tell(); long here = File->Tell();
if (here == EndPos) if (here == EndPos)
{ {
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
@ -248,7 +257,7 @@ void FLACSong::FLACStreamer::CopyToStream (void *&sbuff, FLAC__int32 **buffer, s
{ {
*bytes = EndPos - here; *bytes = EndPos - here;
} }
File.Read (buffer, *bytes); File->Read (buffer, *bytes);
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
} }
} }

View file

@ -33,7 +33,7 @@ extern UINT mididevice;
static BYTE EventLengths[7] = { 2, 2, 2, 2, 1, 1, 2 }; static BYTE EventLengths[7] = { 2, 2, 2, 2, 1, 1, 2 };
static BYTE CommonLengths[15] = { 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static BYTE CommonLengths[15] = { 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
MIDISong2::MIDISong2 (FILE *file, int len) MIDISong2::MIDISong2 (FILE *file, char * musiccache, int len)
: MidiOut (0), PlayerThread (0), : MidiOut (0), PlayerThread (0),
PauseEvent (0), ExitEvent (0), VolumeChangeEvent (0), PauseEvent (0), ExitEvent (0), VolumeChangeEvent (0),
MusHeader (0) MusHeader (0)
@ -42,8 +42,15 @@ MIDISong2::MIDISong2 (FILE *file, int len)
int i; int i;
MusHeader = new BYTE[len]; MusHeader = new BYTE[len];
if (fread (MusHeader, 1, len, file) != (size_t)len) if (file != NULL)
return; {
if (fread (MusHeader, 1, len, file) != (size_t)len)
return;
}
else
{
memcpy(MusHeader, musiccache, len);
}
// Do some validation of the MIDI file // Do some validation of the MIDI file
if (MusHeader[4] != 0 || MusHeader[5] != 0 || MusHeader[6] != 0 || MusHeader[7] != 6) if (MusHeader[4] != 0 || MusHeader[5] != 0 || MusHeader[6] != 0 || MusHeader[7] != 6)

View file

@ -160,7 +160,7 @@ TimiditySong::~TimiditySong ()
#endif #endif
} }
TimiditySong::TimiditySong (FILE *file, int len) TimiditySong::TimiditySong (FILE *file, char * musiccache, int len)
: DiskName ("zmid"), : DiskName ("zmid"),
#ifdef _WIN32 #ifdef _WIN32
ReadWavePipe (INVALID_HANDLE_VALUE), WriteWavePipe (INVALID_HANDLE_VALUE), ReadWavePipe (INVALID_HANDLE_VALUE), WriteWavePipe (INVALID_HANDLE_VALUE),
@ -191,8 +191,15 @@ TimiditySong::TimiditySong (FILE *file, int len)
return; return;
} }
BYTE *buf = new BYTE[len]; BYTE *buf;
fread (buf, 1, len, file);
if (file!=NULL)
{
buf = new BYTE[len];
fread (buf, 1, len, file);
}
else buf = (BYTE*)musiccache;
// The file type has already been checked before this class instance was // The file type has already been checked before this class instance was
// created, so we only need to check one character to determine if this // created, so we only need to check one character to determine if this
@ -205,8 +212,11 @@ TimiditySong::TimiditySong (FILE *file, int len)
{ {
success = ProduceMIDI (buf, f); success = ProduceMIDI (buf, f);
} }
fclose (f); if (file!=NULL)
delete[] buf; {
fclose (f);
delete[] buf;
}
if (success) if (success)
{ {

View file

@ -57,9 +57,9 @@ MODSong::~MODSong ()
} }
} }
MODSong::MODSong (const char *file, int offset, int length) MODSong::MODSong (const char *file_or_data, int offset, int length)
{ {
m_Module = GSnd->OpenModule (file, offset, length); m_Module = GSnd->OpenModule (file_or_data, offset, length);
} }
bool MODSong::IsPlaying () bool MODSong::IsPlaying ()

View file

@ -28,14 +28,22 @@ static const BYTE CtrlTranslate[15] =
121, // reset all controllers 121, // reset all controllers
}; };
MUSSong2::MUSSong2 (FILE *file, int len) MUSSong2::MUSSong2 (FILE *file, char * musiccache, int len)
: MidiOut (0), PlayerThread (0), : MidiOut (0), PlayerThread (0),
PauseEvent (0), ExitEvent (0), VolumeChangeEvent (0), PauseEvent (0), ExitEvent (0), VolumeChangeEvent (0),
MusBuffer (0), MusHeader (0) MusBuffer (0), MusHeader (0)
{ {
MusHeader = (MUSHeader *)new BYTE[len]; MusHeader = (MUSHeader *)new BYTE[len];
if (fread (MusHeader, 1, len, file) != (size_t)len)
return; if (file != NULL)
{
if (fread (MusHeader, 1, len, file) != (size_t)len)
return;
}
else
{
memcpy(MusHeader, musiccache, len);
}
// Do some validation of the MUS file // Do some validation of the MUS file
if (MusHeader->Magic != MAKE_ID('M','U','S','\x1a')) if (MusHeader->Magic != MAKE_ID('M','U','S','\x1a'))

View file

@ -21,12 +21,12 @@ CUSTOM_CVAR (Bool, opl_onechip, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
} }
OPLMUSSong::OPLMUSSong (FILE *file, int len) OPLMUSSong::OPLMUSSong (FILE *file, char * musiccache, int len)
{ {
int rate = *opl_frequency; int rate = *opl_frequency;
int samples = rate/14; int samples = rate/14;
Music = new OPLmusicBlock (file, len, rate, samples); Music = new OPLmusicBlock (file, musiccache, len, rate, samples);
m_Stream = GSnd->CreateStream (FillStream, samples*2, m_Stream = GSnd->CreateStream (FillStream, samples*2,
SoundStream::Mono, rate, this); SoundStream::Mono, rate, this);

View file

@ -46,15 +46,19 @@ CUSTOM_CVAR (Int, spc_frequency, 32000, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
} }
} }
SPCSong::SPCSong (FILE *iofile, int len) SPCSong::SPCSong (FILE *iofile, char * musiccache, int len)
{ {
FileReader file (iofile, len);
if (!LoadEmu ()) if (!LoadEmu ())
{ {
return; return;
} }
FileReader * file;
if (iofile != NULL) file = new FileReader(iofile, len);
else file = new MemoryReader(musiccache, len);
// No sense in using a higher frequency than the final output // No sense in using a higher frequency than the final output
int freq = MIN (*spc_frequency, *snd_samplerate); int freq = MIN (*spc_frequency, *snd_samplerate);
@ -69,6 +73,7 @@ SPCSong::SPCSong (FILE *iofile, int len)
{ {
Printf (PRINT_BOLD, "Could not create music stream.\n"); Printf (PRINT_BOLD, "Could not create music stream.\n");
CloseEmu (); CloseEmu ();
delete file;
return; return;
} }
@ -78,7 +83,7 @@ SPCSong::SPCSong (FILE *iofile, int len)
BYTE spcfile[66048]; BYTE spcfile[66048];
file.Read (spcfile, 66048); file->Read (spcfile, 66048);
if (LoadSPCFile != NULL) if (LoadSPCFile != NULL)
{ {
@ -104,19 +109,19 @@ SPCSong::SPCSong (FILE *iofile, int len)
{ {
DWORD id; DWORD id;
file.Read (&id, 4); file->Read (&id, 4);
if (id == MAKE_ID('x','i','d','6')) if (id == MAKE_ID('x','i','d','6'))
{ {
DWORD size; DWORD size;
file >> size; (*file) >> size;
DWORD pos = 66056; DWORD pos = 66056;
while (pos < size) while (pos < size)
{ {
XID6Tag tag; XID6Tag tag;
file.Read (&tag, 4); file->Read (&tag, 4);
if (tag.Type == 0) if (tag.Type == 0)
{ {
// Don't care about these // Don't care about these
@ -128,7 +133,7 @@ SPCSong::SPCSong (FILE *iofile, int len)
if (tag.Type == 4 && tag.ID == 0x36) if (tag.Type == 4 && tag.ID == 0x36)
{ {
DWORD amp; DWORD amp;
file >> amp; (*file) >> amp;
if (APUVersion < 98) if (APUVersion < 98)
{ {
amp >>= 12; amp >>= 12;
@ -137,11 +142,12 @@ SPCSong::SPCSong (FILE *iofile, int len)
break; break;
} }
} }
file.Seek (LittleShort(tag.Value), SEEK_CUR); file->Seek (LittleShort(tag.Value), SEEK_CUR);
} }
} }
} }
} }
delete file;
} }
SPCSong::~SPCSong () SPCSong::~SPCSong ()

View file

@ -54,9 +54,9 @@ StreamSong::~StreamSong ()
} }
} }
StreamSong::StreamSong (const char *filename, int offset, int len) StreamSong::StreamSong (const char *filename_or_data, int offset, int len)
{ {
m_Stream = GSnd->OpenStream (filename, SoundStream::Loop, offset, len); m_Stream = GSnd->OpenStream (filename_or_data, SoundStream::Loop, offset, len);
} }
bool StreamSong::IsPlaying () bool StreamSong::IsPlaying ()

View file

@ -3,6 +3,7 @@
#include <FLAC++/decoder.h> #include <FLAC++/decoder.h>
#include "s_sound.h" #include "s_sound.h"
#include "files.h" #include "files.h"
#include "w_wad.h"
class FLACSampleLoader : protected FLAC::Decoder::Stream class FLACSampleLoader : protected FLAC::Decoder::Stream
{ {
@ -23,7 +24,7 @@ protected:
void CopyToSample (size_t ofs, FLAC__int32 **buffer, size_t samples); void CopyToSample (size_t ofs, FLAC__int32 **buffer, size_t samples);
FileReader File; FWadLump File;
long StartPos, EndPos; long StartPos, EndPos;
void *SBuff, *SBuff2; void *SBuff, *SBuff2;

View file

@ -1271,6 +1271,32 @@ const char *FWadCollection::GetWadFullName (int wadnum) const
} }
//==========================================================================
//
// IsUncompressedFile
//
// Returns true when the lump is available as an uncompressed portion of
// a file. The music player can play such lumps by streaming but anything
// else has to be loaded into memory first.
//
//==========================================================================
bool FWadCollection::IsUncompressedFile(int lump) const
{
/*
if ((unsigned)lump >= (unsigned)NumLumps)
{
I_Error ("IsUncompressedFile: %u >= NumLumps",lump);
}
LumpRecord * l = &LumpInfo[lump];
if (l->flags & LUMPF_COMPRESSED) return false;
else if (Wads[l->wadnum]->MemoryData!=NULL) return false;
*/
return true;
}
//========================================================================== //==========================================================================
// //
// W_SkinHack // W_SkinHack

View file

@ -30,10 +30,12 @@
#define IWAD_ID (('I'<<24)|('W'<<16)|('A'<<8)|('D')) #define IWAD_ID (('I'<<24)|('W'<<16)|('A'<<8)|('D'))
#define PWAD_ID (('P'<<24)|('W'<<16)|('A'<<8)|('D')) #define PWAD_ID (('P'<<24)|('W'<<16)|('A'<<8)|('D'))
#define RFF_ID (('R'<<24)|('F'<<16)|('F'<<8)|(0x1a)) #define RFF_ID (('R'<<24)|('F'<<16)|('F'<<8)|(0x1a))
#define ZIP_ID (('P'<<24)|('K'<<16)|(3<<8)|(4))
#else #else
#define IWAD_ID (('I')|('W'<<8)|('A'<<16)|('D'<<24)) #define IWAD_ID (('I')|('W'<<8)|('A'<<16)|('D'<<24))
#define PWAD_ID (('P')|('W'<<8)|('A'<<16)|('D'<<24)) #define PWAD_ID (('P')|('W'<<8)|('A'<<16)|('D'<<24))
#define RFF_ID (('R')|('F'<<8)|('F'<<16)|(0x1a<<24)) #define RFF_ID (('R')|('F'<<8)|('F'<<16)|(0x1a<<24))
#define ZIP_ID (('P')|('K'<<8)|(3<<16)|(4<<24))
#endif #endif
// [RH] Remove limit on number of WAD files // [RH] Remove limit on number of WAD files
@ -167,6 +169,7 @@ public:
int GetLumpNamespace (int lump) const; // [RH] Returns the namespace a lump belongs to int GetLumpNamespace (int lump) const; // [RH] Returns the namespace a lump belongs to
bool CheckLumpName (int lump, const char *name) const; // [RH] Returns true if the names match bool CheckLumpName (int lump, const char *name) const; // [RH] Returns true if the names match
bool IsUncompressedFile(int lump) const;
int GetNumLumps () const; int GetNumLumps () const;
protected: protected: