mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-30 17:24:31 +01:00
add AHX support, via mpg123
git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@285 51a99a44-fe44-0410-b1ba-c3e57ba2b86b
This commit is contained in:
parent
2a9f54977b
commit
e017a7324d
2
Makefile
2
Makefile
@ -20,7 +20,7 @@ mingw_winamp:
|
|||||||
$(MAKE) -C winamp in_vgmstream.dll
|
$(MAKE) -C winamp in_vgmstream.dll
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f vgmstream-*
|
rm -rf vgmstream-*
|
||||||
$(MAKE) -C test clean
|
$(MAKE) -C test clean
|
||||||
$(MAKE) -C test -f Makefile.mingw clean
|
$(MAKE) -C test -f Makefile.mingw clean
|
||||||
$(MAKE) -C winamp clean
|
$(MAKE) -C winamp clean
|
||||||
|
@ -23,6 +23,10 @@ PKG_CHECK_MODULES(VORBISFILE, [vorbisfile],,
|
|||||||
[AC_MSG_ERROR([Cannot find libvorbisfile])]
|
[AC_MSG_ERROR([Cannot find libvorbisfile])]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(MPG123, [libmpg123],,
|
||||||
|
[AC_MSG_ERROR([Cannot find libmpg123])]
|
||||||
|
)
|
||||||
|
|
||||||
dnl Check for GTK/GLib/GThread/Pango
|
dnl Check for GTK/GLib/GThread/Pango
|
||||||
|
|
||||||
PKG_CHECK_MODULES(GTK, [glib-2.0 >= 2.6.0 gtk+-2.0 >= 2.6.0 gthread-2.0 pango],
|
PKG_CHECK_MODULES(GTK, [glib-2.0 >= 2.6.0 gtk+-2.0 >= 2.6.0 gthread-2.0 pango],
|
||||||
@ -30,7 +34,7 @@ PKG_CHECK_MODULES(GTK, [glib-2.0 >= 2.6.0 gtk+-2.0 >= 2.6.0 gthread-2.0 pango],
|
|||||||
)
|
)
|
||||||
|
|
||||||
CFLAGS="$CFLAGS $AUDACIOUS_CFLAGS"
|
CFLAGS="$CFLAGS $AUDACIOUS_CFLAGS"
|
||||||
LIBS="$LIBS $AUDACIOUS_LIBS $GTK_LIBS $VORBISFILE_LIBS"
|
LIBS="$LIBS $AUDACIOUS_LIBS $GTK_LIBS $VORBISFILE_LIBS $MPG123_LIBS"
|
||||||
|
|
||||||
plugindir=`pkg-config audacious --variable=plugin_dir`
|
plugindir=`pkg-config audacious --variable=plugin_dir`
|
||||||
AC_SUBST(plugindir)
|
AC_SUBST(plugindir)
|
||||||
|
736
ext_includes/mpg123.h
Normal file
736
ext_includes/mpg123.h
Normal file
@ -0,0 +1,736 @@
|
|||||||
|
/*
|
||||||
|
libmpg123: MPEG Audio Decoder library (version 1.4.3)
|
||||||
|
|
||||||
|
copyright 1995-2007 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||||
|
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MPG123_LIB_H
|
||||||
|
#define MPG123_LIB_H
|
||||||
|
|
||||||
|
/** \file mpg123.h The header file for the libmpg123 MPEG Audio decoder */
|
||||||
|
|
||||||
|
/* These aren't actually in use... seems to work without using libtool. */
|
||||||
|
#ifdef BUILD_MPG123_DLL
|
||||||
|
/* The dll exports. */
|
||||||
|
#define EXPORT __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#ifdef LINK_MPG123_DLL
|
||||||
|
/* The exe imports. */
|
||||||
|
#define EXPORT __declspec(dllimport)
|
||||||
|
#else
|
||||||
|
/* Nothing on normal/UNIX builds */
|
||||||
|
#define EXPORT
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** \defgroup mpg123_init mpg123 library and handle setup
|
||||||
|
*
|
||||||
|
* Functions to initialise and shutdown the mpg123 library and handles.
|
||||||
|
* The parameters of handles have workable defaults, you only have to tune them when you want to tune something;-)
|
||||||
|
* Tip: Use a RVA setting...
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Opaque structure for the libmpg123 decoder handle. */
|
||||||
|
struct mpg123_handle_struct;
|
||||||
|
|
||||||
|
/** Opaque structure for the libmpg123 decoder handle.
|
||||||
|
* Most functions take a pointer to a mpg123_handle as first argument and operate on its data in an object-oriented manner.
|
||||||
|
*/
|
||||||
|
typedef struct mpg123_handle_struct mpg123_handle;
|
||||||
|
|
||||||
|
/** Function to initialise the mpg123 library.
|
||||||
|
* This function is not thread-safe. Call it exactly once before any other work with the library.
|
||||||
|
*
|
||||||
|
* \return MPG123_OK if successful, otherwise an error number.
|
||||||
|
*/
|
||||||
|
EXPORT int mpg123_init(void);
|
||||||
|
|
||||||
|
/** Function to close down the mpg123 library.
|
||||||
|
* This function is not thread-safe. Call it exactly once after any work with the library. */
|
||||||
|
EXPORT void mpg123_exit(void);
|
||||||
|
|
||||||
|
/** Create a handle with optional choice of decoder (named by a string, see mpg123_decoders() or mpg123_supported_decoders()).
|
||||||
|
* and optional retrieval of an error code to feed to mpg123_plain_strerror().
|
||||||
|
* Optional means: Any of or both the parameters may be NULL.
|
||||||
|
*
|
||||||
|
* \return Non-NULL pointer when successful.
|
||||||
|
*/
|
||||||
|
EXPORT mpg123_handle *mpg123_new(const char* decoder, int *error);
|
||||||
|
|
||||||
|
/** Delete handle, mh is either a valid mpg123 handle or NULL. */
|
||||||
|
EXPORT void mpg123_delete(mpg123_handle *mh);
|
||||||
|
|
||||||
|
/** Enumeration of the parameters types that it is possible to set/get. */
|
||||||
|
enum mpg123_parms
|
||||||
|
{
|
||||||
|
MPG123_VERBOSE, /**< set verbosity value for enabling messages to stderr, >= 0 makes sense */
|
||||||
|
MPG123_FLAGS, /**< set all flags, p.ex val = MPG123_GAPLESS|MPG123_MONO_MIX */
|
||||||
|
MPG123_ADD_FLAGS, /**< add some flags */
|
||||||
|
MPG123_FORCE_RATE, /**< when value > 0, force output rate to that value */
|
||||||
|
MPG123_DOWN_SAMPLE, /**< 0=native rate, 1=half rate, 2=quarter rate */
|
||||||
|
MPG123_RVA, /**< one of the RVA choices above */
|
||||||
|
MPG123_DOWNSPEED, /**< play a frame N times */
|
||||||
|
MPG123_UPSPEED, /**< play every Nth frame */
|
||||||
|
MPG123_START_FRAME, /**< start with this frame (skip frames before that) */
|
||||||
|
MPG123_DECODE_FRAMES, /**< decode only this number of frames */
|
||||||
|
MPG123_ICY_INTERVAL, /**< stream contains ICY metadata with this interval */
|
||||||
|
MPG123_OUTSCALE, /**< the scale for output samples (amplitude) */
|
||||||
|
MPG123_TIMEOUT, /**< timeout for reading from a stream (not supported on win32) */
|
||||||
|
MPG123_REMOVE_FLAGS, /**< remove some flags (inverse of MPG123_ADD_FLAGS) */
|
||||||
|
MPG123_RESYNC_LIMIT /**< Try resync on frame parsing for that many bytes or until end of stream (<0). */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Flag bits for MPG123_FLAGS, use the usual binary or to combine. */
|
||||||
|
enum mpg123_param_flags
|
||||||
|
{
|
||||||
|
MPG123_FORCE_MONO = 0x7 /**< 0111 Force some mono mode: This is a test bitmask for seeing if any mono forcing is active. */
|
||||||
|
,MPG123_MONO_LEFT = 0x1 /**< 0001 Force playback of left channel only. */
|
||||||
|
,MPG123_MONO_RIGHT = 0x2 /**< 0010 Force playback of right channel only. */
|
||||||
|
,MPG123_MONO_MIX = 0x4 /**< 0100 Force playback of mixed mono. */
|
||||||
|
,MPG123_FORCE_STEREO = 0x8 /**< 1000 Force stereo output. */
|
||||||
|
,MPG123_FORCE_8BIT = 0x10 /**< 00010000 Force 8bit formats. */
|
||||||
|
,MPG123_QUIET = 0x20 /**< 00100000 Suppress any printouts (overrules verbose). */
|
||||||
|
,MPG123_GAPLESS = 0x40 /**< 01000000 Enable gapless decoding (default on if libmpg123 has support). */
|
||||||
|
,MPG123_NO_RESYNC = 0x80 /**< 10000000 Disable resync stream after error. */
|
||||||
|
,MPG123_SEEKBUFFER = 0x100 /**< 000100000000 Enable small buffer on non-seekable streams to allow some peek-ahead (for better MPEG sync). */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** choices for MPG123_RVA */
|
||||||
|
enum mpg123_param_rva
|
||||||
|
{
|
||||||
|
MPG123_RVA_OFF = 0 /**< RVA disabled (default). */
|
||||||
|
,MPG123_RVA_MIX = 1 /**< Use mix/track/radio gain. */
|
||||||
|
,MPG123_RVA_ALBUM = 2 /**< Use album/audiophile gain */
|
||||||
|
,MPG123_RVA_MAX = MPG123_RVA_ALBUM /**< The maximum RVA code, may increase in future. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* TODO: Assess the possibilities and troubles of changing parameters during playback. */
|
||||||
|
|
||||||
|
/** Set a specific parameter, for a specific mpg123_handle, using a parameter
|
||||||
|
* type key chosen from the mpg123_parms enumeration, to the specified value. */
|
||||||
|
EXPORT int mpg123_param(mpg123_handle *mh, enum mpg123_parms type, long value, double fvalue);
|
||||||
|
|
||||||
|
/** Get a specific parameter, for a specific mpg123_handle.
|
||||||
|
* See the mpg123_parms enumeration for a list of available parameters. */
|
||||||
|
EXPORT int mpg123_getparam(mpg123_handle *mh, enum mpg123_parms type, long *val, double *fval);
|
||||||
|
|
||||||
|
/* @} */
|
||||||
|
|
||||||
|
|
||||||
|
/** \defgroup mpg123_error mpg123 error handling
|
||||||
|
*
|
||||||
|
* Functions to get text version of the error numbers and an enumeration
|
||||||
|
* of the error codes returned by libmpg123.
|
||||||
|
*
|
||||||
|
* Most functions operating on a mpg123_handle simply return MPG123_OK on success and MPG123_ERR on failure (setting the internal error variable of the handle to the specific error code).
|
||||||
|
* Decoding/seek functions may also return message codes MPG123_DONE, MPG123_NEW_FORMAT and MPG123_NEED_MORE.
|
||||||
|
* The positive range of return values is used for "useful" values when appropriate.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Enumeration of the message and error codes and returned by libmpg123 functions. */
|
||||||
|
enum mpg123_errors
|
||||||
|
{
|
||||||
|
MPG123_DONE=-12, /**< Message: Track ended. */
|
||||||
|
MPG123_NEW_FORMAT=-11, /**< Message: Output format will be different on next call. */
|
||||||
|
MPG123_NEED_MORE=-10, /**< Message: For feed reader: "Feed me more!" */
|
||||||
|
MPG123_ERR=-1, /**< Generic Error */
|
||||||
|
MPG123_OK=0, /**< Success */
|
||||||
|
MPG123_BAD_OUTFORMAT, /**< Unable to set up output format! */
|
||||||
|
MPG123_BAD_CHANNEL, /**< Invalid channel number specified. */
|
||||||
|
MPG123_BAD_RATE, /**< Invalid sample rate specified. */
|
||||||
|
MPG123_ERR_16TO8TABLE, /**< Unable to allocate memory for 16 to 8 converter table! */
|
||||||
|
MPG123_BAD_PARAM, /**< Bad parameter id! */
|
||||||
|
MPG123_BAD_BUFFER, /**< Bad buffer given -- invalid pointer or too small size. */
|
||||||
|
MPG123_OUT_OF_MEM, /**< Out of memory -- some malloc() failed. */
|
||||||
|
MPG123_NOT_INITIALIZED, /**< You didn't initialize the library! */
|
||||||
|
MPG123_BAD_DECODER, /**< Invalid decoder choice. */
|
||||||
|
MPG123_BAD_HANDLE, /**< Invalid mpg123 handle. */
|
||||||
|
MPG123_NO_BUFFERS, /**< Unable to initialize frame buffers (out of memory?). */
|
||||||
|
MPG123_BAD_RVA, /**< Invalid RVA mode. */
|
||||||
|
MPG123_NO_GAPLESS, /**< This build doesn't support gapless decoding. */
|
||||||
|
MPG123_NO_SPACE, /**< Not enough buffer space. */
|
||||||
|
MPG123_BAD_TYPES, /**< Incompatible numeric data types. */
|
||||||
|
MPG123_BAD_BAND, /**< Bad equalizer band. */
|
||||||
|
MPG123_ERR_NULL, /**< Null pointer given where valid storage address needed. */
|
||||||
|
MPG123_ERR_READER, /**< Error reading the stream. */
|
||||||
|
MPG123_NO_SEEK_FROM_END,/**< Cannot seek from end (end is not known). */
|
||||||
|
MPG123_BAD_WHENCE, /**< Invalid 'whence' for seek function.*/
|
||||||
|
MPG123_NO_TIMEOUT, /**< Build does not support stream timeouts. */
|
||||||
|
MPG123_BAD_FILE, /**< File access error. */
|
||||||
|
MPG123_NO_SEEK, /**< Seek not supported by stream. */
|
||||||
|
MPG123_NO_READER, /**< No stream opened. */
|
||||||
|
MPG123_BAD_PARS, /**< Bad parameter handle. */
|
||||||
|
MPG123_BAD_INDEX_PAR, /**< Bad parameters to mpg123_index() */
|
||||||
|
MPG123_OUT_OF_SYNC, /**< Lost track in bytestream and did not try to resync. */
|
||||||
|
MPG123_RESYNC_FAIL /**< Resync failed to find valid MPEG data. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Return a string describing that error errcode means. */
|
||||||
|
EXPORT const char* mpg123_plain_strerror(int errcode);
|
||||||
|
|
||||||
|
/** Give string describing what error has occured in the context of handle mh.
|
||||||
|
* When a function operating on an mpg123 handle returns MPG123_ERR, you should check for the actual reason via
|
||||||
|
* char *errmsg = mpg123_strerror(mh)
|
||||||
|
* This function will catch mh == NULL and return the message for MPG123_BAD_HANDLE. */
|
||||||
|
EXPORT const char* mpg123_strerror(mpg123_handle *mh);
|
||||||
|
|
||||||
|
/** Return the plain errcode intead of a string. */
|
||||||
|
EXPORT int mpg123_errcode(mpg123_handle *mh);
|
||||||
|
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
|
||||||
|
/** \defgroup mpg123_decoder mpg123 decoder selection
|
||||||
|
*
|
||||||
|
* Functions to list and select the available decoders.
|
||||||
|
* Perhaps the most prominent feature of mpg123: You have several (optimized) decoders to choose from (on x86 and PPC (MacOS) systems, that is).
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Return a NULL-terminated array of generally available decoder names (plain 8bit ASCII). */
|
||||||
|
EXPORT char **mpg123_decoders();
|
||||||
|
|
||||||
|
/** Return a NULL-terminated array of the decoders supported by the CPU (plain 8bit ASCII). */
|
||||||
|
EXPORT char **mpg123_supported_decoders();
|
||||||
|
|
||||||
|
/** Set the chosen decoder to 'decoder_name' */
|
||||||
|
EXPORT int mpg123_decoder(mpg123_handle *mh, const char* decoder_name);
|
||||||
|
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
|
||||||
|
/** \defgroup mpg123_output mpg123 output audio format
|
||||||
|
*
|
||||||
|
* Functions to get and select the format of the decoded audio.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** 16 or 8 bits, signed or unsigned... all flags fit into 8 bits, float/double are not yet standard and special anyway */
|
||||||
|
enum mpg123_enc_enum
|
||||||
|
{
|
||||||
|
MPG123_ENC_16 = 0x40 /**< 0100 0000 Some 16 bit encoding... */
|
||||||
|
,MPG123_ENC_SIGNED = 0x80 /**< 1000 0000 Some signed encoding... */
|
||||||
|
,MPG123_ENC_8 = 0x0f /**< 0000 1111 Some 8 bit encoding... */
|
||||||
|
,MPG123_ENC_SIGNED_16 = (MPG123_ENC_16|MPG123_ENC_SIGNED|0x10) /**< 1101 0000 signed 16 bit */
|
||||||
|
,MPG123_ENC_UNSIGNED_16 = (MPG123_ENC_16|0x20) /**< 0110 0000 unsigned 16 bit*/
|
||||||
|
,MPG123_ENC_UNSIGNED_8 = 0x01 /**< 0000 0001 unsigned 8 bit*/
|
||||||
|
,MPG123_ENC_SIGNED_8 = (MPG123_ENC_SIGNED|0x02) /**< 1000 0010 signed 8 bit*/
|
||||||
|
,MPG123_ENC_ULAW_8 = 0x04 /**< 0000 0100 ulaw 8 bit*/
|
||||||
|
,MPG123_ENC_ALAW_8 = 0x08 /**< 0000 1000 alaw 8 bit */
|
||||||
|
,MPG123_ENC_ANY = ( MPG123_ENC_SIGNED_16 | MPG123_ENC_UNSIGNED_16 | MPG123_ENC_UNSIGNED_8 | MPG123_ENC_SIGNED_8 | MPG123_ENC_ULAW_8 | MPG123_ENC_ALAW_8 ) /**< any encoding */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** They can be combined into one number (3) to indicate mono and stereo... */
|
||||||
|
enum mpg123_channelcount
|
||||||
|
{
|
||||||
|
MPG123_MONO = 1
|
||||||
|
,MPG123_STEREO = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
/** An array of supported standard sample rates
|
||||||
|
* These are possible native sample rates of MPEG audio files.
|
||||||
|
* You can still force mpg123 to resample to a different one, but by default you will only get audio in one of these samplings.
|
||||||
|
* \param list Store a pointer to the sample rates array there.
|
||||||
|
* \param number Store the number of sample rates there. */
|
||||||
|
EXPORT void mpg123_rates(const long **list, size_t *number);
|
||||||
|
|
||||||
|
/** An array of supported audio encodings.
|
||||||
|
* An audio encoding is a logic OR of members of mpg123_enc_enum.
|
||||||
|
* \param list Store a pointer to the encodings array there.
|
||||||
|
* \param number Store the number of encodings there. */
|
||||||
|
EXPORT void mpg123_encodings(const int **list, size_t *number);
|
||||||
|
|
||||||
|
/** Configure a mpg123 handle to accept no output format at all,
|
||||||
|
* use before specifying supported formats with mpg123_format */
|
||||||
|
EXPORT int mpg123_format_none(mpg123_handle *mh);
|
||||||
|
|
||||||
|
/** Configure mpg123 handle to accept all formats
|
||||||
|
* (also any custom rate you may set) -- this is default. */
|
||||||
|
EXPORT int mpg123_format_all(mpg123_handle *mh);
|
||||||
|
|
||||||
|
/** Set the audio format support of a mpg123_handle in detail:
|
||||||
|
* \param mh audio decoder handle
|
||||||
|
* \param rate The sample rate value (in Hertz).
|
||||||
|
* \param channels A combination of MPG123_STEREO and MPG123_MONO.
|
||||||
|
* \param encodings A combination of accepted encodings for rate and channels, p.ex MPG123_ENC_SIGNED16 | MPG123_ENC_ULAW_8 (or 0 for no support).
|
||||||
|
* \return MPG123_OK on success, MPG123_ERR if there was an error. */
|
||||||
|
EXPORT int mpg123_format(mpg123_handle *mh, long rate, int channels, int encodings);
|
||||||
|
|
||||||
|
/** Check to see if a specific format at a specific rate is supported
|
||||||
|
* by mpg123_handle.
|
||||||
|
* \return 0 for no support (that includes invalid parameters), MPG123_STEREO,
|
||||||
|
* MPG123_MONO or MPG123_STEREO|MPG123_MONO. */
|
||||||
|
EXPORT int mpg123_format_support(mpg123_handle *mh, long rate, int encoding);
|
||||||
|
|
||||||
|
/** Get the current output format written to the addresses givenr. */
|
||||||
|
EXPORT int mpg123_getformat(mpg123_handle *mh, long *rate, int *channels, int *encoding);
|
||||||
|
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
|
||||||
|
/** \defgroup mpg123_input mpg123 file input and decoding
|
||||||
|
*
|
||||||
|
* Functions for input bitstream and decoding operations.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* reading samples / triggering decoding, possible return values: */
|
||||||
|
/** Enumeration of the error codes returned by libmpg123 functions. */
|
||||||
|
|
||||||
|
/** Open and prepare to decode the specified file by filesystem path.
|
||||||
|
* This does not open HTTP urls; libmpg123 contains no networking code.
|
||||||
|
* If you want to decode internet streams, use mpg123_open_fd() or mpg123_open_feed().
|
||||||
|
*/
|
||||||
|
EXPORT int mpg123_open(mpg123_handle *mh, char *path);
|
||||||
|
|
||||||
|
/** Use an already opened file descriptor as the bitstream input
|
||||||
|
* mpg123_close() will _not_ close the file descriptor.
|
||||||
|
*/
|
||||||
|
EXPORT int mpg123_open_fd(mpg123_handle *mh, int fd);
|
||||||
|
|
||||||
|
/** Open a new bitstream and prepare for direct feeding
|
||||||
|
* This works together with mpg123_decode(); you are responsible for reading and feeding the input bitstream.
|
||||||
|
*/
|
||||||
|
EXPORT int mpg123_open_feed(mpg123_handle *mh);
|
||||||
|
|
||||||
|
/** Closes the source, if libmpg123 opened it. */
|
||||||
|
EXPORT int mpg123_close(mpg123_handle *mh);
|
||||||
|
|
||||||
|
/** Read from stream and decode up to outmemsize bytes.
|
||||||
|
* \param outmemory address of output buffer to write to
|
||||||
|
* \param outmemsize maximum number of bytes to write
|
||||||
|
* \param done address to store the number of actually decoded bytes to
|
||||||
|
* \return error/message code (watch out for MPG123_DONE and friends!) */
|
||||||
|
EXPORT int mpg123_read(mpg123_handle *mh, unsigned char *outmemory, size_t outmemsize, size_t *done);
|
||||||
|
|
||||||
|
/** Decode MPEG Audio from inmemory to outmemory.
|
||||||
|
* This is very close to a drop-in replacement for old mpglib.
|
||||||
|
* When you give zero-sized output buffer the input will be parsed until
|
||||||
|
* decoded data is available. This enables you to get MPG123_NEW_FORMAT (and query it)
|
||||||
|
* without taking decoded data.
|
||||||
|
* \param inmemory input buffer
|
||||||
|
* \param inmemsize number of input bytes
|
||||||
|
* \param outmemory output buffer
|
||||||
|
* \param outmemsize maximum number of output bytes
|
||||||
|
* \param done address to store the number of actually decoded bytes to
|
||||||
|
* \return error/message code (watch out especially for MPG123_NEED_MORE)
|
||||||
|
*/
|
||||||
|
EXPORT int mpg123_decode(mpg123_handle *mh, unsigned char *inmemory, size_t inmemsize,
|
||||||
|
unsigned char *outmemory, size_t outmemsize, size_t *done);
|
||||||
|
|
||||||
|
/** Decode next MPEG frame to internal buffer
|
||||||
|
* or read a frame and return after setting a new format.
|
||||||
|
* \param num current frame offset gets stored there
|
||||||
|
* \param audio This pointer is set to the internal buffer to read the decoded audio from.
|
||||||
|
* \param bytes number of output bytes ready in the buffer
|
||||||
|
*/
|
||||||
|
EXPORT int mpg123_decode_frame(mpg123_handle *mh, off_t *num, unsigned char **audio, size_t *bytes);
|
||||||
|
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
|
||||||
|
/** \defgroup mpg123_seek mpg123 position and seeking
|
||||||
|
*
|
||||||
|
* Functions querying and manipulating position in the decoded audio bitstream.
|
||||||
|
* The position is measured in decoded audio samples, or MPEG frame offset for the specific functions.
|
||||||
|
* If gapless code is in effect, the positions are adjusted to compensate the skipped padding/delay - meaning, you should not care about that at all and just use the position defined for the samples you get out of the decoder;-)
|
||||||
|
* The general usage is modelled after stdlib's ftell() and fseek().
|
||||||
|
* Especially, the whence parameter for the seek functions has the same meaning as the one for fseek() and needs the same constants from stdlib.h:
|
||||||
|
* - SEEK_SET: set position to (or near to) specified offset
|
||||||
|
* - SEEK_CUR: change position by offset from now
|
||||||
|
* - SEEK_END: set position to offset from end
|
||||||
|
*
|
||||||
|
* Note that sample-afccurate seek only works when gapless support has been enabled at compile time; seek is frame-accurate otherwise.
|
||||||
|
* Also, seeking is not guaranteed to work for all streams (underlying stream may not support it).
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Returns the current position in samples.
|
||||||
|
* On the next read, you'd get that sample. */
|
||||||
|
EXPORT off_t mpg123_tell(mpg123_handle *mh);
|
||||||
|
|
||||||
|
/** Returns the frame number that the next read will give you data from. */
|
||||||
|
EXPORT off_t mpg123_tellframe(mpg123_handle *mh);
|
||||||
|
|
||||||
|
/** Seek to a desired sample offset.
|
||||||
|
* Set whence to SEEK_SET, SEEK_CUR or SEEK_END.
|
||||||
|
* \return The resulting offset >= 0 or error/message code */
|
||||||
|
EXPORT off_t mpg123_seek(mpg123_handle *mh, off_t sampleoff, int whence);
|
||||||
|
|
||||||
|
/** Seek to a desired sample offset in data feeding mode.
|
||||||
|
* This just prepares things to be right only if you ensure that the next chunk of input data will be from input_offset byte position.
|
||||||
|
* \param input_offset The position it expects to be at the
|
||||||
|
* next time data is fed to mpg123_decode().
|
||||||
|
* \return The resulting offset >= 0 or error/message code */
|
||||||
|
EXPORT off_t mpg123_feedseek(mpg123_handle *mh, off_t sampleoff, int whence, off_t *input_offset);
|
||||||
|
|
||||||
|
/** Seek to a desired MPEG frame index.
|
||||||
|
* Set whence to SEEK_SET, SEEK_CUR or SEEK_END.
|
||||||
|
* \return The resulting offset >= 0 or error/message code */
|
||||||
|
EXPORT off_t mpg123_seek_frame(mpg123_handle *mh, off_t frameoff, int whence);
|
||||||
|
|
||||||
|
/** Return a MPEG frame offset corresponding to an offset in seconds.
|
||||||
|
* This assumes that the samples per frame do not change in the file/stream, which is a good assumption for any sane file/stream only.
|
||||||
|
* \return frame offset >= 0 or error/message code */
|
||||||
|
EXPORT off_t mpg123_timeframe(mpg123_handle *mh, double sec);
|
||||||
|
|
||||||
|
/** Give access to the frame index table that is managed for seeking.
|
||||||
|
* You are asked not to modify the values... unless you are really aware of what you are doing.
|
||||||
|
* \param offsets pointer to the index array
|
||||||
|
* \param step one index byte offset advances this many MPEG frames
|
||||||
|
* \param fill number of recorded index offsets; size of the array */
|
||||||
|
EXPORT int mpg123_index(mpg123_handle *mh, off_t **offsets, off_t *step, size_t *fill);
|
||||||
|
|
||||||
|
/** Get information about current and remaining frames/seconds.
|
||||||
|
* WARNING: This function is there because of special usage by standalone mpg123 and may be removed in the final version of libmpg123!
|
||||||
|
* You provide an offset (in frames) from now and a number of output bytes
|
||||||
|
* served by libmpg123 but not yet played. You get the projected current frame
|
||||||
|
* and seconds, as well as the remaining frames/seconds. This does _not_ care
|
||||||
|
* about skipped samples due to gapless playback. */
|
||||||
|
EXPORT int mpg123_position( mpg123_handle *mh, off_t frame_offset,
|
||||||
|
off_t buffered_bytes, off_t *current_frame,
|
||||||
|
off_t *frames_left, double *current_seconds,
|
||||||
|
double *seconds_left);
|
||||||
|
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
|
||||||
|
/** \defgroup mpg123_voleq mpg123 volume and equalizer
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum mpg123_channels
|
||||||
|
{
|
||||||
|
MPG123_LEFT=0x1, /**< The Left Channel. */
|
||||||
|
MPG123_RIGHT=0x2 /**< The Right Channel. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Set the 32 Band Audio Equalizer settings.
|
||||||
|
* \param channel Can be MPG123_LEFT, MPG123_RIGHT or MPG123_LEFT|MPG123_RIGHT for both.
|
||||||
|
* \param band The equaliser band to change (from 0 to 31)
|
||||||
|
* \param val The (linear) adjustment factor. */
|
||||||
|
EXPORT int mpg123_eq(mpg123_handle *mh, enum mpg123_channels channel, int band, double val);
|
||||||
|
|
||||||
|
/** Reset the 32 Band Audio Equalizer settings to flat */
|
||||||
|
EXPORT int mpg123_reset_eq(mpg123_handle *mh);
|
||||||
|
|
||||||
|
/** Set the absolute output volume including the RVA setting,
|
||||||
|
* vol<0 just applies (a possibly changed) RVA setting. */
|
||||||
|
EXPORT int mpg123_volume(mpg123_handle *mh, double vol);
|
||||||
|
|
||||||
|
/** Adjust output volume including the RVA setting by chosen amount */
|
||||||
|
EXPORT int mpg123_volume_change(mpg123_handle *mh, double change);
|
||||||
|
|
||||||
|
/** Return current volume setting, the actual value due to RVA, and the RVA
|
||||||
|
* adjustment itself. It's all as double float value to abstract the sample
|
||||||
|
* format. The volume values are linear factors / amplitudes (not percent)
|
||||||
|
* and the RVA value is in decibels. */
|
||||||
|
EXPORT int mpg123_getvolume(mpg123_handle *mh, double *base, double *really, double *rva_db);
|
||||||
|
|
||||||
|
/* TODO: Set some preamp in addition / to replace internal RVA handling? */
|
||||||
|
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
|
||||||
|
/** \defgroup mpg123_status mpg123 status and information
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Enumeration of the mode types of Variable Bitrate */
|
||||||
|
enum mpg123_vbr {
|
||||||
|
MPG123_CBR=0, /**< Constant Bitrate Mode (default) */
|
||||||
|
MPG123_VBR, /**< Variable Bitrate Mode */
|
||||||
|
MPG123_ABR /**< Average Bitrate Mode */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Enumeration of the MPEG Versions */
|
||||||
|
enum mpg123_version {
|
||||||
|
MPG123_1_0=0, /**< MPEG Version 1.0 */
|
||||||
|
MPG123_2_0, /**< MPEG Version 2.0 */
|
||||||
|
MPG123_2_5 /**< MPEG Version 2.5 */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Enumeration of the MPEG Audio mode.
|
||||||
|
* Only the mono mode has 1 channel, the others have 2 channels. */
|
||||||
|
enum mpg123_mode {
|
||||||
|
MPG123_M_STEREO=0, /**< Standard Stereo. */
|
||||||
|
MPG123_M_JOINT, /**< Joint Stereo. */
|
||||||
|
MPG123_M_DUAL, /**< Dual Channel. */
|
||||||
|
MPG123_M_MONO /**< Single Channel. */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Enumeration of the MPEG Audio flag bits */
|
||||||
|
enum mpg123_flags {
|
||||||
|
MPG123_CRC=0x1, /**< The bitstream is error protected using 16-bit CRC. */
|
||||||
|
MPG123_COPYRIGHT=0x2, /**< The bitstream is copyrighted. */
|
||||||
|
MPG123_PRIVATE=0x4, /**< The private bit has been set. */
|
||||||
|
MPG123_ORIGINAL=0x8 /**< The bitstream is an original, not a copy. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Data structure for storing information about a frame of MPEG Audio */
|
||||||
|
struct mpg123_frameinfo
|
||||||
|
{
|
||||||
|
enum mpg123_version version; /**< The MPEG version (1.0/2.0/2.5). */
|
||||||
|
int layer; /**< The MPEG Audio Layer (MP1/MP2/MP3). */
|
||||||
|
long rate; /**< The sampling rate in Hz. */
|
||||||
|
enum mpg123_mode mode; /**< The audio mode (Mono, Stereo, Joint-stero, Dual Channel). */
|
||||||
|
int mode_ext; /**< The mode extension bit flag. */
|
||||||
|
int framesize; /**< The size of the frame (in bytes). */
|
||||||
|
enum mpg123_flags flags; /**< MPEG Audio flag bits. */
|
||||||
|
int emphasis; /**< The emphasis type. */
|
||||||
|
int bitrate; /**< Bitrate of the frame (kbps). */
|
||||||
|
int abr_rate; /**< The target average bitrate. */
|
||||||
|
enum mpg123_vbr vbr; /**< The VBR mode. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Get frame information about the MPEG audio bitstream and store it in a mpg123_frameinfo structure. */
|
||||||
|
EXPORT int mpg123_info(mpg123_handle *mh, struct mpg123_frameinfo *mi);
|
||||||
|
|
||||||
|
/** Get the safe output buffer size for all cases (when you want to replace the internal buffer) */
|
||||||
|
EXPORT size_t mpg123_safe_buffer();
|
||||||
|
|
||||||
|
/** Make a full parsing scan of each frame in the file. ID3 tags are found. An accurate length
|
||||||
|
* value is stored. Seek index will be filled. A seek back to current position
|
||||||
|
* is performed. At all, this function refuses work when stream is
|
||||||
|
* not seekable.
|
||||||
|
* \return MPG123_OK or MPG123_ERR.
|
||||||
|
*/
|
||||||
|
EXPORT int mpg123_scan(mpg123_handle *mh);
|
||||||
|
|
||||||
|
/** Return, if possible, the full (expected) length of current track in samples. */
|
||||||
|
EXPORT off_t mpg123_length(mpg123_handle *mh);
|
||||||
|
|
||||||
|
/** Returns the time (seconds) per frame; <0 is error. */
|
||||||
|
EXPORT double mpg123_tpf(mpg123_handle *mh);
|
||||||
|
|
||||||
|
/** Get and reset the clip count. */
|
||||||
|
EXPORT long mpg123_clip(mpg123_handle *mh);
|
||||||
|
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
|
||||||
|
/** \defgroup mpg123_metadata mpg123 metadata handling
|
||||||
|
*
|
||||||
|
* Functions to retrieve the metadata from MPEG Audio files and streams.
|
||||||
|
* Also includes string handling functions.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Data structure for storing strings in a safer way than a standard C-String.
|
||||||
|
* Can also hold a number of null-terminated strings. */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char* p; /**< pointer to the string data */
|
||||||
|
size_t size; /**< raw number of bytes allocated */
|
||||||
|
size_t fill; /**< number of used bytes (including closing zero byte) */
|
||||||
|
} mpg123_string;
|
||||||
|
|
||||||
|
/** Create and allocate memory for a new mpg123_string */
|
||||||
|
EXPORT void mpg123_init_string(mpg123_string* sb);
|
||||||
|
|
||||||
|
/** Free-up mempory for an existing mpg123_string */
|
||||||
|
EXPORT void mpg123_free_string(mpg123_string* sb);
|
||||||
|
|
||||||
|
/** Change the size of a mpg123_string
|
||||||
|
* \return 0 on error, 1 on success */
|
||||||
|
EXPORT int mpg123_resize_string(mpg123_string* sb, size_t news);
|
||||||
|
|
||||||
|
/** Copy the contents of one mpg123_string string to another.
|
||||||
|
* \return 0 on error, 1 on success */
|
||||||
|
EXPORT int mpg123_copy_string(mpg123_string* from, mpg123_string* to);
|
||||||
|
|
||||||
|
/** Append a C-String to an mpg123_string
|
||||||
|
* \return 0 on error, 1 on success */
|
||||||
|
EXPORT int mpg123_add_string(mpg123_string* sb, char* stuff);
|
||||||
|
|
||||||
|
/** Set the conents of a mpg123_string to a C-String
|
||||||
|
* \return 0 on error, 1 on success */
|
||||||
|
EXPORT int mpg123_set_string(mpg123_string* sb, char* stuff);
|
||||||
|
|
||||||
|
/** Sub data structure for ID3v2, for storing various text fields (including comments).
|
||||||
|
* This is for ID3v2 COMM, TXXX and all the other text fields.
|
||||||
|
* Only COMM and TXXX have a description, only COMM has a language.
|
||||||
|
* You should consult the ID3v2 specification for the use of the various text fields ("frames" in ID3v2 documentation, I use "fields" here to separate from MPEG frames). */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char lang[3]; /**< Three-letter language code (not terminated). */
|
||||||
|
char id[4]; /**< The ID3v2 text field id, like TALB, TPE2, ... (4 characters, no string termination). */
|
||||||
|
mpg123_string description; /**< Empty for the generic comment... */
|
||||||
|
mpg123_string text; /**< ... */
|
||||||
|
} mpg123_text;
|
||||||
|
|
||||||
|
/** Data structure for storing IDV3v2 tags.
|
||||||
|
* This structure is not a direct binary mapping with the file contents.
|
||||||
|
* The ID3v2 text frames are allowed to contain multiple strings.
|
||||||
|
* So check for null bytes until you reach the mpg123_string fill.
|
||||||
|
* All text is encoded in UTF-8. */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned char version; /**< 3 or 4 for ID3v2.3 or ID3v2.4. */
|
||||||
|
mpg123_string *title; /**< Title string (pointer into text_list). */
|
||||||
|
mpg123_string *artist; /**< Artist string (pointer into text_list). */
|
||||||
|
mpg123_string *album; /**< Album string (pointer into text_list). */
|
||||||
|
mpg123_string *year; /**< The year as a string (pointer into text_list). */
|
||||||
|
mpg123_string *genre; /**< Genre String (pointer into text_list). The genre string(s) may very well need postprocessing, esp. for ID3v2.3. */
|
||||||
|
mpg123_string *comment; /**< Pointer to last encountered comment text with empty description. */
|
||||||
|
/* Encountered ID3v2 fields are appended to these lists.
|
||||||
|
There can be multiple occurences, the pointers above always point to the last encountered data. */
|
||||||
|
mpg123_text *comment_list; /**< Array of comments. */
|
||||||
|
size_t comments; /**< Number of comments. */
|
||||||
|
mpg123_text *text; /**< Array of ID3v2 text fields */
|
||||||
|
size_t texts; /**< Numer of text fields. */
|
||||||
|
mpg123_text *extra; /**< The array of extra (TXXX) fields. */
|
||||||
|
size_t extras; /**< Number of extra text (TXXX) fields. */
|
||||||
|
} mpg123_id3v2;
|
||||||
|
|
||||||
|
/** Data structure for ID3v1 tags (the last 128 bytes of a file).
|
||||||
|
* Don't take anything for granted (like string termination)!
|
||||||
|
* Also note the change ID3v1.1 did: comment[28] = 0; comment[19] = track_number
|
||||||
|
* It is your task to support ID3v1 only or ID3v1.1 ...*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char tag[3]; /**< Always the string "TAG", the classic intro. */
|
||||||
|
char title[30]; /**< Title string. */
|
||||||
|
char artist[30]; /**< Artist string. */
|
||||||
|
char album[30]; /**< Album string. */
|
||||||
|
char year[4]; /**< Year string. */
|
||||||
|
char comment[30]; /**< Comment string. */
|
||||||
|
unsigned char genre; /**< Genre index. */
|
||||||
|
} mpg123_id3v1;
|
||||||
|
|
||||||
|
#define MPG123_ID3 0x3 /**< 0011 There is some ID3 info. Also matches 0010 or NEW_ID3. */
|
||||||
|
#define MPG123_NEW_ID3 0x1 /**< 0001 There is ID3 info that changed since last call to mpg123_id3. */
|
||||||
|
#define MPG123_ICY 0xc /**< 1100 There is some ICY info. Also matches 0100 or NEW_ICY.*/
|
||||||
|
#define MPG123_NEW_ICY 0x4 /**< 0100 There is ICY info that changed since last call to mpg123_icy. */
|
||||||
|
|
||||||
|
/** Query if there is (new) meta info, be it ID3 or ICY (or something new in future).
|
||||||
|
The check function returns a combination of flags. */
|
||||||
|
EXPORT int mpg123_meta_check(mpg123_handle *mh); /* On error (no valid handle) just 0 is returned. */
|
||||||
|
|
||||||
|
/** Point v1 and v2 to existing data structures wich may change on any next read/decode function call.
|
||||||
|
* v1 and/or v2 can be set to NULL when there is no corresponding data.
|
||||||
|
* \return Return value is MPG123_OK or MPG123_ERR, */
|
||||||
|
EXPORT int mpg123_id3(mpg123_handle *mh, mpg123_id3v1 **v1, mpg123_id3v2 **v2);
|
||||||
|
|
||||||
|
/** Point icy_meta to existing data structure wich may change on any next read/decode function call.
|
||||||
|
* \return Return value is MPG123_OK or MPG123_ERR, */
|
||||||
|
EXPORT int mpg123_icy(mpg123_handle *mh, char **icy_meta); /* same for ICY meta string */
|
||||||
|
|
||||||
|
/* @} */
|
||||||
|
|
||||||
|
|
||||||
|
/** \defgroup mpg123_advpar mpg123 advanced parameter API
|
||||||
|
*
|
||||||
|
* Direct access to a parameter set without full handle around it.
|
||||||
|
* Possible uses:
|
||||||
|
* - Influence behaviour of library _during_ initialization of handle (MPG123_VERBOSE).
|
||||||
|
* - Use one set of parameters for multiple handles.
|
||||||
|
*
|
||||||
|
* The functions for handling mpg123_pars (mpg123_par() and mpg123_fmt()
|
||||||
|
* family) directly return a fully qualified mpg123 error code, the ones
|
||||||
|
* operating on full handles normally MPG123_OK or MPG123_ERR, storing the
|
||||||
|
* specific error code itseld inside the handle.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Opaque structure for the libmpg123 decoder parameters. */
|
||||||
|
struct mpg123_pars_struct;
|
||||||
|
|
||||||
|
/** Opaque structure for the libmpg123 decoder parameters. */
|
||||||
|
typedef struct mpg123_pars_struct mpg123_pars;
|
||||||
|
|
||||||
|
/** Create a handle with preset parameters. */
|
||||||
|
EXPORT mpg123_handle *mpg123_parnew(mpg123_pars *mp, const char* decoder, int *error);
|
||||||
|
|
||||||
|
/** Allocate memory for and return a pointer to a new mpg123_pars */
|
||||||
|
EXPORT mpg123_pars *mpg123_new_pars(int *error);
|
||||||
|
|
||||||
|
/** Delete and free up memory used by a mpg123_pars data structure */
|
||||||
|
EXPORT void mpg123_delete_pars(mpg123_pars* mp);
|
||||||
|
|
||||||
|
/** Configure mpg123 parameters to accept no output format at all,
|
||||||
|
* use before specifying supported formats with mpg123_format */
|
||||||
|
EXPORT int mpg123_fmt_none(mpg123_pars *mp);
|
||||||
|
|
||||||
|
/** Configure mpg123 parameters to accept all formats
|
||||||
|
* (also any custom rate you may set) -- this is default. */
|
||||||
|
EXPORT int mpg123_fmt_all(mpg123_pars *mp);
|
||||||
|
|
||||||
|
/** Set the audio format support of a mpg123_pars in detail:
|
||||||
|
\param rate The sample rate value (in Hertz).
|
||||||
|
\param channels A combination of MPG123_STEREO and MPG123_MONO.
|
||||||
|
\param encodings A combination of accepted encodings for rate and channels, p.ex MPG123_ENC_SIGNED16|MPG123_ENC_ULAW_8 (or 0 for no support).
|
||||||
|
\return 0 on success, -1 if there was an error. /
|
||||||
|
*/
|
||||||
|
EXPORT int mpg123_fmt(mpg123_pars *mh, long rate, int channels, int encodings); /* 0 is good, -1 is error */
|
||||||
|
|
||||||
|
/** Check to see if a specific format at a specific rate is supported
|
||||||
|
* by mpg123_pars.
|
||||||
|
* \return 0 for no support (that includes invalid parameters), MPG123_STEREO,
|
||||||
|
* MPG123_MONO or MPG123_STEREO|MPG123_MONO. */
|
||||||
|
EXPORT int mpg123_fmt_support(mpg123_pars *mh, long rate, int encoding);
|
||||||
|
|
||||||
|
/** Set a specific parameter, for a specific mpg123_pars, using a parameter
|
||||||
|
* type key chosen from the mpg123_parms enumeration, to the specified value. */
|
||||||
|
EXPORT int mpg123_par(mpg123_pars *mp, enum mpg123_parms type, long value, double fvalue);
|
||||||
|
|
||||||
|
/** Get a specific parameter, for a specific mpg123_pars.
|
||||||
|
* See the mpg123_parms enumeration for a list of available parameters. */
|
||||||
|
EXPORT int mpg123_getpar(mpg123_pars *mp, enum mpg123_parms type, long *val, double *fval);
|
||||||
|
|
||||||
|
/* @} */
|
||||||
|
|
||||||
|
|
||||||
|
/** \defgroup mpg123_lowio mpg123 low level I/O
|
||||||
|
* You may want to do tricky stuff with I/O that does not work with mpg123's default file access or you want to make it decode into your own pocket...
|
||||||
|
*
|
||||||
|
* @{ */
|
||||||
|
|
||||||
|
/** Replace default internal buffer with user-supplied buffer.
|
||||||
|
* Instead of working on it's own private buffer, mpg123 will directly use the one you provide for storing decoded audio. */
|
||||||
|
EXPORT int mpg123_replace_buffer(mpg123_handle *mh, unsigned char *data, size_t size);
|
||||||
|
|
||||||
|
/** The max size of one frame's decoded output with current settings.
|
||||||
|
* Use that to determine an appropriate minimum buffer size for decoding one frame. */
|
||||||
|
EXPORT size_t mpg123_outblock(mpg123_handle *mh);
|
||||||
|
|
||||||
|
/** Replace low-level stream access functions; read and lseek as known in POSIX.
|
||||||
|
* You can use this to make any fancy file opening/closing yourself,
|
||||||
|
* using open_fd to set the file descriptor for your read/lseek (doesn't need to be a "real" file descriptor...).
|
||||||
|
* Setting a function to NULL means that the default internal read is
|
||||||
|
* used (active from next mpg123_open call on). */
|
||||||
|
EXPORT int mpg123_replace_reader( mpg123_handle *mh,
|
||||||
|
ssize_t (*r_read) (int, void *, size_t),
|
||||||
|
off_t (*r_lseek)(int, off_t, int) );
|
||||||
|
|
||||||
|
/* @} */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -4,5 +4,8 @@ export DLLTOOL=i586-mingw32msvc-dlltool
|
|||||||
libvorbis.a: libvorbis.def
|
libvorbis.a: libvorbis.def
|
||||||
$(DLLTOOL) -d libvorbis.def -l libvorbis.a
|
$(DLLTOOL) -d libvorbis.def -l libvorbis.a
|
||||||
|
|
||||||
|
libmpg123-0.a: libmpg123-0.def
|
||||||
|
$(DLLTOOL) -d libmpg123-0.def -l libmpg123-0.a
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f libvorbis.a
|
rm -f libvorbis.a libmpg123-0.a
|
||||||
|
@ -82,6 +82,30 @@
|
|||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\libmpg123-0.dll.def"
|
||||||
|
>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
Description="Building library stub"
|
||||||
|
CommandLine="lib /def:libmpg123-0.def /machine:x86"
|
||||||
|
Outputs="libmpg123-0.lib libmpg123-0.exp"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
Description="Building library stub"
|
||||||
|
CommandLine="lib /def:libmpg123-0.def /machine:x86"
|
||||||
|
Outputs="libmpg123-0.lib libmpg123-0.exp"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
</File>
|
||||||
</Files>
|
</Files>
|
||||||
<Globals>
|
<Globals>
|
||||||
</Globals>
|
</Globals>
|
||||||
|
68
ext_libs/libmpg123-0.def
Executable file
68
ext_libs/libmpg123-0.def
Executable file
@ -0,0 +1,68 @@
|
|||||||
|
LIBRARY libmpg123-0.dll
|
||||||
|
EXPORTS
|
||||||
|
mpg123_init
|
||||||
|
mpg123_exit
|
||||||
|
mpg123_new
|
||||||
|
mpg123_delete
|
||||||
|
mpg123_plain_strerror
|
||||||
|
mpg123_strerror
|
||||||
|
mpg123_errcode
|
||||||
|
mpg123_decoders
|
||||||
|
mpg123_supported_decoders
|
||||||
|
mpg123_decoder
|
||||||
|
mpg123_rates
|
||||||
|
mpg123_encodings
|
||||||
|
mpg123_format_none
|
||||||
|
mpg123_format_all
|
||||||
|
mpg123_format
|
||||||
|
mpg123_format_support
|
||||||
|
mpg123_getformat
|
||||||
|
mpg123_open
|
||||||
|
mpg123_open_feed
|
||||||
|
mpg123_open_fd
|
||||||
|
mpg123_close
|
||||||
|
mpg123_replace_reader
|
||||||
|
mpg123_tell
|
||||||
|
mpg123_tellframe
|
||||||
|
mpg123_position
|
||||||
|
mpg123_read
|
||||||
|
mpg123_decode
|
||||||
|
mpg123_decode_frame
|
||||||
|
mpg123_seek
|
||||||
|
mpg123_feedseek
|
||||||
|
mpg123_seek_frame
|
||||||
|
mpg123_timeframe
|
||||||
|
mpg123_index
|
||||||
|
mpg123_eq
|
||||||
|
mpg123_reset_eq
|
||||||
|
mpg123_volume
|
||||||
|
mpg123_volume_change
|
||||||
|
mpg123_getvolume
|
||||||
|
mpg123_info
|
||||||
|
mpg123_safe_buffer
|
||||||
|
mpg123_outblock
|
||||||
|
mpg123_replace_buffer
|
||||||
|
mpg123_scan
|
||||||
|
mpg123_length
|
||||||
|
mpg123_tpf
|
||||||
|
mpg123_clip
|
||||||
|
mpg123_init_string
|
||||||
|
mpg123_free_string
|
||||||
|
mpg123_resize_string
|
||||||
|
mpg123_copy_string
|
||||||
|
mpg123_add_string
|
||||||
|
mpg123_set_string
|
||||||
|
mpg123_meta_check
|
||||||
|
mpg123_id3
|
||||||
|
mpg123_icy
|
||||||
|
mpg123_parnew
|
||||||
|
mpg123_new_pars
|
||||||
|
mpg123_delete_pars
|
||||||
|
mpg123_param
|
||||||
|
mpg123_getparam
|
||||||
|
mpg123_fmt_none
|
||||||
|
mpg123_fmt_all
|
||||||
|
mpg123_fmt
|
||||||
|
mpg123_fmt_support
|
||||||
|
mpg123_par
|
||||||
|
mpg123_getpar
|
20
readme.txt
20
readme.txt
@ -1,20 +1,23 @@
|
|||||||
vgmstream
|
vgmstream
|
||||||
|
|
||||||
This is vgmstream, a library for playing streamed audio from video games.
|
This is vgmstream, a library for playing streamed audio from video games.
|
||||||
It is very much under development. There are two end-user bits, a command
|
It is very much under development. There are two end-user bits: a command
|
||||||
line decoder called "test", and a simple Winamp plugin called "in_vgmstream".
|
line decoder called "test", and a simple Winamp plugin called "in_vgmstream".
|
||||||
|
|
||||||
--- needed files (for Windows) ---
|
--- needed files (for Windows) ---
|
||||||
Since Ogg Vorbis is now supported, you will need to have libvorbis.dll.
|
Since Ogg Vorbis and MPEG audio are now supported, you will need to have
|
||||||
I suggest this one:
|
libvorbis.dll and libmpg123-0.dll.
|
||||||
|
I suggest getting libvorbis.dll here:
|
||||||
http://www.rarewares.org/files/ogg/libvorbis1.2.0.zip
|
http://www.rarewares.org/files/ogg/libvorbis1.2.0.zip
|
||||||
and the companion Intel math dll, if you need it:
|
and the companion Intel math dll:
|
||||||
http://www.rarewares.org/files/libmmd9.1.zip
|
http://www.rarewares.org/files/libmmd9.1.zip
|
||||||
|
And libmpg123-0.dll from this archive:
|
||||||
|
http://www.mpg123.de/download/win32/mpg123-1.4.3-x86.zip
|
||||||
|
|
||||||
Put libvorbis.dll and libmmd.dll somewhere Windows can find them. For
|
Put libvorbis.dll, libmmd.dll, and libmpg123-0.dll somewhere Windows can find
|
||||||
in_vgmstream this means in the directory with winamp.exe, or in a system
|
them. For in_vgmstream this means in the directory with winamp.exe, or in a
|
||||||
directory. For test.exe that means in this means in the same directory as
|
system directory. For test.exe this means in the same directory as test.exe,
|
||||||
test.exe, or in a system directory.
|
or in a system directory.
|
||||||
|
|
||||||
--- test.exe ---
|
--- test.exe ---
|
||||||
Usage: test.exe [-o outfile.wav] [-l loop count]
|
Usage: test.exe [-o outfile.wav] [-l loop count]
|
||||||
@ -94,6 +97,7 @@ File types supported by this version of vgmstream:
|
|||||||
- .aiff (8/16 bit PCM)
|
- .aiff (8/16 bit PCM)
|
||||||
- .str (SDX2 DPCM)
|
- .str (SDX2 DPCM)
|
||||||
- .aud (IMA ADPCM, WS DPCM)
|
- .aud (IMA ADPCM, WS DPCM)
|
||||||
|
- .ahx (MPEG-2 Layer II)
|
||||||
|
|
||||||
Enjoy!
|
Enjoy!
|
||||||
-hcs
|
-hcs
|
||||||
|
@ -10,7 +10,8 @@ CODING_OBJS=coding/adx_decoder.o \
|
|||||||
coding/eaxa_decoder.o \
|
coding/eaxa_decoder.o \
|
||||||
coding/ogg_vorbis_decoder.o \
|
coding/ogg_vorbis_decoder.o \
|
||||||
coding/sdx2_decoder.o \
|
coding/sdx2_decoder.o \
|
||||||
coding/ws_decoder.o
|
coding/ws_decoder.o \
|
||||||
|
coding/mpeg_decoder.o
|
||||||
|
|
||||||
LAYOUT_OBJS=layout/ast_blocked.o \
|
LAYOUT_OBJS=layout/ast_blocked.o \
|
||||||
layout/blocked.o \
|
layout/blocked.o \
|
||||||
@ -63,7 +64,8 @@ META_OBJS=meta/adx_header.o \
|
|||||||
meta/ps2_bmdx.o \
|
meta/ps2_bmdx.o \
|
||||||
meta/aifc.o \
|
meta/aifc.o \
|
||||||
meta/str_snds.o \
|
meta/str_snds.o \
|
||||||
meta/ws_aud.o
|
meta/ws_aud.o \
|
||||||
|
meta/ahx.o
|
||||||
|
|
||||||
OBJECTS=vgmstream.o streamfile.o util.o $(CODING_OBJS) $(LAYOUT_OBJS) $(META_OBJS)
|
OBJECTS=vgmstream.o streamfile.o util.o $(CODING_OBJS) $(LAYOUT_OBJS) $(META_OBJS)
|
||||||
|
|
||||||
|
@ -4,6 +4,6 @@ AM_CFLAGS = -Wall @CFLAGS@ -I$(top_builddir) -I$(top_srcdir)
|
|||||||
AM_MAKEFLAGS=-f Makefile.unix
|
AM_MAKEFLAGS=-f Makefile.unix
|
||||||
|
|
||||||
libcoding_la_LDFLAGS =
|
libcoding_la_LDFLAGS =
|
||||||
libcoding_la_SOURCES = adx_decoder.c eaxa_decoder.c g721_decoder.c ima_decoder.c ngc_afc_decoder.c ngc_dsp_decoder.c ngc_dtk_decoder.c pcm_decoder.c psx_decoder.c xa_decoder.c ogg_vorbis_decoder.c sdx2_decoder.c ws_decoder.c
|
libcoding_la_SOURCES = adx_decoder.c eaxa_decoder.c g721_decoder.c ima_decoder.c ngc_afc_decoder.c ngc_dsp_decoder.c ngc_dtk_decoder.c pcm_decoder.c psx_decoder.c xa_decoder.c ogg_vorbis_decoder.c sdx2_decoder.c ws_decoder.c mpeg_decoder.c
|
||||||
|
|
||||||
EXTRA_DIST = coding.h g72x_state.h
|
EXTRA_DIST = coding.h g72x_state.h
|
||||||
|
@ -41,4 +41,10 @@ void decode_sdx2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing,
|
|||||||
|
|
||||||
void decode_ws(VGMSTREAM * vgmstream, int channel, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
void decode_ws(VGMSTREAM * vgmstream, int channel, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||||
|
|
||||||
|
#ifdef VGM_USE_MPEG
|
||||||
|
void decode_fake_mpeg2_l2(VGMSTREAMCHANNEL * stream,
|
||||||
|
fake_mpeg2_l2_codec_data * data,
|
||||||
|
sample * outbuf, int32_t samples_to_do);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
88
src/coding/mpeg_decoder.c
Normal file
88
src/coding/mpeg_decoder.c
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#include "../vgmstream.h"
|
||||||
|
|
||||||
|
#ifdef VGM_USE_MPEG
|
||||||
|
#include <string.h>
|
||||||
|
#include <mpg123.h>
|
||||||
|
#include "coding.h"
|
||||||
|
#include "../util.h"
|
||||||
|
|
||||||
|
/* mono, mpg123 expects frames of 0x414 (160kbps, 22050Hz) but they
|
||||||
|
* actually vary and are much shorter */
|
||||||
|
void decode_fake_mpeg2_l2(VGMSTREAMCHANNEL *stream,
|
||||||
|
fake_mpeg2_l2_codec_data * data,
|
||||||
|
sample * outbuf, int32_t samples_to_do) {
|
||||||
|
int samples_done = 0;
|
||||||
|
|
||||||
|
while (samples_done < samples_to_do) {
|
||||||
|
size_t bytes_done;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (!data->buffer_full) {
|
||||||
|
/* fill buffer up to next frame ending (or file ending) */
|
||||||
|
int bytes_into_header = 0;
|
||||||
|
const uint8_t header[4] = {0xff,0xf5,0xe0,0xc0};
|
||||||
|
off_t frame_offset = 0;
|
||||||
|
|
||||||
|
/* assume that we are starting at a header, skip it and look for the
|
||||||
|
* next one */
|
||||||
|
read_streamfile(data->buffer, stream->offset+frame_offset, 4,
|
||||||
|
stream->streamfile);
|
||||||
|
frame_offset += 4;
|
||||||
|
|
||||||
|
do {
|
||||||
|
uint8_t byte;
|
||||||
|
byte =
|
||||||
|
read_8bit(stream->offset+frame_offset,stream->streamfile);
|
||||||
|
data->buffer[frame_offset] = byte;
|
||||||
|
frame_offset++;
|
||||||
|
|
||||||
|
if (byte == header[bytes_into_header]) {
|
||||||
|
bytes_into_header++;
|
||||||
|
} else {
|
||||||
|
/* This might have been the first byte of the header, so
|
||||||
|
* we need to check again.
|
||||||
|
* No need to get more complicated than this, though, since
|
||||||
|
* there are no repeated characters in the search string. */
|
||||||
|
if (bytes_into_header>0) {
|
||||||
|
frame_offset--;
|
||||||
|
}
|
||||||
|
bytes_into_header=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes_into_header==4) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (frame_offset < AHX_EXPECTED_FRAME_SIZE);
|
||||||
|
|
||||||
|
if (bytes_into_header==4) frame_offset-=4;
|
||||||
|
memset(data->buffer+frame_offset,0,
|
||||||
|
AHX_EXPECTED_FRAME_SIZE-frame_offset);
|
||||||
|
|
||||||
|
data->buffer_full = 1;
|
||||||
|
data->buffer_used = 0;
|
||||||
|
|
||||||
|
stream->offset += frame_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data->buffer_used) {
|
||||||
|
rc = mpg123_decode(data->m,
|
||||||
|
data->buffer,AHX_EXPECTED_FRAME_SIZE,
|
||||||
|
(unsigned char *)(outbuf+samples_done),
|
||||||
|
(samples_to_do-samples_done)*sizeof(sample),
|
||||||
|
&bytes_done);
|
||||||
|
data->buffer_used = 1;
|
||||||
|
} else {
|
||||||
|
rc = mpg123_decode(data->m,
|
||||||
|
NULL,0,
|
||||||
|
(unsigned char *)(outbuf+samples_done),
|
||||||
|
(samples_to_do-samples_done)*sizeof(sample),
|
||||||
|
&bytes_done);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == MPG123_NEED_MORE) data->buffer_full = 0;
|
||||||
|
|
||||||
|
samples_done += bytes_done/sizeof(sample);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -4,6 +4,6 @@ AM_CFLAGS = -Wall @CFLAGS@ -I$(top_builddir) -I$(top_srcdir)
|
|||||||
AM_MAKEFLAGS=-f Makefile.unix
|
AM_MAKEFLAGS=-f Makefile.unix
|
||||||
|
|
||||||
libmeta_la_LDFLAGS =
|
libmeta_la_LDFLAGS =
|
||||||
libmeta_la_SOURCES = Cstr.c adx_header.c afc_header.c agsc.c ast.c brstm.c ea_header.c gcsw.c halpst.c nds_strm.c ngc_adpdtk.c ngc_caf.c ngc_dsp_std.c ps2_ads.c ps2_exst.c ps2_ild.c ps2_int.c ps2_mib.c ps2_mic.c ps2_npsf.c ps2_pnb.c ps2_rxw.c ps2_str.c ps2_svag.c ps2_vag.c ps2_vpk.c psx_cdxa.c raw.c rs03.c rsf.c rwsd.c psx_gms.c xbox_xwav.c xbox_wavm.c genh.c ogg_vorbis_file.c ps2_bmdx.c aifc.c str_snds.c ws_aud.c
|
libmeta_la_SOURCES = Cstr.c adx_header.c afc_header.c agsc.c ast.c brstm.c ea_header.c gcsw.c halpst.c nds_strm.c ngc_adpdtk.c ngc_caf.c ngc_dsp_std.c ps2_ads.c ps2_exst.c ps2_ild.c ps2_int.c ps2_mib.c ps2_mic.c ps2_npsf.c ps2_pnb.c ps2_rxw.c ps2_str.c ps2_svag.c ps2_vag.c ps2_vpk.c psx_cdxa.c raw.c rs03.c rsf.c rwsd.c psx_gms.c xbox_xwav.c xbox_wavm.c genh.c ogg_vorbis_file.c ps2_bmdx.c aifc.c str_snds.c ws_aud.c ahx.c
|
||||||
|
|
||||||
EXTRA_DIST = meta.h
|
EXTRA_DIST = meta.h
|
||||||
|
121
src/meta/ahx.c
Normal file
121
src/meta/ahx.c
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
#include "../vgmstream.h"
|
||||||
|
|
||||||
|
#ifdef VGM_USE_MPEG
|
||||||
|
|
||||||
|
#include "meta.h"
|
||||||
|
#include "../util.h"
|
||||||
|
|
||||||
|
/* AHX is a CRI format which contains an MPEG-2 Layer 2 audio stream.
|
||||||
|
* Although the MPEG frame headers are incorrect... */
|
||||||
|
|
||||||
|
VGMSTREAM * init_vgmstream_ahx(STREAMFILE *streamFile) {
|
||||||
|
VGMSTREAM * vgmstream = NULL;
|
||||||
|
off_t stream_offset;
|
||||||
|
size_t filesize;
|
||||||
|
char filename[260];
|
||||||
|
int channel_count = 1;
|
||||||
|
int loop_flag = 0;
|
||||||
|
fake_mpeg2_l2_codec_data *data = NULL;
|
||||||
|
|
||||||
|
/* check extension, case insensitive */
|
||||||
|
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||||
|
if (strcasecmp("ahx",filename_extension(filename))) goto fail;
|
||||||
|
|
||||||
|
filesize = get_streamfile_size(streamFile);
|
||||||
|
|
||||||
|
/* check first 2 bytes */
|
||||||
|
if ((uint16_t)read_16bitBE(0,streamFile)!=0x8000) goto fail;
|
||||||
|
|
||||||
|
/* get stream offset, check for CRI signature just before */
|
||||||
|
stream_offset = (uint16_t)read_16bitBE(2,streamFile) + 4;
|
||||||
|
if ((uint16_t)read_16bitBE(stream_offset-6,streamFile)!=0x2863 ||/* "(c" */
|
||||||
|
(uint32_t)read_32bitBE(stream_offset-4,streamFile)!=0x29435249 /* ")CRI" */
|
||||||
|
) goto fail;
|
||||||
|
|
||||||
|
/* check for encoding type */
|
||||||
|
/* 2 is for some unknown fixed filter, 3 is standard ADX, 4 is
|
||||||
|
* ADX with exponential scale, 0x11 is AHX */
|
||||||
|
/* Sappharad reports that old AHXs (Sonic Adventure 2) don't have this flag.
|
||||||
|
* When I see one perhaps I can add an exception for those. */
|
||||||
|
if (read_8bit(4,streamFile) != 0x11) goto fail;
|
||||||
|
|
||||||
|
/* check for frame size (0 for AHX) */
|
||||||
|
if (read_8bit(5,streamFile) != 0) goto fail;
|
||||||
|
|
||||||
|
/* check for bits per sample? (0 for AHX) */
|
||||||
|
if (read_8bit(6,streamFile) != 0) goto fail;
|
||||||
|
|
||||||
|
/* check channel count (only mono AHXs are known) */
|
||||||
|
if (read_8bit(7,streamFile) != 1) goto fail;
|
||||||
|
|
||||||
|
/* At this point we almost certainly have an ADX file,
|
||||||
|
* so let's build the VGMSTREAM. */
|
||||||
|
|
||||||
|
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||||
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
|
/* fill in the vital statistics */
|
||||||
|
vgmstream->num_samples = read_32bitBE(0xc,streamFile);
|
||||||
|
/* This is the One True Samplerate, the MPEG headers lie. */
|
||||||
|
vgmstream->sample_rate = read_32bitBE(8,streamFile);
|
||||||
|
|
||||||
|
vgmstream->coding_type = coding_fake_MPEG2_L2;
|
||||||
|
vgmstream->layout_type = layout_fake_mpeg;
|
||||||
|
vgmstream->meta_type = meta_AHX;
|
||||||
|
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
STREAMFILE * chstreamfile;
|
||||||
|
|
||||||
|
chstreamfile = streamFile->open(streamFile,filename,
|
||||||
|
STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||||
|
if (!chstreamfile) goto fail;
|
||||||
|
|
||||||
|
for (i=0;i<channel_count;i++) {
|
||||||
|
vgmstream->ch[i].streamfile = chstreamfile;
|
||||||
|
|
||||||
|
vgmstream->ch[i].channel_start_offset=
|
||||||
|
vgmstream->ch[i].offset=
|
||||||
|
stream_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ooh, fun part, set up mpg123 */
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
data = calloc(1,sizeof(fake_mpeg2_l2_codec_data));
|
||||||
|
if (!data) goto fail;
|
||||||
|
|
||||||
|
data->m = mpg123_new(NULL,&rc);
|
||||||
|
if (rc==MPG123_NOT_INITIALIZED) {
|
||||||
|
if (mpg123_init()!=MPG123_OK) goto fail;
|
||||||
|
data->m = mpg123_new(NULL,&rc);
|
||||||
|
if (rc!=MPG123_OK) goto fail;
|
||||||
|
} else if (rc!=MPG123_OK) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mpg123_open_feed(data->m)!=MPG123_OK) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
vgmstream->codec_data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vgmstream;
|
||||||
|
|
||||||
|
/* clean up anything we may have opened */
|
||||||
|
fail:
|
||||||
|
if (data) {
|
||||||
|
if (data->m) {
|
||||||
|
mpg123_delete(data->m);
|
||||||
|
data->m = NULL;
|
||||||
|
}
|
||||||
|
free(data);
|
||||||
|
data = NULL;
|
||||||
|
}
|
||||||
|
if (vgmstream) close_vgmstream(vgmstream);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -97,4 +97,8 @@ VGMSTREAM * init_vgmstream_str_snds(STREAMFILE * streamFile);
|
|||||||
|
|
||||||
VGMSTREAM * init_vgmstream_ws_aud(STREAMFILE * streamFile);
|
VGMSTREAM * init_vgmstream_ws_aud(STREAMFILE * streamFile);
|
||||||
|
|
||||||
|
#ifdef VGM_USE_MPEG
|
||||||
|
VGMSTREAM * init_vgmstream_ahx(STREAMFILE * streamFile);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
#include "layout/layout.h"
|
#include "layout/layout.h"
|
||||||
#include "coding/coding.h"
|
#include "coding/coding.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* List of functions that will recognize files. These should correspond pretty
|
* List of functions that will recognize files. These should correspond pretty
|
||||||
* directly to the metadata types
|
* directly to the metadata types
|
||||||
@ -64,6 +63,9 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = {
|
|||||||
init_vgmstream_aifc,
|
init_vgmstream_aifc,
|
||||||
init_vgmstream_str_snds,
|
init_vgmstream_str_snds,
|
||||||
init_vgmstream_ws_aud,
|
init_vgmstream_ws_aud,
|
||||||
|
#ifdef VGM_USE_MPEG
|
||||||
|
init_vgmstream_ahx,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#define INIT_VGMSTREAM_FCNS (sizeof(init_vgmstream_fcns)/sizeof(init_vgmstream_fcns[0]))
|
#define INIT_VGMSTREAM_FCNS (sizeof(init_vgmstream_fcns)/sizeof(init_vgmstream_fcns[0]))
|
||||||
@ -137,13 +139,23 @@ void reset_vgmstream(VGMSTREAM * vgmstream) {
|
|||||||
|
|
||||||
#ifdef VGM_USE_VORBIS
|
#ifdef VGM_USE_VORBIS
|
||||||
if (vgmstream->meta_type==meta_ogg_vorbis) {
|
if (vgmstream->meta_type==meta_ogg_vorbis) {
|
||||||
ogg_vorbis_codec_data *data =
|
ogg_vorbis_codec_data *data = vgmstream->codec_data;
|
||||||
(ogg_vorbis_codec_data *)(vgmstream->codec_data);
|
|
||||||
OggVorbis_File *ogg_vorbis_file = &(data->ogg_vorbis_file);
|
OggVorbis_File *ogg_vorbis_file = &(data->ogg_vorbis_file);
|
||||||
|
|
||||||
ov_pcm_seek(ogg_vorbis_file, 0);
|
ov_pcm_seek(ogg_vorbis_file, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef VGM_USE_MPEG
|
||||||
|
if (vgmstream->coding_type==coding_fake_MPEG2_L2) {
|
||||||
|
off_t input_offset;
|
||||||
|
fake_mpeg2_l2_codec_data *data = vgmstream->codec_data;
|
||||||
|
|
||||||
|
/* input_offset is ignored as we can assume it will be 0 for a seek
|
||||||
|
* to sample 0 */
|
||||||
|
mpg123_feedseek(data->m,0,SEEK_SET,&input_offset);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* simply allocate memory for the VGMSTREAM and its channels */
|
/* simply allocate memory for the VGMSTREAM and its channels */
|
||||||
@ -230,12 +242,10 @@ void close_vgmstream(VGMSTREAM * vgmstream) {
|
|||||||
|
|
||||||
#ifdef VGM_USE_VORBIS
|
#ifdef VGM_USE_VORBIS
|
||||||
if (vgmstream->meta_type==meta_ogg_vorbis) {
|
if (vgmstream->meta_type==meta_ogg_vorbis) {
|
||||||
ogg_vorbis_codec_data *data =
|
ogg_vorbis_codec_data *data = vgmstream->codec_data;
|
||||||
(ogg_vorbis_codec_data *)(vgmstream->codec_data);
|
|
||||||
if (vgmstream->codec_data) {
|
if (vgmstream->codec_data) {
|
||||||
OggVorbis_File *ogg_vorbis_file = &(data->ogg_vorbis_file);
|
OggVorbis_File *ogg_vorbis_file = &(data->ogg_vorbis_file);
|
||||||
|
|
||||||
|
|
||||||
ov_clear(ogg_vorbis_file);
|
ov_clear(ogg_vorbis_file);
|
||||||
|
|
||||||
close_streamfile(data->ov_streamfile.streamfile);
|
close_streamfile(data->ov_streamfile.streamfile);
|
||||||
@ -245,6 +255,23 @@ void close_vgmstream(VGMSTREAM * vgmstream) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef VGM_USE_MPEG
|
||||||
|
if (vgmstream->coding_type==coding_fake_MPEG2_L2) {
|
||||||
|
fake_mpeg2_l2_codec_data *data = vgmstream->codec_data;
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
mpg123_delete(data->m);
|
||||||
|
free(vgmstream->codec_data);
|
||||||
|
vgmstream->codec_data = NULL;
|
||||||
|
/* The astute reader will note that a call to mpg123_exit is never
|
||||||
|
* make. While is is evilly breaking our contract with mpg123, it
|
||||||
|
* doesn't actually do anything except set the "initialized" flag
|
||||||
|
* to 0. And if we exit we run the risk of turning it off when
|
||||||
|
* someone else in another thread is using it. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
free(vgmstream);
|
free(vgmstream);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,6 +289,9 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre
|
|||||||
break;
|
break;
|
||||||
#ifdef VGM_USE_VORBIS
|
#ifdef VGM_USE_VORBIS
|
||||||
case layout_ogg_vorbis:
|
case layout_ogg_vorbis:
|
||||||
|
#endif
|
||||||
|
#ifdef VGM_USE_MPEG
|
||||||
|
case layout_fake_mpeg:
|
||||||
#endif
|
#endif
|
||||||
case layout_dtk_interleave:
|
case layout_dtk_interleave:
|
||||||
case layout_none:
|
case layout_none:
|
||||||
@ -291,6 +321,9 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
|
|||||||
case coding_PCM8:
|
case coding_PCM8:
|
||||||
#ifdef VGM_USE_VORBIS
|
#ifdef VGM_USE_VORBIS
|
||||||
case coding_ogg_vorbis:
|
case coding_ogg_vorbis:
|
||||||
|
#endif
|
||||||
|
#ifdef VGM_USE_MPEG
|
||||||
|
case coding_fake_MPEG2_L2:
|
||||||
#endif
|
#endif
|
||||||
case coding_SDX2:
|
case coding_SDX2:
|
||||||
return 1;
|
return 1;
|
||||||
@ -515,6 +548,16 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
|
|||||||
samples_to_do);
|
samples_to_do);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#ifdef VGM_USE_MPEG
|
||||||
|
case coding_fake_MPEG2_L2:
|
||||||
|
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||||
|
decode_fake_mpeg2_l2(
|
||||||
|
&vgmstream->ch[chan],
|
||||||
|
vgmstream->codec_data,
|
||||||
|
buffer+samples_written*vgmstream->channels,samples_to_do);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -713,6 +756,11 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
|
|||||||
case coding_WS:
|
case coding_WS:
|
||||||
snprintf(temp,TEMPSIZE,"Westwood Studios DPCM");
|
snprintf(temp,TEMPSIZE,"Westwood Studios DPCM");
|
||||||
break;
|
break;
|
||||||
|
#ifdef VGM_USE_MPEG
|
||||||
|
case coding_fake_MPEG2_L2:
|
||||||
|
snprintf(temp,TEMPSIZE,"MPEG-2 Layer II Audio");
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
snprintf(temp,TEMPSIZE,"CANNOT DECODE");
|
snprintf(temp,TEMPSIZE,"CANNOT DECODE");
|
||||||
}
|
}
|
||||||
@ -763,6 +811,12 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
|
|||||||
case layout_ws_aud_blocked:
|
case layout_ws_aud_blocked:
|
||||||
snprintf(temp,TEMPSIZE,"Westwood Studios .aud blocked");
|
snprintf(temp,TEMPSIZE,"Westwood Studios .aud blocked");
|
||||||
break;
|
break;
|
||||||
|
#ifdef VGM_USE_MPEG
|
||||||
|
case layout_fake_mpeg:
|
||||||
|
snprintf(temp,TEMPSIZE,"MPEG Audio stream with incorrect frame headers");
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
snprintf(temp,TEMPSIZE,"INCONCEIVABLE");
|
snprintf(temp,TEMPSIZE,"INCONCEIVABLE");
|
||||||
}
|
}
|
||||||
@ -969,6 +1023,11 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
|
|||||||
case meta_WS_AUD_old:
|
case meta_WS_AUD_old:
|
||||||
snprintf(temp,TEMPSIZE,"Westwood Studios .aud (old) header");
|
snprintf(temp,TEMPSIZE,"Westwood Studios .aud (old) header");
|
||||||
break;
|
break;
|
||||||
|
#ifdef VGM_USE_MPEG
|
||||||
|
case meta_AHX:
|
||||||
|
snprintf(temp,TEMPSIZE,"CRI AHX header");
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
snprintf(temp,TEMPSIZE,"THEY SHOULD HAVE SENT A POET");
|
snprintf(temp,TEMPSIZE,"THEY SHOULD HAVE SENT A POET");
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,21 @@
|
|||||||
#ifndef _VGMSTREAM_H
|
#ifndef _VGMSTREAM_H
|
||||||
#define _VGMSTREAM_H
|
#define _VGMSTREAM_H
|
||||||
|
|
||||||
|
/* Vorbis and MPEG decoding are done by external libraries.
|
||||||
|
* If someone wants to do a standalone build, they can do it by simply
|
||||||
|
* removing these defines (and the references to the libraries in the
|
||||||
|
* Makefile) */
|
||||||
#define VGM_USE_VORBIS
|
#define VGM_USE_VORBIS
|
||||||
|
#define VGM_USE_MPEG
|
||||||
|
|
||||||
#include "streamfile.h"
|
#include "streamfile.h"
|
||||||
#include "coding/g72x_state.h"
|
#include "coding/g72x_state.h"
|
||||||
#ifdef VGM_USE_VORBIS
|
#ifdef VGM_USE_VORBIS
|
||||||
#include <vorbis/vorbisfile.h>
|
#include <vorbis/vorbisfile.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef VGM_USE_MPEG
|
||||||
|
#include <mpg123.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* The encoding type specifies the format the sound data itself takes */
|
/* The encoding type specifies the format the sound data itself takes */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -39,6 +47,9 @@ typedef enum {
|
|||||||
coding_DVI_IMA, /* DVI (bare IMA, high nibble first), aka ADP4 */
|
coding_DVI_IMA, /* DVI (bare IMA, high nibble first), aka ADP4 */
|
||||||
coding_IMA, /* bare IMA, low nibble first */
|
coding_IMA, /* bare IMA, low nibble first */
|
||||||
coding_WS, /* Westwood Studios' custom VBR ADPCM */
|
coding_WS, /* Westwood Studios' custom VBR ADPCM */
|
||||||
|
#ifdef VGM_USE_MPEG
|
||||||
|
coding_fake_MPEG2_L2, /* MPEG-2 Level 2 (AHX), with lying headers */
|
||||||
|
#endif
|
||||||
} coding_t;
|
} coding_t;
|
||||||
|
|
||||||
/* The layout type specifies how the sound data is laid out in the file */
|
/* The layout type specifies how the sound data is laid out in the file */
|
||||||
@ -68,6 +79,9 @@ typedef enum {
|
|||||||
#ifdef VGM_USE_VORBIS
|
#ifdef VGM_USE_VORBIS
|
||||||
layout_ogg_vorbis, /* ogg vorbis file */
|
layout_ogg_vorbis, /* ogg vorbis file */
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef VGM_USE_MPEG
|
||||||
|
layout_fake_mpeg, /* MPEG audio stream with bad frame headers (AHX) */
|
||||||
|
#endif
|
||||||
} layout_t;
|
} layout_t;
|
||||||
|
|
||||||
/* The meta type specifies how we know what we know about the file. We may know because of a header we read, some of it may have been guessed from filenames, etc. */
|
/* The meta type specifies how we know what we know about the file. We may know because of a header we read, some of it may have been guessed from filenames, etc. */
|
||||||
@ -149,6 +163,9 @@ typedef enum {
|
|||||||
meta_STR_SNDS, /* .str with SNDS blocks and SHDR header */
|
meta_STR_SNDS, /* .str with SNDS blocks and SHDR header */
|
||||||
meta_WS_AUD, /* Westwood Studios .aud */
|
meta_WS_AUD, /* Westwood Studios .aud */
|
||||||
meta_WS_AUD_old, /* Westwood Studios .aud, old style */
|
meta_WS_AUD_old, /* Westwood Studios .aud, old style */
|
||||||
|
#ifdef VGM_USE_MPEG
|
||||||
|
meta_AHX, /* CRI AHX header (same structure as ADX) */
|
||||||
|
#endif
|
||||||
} meta_t;
|
} meta_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -259,6 +276,15 @@ typedef struct {
|
|||||||
} ogg_vorbis_codec_data;
|
} ogg_vorbis_codec_data;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef VGM_USE_MPEG
|
||||||
|
#define AHX_EXPECTED_FRAME_SIZE 0x414
|
||||||
|
typedef struct {
|
||||||
|
uint8_t buffer[AHX_EXPECTED_FRAME_SIZE];
|
||||||
|
int buffer_used;
|
||||||
|
int buffer_full;
|
||||||
|
mpg123_handle *m;
|
||||||
|
} fake_mpeg2_l2_codec_data;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* do format detection, return pointer to a usable VGMSTREAM, or NULL on failure */
|
/* do format detection, return pointer to a usable VGMSTREAM, or NULL on failure */
|
||||||
VGMSTREAM * init_vgmstream(const char * const filename);
|
VGMSTREAM * init_vgmstream(const char * const filename);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
export SHELL = /bin/sh
|
export SHELL = /bin/sh
|
||||||
export CFLAGS=-Wall -O3
|
export CFLAGS=-Wall -O3
|
||||||
export LDFLAGS=-lm -L../src -lvgmstream -lvorbisfile
|
export LDFLAGS=-lm -L../src -lvgmstream -lvorbisfile -lmpg123
|
||||||
export STRIP=strip
|
export STRIP=strip
|
||||||
|
|
||||||
.PHONY: libvgmstream.a
|
.PHONY: libvgmstream.a
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
export SHELL = /bin/sh
|
export SHELL = /bin/sh
|
||||||
export CFLAGS=-Wall -O3 -I../ext_includes
|
export CFLAGS=-Wall -O3 -I../ext_includes
|
||||||
export LDFLAGS=-lm -L../src -L../ext_libs -lvgmstream -lvorbis
|
export LDFLAGS=-lm -L../src -L../ext_libs -lvgmstream -lvorbis -lmpg123-0
|
||||||
export CC=i586-mingw32msvc-gcc
|
export CC=i586-mingw32msvc-gcc
|
||||||
export AR=i586-mingw32msvc-ar
|
export AR=i586-mingw32msvc-ar
|
||||||
export STRIP=i586-mingw32msvc-strip
|
export STRIP=i586-mingw32msvc-strip
|
||||||
|
|
||||||
.PHONY: libvgmstream.a libvorbis.a
|
.PHONY: libvgmstream.a libvorbis.a libmpg123-0.a
|
||||||
|
|
||||||
test.exe: libvgmstream.a libvorbis.a
|
test.exe: libvgmstream.a libvorbis.a libmpg123-0.a
|
||||||
$(CC) $(CFLAGS) "-DVERSION=\"`../version.sh`\"" test.c $(LDFLAGS) -o test.exe
|
$(CC) $(CFLAGS) "-DVERSION=\"`../version.sh`\"" test.c $(LDFLAGS) -o test.exe
|
||||||
$(STRIP) test.exe
|
$(STRIP) test.exe
|
||||||
|
|
||||||
@ -17,5 +17,8 @@ libvgmstream.a:
|
|||||||
libvorbis.a:
|
libvorbis.a:
|
||||||
$(MAKE) -C ../ext_libs -f Makefile.mingw $@
|
$(MAKE) -C ../ext_libs -f Makefile.mingw $@
|
||||||
|
|
||||||
|
libmpg123-0.a:
|
||||||
|
$(MAKE) -C ../ext_libs -f Makefile.mingw $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f test.exe
|
rm -f test.exe
|
||||||
|
@ -63,6 +63,7 @@ gchar *vgmstream_exts [] = {
|
|||||||
"wsi",
|
"wsi",
|
||||||
"aifc",
|
"aifc",
|
||||||
"aud",
|
"aud",
|
||||||
|
"ahx",
|
||||||
/* terminator */
|
/* terminator */
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
export SHELL = /bin/sh
|
export SHELL = /bin/sh
|
||||||
export CFLAGS=-Wall -O3 -I../ext_includes
|
export CFLAGS=-Wall -O3 -I../ext_includes
|
||||||
export LDFLAGS=-lm -L../src -L../ext_libs -lvgmstream -lvorbis
|
export LDFLAGS=-lm -L../src -L../ext_libs -lvgmstream -lvorbis -lmpg123-0
|
||||||
export CC=i586-mingw32msvc-gcc
|
export CC=i586-mingw32msvc-gcc
|
||||||
export AR=i586-mingw32msvc-ar
|
export AR=i586-mingw32msvc-ar
|
||||||
export STRIP=i586-mingw32msvc-strip
|
export STRIP=i586-mingw32msvc-strip
|
||||||
export WINDRES=i586-mingw32msvc-windres
|
export WINDRES=i586-mingw32msvc-windres
|
||||||
|
|
||||||
.PHONY: libvgmstream.a libvorbis.a
|
.PHONY: libvgmstream.a libvorbis.a libmpg123-0.a
|
||||||
|
|
||||||
in_vgmstream.dll: libvgmstream.a libvorbis.a in_vgmstream.c resource.o
|
in_vgmstream.dll: libvgmstream.a libvorbis.a libmpg123-0.a in_vgmstream.c resource.o
|
||||||
$(CC) -shared $(CFLAGS) "-DVERSION=\"`../version.sh`\"" in_vgmstream.c resource.o $(LDFLAGS) -o in_vgmstream.dll
|
$(CC) -shared $(CFLAGS) "-DVERSION=\"`../version.sh`\"" in_vgmstream.c resource.o $(LDFLAGS) -o in_vgmstream.dll
|
||||||
$(STRIP) in_vgmstream.dll
|
$(STRIP) in_vgmstream.dll
|
||||||
|
|
||||||
@ -21,5 +21,8 @@ libvgmstream.a:
|
|||||||
libvorbis.a:
|
libvorbis.a:
|
||||||
$(MAKE) -C ../ext_libs -f Makefile.mingw libvorbis.a
|
$(MAKE) -C ../ext_libs -f Makefile.mingw libvorbis.a
|
||||||
|
|
||||||
|
libmpg123-0.a:
|
||||||
|
$(MAKE) -C ../ext_libs -f Makefile.mingw libmpg123-0.a
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f in_vgmstream.dll resource.o
|
rm -f in_vgmstream.dll resource.o
|
||||||
|
@ -121,6 +121,7 @@ char * extension_list[] = {
|
|||||||
"wsi\0WSI Audio File (*.WSI)\0",
|
"wsi\0WSI Audio File (*.WSI)\0",
|
||||||
"aifc\0AIFC Audio File (*.AIFC)\0",
|
"aifc\0AIFC Audio File (*.AIFC)\0",
|
||||||
"aud\0AUD Audio File (*.AUD)\0",
|
"aud\0AUD Audio File (*.AUD)\0",
|
||||||
|
"ahx\0AHX Audio File (*.AHX)\0",
|
||||||
};
|
};
|
||||||
|
|
||||||
void about(HWND hwndParent) {
|
void about(HWND hwndParent) {
|
||||||
|
Loading…
Reference in New Issue
Block a user