/* 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(); }