diff --git a/engine/client/s_main.c b/engine/client/s_main.c index a64a3a47..ae3eafb6 100644 --- a/engine/client/s_main.c +++ b/engine/client/s_main.c @@ -1546,7 +1546,7 @@ void S_RawSamples( uint samples, uint rate, word width, word channels, const byt { int snd_vol; - if( entnum < 0 ) snd_vol = 128; // bg track or movie track + if( entnum < 0 ) snd_vol = 256; // bg track or movie track if( snd_vol < 0 ) snd_vol = 0; // fixup negative values S_RawEntSamples( entnum, samples, rate, width, channels, data, snd_vol ); diff --git a/engine/common/soundlib/mpeg.lib b/engine/common/soundlib/mpeg.lib index ab776f3a..a2f30235 100644 Binary files a/engine/common/soundlib/mpeg.lib and b/engine/common/soundlib/mpeg.lib differ diff --git a/engine/common/soundlib/mpeg_dbg.lib b/engine/common/soundlib/mpeg_dbg.lib index 8fa8630a..d192617c 100644 Binary files a/engine/common/soundlib/mpeg_dbg.lib and b/engine/common/soundlib/mpeg_dbg.lib differ diff --git a/engine/common/soundlib/snd_mp3.c b/engine/common/soundlib/snd_mp3.c index 4a27667d..e19f539b 100644 --- a/engine/common/soundlib/snd_mp3.c +++ b/engine/common/soundlib/snd_mp3.c @@ -24,37 +24,26 @@ GNU General Public License for more details. #define MP3_OK 0 #define MP3_NEED_MORE 1 -typedef struct mpeg_s +typedef struct { - void *state; // hidden decoder state - void *file; + int rate; // num samples per second (e.g. 11025 - 11 khz) + int channels; // num channels (1 - mono, 2 - stereo) + int playtime; // stream size in milliseconds +} wavinfo_t; - // custom stdio - long (*fread)( void *handle, void *buf, size_t count ); - long (*fseek)( void *handle, long offset, int whence ); - void (*close)( void *handle ); +// custom stdio +typedef long (*pfread)( void *handle, void *buf, size_t count ); +typedef long (*pfseek)( void *handle, long offset, int whence ); - // user info - int channels; // num channels - int samples; // per one second - int play_time; // stream size in milliseconds - int rate; // frequency - int outsize; // current data size - char out[8192]; // temporary buffer - size_t streamsize; // size in bytes - char error[256]; // error buffer -} mpeg_t; - - -// mpg123 exports -extern int create_decoder( mpeg_t *mpg ); -extern int feed_mpeg_header( mpeg_t *mpg, const char *data, long bufsize, long streamsize ); -extern int feed_mpeg_stream( mpeg_t *mpg, const char *data, long bufsize ); -extern int open_mpeg_stream( mpeg_t *mpg, void *file ); -extern int read_mpeg_stream( mpeg_t *mpg ); -extern int get_stream_pos( mpeg_t *mpg ); -extern int set_stream_pos( mpeg_t *mpg, int curpos ); -extern void close_decoder( mpeg_t *mpg ); +extern void *create_decoder( int *error ); +extern int feed_mpeg_header( void *mpg, const char *data, long bufsize, long streamsize, wavinfo_t *sc ); +extern int feed_mpeg_stream( void *mpg, const char *data, long bufsize, char *outbuf, size_t *outsize ); +extern int open_mpeg_stream( void *mpg, void *file, pfread f_read, pfseek f_seek, wavinfo_t *sc ); +extern int read_mpeg_stream( void *mpg, char *outbuf, size_t *outsize ); +extern int get_stream_pos( void *mpg ); +extern int set_stream_pos( void *mpg, int curpos ); +extern void close_decoder( void *mpg ); +const char *get_error( void *mpeg ); /* ================================================================= @@ -65,41 +54,50 @@ extern void close_decoder( mpeg_t *mpg ); */ qboolean Sound_LoadMPG( const char *name, const byte *buffer, size_t filesize ) { - mpeg_t mpeg; + void *mpeg; size_t pos = 0; size_t bytesWrite = 0; + char out[OUTBUF_SIZE]; + size_t outsize; + int ret; + wavinfo_t sc; // load the file if( !buffer || filesize < FRAME_SIZE ) return false; // couldn't create decoder - if( !create_decoder( &mpeg )) - { - MsgDev( D_ERROR, "%s\n", mpeg.error ); + if(( mpeg = create_decoder( &ret )) == NULL ) return false; - } + +#ifdef _DEBUG + if( ret ) MsgDev( D_ERROR, %s\n", get_error( mpeg )); +#endif // trying to read header - if( !feed_mpeg_header( &mpeg, buffer, FRAME_SIZE, filesize )) + if( !feed_mpeg_header( mpeg, buffer, FRAME_SIZE, filesize, &sc )) { - MsgDev( D_ERROR, "Sound_LoadMPG: (%s) is probably corrupted (%s)\n", name, mpeg.error ); - close_decoder( &mpeg ); +#ifdef _DEBUG + MsgDev( D_ERROR, "Sound_LoadMPG: failed to load (%s): %s\n", name, get_error( mpeg )); +#else + MsgDev( D_ERROR, "Sound_LoadMPG: (%s) is probably corrupted\n", name ); +#endif + close_decoder( mpeg ); return false; } - sound.channels = mpeg.channels; - sound.rate = mpeg.rate; + sound.channels = sc.channels; + sound.rate = sc.rate; sound.width = 2; // always 16-bit PCM sound.loopstart = -1; - sound.size = ( sound.channels * sound.rate * sound.width ) * ( mpeg.play_time / 1000 ); // in bytes + sound.size = ( sound.channels * sound.rate * sound.width ) * ( sc.playtime / 1000 ); // in bytes pos += FRAME_SIZE; // evaluate pos if( !sound.size ) { // bad mpeg file ? MsgDev( D_ERROR, "Sound_LoadMPG: (%s) is probably corrupted\n", name ); - close_decoder( &mpeg ); + close_decoder( mpeg ); return false; } @@ -109,9 +107,9 @@ qboolean Sound_LoadMPG( const char *name, const byte *buffer, size_t filesize ) // decompress mpg into pcm wav format while( bytesWrite < sound.size ) { - int outsize; + int size; - if( feed_mpeg_stream( &mpeg, NULL, 0 ) != MP3_OK && mpeg.outsize <= 0 ) + if( feed_mpeg_stream( mpeg, NULL, 0, out, &outsize ) != MP3_OK && outsize <= 0 ) { char *data = (char *)buffer + pos; int bufsize; @@ -122,20 +120,20 @@ qboolean Sound_LoadMPG( const char *name, const byte *buffer, size_t filesize ) else bufsize = FRAME_SIZE; pos += bufsize; - if( feed_mpeg_stream( &mpeg, data, bufsize ) != MP3_OK ) + if( feed_mpeg_stream( mpeg, data, bufsize, out, &outsize ) != MP3_OK ) break; // there was end of the stream } - if( bytesWrite + mpeg.outsize > sound.size ) - outsize = ( sound.size - bytesWrite ); - else outsize = mpeg.outsize; + if( bytesWrite + outsize > sound.size ) + size = ( sound.size - bytesWrite ); + else size = outsize; - memcpy( &sound.wav[bytesWrite], mpeg.out, outsize ); + memcpy( &sound.wav[bytesWrite], out, size ); bytesWrite += outsize; } sound.samples = bytesWrite / ( sound.width * sound.channels ); - close_decoder( &mpeg ); + close_decoder( mpeg ); return true; } @@ -147,9 +145,11 @@ Stream_OpenMPG */ stream_t *Stream_OpenMPG( const char *filename ) { - mpeg_t *mpegFile; stream_t *stream; + void *mpeg; file_t *file; + int ret; + wavinfo_t sc; file = FS_Open( filename, "rb", false ); if( !file ) return NULL; @@ -159,39 +159,38 @@ stream_t *Stream_OpenMPG( const char *filename ) stream->file = file; stream->pos = 0; - mpegFile = Mem_Alloc( host.soundpool, sizeof( mpeg_t )); - // couldn't create decoder - if( !create_decoder( mpegFile )) + if(( mpeg = create_decoder( &ret )) == NULL ) { - MsgDev( D_ERROR, "Stream_OpenMPG: couldn't create decoder: %s\n", mpegFile->error ); - Mem_Free( mpegFile ); + MsgDev( D_ERROR, "Stream_OpenMPG: couldn't create decoder\n" ); Mem_Free( stream ); FS_Close( file ); return NULL; } - mpegFile->fread = FS_Read; - mpegFile->fseek = FS_Seek; - mpegFile->close = FS_Close; - +#ifdef _DEBUG + if( ret ) MsgDev( D_ERROR, %s\n", get_error( mpeg )); +#endif // trying to open stream and read header - if( !open_mpeg_stream( mpegFile, file )) + if( !open_mpeg_stream( mpeg, file, FS_Read, FS_Seek, &sc )) { - MsgDev( D_ERROR, "Sound_LoadMPG: (%s) is probably corrupted: %s\n", filename, mpegFile->error ); - close_decoder( mpegFile ); - Mem_Free( mpegFile ); +#ifdef _DEBUG + MsgDev( D_ERROR, "Stream_OpenMPG: failed to load (%s): %s\n", filename, get_error( mpeg )); +#else + MsgDev( D_ERROR, "Stream_OpenMPG: (%s) is probably corrupted\n", filename ); +#endif + close_decoder( mpeg ); Mem_Free( stream ); FS_Close( file ); + return NULL; } stream->buffsize = 0; // how many samples left from previous frame - stream->channels = mpegFile->channels; - stream->pos += mpegFile->outsize; - stream->rate = mpegFile->rate; + stream->channels = sc.channels; + stream->rate = sc.rate; stream->width = 2; // always 16 bit - stream->ptr = mpegFile; + stream->ptr = mpeg; stream->type = WF_MPGDATA; return stream; @@ -208,43 +207,31 @@ long Stream_ReadMPG( stream_t *stream, long needBytes, void *buffer ) { // buffer handling int bytesWritten = 0; - int result; - mpeg_t *mpg; + void *mpg; - mpg = (mpeg_t *)stream->ptr; - Assert( mpg != NULL ); + mpg = stream->ptr; while( 1 ) { - long outsize; byte *data; + long outsize; if( !stream->buffsize ) { - result = read_mpeg_stream( mpg ); - stream->pos += mpg->outsize; - - if( result != MP3_OK ) - { - // if there are no bytes remainig so we can decompress the new frame - result = read_mpeg_stream( mpg ); - stream->pos += mpg->outsize; - - if( result != MP3_OK ) - break; // there was end of the stream - } + if( read_mpeg_stream( mpg, stream->temp, &stream->pos ) != MP3_OK ) + break; // there was end of the stream } // check remaining size - if( bytesWritten + mpg->outsize > needBytes ) + if( bytesWritten + stream->pos > needBytes ) outsize = ( needBytes - bytesWritten ); - else outsize = mpg->outsize; + else outsize = stream->pos; // copy raw sample to output buffer data = (byte *)buffer + bytesWritten; - memcpy( data, &mpg->out[stream->buffsize], outsize ); + memcpy( data, &stream->temp[stream->buffsize], outsize ); bytesWritten += outsize; - mpg->outsize -= outsize; + stream->pos -= outsize; stream->buffsize += outsize; // continue from this sample on a next call @@ -266,11 +253,9 @@ assume stream is valid */ long Stream_SetPosMPG( stream_t *stream, long newpos ) { - int newPos = set_stream_pos( stream->ptr, newpos ); - - if( newPos != -1 ) + if( set_stream_pos( stream->ptr, newpos ) != -1 ) { - stream->pos = newPos; + // flush any previous data stream->buffsize = 0; return true; } @@ -302,11 +287,14 @@ void Stream_FreeMPG( stream_t *stream ) { if( stream->ptr ) { - mpeg_t *mpg; + close_decoder( stream->ptr ); + stream->ptr = NULL; + } - mpg = (mpeg_t *)stream->ptr; - close_decoder( mpg ); - Mem_Free( stream->ptr ); + if( stream->file ) + { + FS_Close( stream->file ); + stream->file = NULL; } Mem_Free( stream ); diff --git a/engine/common/soundlib/snd_wav.c b/engine/common/soundlib/snd_wav.c index f5fa57e3..a5e3e1d6 100644 --- a/engine/common/soundlib/snd_wav.c +++ b/engine/common/soundlib/snd_wav.c @@ -405,7 +405,7 @@ assume stream is valid */ long Stream_ReadWAV( stream_t *stream, long bytes, void *buffer ) { - int samples, remaining; + int remaining; if( !stream->file ) return 0; // invalid file @@ -414,7 +414,6 @@ long Stream_ReadWAV( stream_t *stream, long bytes, void *buffer ) if( bytes > remaining ) bytes = remaining; stream->pos += bytes; - samples = ( bytes / stream->width ) / stream->channels; FS_Read( stream->file, buffer, bytes ); return bytes; diff --git a/engine/common/soundlib/soundlib.h b/engine/common/soundlib/soundlib.h index 8677be2c..636f25d6 100644 --- a/engine/common/soundlib/soundlib.h +++ b/engine/common/soundlib/soundlib.h @@ -19,6 +19,7 @@ GNU General Public License for more details. #include "common.h" #define FRAME_SIZE 32768 // must match with mp3 frame size +#define OUTBUF_SIZE 8192 // don't change! typedef struct loadwavfmt_s { @@ -63,17 +64,19 @@ typedef struct stream_s { const streamfmt_t *format; // streamformat to operate - // current stream state + // stream info file_t *file; // stream file int width; // resolution - num bits divided by 8 (8 bit is 1, 16 bit is 2) int rate; // stream rate int channels; // stream channels int type; // wavtype size_t size; // total stream size - int pos; // actual track position + + // current stream state void *ptr; // internal decoder state + char temp[OUTBUF_SIZE]; // mpeg decoder stuff + size_t pos; // actual track position (or actual buffer remains) int buffsize; // cached buffer size - qboolean timejump; // true if position is changed }; /*