30 Jan 2017

This commit is contained in:
g-cont 2017-01-30 00:00:00 +03:00 committed by Alibek Omarov
parent 537f5cf039
commit a7b6617b6c
6 changed files with 91 additions and 101 deletions

View File

@ -1546,7 +1546,7 @@ void S_RawSamples( uint samples, uint rate, word width, word channels, const byt
{ {
int snd_vol; 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 if( snd_vol < 0 ) snd_vol = 0; // fixup negative values
S_RawEntSamples( entnum, samples, rate, width, channels, data, snd_vol ); S_RawEntSamples( entnum, samples, rate, width, channels, data, snd_vol );

Binary file not shown.

Binary file not shown.

View File

@ -24,37 +24,26 @@ GNU General Public License for more details.
#define MP3_OK 0 #define MP3_OK 0
#define MP3_NEED_MORE 1 #define MP3_NEED_MORE 1
typedef struct mpeg_s typedef struct
{ {
void *state; // hidden decoder state int rate; // num samples per second (e.g. 11025 - 11 khz)
void *file; int channels; // num channels (1 - mono, 2 - stereo)
int playtime; // stream size in milliseconds
} wavinfo_t;
// custom stdio // custom stdio
long (*fread)( void *handle, void *buf, size_t count ); typedef long (*pfread)( void *handle, void *buf, size_t count );
long (*fseek)( void *handle, long offset, int whence ); typedef long (*pfseek)( void *handle, long offset, int whence );
void (*close)( void *handle );
// user info extern void *create_decoder( int *error );
int channels; // num channels extern int feed_mpeg_header( void *mpg, const char *data, long bufsize, long streamsize, wavinfo_t *sc );
int samples; // per one second extern int feed_mpeg_stream( void *mpg, const char *data, long bufsize, char *outbuf, size_t *outsize );
int play_time; // stream size in milliseconds extern int open_mpeg_stream( void *mpg, void *file, pfread f_read, pfseek f_seek, wavinfo_t *sc );
int rate; // frequency extern int read_mpeg_stream( void *mpg, char *outbuf, size_t *outsize );
int outsize; // current data size extern int get_stream_pos( void *mpg );
char out[8192]; // temporary buffer extern int set_stream_pos( void *mpg, int curpos );
size_t streamsize; // size in bytes extern void close_decoder( void *mpg );
char error[256]; // error buffer const char *get_error( void *mpeg );
} 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 );
/* /*
================================================================= =================================================================
@ -65,41 +54,50 @@ extern void close_decoder( mpeg_t *mpg );
*/ */
qboolean Sound_LoadMPG( const char *name, const byte *buffer, size_t filesize ) qboolean Sound_LoadMPG( const char *name, const byte *buffer, size_t filesize )
{ {
mpeg_t mpeg; void *mpeg;
size_t pos = 0; size_t pos = 0;
size_t bytesWrite = 0; size_t bytesWrite = 0;
char out[OUTBUF_SIZE];
size_t outsize;
int ret;
wavinfo_t sc;
// load the file // load the file
if( !buffer || filesize < FRAME_SIZE ) if( !buffer || filesize < FRAME_SIZE )
return false; return false;
// couldn't create decoder // couldn't create decoder
if( !create_decoder( &mpeg )) if(( mpeg = create_decoder( &ret )) == NULL )
{
MsgDev( D_ERROR, "%s\n", mpeg.error );
return false; return false;
}
#ifdef _DEBUG
if( ret ) MsgDev( D_ERROR, %s\n", get_error( mpeg ));
#endif
// trying to read header // 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 ); #ifdef _DEBUG
close_decoder( &mpeg ); 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; return false;
} }
sound.channels = mpeg.channels; sound.channels = sc.channels;
sound.rate = mpeg.rate; sound.rate = sc.rate;
sound.width = 2; // always 16-bit PCM sound.width = 2; // always 16-bit PCM
sound.loopstart = -1; 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 pos += FRAME_SIZE; // evaluate pos
if( !sound.size ) if( !sound.size )
{ {
// bad mpeg file ? // bad mpeg file ?
MsgDev( D_ERROR, "Sound_LoadMPG: (%s) is probably corrupted\n", name ); MsgDev( D_ERROR, "Sound_LoadMPG: (%s) is probably corrupted\n", name );
close_decoder( &mpeg ); close_decoder( mpeg );
return false; return false;
} }
@ -109,9 +107,9 @@ qboolean Sound_LoadMPG( const char *name, const byte *buffer, size_t filesize )
// decompress mpg into pcm wav format // decompress mpg into pcm wav format
while( bytesWrite < sound.size ) 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; char *data = (char *)buffer + pos;
int bufsize; int bufsize;
@ -122,20 +120,20 @@ qboolean Sound_LoadMPG( const char *name, const byte *buffer, size_t filesize )
else bufsize = FRAME_SIZE; else bufsize = FRAME_SIZE;
pos += bufsize; 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 break; // there was end of the stream
} }
if( bytesWrite + mpeg.outsize > sound.size ) if( bytesWrite + outsize > sound.size )
outsize = ( sound.size - bytesWrite ); size = ( sound.size - bytesWrite );
else outsize = mpeg.outsize; else size = outsize;
memcpy( &sound.wav[bytesWrite], mpeg.out, outsize ); memcpy( &sound.wav[bytesWrite], out, size );
bytesWrite += outsize; bytesWrite += outsize;
} }
sound.samples = bytesWrite / ( sound.width * sound.channels ); sound.samples = bytesWrite / ( sound.width * sound.channels );
close_decoder( &mpeg ); close_decoder( mpeg );
return true; return true;
} }
@ -147,9 +145,11 @@ Stream_OpenMPG
*/ */
stream_t *Stream_OpenMPG( const char *filename ) stream_t *Stream_OpenMPG( const char *filename )
{ {
mpeg_t *mpegFile;
stream_t *stream; stream_t *stream;
void *mpeg;
file_t *file; file_t *file;
int ret;
wavinfo_t sc;
file = FS_Open( filename, "rb", false ); file = FS_Open( filename, "rb", false );
if( !file ) return NULL; if( !file ) return NULL;
@ -159,39 +159,38 @@ stream_t *Stream_OpenMPG( const char *filename )
stream->file = file; stream->file = file;
stream->pos = 0; stream->pos = 0;
mpegFile = Mem_Alloc( host.soundpool, sizeof( mpeg_t ));
// couldn't create decoder // 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 ); MsgDev( D_ERROR, "Stream_OpenMPG: couldn't create decoder\n" );
Mem_Free( mpegFile );
Mem_Free( stream ); Mem_Free( stream );
FS_Close( file ); FS_Close( file );
return NULL; return NULL;
} }
mpegFile->fread = FS_Read; #ifdef _DEBUG
mpegFile->fseek = FS_Seek; if( ret ) MsgDev( D_ERROR, %s\n", get_error( mpeg ));
mpegFile->close = FS_Close; #endif
// trying to open stream and read header // 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 ); #ifdef _DEBUG
close_decoder( mpegFile ); MsgDev( D_ERROR, "Stream_OpenMPG: failed to load (%s): %s\n", filename, get_error( mpeg ));
Mem_Free( mpegFile ); #else
MsgDev( D_ERROR, "Stream_OpenMPG: (%s) is probably corrupted\n", filename );
#endif
close_decoder( mpeg );
Mem_Free( stream ); Mem_Free( stream );
FS_Close( file ); FS_Close( file );
return NULL; return NULL;
} }
stream->buffsize = 0; // how many samples left from previous frame stream->buffsize = 0; // how many samples left from previous frame
stream->channels = mpegFile->channels; stream->channels = sc.channels;
stream->pos += mpegFile->outsize; stream->rate = sc.rate;
stream->rate = mpegFile->rate;
stream->width = 2; // always 16 bit stream->width = 2; // always 16 bit
stream->ptr = mpegFile; stream->ptr = mpeg;
stream->type = WF_MPGDATA; stream->type = WF_MPGDATA;
return stream; return stream;
@ -208,43 +207,31 @@ long Stream_ReadMPG( stream_t *stream, long needBytes, void *buffer )
{ {
// buffer handling // buffer handling
int bytesWritten = 0; int bytesWritten = 0;
int result; void *mpg;
mpeg_t *mpg;
mpg = (mpeg_t *)stream->ptr; mpg = stream->ptr;
Assert( mpg != NULL );
while( 1 ) while( 1 )
{ {
long outsize;
byte *data; byte *data;
long outsize;
if( !stream->buffsize ) if( !stream->buffsize )
{ {
result = read_mpeg_stream( mpg ); if( read_mpeg_stream( mpg, stream->temp, &stream->pos ) != MP3_OK )
stream->pos += mpg->outsize; break; // there was end of the stream
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
}
} }
// check remaining size // check remaining size
if( bytesWritten + mpg->outsize > needBytes ) if( bytesWritten + stream->pos > needBytes )
outsize = ( needBytes - bytesWritten ); outsize = ( needBytes - bytesWritten );
else outsize = mpg->outsize; else outsize = stream->pos;
// copy raw sample to output buffer // copy raw sample to output buffer
data = (byte *)buffer + bytesWritten; data = (byte *)buffer + bytesWritten;
memcpy( data, &mpg->out[stream->buffsize], outsize ); memcpy( data, &stream->temp[stream->buffsize], outsize );
bytesWritten += outsize; bytesWritten += outsize;
mpg->outsize -= outsize; stream->pos -= outsize;
stream->buffsize += outsize; stream->buffsize += outsize;
// continue from this sample on a next call // continue from this sample on a next call
@ -266,11 +253,9 @@ assume stream is valid
*/ */
long Stream_SetPosMPG( stream_t *stream, long newpos ) long Stream_SetPosMPG( stream_t *stream, long newpos )
{ {
int newPos = set_stream_pos( stream->ptr, newpos ); if( set_stream_pos( stream->ptr, newpos ) != -1 )
if( newPos != -1 )
{ {
stream->pos = newPos; // flush any previous data
stream->buffsize = 0; stream->buffsize = 0;
return true; return true;
} }
@ -302,11 +287,14 @@ void Stream_FreeMPG( stream_t *stream )
{ {
if( stream->ptr ) if( stream->ptr )
{ {
mpeg_t *mpg; close_decoder( stream->ptr );
stream->ptr = NULL;
}
mpg = (mpeg_t *)stream->ptr; if( stream->file )
close_decoder( mpg ); {
Mem_Free( stream->ptr ); FS_Close( stream->file );
stream->file = NULL;
} }
Mem_Free( stream ); Mem_Free( stream );

View File

@ -405,7 +405,7 @@ assume stream is valid
*/ */
long Stream_ReadWAV( stream_t *stream, long bytes, void *buffer ) long Stream_ReadWAV( stream_t *stream, long bytes, void *buffer )
{ {
int samples, remaining; int remaining;
if( !stream->file ) return 0; // invalid file 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; if( bytes > remaining ) bytes = remaining;
stream->pos += bytes; stream->pos += bytes;
samples = ( bytes / stream->width ) / stream->channels;
FS_Read( stream->file, buffer, bytes ); FS_Read( stream->file, buffer, bytes );
return bytes; return bytes;

View File

@ -19,6 +19,7 @@ GNU General Public License for more details.
#include "common.h" #include "common.h"
#define FRAME_SIZE 32768 // must match with mp3 frame size #define FRAME_SIZE 32768 // must match with mp3 frame size
#define OUTBUF_SIZE 8192 // don't change!
typedef struct loadwavfmt_s typedef struct loadwavfmt_s
{ {
@ -63,17 +64,19 @@ typedef struct stream_s
{ {
const streamfmt_t *format; // streamformat to operate const streamfmt_t *format; // streamformat to operate
// current stream state // stream info
file_t *file; // stream file file_t *file; // stream file
int width; // resolution - num bits divided by 8 (8 bit is 1, 16 bit is 2) int width; // resolution - num bits divided by 8 (8 bit is 1, 16 bit is 2)
int rate; // stream rate int rate; // stream rate
int channels; // stream channels int channels; // stream channels
int type; // wavtype int type; // wavtype
size_t size; // total stream size size_t size; // total stream size
int pos; // actual track position
// current stream state
void *ptr; // internal decoder 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 int buffsize; // cached buffer size
qboolean timejump; // true if position is changed
}; };
/* /*