xash3d-fwgs/engine/common/soundlib/libmpg/libmpg.c

135 lines
3.1 KiB
C

/*
libmpg.c - compact version of famous library mpg123
Copyright (C) 2017 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "mpg123.h"
#include "libmpg.h"
void *create_decoder( int *error )
{
void *mpg;
int ret;
if( error ) *error = 0;
mpg123_init();
mpg = mpg123_new( &ret );
if( !mpg ) return NULL;
ret = mpg123_param( mpg, MPG123_FLAGS, MPG123_FUZZY|MPG123_SEEKBUFFER|MPG123_GAPLESS );
if( ret != MPG123_OK && error )
*error = 1;
// let the seek index auto-grow and contain an entry for every frame
ret = mpg123_param( mpg, MPG123_INDEX_SIZE, -1 );
if( ret != MPG123_OK && error )
*error = 1;
return mpg;
}
int feed_mpeg_header( void *mpg, const byte *data, long bufsize, long streamsize, wavinfo_t *sc )
{
mpg123_handle_t *mh = (mpg123_handle_t *)mpg;
int ret, no;
if( !mh || !sc ) return 0;
ret = mpg123_open_feed( mh );
if( ret != MPG123_OK )
return 0;
// feed input chunk and get first chunk of decoded audio.
ret = mpg123_decode( mh, data, bufsize, NULL, 0, NULL );
if( ret != MPG123_NEW_FORMAT )
return 0; // there were errors
mpg123_getformat( mh, &sc->rate, &sc->channels, &no );
mpg123_format_none( mh );
mpg123_format( mh, sc->rate, sc->channels, MPG123_ENC_SIGNED_16 );
// some hacking to get function get_songlen to working properly
mh->rdat.filelen = streamsize;
sc->playtime = get_songlen( mh, -1 ) * 1000;
return 1;
}
int feed_mpeg_stream( void *mpg, const byte *data, long bufsize, byte *outbuf, size_t *outsize )
{
switch( mpg123_decode( mpg, data, bufsize, outbuf, OUTBUF_SIZE, outsize ))
{
case MPG123_NEED_MORE:
return MP3_NEED_MORE;
case MPG123_OK:
return MP3_OK;
default:
return MP3_ERR;
}
}
int open_mpeg_stream( void *mpg, void *file, pfread f_read, pfseek f_seek, wavinfo_t *sc )
{
mpg123_handle_t *mh = (mpg123_handle_t *)mpg;
int ret, no;
if( !mh || !sc ) return 0;
ret = mpg123_replace_reader_handle( mh, (void *)f_read, (void *)f_seek, NULL );
if( ret != MPG123_OK )
return 0;
ret = mpg123_open_handle( mh, file );
if( ret != MPG123_OK )
return 0;
ret = mpg123_getformat( mh, &sc->rate, &sc->channels, &no );
if( ret != MPG123_OK )
return 0;
mpg123_format_none( mh );
mpg123_format( mh, sc->rate, sc->channels, MPG123_ENC_SIGNED_16 );
sc->playtime = get_songlen( mh, -1 ) * 1000;
return 1;
}
int read_mpeg_stream( void *mpg, byte *outbuf, size_t *outsize )
{
switch( mpg123_read( mpg, outbuf, OUTBUF_SIZE, outsize ))
{
case MPG123_OK:
return MP3_OK;
default:
return MP3_ERR;
}
}
int get_stream_pos( void *mpg )
{
return mpg123_tell( mpg );
}
int set_stream_pos( void *mpg, int curpos )
{
return mpg123_seek( mpg, curpos, SEEK_SET );
}
void close_decoder( void *mpg )
{
mpg123_delete( mpg );
mpg123_exit();
}