30 Jan 2017
This commit is contained in:
parent
537f5cf039
commit
a7b6617b6c
|
@ -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.
|
@ -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 );
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Reference in New Issue