mirror of
https://github.com/dhewm/dhewm3.git
synced 2025-01-19 07:51:54 +00:00
Use stb_vorbis instead of libogg and libvorbis(file)
Seems to work; note that idWaveFile is only ever used in idSoundSample::Load() As stb_vorbis doesn't support custom callbacks for reading, I feed it the full .ogg files as a buffer. Shouldn't make much of a difference though - either the whole file is decoded on load anyway (so the buffer is freed after decoding, or it's streamed, but in that case the old code also kept the whole ogg file in memory by using idFily_Memory. I also added warning messages in places where calls to stb_vorbis_*() can fail, where there were none in the equivalent libvorbis code.
This commit is contained in:
parent
1ae268a20e
commit
1c13fe2d39
7 changed files with 133 additions and 368 deletions
|
@ -153,15 +153,6 @@ endif()
|
||||||
find_package(ZLIB REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||||
|
|
||||||
find_package(OGG REQUIRED)
|
|
||||||
include_directories(${OGG_INCLUDE_DIR})
|
|
||||||
|
|
||||||
find_package(Vorbis REQUIRED)
|
|
||||||
include_directories(${VORBIS_INCLUDE_DIR})
|
|
||||||
|
|
||||||
find_package(VorbisFile REQUIRED)
|
|
||||||
include_directories(${VORBISFILE_INCLUDE_DIR})
|
|
||||||
|
|
||||||
find_package(OpenAL REQUIRED)
|
find_package(OpenAL REQUIRED)
|
||||||
include_directories(${OPENAL_INCLUDE_DIR})
|
include_directories(${OPENAL_INCLUDE_DIR})
|
||||||
|
|
||||||
|
@ -1014,9 +1005,6 @@ if(CORE)
|
||||||
target_link_libraries(${DHEWM3BINARY}
|
target_link_libraries(${DHEWM3BINARY}
|
||||||
idlib
|
idlib
|
||||||
${OPENAL_LIBRARY}
|
${OPENAL_LIBRARY}
|
||||||
${VORBISFILE_LIBRARIES}
|
|
||||||
${VORBIS_LIBRARIES}
|
|
||||||
${OGG_LIBRARIES}
|
|
||||||
${CURL_LIBRARY}
|
${CURL_LIBRARY}
|
||||||
${ZLIB_LIBRARY}
|
${ZLIB_LIBRARY}
|
||||||
${SDLx_LIBRARY}
|
${SDLx_LIBRARY}
|
||||||
|
@ -1046,9 +1034,6 @@ if(DEDICATED)
|
||||||
set_target_properties(${DHEWM3BINARY}ded PROPERTIES LINK_FLAGS "${ldflags}")
|
set_target_properties(${DHEWM3BINARY}ded PROPERTIES LINK_FLAGS "${ldflags}")
|
||||||
target_link_libraries(${DHEWM3BINARY}ded
|
target_link_libraries(${DHEWM3BINARY}ded
|
||||||
idlib
|
idlib
|
||||||
${VORBISFILE_LIBRARIES}
|
|
||||||
${VORBIS_LIBRARIES}
|
|
||||||
${OGG_LIBRARIES}
|
|
||||||
${CURL_LIBRARY}
|
${CURL_LIBRARY}
|
||||||
${ZLIB_LIBRARY}
|
${ZLIB_LIBRARY}
|
||||||
${SDLx_LIBRARY}
|
${SDLx_LIBRARY}
|
||||||
|
|
|
@ -26,9 +26,17 @@ If you have questions concerning this license or the applicable additional terms
|
||||||
===========================================================================
|
===========================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define OV_EXCLUDE_STATIC_CALLBACKS
|
|
||||||
#include <vorbis/codec.h>
|
#include "SDL_endian.h"
|
||||||
#include <vorbis/vorbisfile.h>
|
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||||
|
#define STB_VORBIS_BIG_ENDIAN
|
||||||
|
#endif
|
||||||
|
#define STB_VORBIS_NO_STDIO
|
||||||
|
#define STB_VORBIS_NO_PUSHDATA_API // we're using the pulldata API
|
||||||
|
#include "stb_vorbis.h"
|
||||||
|
#undef L // the implementation part of stb_vorbis has these defines, they confuse other code..
|
||||||
|
#undef C
|
||||||
|
#undef R
|
||||||
|
|
||||||
#include "sys/platform.h"
|
#include "sys/platform.h"
|
||||||
#include "framework/FileSystem.h"
|
#include "framework/FileSystem.h"
|
||||||
|
@ -49,6 +57,9 @@ idDynamicBlockAlloc<byte, 1<<20, 128> decoderMemoryAllocator;
|
||||||
|
|
||||||
const int MIN_OGGVORBIS_MEMORY = 768 * 1024;
|
const int MIN_OGGVORBIS_MEMORY = 768 * 1024;
|
||||||
|
|
||||||
|
// DG: this was only used with original Doom3's patched libvorbis
|
||||||
|
// TODO: could use it in stb_vorbis setup_malloc() etc
|
||||||
|
#if 0
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void *_decoder_malloc( size_t size );
|
void *_decoder_malloc( size_t size );
|
||||||
void *_decoder_calloc( size_t num, size_t size );
|
void *_decoder_calloc( size_t num, size_t size );
|
||||||
|
@ -78,6 +89,51 @@ void *_decoder_realloc( void *memblock, size_t size ) {
|
||||||
void _decoder_free( void *memblock ) {
|
void _decoder_free( void *memblock ) {
|
||||||
decoderMemoryAllocator.Free( (byte *)memblock );
|
decoderMemoryAllocator.Free( (byte *)memblock );
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const char* my_stbv_strerror(int stbVorbisError)
|
||||||
|
{
|
||||||
|
switch(stbVorbisError)
|
||||||
|
{
|
||||||
|
case VORBIS__no_error: return "No Error";
|
||||||
|
#define ERRCASE(X) \
|
||||||
|
case VORBIS_ ## X : return #X;
|
||||||
|
|
||||||
|
ERRCASE( need_more_data ) // not a real error
|
||||||
|
|
||||||
|
ERRCASE( invalid_api_mixing ) // can't mix API modes
|
||||||
|
ERRCASE( outofmem ) // not enough memory
|
||||||
|
ERRCASE( feature_not_supported ) // uses floor 0
|
||||||
|
ERRCASE( too_many_channels ) // STB_VORBIS_MAX_CHANNELS is too small
|
||||||
|
ERRCASE( file_open_failure ) // fopen() failed
|
||||||
|
ERRCASE( seek_without_length ) // can't seek in unknown-length file
|
||||||
|
|
||||||
|
ERRCASE( unexpected_eof ) // file is truncated?
|
||||||
|
ERRCASE( seek_invalid ) // seek past EOF
|
||||||
|
|
||||||
|
// decoding errors (corrupt/invalid stream) -- you probably
|
||||||
|
// don't care about the exact details of these
|
||||||
|
|
||||||
|
// vorbis errors:
|
||||||
|
ERRCASE( invalid_setup )
|
||||||
|
ERRCASE( invalid_stream )
|
||||||
|
|
||||||
|
// ogg errors:
|
||||||
|
ERRCASE( missing_capture_pattern )
|
||||||
|
ERRCASE( invalid_stream_structure_version )
|
||||||
|
ERRCASE( continued_packet_flag_invalid )
|
||||||
|
ERRCASE( incorrect_stream_serial_number )
|
||||||
|
ERRCASE( invalid_first_page )
|
||||||
|
ERRCASE( bad_packet_type )
|
||||||
|
ERRCASE( cant_find_last_page )
|
||||||
|
ERRCASE( seek_failed )
|
||||||
|
ERRCASE( ogg_skeleton_not_supported )
|
||||||
|
|
||||||
|
#undef ERRCASE
|
||||||
|
}
|
||||||
|
assert(0 && "unknown stb_vorbis errorcode!");
|
||||||
|
return "Unknown Error!";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -88,80 +144,12 @@ void _decoder_free( void *memblock ) {
|
||||||
===================================================================================
|
===================================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
====================
|
|
||||||
FS_ReadOGG
|
|
||||||
====================
|
|
||||||
*/
|
|
||||||
size_t FS_ReadOGG( void *dest, size_t size1, size_t size2, void *fh ) {
|
|
||||||
idFile *f = reinterpret_cast<idFile *>(fh);
|
|
||||||
return f->Read( dest, size1 * size2 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
====================
|
|
||||||
FS_SeekOGG
|
|
||||||
====================
|
|
||||||
*/
|
|
||||||
int FS_SeekOGG( void *fh, ogg_int64_t to, int type ) {
|
|
||||||
fsOrigin_t retype = FS_SEEK_SET;
|
|
||||||
|
|
||||||
if ( type == SEEK_CUR ) {
|
|
||||||
retype = FS_SEEK_CUR;
|
|
||||||
} else if ( type == SEEK_END ) {
|
|
||||||
retype = FS_SEEK_END;
|
|
||||||
} else if ( type == SEEK_SET ) {
|
|
||||||
retype = FS_SEEK_SET;
|
|
||||||
} else {
|
|
||||||
common->FatalError( "fs_seekOGG: seek without type\n" );
|
|
||||||
}
|
|
||||||
idFile *f = reinterpret_cast<idFile *>(fh);
|
|
||||||
return f->Seek( to, retype );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
====================
|
|
||||||
FS_CloseOGG
|
|
||||||
====================
|
|
||||||
*/
|
|
||||||
int FS_CloseOGG( void *fh ) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
====================
|
|
||||||
FS_TellOGG
|
|
||||||
====================
|
|
||||||
*/
|
|
||||||
long FS_TellOGG( void *fh ) {
|
|
||||||
idFile *f = reinterpret_cast<idFile *>(fh);
|
|
||||||
return f->Tell();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
====================
|
|
||||||
ov_openFile
|
|
||||||
====================
|
|
||||||
*/
|
|
||||||
int ov_openFile( idFile *f, OggVorbis_File *vf ) {
|
|
||||||
ov_callbacks callbacks;
|
|
||||||
|
|
||||||
memset( vf, 0, sizeof( OggVorbis_File ) );
|
|
||||||
|
|
||||||
callbacks.read_func = FS_ReadOGG;
|
|
||||||
callbacks.seek_func = FS_SeekOGG;
|
|
||||||
callbacks.close_func = FS_CloseOGG;
|
|
||||||
callbacks.tell_func = FS_TellOGG;
|
|
||||||
return ov_open_callbacks((void *)f, vf, NULL, -1, callbacks);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
====================
|
====================
|
||||||
idWaveFile::OpenOGG
|
idWaveFile::OpenOGG
|
||||||
====================
|
====================
|
||||||
*/
|
*/
|
||||||
int idWaveFile::OpenOGG( const char* strFileName, waveformatex_t *pwfx ) {
|
int idWaveFile::OpenOGG( const char* strFileName, waveformatex_t *pwfx ) {
|
||||||
OggVorbis_File *ov;
|
|
||||||
|
|
||||||
memset( pwfx, 0, sizeof( waveformatex_t ) );
|
memset( pwfx, 0, sizeof( waveformatex_t ) );
|
||||||
|
|
||||||
|
@ -172,11 +160,17 @@ int idWaveFile::OpenOGG( const char* strFileName, waveformatex_t *pwfx ) {
|
||||||
|
|
||||||
Sys_EnterCriticalSection( CRITICAL_SECTION_ONE );
|
Sys_EnterCriticalSection( CRITICAL_SECTION_ONE );
|
||||||
|
|
||||||
ov = new OggVorbis_File;
|
int fileSize = mhmmio->Length();
|
||||||
|
byte* oggFileData = (byte*)Mem_Alloc( fileSize );
|
||||||
|
|
||||||
if( ov_openFile( mhmmio, ov ) < 0 ) {
|
mhmmio->Read( oggFileData, fileSize );
|
||||||
delete ov;
|
|
||||||
|
int stbverr = 0;
|
||||||
|
stb_vorbis *ov = stb_vorbis_open_memory( oggFileData, fileSize, &stbverr, NULL );
|
||||||
|
if( ov == NULL ) {
|
||||||
|
Mem_Free( oggFileData );
|
||||||
Sys_LeaveCriticalSection( CRITICAL_SECTION_ONE );
|
Sys_LeaveCriticalSection( CRITICAL_SECTION_ONE );
|
||||||
|
common->Warning( "Opening OGG file '%s' with stb_vorbis failed: %s\n", strFileName, my_stbv_strerror(stbverr) );
|
||||||
fileSystem->CloseFile( mhmmio );
|
fileSystem->CloseFile( mhmmio );
|
||||||
mhmmio = NULL;
|
mhmmio = NULL;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -184,20 +178,26 @@ int idWaveFile::OpenOGG( const char* strFileName, waveformatex_t *pwfx ) {
|
||||||
|
|
||||||
mfileTime = mhmmio->Timestamp();
|
mfileTime = mhmmio->Timestamp();
|
||||||
|
|
||||||
vorbis_info *vi = ov_info( ov, -1 );
|
stb_vorbis_info stbvi = stb_vorbis_get_info( ov );
|
||||||
|
int numSamples = stb_vorbis_stream_length_in_samples( ov );
|
||||||
|
if(numSamples == 0) {
|
||||||
|
stbverr = stb_vorbis_get_error( ov );
|
||||||
|
common->Warning( "Couldn't get sound length of '%s' with stb_vorbis: %s\n", strFileName, my_stbv_strerror(stbverr) );
|
||||||
|
// TODO: return -1 etc?
|
||||||
|
}
|
||||||
|
|
||||||
mpwfx.Format.nSamplesPerSec = vi->rate;
|
mpwfx.Format.nSamplesPerSec = stbvi.sample_rate;
|
||||||
mpwfx.Format.nChannels = vi->channels;
|
mpwfx.Format.nChannels = stbvi.channels;
|
||||||
mpwfx.Format.wBitsPerSample = sizeof(short) * 8;
|
mpwfx.Format.wBitsPerSample = sizeof(short) * 8;
|
||||||
mdwSize = ov_pcm_total( ov, -1 ) * vi->channels; // pcm samples * num channels
|
mdwSize = numSamples * stbvi.channels; // pcm samples * num channels
|
||||||
mbIsReadingFromMemory = false;
|
mbIsReadingFromMemory = false;
|
||||||
|
|
||||||
if ( idSoundSystemLocal::s_realTimeDecoding.GetBool() ) {
|
if ( idSoundSystemLocal::s_realTimeDecoding.GetBool() ) {
|
||||||
|
|
||||||
ov_clear( ov );
|
stb_vorbis_close( ov );
|
||||||
fileSystem->CloseFile( mhmmio );
|
fileSystem->CloseFile( mhmmio );
|
||||||
mhmmio = NULL;
|
mhmmio = NULL;
|
||||||
delete ov;
|
Mem_Free( oggFileData );
|
||||||
|
|
||||||
mpwfx.Format.wFormatTag = WAVE_FORMAT_TAG_OGG;
|
mpwfx.Format.wFormatTag = WAVE_FORMAT_TAG_OGG;
|
||||||
mhmmio = fileSystem->OpenFileRead( strFileName );
|
mhmmio = fileSystem->OpenFileRead( strFileName );
|
||||||
|
@ -206,6 +206,7 @@ int idWaveFile::OpenOGG( const char* strFileName, waveformatex_t *pwfx ) {
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
ogg = ov;
|
ogg = ov;
|
||||||
|
oggData = oggFileData;
|
||||||
|
|
||||||
mpwfx.Format.wFormatTag = WAVE_FORMAT_TAG_PCM;
|
mpwfx.Format.wFormatTag = WAVE_FORMAT_TAG_PCM;
|
||||||
mMemSize = mdwSize * sizeof( short );
|
mMemSize = mdwSize * sizeof( short );
|
||||||
|
@ -226,18 +227,27 @@ idWaveFile::ReadOGG
|
||||||
====================
|
====================
|
||||||
*/
|
*/
|
||||||
int idWaveFile::ReadOGG( byte* pBuffer, int dwSizeToRead, int *pdwSizeRead ) {
|
int idWaveFile::ReadOGG( byte* pBuffer, int dwSizeToRead, int *pdwSizeRead ) {
|
||||||
int total = dwSizeToRead;
|
// DG: Note that stb_vorbis_get_samples_short_interleaved() operates on shorts,
|
||||||
char *bufferPtr = (char *)pBuffer;
|
// while VorbisFile's ov_read() operates on bytes, so some numbers are different
|
||||||
OggVorbis_File *ov = (OggVorbis_File *) ogg;
|
int total = dwSizeToRead/sizeof(short);
|
||||||
|
short *bufferPtr = (short *)pBuffer;
|
||||||
|
stb_vorbis *ov = (stb_vorbis *) ogg;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
int ret = ov_read( ov, bufferPtr, total >= 4096 ? 4096 : total, Swap_IsBigEndian(), 2, 1, NULL );
|
int numShorts = total; // total >= 2048 ? 2048 : total; - I think stb_vorbis doesn't mind decoding all of it
|
||||||
|
int ret = stb_vorbis_get_samples_short_interleaved( ov, mpwfx.Format.nChannels, bufferPtr, numShorts );
|
||||||
if ( ret == 0 ) {
|
if ( ret == 0 ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ( ret < 0 ) {
|
if ( ret < 0 ) {
|
||||||
|
int stbverr = stb_vorbis_get_error( ov );
|
||||||
|
common->Warning( "idWaveFile::ReadOGG() stb_vorbis_get_samples_short_interleaved() failed: %s\n", my_stbv_strerror(stbverr) );
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
// for some reason, stb_vorbis_get_samples_short_interleaved() takes the absolute
|
||||||
|
// number of shorts to read as a function argument, but returns the number of samples
|
||||||
|
// that were read PER CHANNEL
|
||||||
|
ret *= mpwfx.Format.nChannels;
|
||||||
bufferPtr += ret;
|
bufferPtr += ret;
|
||||||
total -= ret;
|
total -= ret;
|
||||||
} while( total > 0 );
|
} while( total > 0 );
|
||||||
|
@ -257,15 +267,16 @@ idWaveFile::CloseOGG
|
||||||
====================
|
====================
|
||||||
*/
|
*/
|
||||||
int idWaveFile::CloseOGG( void ) {
|
int idWaveFile::CloseOGG( void ) {
|
||||||
OggVorbis_File *ov = (OggVorbis_File *) ogg;
|
stb_vorbis* ov = (stb_vorbis *)ogg;
|
||||||
if ( ov != NULL ) {
|
if ( ov != NULL ) {
|
||||||
Sys_EnterCriticalSection( CRITICAL_SECTION_ONE );
|
Sys_EnterCriticalSection( CRITICAL_SECTION_ONE );
|
||||||
ov_clear( ov );
|
stb_vorbis_close( ov );
|
||||||
delete ov;
|
|
||||||
Sys_LeaveCriticalSection( CRITICAL_SECTION_ONE );
|
Sys_LeaveCriticalSection( CRITICAL_SECTION_ONE );
|
||||||
fileSystem->CloseFile( mhmmio );
|
fileSystem->CloseFile( mhmmio );
|
||||||
mhmmio = NULL;
|
mhmmio = NULL;
|
||||||
ogg = NULL;
|
ogg = NULL;
|
||||||
|
Mem_Free( oggData );
|
||||||
|
oggData = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -297,9 +308,8 @@ private:
|
||||||
idSoundSample * lastSample; // last sample being decoded
|
idSoundSample * lastSample; // last sample being decoded
|
||||||
int lastSampleOffset; // last offset into the decoded sample
|
int lastSampleOffset; // last offset into the decoded sample
|
||||||
int lastDecodeTime; // last time decoding sound
|
int lastDecodeTime; // last time decoding sound
|
||||||
idFile_Memory file; // encoded file in memory
|
|
||||||
|
|
||||||
OggVorbis_File ogg; // OggVorbis file
|
stb_vorbis* stbv; // stb_vorbis (Ogg) handle, using lastSample->nonCacheData
|
||||||
};
|
};
|
||||||
|
|
||||||
idBlockAlloc<idSampleDecoderLocal, 64> sampleDecoderAllocator;
|
idBlockAlloc<idSampleDecoderLocal, 64> sampleDecoderAllocator;
|
||||||
|
@ -376,6 +386,7 @@ void idSampleDecoderLocal::Clear( void ) {
|
||||||
lastSample = NULL;
|
lastSample = NULL;
|
||||||
lastSampleOffset = 0;
|
lastSampleOffset = 0;
|
||||||
lastDecodeTime = 0;
|
lastDecodeTime = 0;
|
||||||
|
stbv = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -391,8 +402,8 @@ void idSampleDecoderLocal::ClearDecoder( void ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WAVE_FORMAT_TAG_OGG: {
|
case WAVE_FORMAT_TAG_OGG: {
|
||||||
ov_clear( &ogg );
|
stb_vorbis_close( stbv );
|
||||||
memset( &ogg, 0, sizeof( ogg ) );
|
stbv = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -526,8 +537,12 @@ int idSampleDecoderLocal::DecodeOGG( idSoundSample *sample, int sampleOffset44k,
|
||||||
failed = true;
|
failed = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
file.SetData( (const char *)sample->nonCacheData, sample->objectMemSize );
|
assert(stbv == NULL);
|
||||||
if ( ov_openFile( &file, &ogg ) < 0 ) {
|
int stbVorbErr = 0;
|
||||||
|
stbv = stb_vorbis_open_memory( sample->nonCacheData, sample->objectMemSize, &stbVorbErr, NULL );
|
||||||
|
if ( stbv == NULL ) {
|
||||||
|
common->Warning( "idSampleDecoderLocal::DecodeOGG() stb_vorbis_open_memory() for %s failed: %s\n",
|
||||||
|
sample->name.c_str(), my_stbv_strerror(stbVorbErr) );
|
||||||
failed = true;
|
failed = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -535,9 +550,22 @@ int idSampleDecoderLocal::DecodeOGG( idSoundSample *sample, int sampleOffset44k,
|
||||||
lastSample = sample;
|
lastSample = sample;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( sample->objectInfo.nChannels > 2 ) {
|
||||||
|
assert( 0 && ">2 channels currently not supported (samplesBuf expects 1 or 2)" );
|
||||||
|
common->Warning( "Ogg Vorbis files with >2 channels are not supported!\n" );
|
||||||
|
// no idea if other parts of the engine support more than stereo;
|
||||||
|
// pretty sure though the standard gamedata doesn't use it (positional sounds must be mono anyway)
|
||||||
|
failed = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// seek to the right offset if necessary
|
// seek to the right offset if necessary
|
||||||
if ( sampleOffset != lastSampleOffset ) {
|
if ( sampleOffset != lastSampleOffset ) {
|
||||||
if ( ov_pcm_seek( &ogg, sampleOffset / sample->objectInfo.nChannels ) != 0 ) {
|
if ( stb_vorbis_seek( stbv, sampleOffset / sample->objectInfo.nChannels ) == 0 ) {
|
||||||
|
int stbVorbErr = stb_vorbis_get_error( stbv );
|
||||||
|
int offset = sampleOffset / sample->objectInfo.nChannels;
|
||||||
|
common->Warning( "idSampleDecoderLocal::DecodeOGG() stb_vorbis_seek(%d) for %s failed: %s\n",
|
||||||
|
offset, sample->name.c_str(), my_stbv_strerror( stbVorbErr ) );
|
||||||
failed = true;
|
failed = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -549,9 +577,16 @@ int idSampleDecoderLocal::DecodeOGG( idSoundSample *sample, int sampleOffset44k,
|
||||||
totalSamples = sampleCount;
|
totalSamples = sampleCount;
|
||||||
readSamples = 0;
|
readSamples = 0;
|
||||||
do {
|
do {
|
||||||
float **samples;
|
// DG: in contrast to libvorbisfile's ov_read_float(), stb_vorbis_get_samples_float() expects you to
|
||||||
int ret = ov_read_float( &ogg, &samples, totalSamples / sample->objectInfo.nChannels, NULL );
|
// pass a buffer to store the decoded samples in, so limit it to 4096 samples/channel per iteration
|
||||||
|
float samplesBuf[2][MIXBUFFER_SAMPLES];
|
||||||
|
float* samples[2] = { samplesBuf[0], samplesBuf[1] };
|
||||||
|
int reqSamples = Min( MIXBUFFER_SAMPLES, totalSamples / sample->objectInfo.nChannels );
|
||||||
|
int ret = stb_vorbis_get_samples_float( stbv, sample->objectInfo.nChannels, samples, reqSamples );
|
||||||
if ( ret == 0 ) {
|
if ( ret == 0 ) {
|
||||||
|
int stbVorbErr = stb_vorbis_get_error( stbv );
|
||||||
|
common->Warning( "idSampleDecoderLocal::DecodeOGG() stb_vorbis_get_samples_float() for %s failed: %s\n",
|
||||||
|
sample->name.c_str(), my_stbv_strerror( stbVorbErr ) );
|
||||||
failed = true;
|
failed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,6 +202,7 @@ private:
|
||||||
dword mulDataSize;
|
dword mulDataSize;
|
||||||
|
|
||||||
void * ogg; // only !NULL when !s_realTimeDecoding
|
void * ogg; // only !NULL when !s_realTimeDecoding
|
||||||
|
byte* oggData; // the contents of the .ogg for stbi_vorbis (it doesn't support custom reading callbacks)
|
||||||
bool isOgg;
|
bool isOgg;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -46,6 +46,7 @@ idWaveFile::idWaveFile( void ) {
|
||||||
mpbData = NULL;
|
mpbData = NULL;
|
||||||
ogg = NULL;
|
ogg = NULL;
|
||||||
isOgg = false;
|
isOgg = false;
|
||||||
|
oggData = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
|
@ -1,83 +0,0 @@
|
||||||
# Locate OGG
|
|
||||||
# This module defines XXX_FOUND, XXX_INCLUDE_DIRS and XXX_LIBRARIES standard variables
|
|
||||||
#
|
|
||||||
# $OGGDIR is an environment variable that would
|
|
||||||
# correspond to the ./configure --prefix=$OGGDIR
|
|
||||||
# used in building OGG.
|
|
||||||
|
|
||||||
SET(OGG_SEARCH_PATHS
|
|
||||||
~/Library/Frameworks
|
|
||||||
/Library/Frameworks
|
|
||||||
/usr/local
|
|
||||||
/usr
|
|
||||||
/sw # Fink
|
|
||||||
/opt/local # DarwinPorts
|
|
||||||
/opt/csw # Blastwave
|
|
||||||
/opt
|
|
||||||
)
|
|
||||||
|
|
||||||
SET(MSVC_YEAR_NAME)
|
|
||||||
IF (MSVC_VERSION GREATER 1599) # >= 1600
|
|
||||||
SET(MSVC_YEAR_NAME VS2010)
|
|
||||||
ELSEIF(MSVC_VERSION GREATER 1499) # >= 1500
|
|
||||||
SET(MSVC_YEAR_NAME VS2008)
|
|
||||||
ELSEIF(MSVC_VERSION GREATER 1399) # >= 1400
|
|
||||||
SET(MSVC_YEAR_NAME VS2005)
|
|
||||||
ELSEIF(MSVC_VERSION GREATER 1299) # >= 1300
|
|
||||||
SET(MSVC_YEAR_NAME VS2003)
|
|
||||||
ELSEIF(MSVC_VERSION GREATER 1199) # >= 1200
|
|
||||||
SET(MSVC_YEAR_NAME VS6)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
FIND_PATH(OGG_INCLUDE_DIR
|
|
||||||
NAMES ogg/ogg.h ogg/os_types.h
|
|
||||||
HINTS
|
|
||||||
$ENV{OGGDIR}
|
|
||||||
$ENV{OGG_PATH}
|
|
||||||
PATH_SUFFIXES include
|
|
||||||
PATHS ${OGG_SEARCH_PATHS}
|
|
||||||
)
|
|
||||||
|
|
||||||
FIND_LIBRARY(OGG_LIBRARY
|
|
||||||
NAMES ogg libogg
|
|
||||||
HINTS
|
|
||||||
$ENV{OGGDIR}
|
|
||||||
$ENV{OGG_PATH}
|
|
||||||
PATH_SUFFIXES lib lib64 win32/Dynamic_Release "Win32/${MSVC_YEAR_NAME}/x64/Release" "Win32/${MSVC_YEAR_NAME}/Win32/Release"
|
|
||||||
PATHS ${OGG_SEARCH_PATHS}
|
|
||||||
)
|
|
||||||
|
|
||||||
# First search for d-suffixed libs
|
|
||||||
FIND_LIBRARY(OGG_LIBRARY_DEBUG
|
|
||||||
NAMES oggd ogg_d liboggd libogg_d
|
|
||||||
HINTS
|
|
||||||
$ENV{OGGDIR}
|
|
||||||
$ENV{OGG_PATH}
|
|
||||||
PATH_SUFFIXES lib lib64 win32/Dynamic_Debug "Win32/${MSVC_YEAR_NAME}/x64/Debug" "Win32/${MSVC_YEAR_NAME}/Win32/Debug"
|
|
||||||
PATHS ${OGG_SEARCH_PATHS}
|
|
||||||
)
|
|
||||||
|
|
||||||
IF(NOT OGG_LIBRARY_DEBUG)
|
|
||||||
# Then search for non suffixed libs if necessary, but only in debug dirs
|
|
||||||
FIND_LIBRARY(OGG_LIBRARY_DEBUG
|
|
||||||
NAMES ogg libogg
|
|
||||||
HINTS
|
|
||||||
$ENV{OGGDIR}
|
|
||||||
$ENV{OGG_PATH}
|
|
||||||
PATH_SUFFIXES win32/Dynamic_Debug "Win32/${MSVC_YEAR_NAME}/x64/Debug" "Win32/${MSVC_YEAR_NAME}/Win32/Debug"
|
|
||||||
PATHS ${OGG_SEARCH_PATHS}
|
|
||||||
)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
|
|
||||||
IF(OGG_LIBRARY)
|
|
||||||
IF(OGG_LIBRARY_DEBUG)
|
|
||||||
SET(OGG_LIBRARIES optimized "${OGG_LIBRARY}" debug "${OGG_LIBRARY_DEBUG}")
|
|
||||||
ELSE()
|
|
||||||
SET(OGG_LIBRARIES "${OGG_LIBRARY}") # Could add "general" keyword, but it is optional
|
|
||||||
ENDIF()
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
# handle the QUIETLY and REQUIRED arguments and set XXX_FOUND to TRUE if all listed variables are TRUE
|
|
||||||
INCLUDE(FindPackageHandleStandardArgs)
|
|
||||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OGG DEFAULT_MSG OGG_LIBRARIES OGG_INCLUDE_DIR)
|
|
|
@ -1,83 +0,0 @@
|
||||||
# Locate Vorbis
|
|
||||||
# This module defines XXX_FOUND, XXX_INCLUDE_DIRS and XXX_LIBRARIES standard variables
|
|
||||||
#
|
|
||||||
# $VORBISDIR is an environment variable that would
|
|
||||||
# correspond to the ./configure --prefix=$VORBISDIR
|
|
||||||
# used in building Vorbis.
|
|
||||||
|
|
||||||
SET(VORBIS_SEARCH_PATHS
|
|
||||||
~/Library/Frameworks
|
|
||||||
/Library/Frameworks
|
|
||||||
/usr/local
|
|
||||||
/usr
|
|
||||||
/sw # Fink
|
|
||||||
/opt/local # DarwinPorts
|
|
||||||
/opt/csw # Blastwave
|
|
||||||
/opt
|
|
||||||
)
|
|
||||||
|
|
||||||
SET(MSVC_YEAR_NAME)
|
|
||||||
IF (MSVC_VERSION GREATER 1599) # >= 1600
|
|
||||||
SET(MSVC_YEAR_NAME VS2010)
|
|
||||||
ELSEIF(MSVC_VERSION GREATER 1499) # >= 1500
|
|
||||||
SET(MSVC_YEAR_NAME VS2008)
|
|
||||||
ELSEIF(MSVC_VERSION GREATER 1399) # >= 1400
|
|
||||||
SET(MSVC_YEAR_NAME VS2005)
|
|
||||||
ELSEIF(MSVC_VERSION GREATER 1299) # >= 1300
|
|
||||||
SET(MSVC_YEAR_NAME VS2003)
|
|
||||||
ELSEIF(MSVC_VERSION GREATER 1199) # >= 1200
|
|
||||||
SET(MSVC_YEAR_NAME VS6)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
FIND_PATH(VORBIS_INCLUDE_DIR
|
|
||||||
NAMES vorbis/codec.h
|
|
||||||
HINTS
|
|
||||||
$ENV{VORBISDIR}
|
|
||||||
$ENV{VORBIS_PATH}
|
|
||||||
PATH_SUFFIXES include
|
|
||||||
PATHS ${VORBIS_SEARCH_PATHS}
|
|
||||||
)
|
|
||||||
|
|
||||||
FIND_LIBRARY(VORBIS_LIBRARY
|
|
||||||
NAMES vorbis libvorbis
|
|
||||||
HINTS
|
|
||||||
$ENV{VORBISDIR}
|
|
||||||
$ENV{VORBIS_PATH}
|
|
||||||
PATH_SUFFIXES lib lib64 win32/Vorbis_Dynamic_Release "Win32/${MSVC_YEAR_NAME}/x64/Release" "Win32/${MSVC_YEAR_NAME}/Win32/Release"
|
|
||||||
PATHS ${VORBIS_SEARCH_PATHS}
|
|
||||||
)
|
|
||||||
|
|
||||||
# First search for d-suffixed libs
|
|
||||||
FIND_LIBRARY(VORBIS_LIBRARY_DEBUG
|
|
||||||
NAMES vorbisd vorbis_d libvorbisd libvorbis_d
|
|
||||||
HINTS
|
|
||||||
$ENV{VORBISDIR}
|
|
||||||
$ENV{VORBIS_PATH}
|
|
||||||
PATH_SUFFIXES lib lib64 win32/Vorbis_Dynamic_Debug "Win32/${MSVC_YEAR_NAME}/x64/Debug" "Win32/${MSVC_YEAR_NAME}/Win32/Debug"
|
|
||||||
PATHS ${VORBIS_SEARCH_PATHS}
|
|
||||||
)
|
|
||||||
|
|
||||||
IF(NOT VORBIS_LIBRARY_DEBUG)
|
|
||||||
# Then search for non suffixed libs if necessary, but only in debug dirs
|
|
||||||
FIND_LIBRARY(VORBIS_LIBRARY_DEBUG
|
|
||||||
NAMES vorbis libvorbis
|
|
||||||
HINTS
|
|
||||||
$ENV{VORBISDIR}
|
|
||||||
$ENV{VORBIS_PATH}
|
|
||||||
PATH_SUFFIXES win32/Vorbis_Dynamic_Debug "Win32/${MSVC_YEAR_NAME}/x64/Debug" "Win32/${MSVC_YEAR_NAME}/Win32/Debug"
|
|
||||||
PATHS ${VORBIS_SEARCH_PATHS}
|
|
||||||
)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
|
|
||||||
IF(VORBIS_LIBRARY)
|
|
||||||
IF(VORBIS_LIBRARY_DEBUG)
|
|
||||||
SET(VORBIS_LIBRARIES optimized "${VORBIS_LIBRARY}" debug "${VORBIS_LIBRARY_DEBUG}")
|
|
||||||
ELSE()
|
|
||||||
SET(VORBIS_LIBRARIES "${VORBIS_LIBRARY}") # Could add "general" keyword, but it is optional
|
|
||||||
ENDIF()
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
# handle the QUIETLY and REQUIRED arguments and set XXX_FOUND to TRUE if all listed variables are TRUE
|
|
||||||
INCLUDE(FindPackageHandleStandardArgs)
|
|
||||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(VORBIS DEFAULT_MSG VORBIS_LIBRARIES VORBIS_INCLUDE_DIR)
|
|
|
@ -1,91 +0,0 @@
|
||||||
# Locate VorbisFile
|
|
||||||
# This module defines XXX_FOUND, XXX_INCLUDE_DIRS and XXX_LIBRARIES standard variables
|
|
||||||
#
|
|
||||||
# $VORBISDIR is an environment variable that would
|
|
||||||
# correspond to the ./configure --prefix=$VORBISDIR
|
|
||||||
# used in building Vorbis.
|
|
||||||
|
|
||||||
SET(VORBISFILE_SEARCH_PATHS
|
|
||||||
~/Library/Frameworks
|
|
||||||
/Library/Frameworks
|
|
||||||
/usr/local
|
|
||||||
/usr
|
|
||||||
/sw # Fink
|
|
||||||
/opt/local # DarwinPorts
|
|
||||||
/opt/csw # Blastwave
|
|
||||||
/opt
|
|
||||||
)
|
|
||||||
|
|
||||||
SET(MSVC_YEAR_NAME)
|
|
||||||
IF (MSVC_VERSION GREATER 1599) # >= 1600
|
|
||||||
SET(MSVC_YEAR_NAME VS2010)
|
|
||||||
ELSEIF(MSVC_VERSION GREATER 1499) # >= 1500
|
|
||||||
SET(MSVC_YEAR_NAME VS2008)
|
|
||||||
ELSEIF(MSVC_VERSION GREATER 1399) # >= 1400
|
|
||||||
SET(MSVC_YEAR_NAME VS2005)
|
|
||||||
ELSEIF(MSVC_VERSION GREATER 1299) # >= 1300
|
|
||||||
SET(MSVC_YEAR_NAME VS2003)
|
|
||||||
ELSEIF(MSVC_VERSION GREATER 1199) # >= 1200
|
|
||||||
SET(MSVC_YEAR_NAME VS6)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
FIND_PATH(VORBISFILE_INCLUDE_DIR
|
|
||||||
NAMES vorbis/vorbisfile.h
|
|
||||||
HINTS
|
|
||||||
$ENV{VORBISFILEDIR}
|
|
||||||
$ENV{VORBISFILE_PATH}
|
|
||||||
$ENV{VORBISDIR}
|
|
||||||
$ENV{VORBIS_PATH}
|
|
||||||
PATH_SUFFIXES include
|
|
||||||
PATHS ${VORBISFILE_SEARCH_PATHS}
|
|
||||||
)
|
|
||||||
|
|
||||||
FIND_LIBRARY(VORBISFILE_LIBRARY
|
|
||||||
NAMES vorbisfile libvorbisfile
|
|
||||||
HINTS
|
|
||||||
$ENV{VORBISFILEDIR}
|
|
||||||
$ENV{VORBISFILE_PATH}
|
|
||||||
$ENV{VORBISDIR}
|
|
||||||
$ENV{VORBIS_PATH}
|
|
||||||
PATH_SUFFIXES lib lib64 win32/VorbisFile_Dynamic_Release "Win32/${MSVC_YEAR_NAME}/x64/Release" "Win32/${MSVC_YEAR_NAME}/Win32/Release"
|
|
||||||
PATHS ${VORBISFILE_SEARCH_PATHS}
|
|
||||||
)
|
|
||||||
|
|
||||||
# First search for d-suffixed libs
|
|
||||||
FIND_LIBRARY(VORBISFILE_LIBRARY_DEBUG
|
|
||||||
NAMES vorbisfiled vorbisfile_d libvorbisfiled libvorbisfile_d
|
|
||||||
HINTS
|
|
||||||
$ENV{VORBISFILEDIR}
|
|
||||||
$ENV{VORBISFILE_PATH}
|
|
||||||
$ENV{VORBISDIR}
|
|
||||||
$ENV{VORBIS_PATH}
|
|
||||||
PATH_SUFFIXES lib lib64 win32/VorbisFile_Dynamic_Debug "Win32/${MSVC_YEAR_NAME}/x64/Debug" "Win32/${MSVC_YEAR_NAME}/Win32/Debug"
|
|
||||||
PATHS ${VORBISFILE_SEARCH_PATHS}
|
|
||||||
)
|
|
||||||
|
|
||||||
IF(NOT VORBISFILE_LIBRARY_DEBUG)
|
|
||||||
# Then search for non suffixed libs if necessary, but only in debug dirs
|
|
||||||
FIND_LIBRARY(VORBISFILE_LIBRARY_DEBUG
|
|
||||||
NAMES vorbisfile libvorbisfile
|
|
||||||
HINTS
|
|
||||||
$ENV{VORBISFILEDIR}
|
|
||||||
$ENV{VORBISFILE_PATH}
|
|
||||||
$ENV{VORBISDIR}
|
|
||||||
$ENV{VORBIS_PATH}
|
|
||||||
PATH_SUFFIXES win32/VorbisFile_Dynamic_Debug "Win32/${MSVC_YEAR_NAME}/x64/Debug" "Win32/${MSVC_YEAR_NAME}/Win32/Debug"
|
|
||||||
PATHS ${VORBISFILE_SEARCH_PATHS}
|
|
||||||
)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
|
|
||||||
IF(VORBISFILE_LIBRARY)
|
|
||||||
IF(VORBISFILE_LIBRARY_DEBUG)
|
|
||||||
SET(VORBISFILE_LIBRARIES optimized "${VORBISFILE_LIBRARY}" debug "${VORBISFILE_LIBRARY_DEBUG}")
|
|
||||||
ELSE()
|
|
||||||
SET(VORBISFILE_LIBRARIES "${VORBISFILE_LIBRARY}") # Could add "general" keyword, but it is optional
|
|
||||||
ENDIF()
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
# handle the QUIETLY and REQUIRED arguments and set XXX_FOUND to TRUE if all listed variables are TRUE
|
|
||||||
INCLUDE(FindPackageHandleStandardArgs)
|
|
||||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(VORBISFILE DEFAULT_MSG VORBISFILE_LIBRARIES VORBISFILE_INCLUDE_DIR)
|
|
Loading…
Reference in a new issue