mpg123 - Fast console MPEG Audio Player and decoder library
http://www.mpg123.de/
Reason
- ACM decorder is poor sound quality. mpg123 supported Float32.
ACM decorder mix little noise for realtime decode.
ACM decoder need MP3 Codec
ACM decoder is very slow. mpg123 is very fast.
License is gray. mpg123 is LGPL.
Libmpg123 is MP3 libraly by LGPL. But DLL don't run on PB. Because no use _stdcall
This tips is making DLL and sample.pb.
I live in Japan, and I can't distribute libmpg123.dll by Japanese law.

GNU GCC use... this need
NEXTInstalled MinGW32 and MinSYS
How to install MinGW32
http://sourceforge.net/project/showfile ... up_id=2435
MinGW-5.1.4.exe
->Download and install
->I Agree
->Current
->Full installation
->C:\MinGW
Downloading and install
How to install MinSYS
http://sourceforge.net/project/showfile ... up_id=2435
MSYS-1.0.11.exe
This will install "Minimal SYStem". Do you wish to continue? -> Yes
->C:\MSYS\1.0
->MinGW
->Install
This is a post install process that will try to normalize between
your MinGW install if any as well as your previous MSYS installs
if any. I don't have any traps as aborts will not hurt anything.
Do you wish to continue with the post install? [yn ] y
Do you have MinGW installed? [yn ] y
Please answer the following in the form of c:/foo/bar.
Where is your MinGW installation? C:/MinGW
How to setup MinGW
Run MinSys
$ echo $PATH
->Check OK?
$ cd /etc/
$ cp fstab.sample fstab
->Edit
#C:/ActiveState/perl /perl
->Exit minsys, Run minsys (reboot)
$ ls -l /mingw
->Check OK?
Download mpg123-1.9.1.tar.bz2
http://sourceforge.net/projects/mpg123/files/
use 7zip (windows)
Extract to
C:\msys\1.0\home\<user>\
Created directory "mpg123-1.9.1"
You must change source file. Now, DLL's target is MinGW only.
Change or Add "_stdcall"
/configure
Change configure Lines::12997
ccalign="yes" to ccalign="no"
Code: Select all
ccalign="unknown"
if test x"$ccalign" = xunknown; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking __attribute__((aligned(16)))" >&5
$as_echo_n "checking __attribute__((aligned(16)))... " >&6; }
ccalign="no"
echo '__attribute__((aligned(16))) float var;' > conftest.c
if $CC -c -o conftest.o conftest.c >/dev/null 2>&1; then
ccalign="no"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f conftest.o conftest.c
fi
/src/libmpg123/
libmpg123.c :: All change
attribute_align_arg -> __stdcall
Code: Select all
int __stdcall mpg123_init(void)
{
ALIGNCHECKK
if((sizeof(short) != 2) || (sizeof(long) < 4)) return MPG123_BAD_TYPES;
if(initialized) return MPG123_OK; /* no need to initialize twice */
#ifndef NO_LAYER12
init_layer12(); /* inits also shared tables with layer1 */
#endif
#ifndef NO_LAYER3
init_layer3();
#endif
prepare_decode_tables();
check_decoders();
initialized = 1;
return MPG123_OK;
}
Code: Select all
/** Function to initialise the mpg123 library.
* This function is not thread-safe. Call it exactly once per process, before any other (possibly threaded) work with the library.
*
* \return MPG123_OK if successful, otherwise an error number.
*/
EXPORT int __stdcall mpg123_init(void);
/** Function to close down the mpg123 library.
* This function is not thread-safe. Call it exactly once per process, before any other (possibly threaded) work with the library. */
EXPORT void __stdcall mpg123_exit(void);
Code: Select all
struct reader_data
{
off_t filelen; /* total file length or total buffer size */
off_t filepos; /* position in file or position in buffer chain */
int filept;
int flags;
#ifndef WIN32
long timeout_sec;
#endif
ssize_t (*fdread) (mpg123_handle *, void *, size_t);
/* User can replace the read and lseek functions. The r_* are the stored replacement functions or NULL,
The second two pointers are the actual workers (default map to POSIX read/lseek). */
ssize_t __stdcall (*r_read) (int fd, void *buf, size_t count);
off_t __stdcall (*r_lseek)(int fd, off_t offset, int whence);
ssize_t __stdcall (*read) (int fd, void *buf, size_t count);
off_t __stdcall (*lseek)(int fd, off_t offset, int whence);
/* Buffered readers want that abstracted, set internally. */
ssize_t (*fullread)(mpg123_handle *, unsigned char *, ssize_t);
struct bufferchain buffer; /* Not dynamically allocated, these few struct bytes aren't worth the trouble. */
};
Code: Select all
static int default_init(mpg123_handle *fr);
static off_t get_fileinfo(mpg123_handle *);
static ssize_t __stdcall posix_read(int fd, void *buf, size_t count){ return read(fd, buf, count); }
static off_t __stdcall posix_lseek(int fd, off_t offset, int whence){ return lseek(fd, offset, whence); }
Code: Select all
double __stdcall mpg123_tpf(mpg123_handle *fr)
{
static int bs[4] = { 0,384,1152,1152 };
double tpf;
if(fr == NULL) return -1;
tpf = (double) bs[fr->lay];
tpf /= freqs[fr->sampling_frequency] << (fr->lsf);
return tpf;
}
int __stdcall mpg123_position(mpg123_handle *fr, off_t no, off_t buffsize,
off_t *current_frame, off_t *frames_left,
double *current_seconds, double *seconds_left)
frame.c, format.c, optimize.c, libmpg123.c, stringbuf.c
If Error display, check code. example stringbuf.c ..... err, check stringbuf.c$ makedll.sh
ReCompile
$ make clean
$ makedll.sh
Warning only is OK! DLL made Root Directory!!
"libmpg123-0.dll" 278KB
PureBasic Sample
This is mp3 to wav. If error, Registory EBP changed. Check debug assembly.
Code: Select all
; Author oryaaaaa / 2009.10.16
;
; This example original is here
; http://www.mpg123.de/api/mpg123__to__wav_8c-source.shtml
#MPG123_ENC_16 = $040
#MPG123_ENC_SIGNED = $080
#MPG123_ENC_SIGNED_16 = #MPG123_ENC_16|#MPG123_ENC_SIGNED|$10
#MPG123_OK=0
#MPG123_ERR=-1
#MPG123_DONE=-12
#MPG123_NEW_FORMAT=-11
#MPG123_NEED_MORE=-10
Global mpg123_close.l, mpg123_delete.l, mpg123_exit.l, mpg123_init.l
Global mpg123_new.l, mpg123_init.l, mpg123_new.l, mpg123_open.l
Global mpg123_fmt_none.l, mpg123_getformat.l, mpg123_plain_strerror.l
Global mpg123_strerror.l, mpg123_format.l, mpg123_read, mpg123_outblock.l
Procedure libmpg123_Init()
Shared DLL.l
DLL = LoadLibraryM(?L1)
If DLL
mpg123_close = GetProcAddressM(DLL, "mpg123_close")
mpg123_delete = GetProcAddressM(DLL, "mpg123_delete")
mpg123_exit = GetProcAddressM(DLL, "mpg123_exit")
;
mpg123_init = GetProcAddressM(DLL, "mpg123_init")
;
mpg123_new = GetProcAddressM(DLL, "mpg123_new")
mpg123_open = GetProcAddressM(DLL, "mpg123_open")
mpg123_fmt_none = GetProcAddressM(DLL, "mpg123_fmt_none")
mpg123_getformat = GetProcAddressM(DLL, "mpg123_getformat")
mpg123_outblock = GetProcAddressM(DLL, "mpg123_outblock")
;
mpg123_plain_strerror = GetProcAddressM(DLL, "mpg123_plain_strerror")
mpg123_strerror = GetProcAddressM(DLL, "mpg123_strerror")
;
mpg123_format = GetProcAddressM(DLL, "mpg123_format")
;
mpg123_read = GetProcAddressM(DLL, "mpg123_read")
EndIf
DataSection
L1: IncludeBinary "libmpg123-0.dll"
EndDataSection
EndProcedure
Procedure libmpg123_End()
Shared DLL.l
FreeLibraryM(DLL)
EndProcedure
Procedure.l mpg123_close(mh.l)
ProcedureReturn CallFunctionFast(mpg123_close, mh)
EndProcedure
Procedure.l mpg123_delete(mh.l)
ProcedureReturn CallFunctionFast(mpg123_delete, mh)
EndProcedure
Procedure.l mpg123_exit()
ProcedureReturn CallFunctionFast(mpg123_exit)
EndProcedure
Procedure.l mpg123_init()
ProcedureReturn CallFunctionFast(mpg123_init)
EndProcedure
Procedure.l mpg123_new(decoder.l, mh.l)
ProcedureReturn CallFunctionFast(mpg123_new, decoder, mh)
EndProcedure
Procedure.l mpg123_open(mh.l, Path.l)
ProcedureReturn CallFunctionFast(mpg123_open, mh, Path)
EndProcedure
Procedure.l mpg123_fmt_none(mh.l)
ProcedureReturn CallFunctionFast(mpg123_fmt_none, mh)
EndProcedure
Procedure.l mpg123_getformat(mh.l, rate.l, channels.l, encoding.l)
ProcedureReturn CallFunctionFast(mpg123_getformat, mh, rate, channels, encoding)
EndProcedure
Procedure.s mpg123_plain_strerror(errcode.l)
Protected Result.s
Select errcode
Case 0
ProcedureReturn "No error... (code 0)"
Case 1
ProcedureReturn "Unable to set up output format! (code 1)"
Case 2
ProcedureReturn "Invalid channel number specified. (code 2)"
Case 3
ProcedureReturn "Invalid sample rate specified. (code 3)"
Case 4
ProcedureReturn "Unable to allocate memory for 16 to 8 converter table! (code 4)"
Case 5
ProcedureReturn "Bad parameter id! (code 5)"
Case 6
ProcedureReturn "Bad buffer given -- invalid pointer or too small size. (code 6)"
Case 7
ProcedureReturn "Out of memory -- some malloc() failed. (code 7)"
Case 8
ProcedureReturn "You didn't initialize the library! (code 8)"
Case 9
ProcedureReturn "Invalid decoder choice. (code 9)"
Case 10
ProcedureReturn "Invalid mpg123 handle. (code 10)"
Case 11
ProcedureReturn "Unable to initialize frame buffers (out of memory?)! (code 11)"
Case 12
ProcedureReturn "Invalid RVA mode. (code 12)"
Case 13
ProcedureReturn "This build doesn't support gapless decoding. (code 13)"
Case 14
ProcedureReturn "Not enough buffer space. (code 14)"
Case 15
ProcedureReturn "Incompatible numeric data types. (code 15)"
Case 16
ProcedureReturn "Bad equalizer band. (code 16)"
Case 17
ProcedureReturn "Null pointer given where valid storage address needed. (code 17)"
Case 18
ProcedureReturn "Error reading the stream. (code 18)"
Case 19
ProcedureReturn "Cannot seek from end (end is not known). (code 19)"
Case 20
ProcedureReturn "Invalid 'whence' for seek function. (code 20)"
Case 21
ProcedureReturn "Build does not support stream timeouts. (code 21)"
Case 22
ProcedureReturn "File access error. (code 22)"
Case 23
ProcedureReturn "Seek not supported by stream. (code 23)"
Case 24
ProcedureReturn "No stream opened. (code 24)"
Case 25
ProcedureReturn "Bad parameter handle. (code 25)"
Case 26
ProcedureReturn "Invalid parameter addresses for index retrieval. (code 26)"
Case 27
ProcedureReturn "Lost track in the bytestream and did not attempt resync. (code 27)"
Case 28
ProcedureReturn "Failed to find valid MPEG data within limit on resync. (code 28)"
Case #MPG123_ERR
ProcedureReturn "A generic mpg123 error."
Case #MPG123_DONE
ProcedureReturn "Message: I am done with this track."
Case #MPG123_NEED_MORE
ProcedureReturn "Message: Feed me more input data!"
Case #MPG123_NEW_FORMAT
ProcedureReturn "Message: Prepare for a changed audio format!"
Default
ProcedureReturn "I have no idea - an unknown error code!"
EndSelect
EndProcedure
Procedure.s mpg123_strerror(mh.l)
ProcedureReturn Str(CallFunctionFast(mpg123_strerror, mh))
EndProcedure
Procedure.l mpg123_format(mh.l, rate.l, channels.l, encoding.l)
ProcedureReturn CallFunctionFast(mpg123_format, mh, rate, channels, encoding)
EndProcedure
Procedure.l mpg123_read(mh, outmemory.l, outmemsize.l, done.l)
ProcedureReturn CallFunctionFast(mpg123_read, mh, outmemory, outmemsize, done)
EndProcedure
ProcedureDLL.l mpg123_outblock(mh.l)
ProcedureReturn CallFunctionFast(mpg123_outblock, mh)
EndProcedure
; Program Parameter
Global FileInput.s, FileOutput.s
FileInput = ProgramParameter(0)
FileOutput = ProgramParameter(1)
Procedure usage()
PrintN("Usage:mpg123_to_wav <input> <output>")
EndProcedure
Procedure mpg123_Cleanup(mpg123_handle.l)
mpg123_close(mpg123_handle)
mpg123_delete(mpg123_handle)
mpg123_exit()
EndProcedure
Procedure.l Main()
CallDebugger
Protected sndfile.l, mpg123_handle.l, *Buffer, sample.l
Protected buffer_size.l, done.l, channels.l, encoding.l, rate.l, err.l = #MPG123_OK
If CountProgramParameters()<>2
usage()
PrintN("Input file:"+FileInput)
PrintN("Output file:"+FileOutput)
EndIf
err = mpg123_init()
Debug err
If err = #MPG123_OK
mpg123_handle = mpg123_new(#Null, err)
If mpg123_handle
If mpg123_open(mpg123_handle, @FileInput)=#MPG123_OK
If mpg123_getformat(mpg123_handle, @rate, @channels, @encoding)=#MPG123_OK
Else
PrintN("Trouble with mpg123::"+mpg123_plain_strerror(err)+" "+mpg123_strerror(mpg123_handle) )
ProcedureReturn
EndIf
Else
PrintN("Trouble with mpg123::"+mpg123_plain_strerror(err)+" "+mpg123_strerror(mpg123_handle) )
ProcedureReturn
EndIf
Else
PrintN("Trouble with mpg123:: Error mpg123_new")
ProcedureReturn
EndIf
If encoding<>#MPG123_ENC_SIGNED_16
mpg123_Cleanup(mpg123_handle)
PrintN("Bad encording:: "+Str(encoding))
ProcedureReturn
EndIf
mpg123_fmt_none(mpg123_handle)
mpg123_format(mpg123_handle, rate, channels, encoding)
buffer_size = mpg123_outblock(mpg123_handle)
*Buffer = AllocateMemory( buffer_size )
Print("Creating 16 bit WAV with "+Str(channels)+" channels and "+Str(rate)+"Hz")
sndfile = CreateFile(#PB_Any, FileOutput)
If sndfile=#Null
PrintN("Cannot open output file")
mpg123_Cleanup(mpg123_handle)
ProcedureReturn
EndIf
Repeat
err = mpg123_read(mpg123_handle, *Buffer, buffer_size, @done)
WriteData(sndfile, *Buffer, done)
Until err <> #MPG123_OK
If err<>#MPG123_DONE
PrintN("Warning: Decording ended prematuely because: "+mpg123_strerror(mpg123_handle)+" "+mpg123_plain_strerror(err))
mpg123_Cleanup(mpg123_handle)
EndIf
CloseFile(sndfile)
FreeMemory(*Buffer)
sample / channels
PrintN( Str(sample) +" samples written")
mpg123_Cleanup(mpg123_handle)
EndIf
CallDebugger
EndProcedure
libmpg123_Init()
FileInput = OpenFileRequester("Audio MP3 File", "*.mp3", "MP3 file *.mp3 | *.mp3", 0)
FileOutput = ReplaceString(FileInput, ".mp3", "_raw.wav")
OpenConsole()
ConsoleTitle("PureBasic - mpglib123.dll example")
Main()
Inkey()
libmpg123_End()
End
This Wav is Raw. You can use audacity.
Raw Import -> Signed 16bit PCM / none / streo / 100 / 44100
Play!!
Reading Thanks

A free gift
Sample code binary (PB4.4 Beta5)
http://purebasic.coolverse.jp/_userdata/dec.zip
Tips Gapless decode
mpg123_param don't run on PB. Then you change source code.
1.ReSync Size 1024 to xxxxx
frame.c
Code: Select all
mp->resync_limit = 1024;
some source
Code: Select all
#ifdef GAPLESS
fr->p.flags = MPG123_GAPLESS | fr->p.flags; //Add lines
if(fr->p.flags & MPG123_GAPLESS)
{
Code: Select all
if(fr->lastoff && fr->num == fr->lastframe)
{
off_t byteoff = samples_to_bytes(fr, fr->lastoff);
if((off_t)fr->buffer.fill > byteoff)
{
fr->buffer.fill = byteoff;
}
//<Dis> fr->lastoff = 0; /* Only enter here once... when you seek, lastoff should be reset. */
}
1.Prepare
Code: Select all
Procedure.b mpg123_Initialize()
libmpg123_Init()
If mpg123_init() = #MPG123_OK
mpg123_handle = mpg123_new(#Null, err)
If mpg123_handle
mpg123_open_feed(mpg123_handle)
mpg123_format_none(mpg123_handle)
mpg123_format(mpg123_handle, 44100, 2, #MPG123_ENC_SIGNED_16)
NR_mpg123_BufferSize = mpg123_outblock(mpg123_handle)
*NR_mpg123_Buffer = AllocateMemory( NR_mpg123_BufferSize )
ProcedureReturn #True
;EndIf
EndIf
EndIf
ProcedureReturn #False
EndProcedure
Procedure mpg123_Ending()
FreeMemory(*NR_mpg123_Buffer)
mpg123_close(mpg123_handle)
mpg123_delete(mpg123_handle)
mpg123_exit()
libmpg123_End()
EndProcedure
Code: Select all
err = mpg123_decode(mpg123_handle, *Buf, Len, *mpg123_Buffer, mpg123_BufferSize, @done)
If err=#MPG123_NEW_FORMAT
mpg123_getformat(mpg123_handle, @rate, @channels, @encoding)
EndIf
If err=#MPG123_OK
SaveBuffer(*mpg123_Buffer, done)
EndIf
If err<>#MPG123_DONE
Repeat
err = mpg123_decode(mpg123_handle, #Null, 0, *mpg123_Buffer, NR_mpg123_BufferSize, @done)
If done=0
err=#MPG123_DONE
Break
EndIf
SaveBuffer(*mpg123_Buffer, done)
Until err<>#MPG123_OK And err<>#MPG123_NEED_MORE
EndIf
If err<>#MPG123_DONE And err<>#MPG123_OK
Debug err
EndIf