minimp3 source code

For discussions about programming, programming questions/advice, and projects that don't really have anything to do with Puppy.
Message
Author
User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#31 Post by technosaurus »

goingnuts wrote:
While surfing I found this page with some nice instructions for streaming mp3 and a poor mans skype... :)

Might be that the minimp3 could also be hacked to play URL playlists? The mpg123 can play internet radio by issuing the following command:

Code: Select all

mpg123 -@ http://players.creacast.com/creacast/classique/playlist.pls
I looked into doing poor mans voip this way but hit a brick wall when looking for a way to get the non.local IP address ... needed some external server like dyndns but I never solved it ... only tested locally with local IPs using ffmpeg... still I like the Unix philosophy of tools doing 1thing well and using them together liberally rather than reinvent existing code every time you need to combine 2+ functions. ... for instance you can use netcat, SSH, telnet, dropbear... instead of bolting their capabilities into a program so it can work over the net.
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

Ibidem
Posts: 549
Joined: Wed 26 May 2010, 03:31
Location: State of Jefferson

#32 Post by Ibidem »

goingnuts wrote: The mpg123 seems to compile easy with diet (a small diff and build script attached). It gives a 212K static bin. Wonder at what size musl will do that?

Tried to use the latest mpg123 ("mpg123-1.13.8") - it compiled but did have issues playing mp3. Then went for mpg123-1.13.4 which also compiles and on top of that actually plays mp3.

Also did a quick test with mpg321 but that seems harder to patch for diet libc.

While surfing I found this page with some nice instructions for streaming mp3 and a poor mans skype... :)

Might be that the minimp3 could also be hacked to play URL playlists? The mpg123 can play internet radio by issuing the following command:

Code: Select all

mpg123 -@ http://players.creacast.com/creacast/classique/playlist.pls
I've done the mpg123 internet radio thing a bit. It's nice and simple.

But I'd advise not trying to add netwirking--mpg123 is the undisputed King of the Hill there, you'll add a good bit of bloat, and you can probably do it via curl <url>|minimp3 - or such anyhow... (I assume that minimp3 supports stdin as a file?)
And FWIW-pls is not an mp3, so you'd have to implement a pls parser...best done in shell script.

Don't bother with mpg321-it was relevant several years ago, but IIRC current mpg123 has improved decoding on sub-pentium machines (which was the only reason to use mpg321).

Ibidem
Posts: 549
Joined: Wed 26 May 2010, 03:31
Location: State of Jefferson

#33 Post by Ibidem »

goingnuts wrote:Ibidem: Thats a small difference in size - I think I will start looking more close on the musl!

The mpg123 seems to compile easy with diet (a small diff and build script attached). It gives a 212K static bin. Wonder at what size musl will do that?

Tried to use the latest mpg123 ("mpg123-1.13.8") - it compiled but did have issues playing mp3. Then went for mpg123-1.13.4 which also compiles and on top of that actually plays mp3.
mpg123, 1.13.4:
274612 bytes stripped, statically linked, stripped, compiled with -Os, using OSS audio only.
No other tricks involved except getting the Linux headers included, and building with -D_GNU_SOURCE.
This is upstream source, unpatched. Plays streaming mp3 fine.

In the FWIW department:
All these numbers are with a stock musl, including full UTF8 and everything else...Rich Felker says
I would believe that it's possible to get smaller binaries with a
uClibc that's had lots of features turned off when the library was
built, meaning that those features are completely unavailable to
applications. On the other hand, I suspect musl will easily beat
uClibc in static linking size when uClibc is full-featured (UTF-8,
pthread, full malloc, stdio, hex floats in printf, ...) because musl
takes a lot more care not to have unnecessary cross-dependency between .o files in the static lib. Still, some things are impossible to
optimize out with the linker - for example, printf always pulls in a
minimum amount of UTF-8 conversion code for %ls and %c.

goingnuts
Posts: 932
Joined: Sun 07 Dec 2008, 13:33
Contact:

#34 Post by goingnuts »

Ibidem: With my uclibc (uClibc-0.9.27) I can get it down to 304K static/striped/oss only.

Tried to use musl-0.8.10 (compiled by "make" and installed by "new2dir make install")

Compiling mpg123 with musl was not 100 % successful:
Had to comment out #undef HAVE_MMAP in mpg123´s config.h.in to get mpg123 compiled and ended up with approx. 346K static/stripped bin. But it would not play...D...!

I will keep practice the musl though...

Any chance you could provide a musl-pet/sfs? Or maybe some examples of howto build simple things?

Ibidem
Posts: 549
Joined: Wed 26 May 2010, 03:31
Location: State of Jefferson

#35 Post by Ibidem »

1. Compile and install musl, preferably from git head (a release is a tag, not a branch, so all fixes are in git).
Copy config.mak from dist/ and adjust as you want.
PREFIX defaults to /usr/local/musl, and should not be set to /, /usr, or /usr/local (or you will kill your OS)
2. Get the linux kernel headers (linux-libc-dev, not the ones for building modules) and put them somewhere (I use /opt/musl/lin)
There should be a linux/ directory in there.
3. export CC=musl-gcc; export CFLAGS="-Os -static -fno-stack-protector -I/opt/musl/lin -D_GNU_SOURCE"
Don't forget the -D_GNU_SOURCE - most stuff won't build without that, though some will. -I/... should point to the linux headers.
(Note-the linux headers are needed for OSS and a lot besides)
4. Now run configure and make.

That's all that I know is needed.

goingnuts
Posts: 932
Joined: Sun 07 Dec 2008, 13:33
Contact:

#36 Post by goingnuts »

Ibidem: Thanks a lot - I will try that

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#37 Post by technosaurus »

I recently took a look at this and noticed that many arrays are malloc'ed and then filled with unchanging data and that some ranges of the arrays are not even used. If these were setup in pre-allocated tables, many of the process intensive computations could be avoided and overall memory usage would be reduced.

csa_table - only uses parts [0], [2] and [3]
ci_table is only used to compute ca and cs ....could be replaced with precalculated ca and cs, but since only 1 more array is used in the csa_table - may as well just precompute them all (TODO)

table_4_3_exp and table_4_3_value get malloc'ed and computed anyhow, so may as well precompute those

huff_vlc, exp_table and exp_value_table are pre-allocated so no reason not to precalculate them

...lots more but I found an MIT licensed decoder from fluendo
https://core.fluendo.com/gstreamer/svn/ ... o-mp3/src/

and even better - Public Domain
https://sites.google.com/a/kmlager.com/www/projects
with sources here:
http://sourceforge.net/p/mp3dec/code/HEAD/tree/src/
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#38 Post by technosaurus »

Here is an ID3 tag stripper for players that they mess with

Code: Select all

#include <fcntl.h>
#define DUMPTAGS
int main(int argc, char **argv){
	unsigned char buf[4096];
	int len,fd = open(argv[1],O_RDONLY);
	while (len=read(fd,buf,10)){ // handle ID3v2 tags (maybe multiple)
		if (buf[0]=='I' && buf[1]=='D' && buf[2]=='3'){
			len=read(fd,buf,buf[9]|(buf[8] << 7)|(buf[7] << 14)|(buf[6] << 21));
#ifdef DUMPTAGS
			write(2,buf,len);
#endif
		} else break;
	}
	while (write(1,buf,len)){
		unsigned char tag[3] = {'T','A','G'}, *end;
		len=read(fd,buf,4096);
		end=(unsigned char *)memmem(buf,len,&tag,3);
		if (end){ //handle ID3v1 tag (should only be 1)
			write(1,buf,end-buf);
#ifdef DUMPTAGS
			write(2,end,len-(end-buf));
#endif
			break;
		}
	}
}
to strip a file and save the tags:
id3strip my.mp3 >mynew.mp3 2>my.tags

to strip only:
id3strip my.mp3 >mynew.mp3 2>/dev/null

to combine a bunch of mp3s
# 1st create empty file mynew.mp3 - not shown
for x in *.mp3; do
id3strip "$x" >>mynew.mp3 2>/dev/null
done
Last edited by technosaurus on Thu 19 Jun 2014, 05:15, edited 1 time in total.
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

disciple
Posts: 6984
Joined: Sun 21 May 2006, 01:46
Location: Auckland, New Zealand

#39 Post by disciple »

Just in case anyone else wants to look at it, the original site for minimp3 seems to have moved to http://keyj.emphy.de/minimp3/.
He has some other interesting stuff on there - Photojoin looks handy and he has a proposed filesystem to improve boot performance with live CDs: http://keyj.emphy.de/profs-proposal/
One thing I can't understand, Techno - he said that minimp3 is slow because it is based on the ffmpeg decoder. So were we interested in it here because we care about ram much more than speed? Or does the speed improve with uclibc or something?
Do you know a good gtkdialog program? Please post a link here

Classic Puppy quotes

ROOT FOREVER
GTK2 FOREVER

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#40 Post by technosaurus »

really I wanted something that could fit inside my 1mb linux kernel with X,jwm&rxvt in the initramfs ... turns out recording with 8kz MU_LAW format using arecord allows you to use cat $file >/dev/audio
I just compress it with xz -ze9 and then use zcat for simple, lossless compression
(Note: adding a simple delta encoder and decoder would still be really fast and compress ~15% better source )

Here my public domain ogg player that uses Sean Barrett's public domain stb_vorbis

Code: Select all

//diet gcc -Os -finline-small-functions oggplay.c -ffunction-sections -fdata-sections -fmerge-all-constants -Wl,--gc-sections,-s -o oggplay -lm
#define STB_VORBIS_NO_PUSHDATA_API
#define STB_VORBIS_NO_INLINE_DECODE

#include "stb_vorbis.c"
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/soundcard.h>

static inline void write2(char *msg){
	write(2,msg,strlen(msg));
}

int main(int argc, char **argv){
	int error,
	value = AFMT_S16_LE ,
	pcm = open("/dev/dsp", O_WRONLY);
	if (pcm < 0)
		write2("cannot get fd\n");
	if (ioctl(pcm, SNDCTL_DSP_SETFMT, &value) < 0)
		write2("cannot set audio format: %s\n");

while (--argc) {
    short *decoded;
    int channels, len, sample_rate;
    len = stb_vorbis_decode_filename(argv[argc], &channels, &sample_rate, &decoded);
    if (ioctl(pcm, SNDCTL_DSP_CHANNELS, &channels) < 0)
		write2("cannot set channels");
    if (ioctl(pcm, SNDCTL_DSP_SPEED, &sample_rate) < 0)
		write2("cannot set sample rate");
	if (len>0) write(pcm,decoded,len*channels);
}
close(pcm);
return 0;
}
note on pulseaudio systems run all of these programs with padsp
padsp minimp3 my.mp3
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#41 Post by technosaurus »

I reworked Krister Lagerstrom's public domain code a bit... my modifications are also public domain... work is still in progress adding the optimizations in as compile time options, but the big ones are there, (however if you want to add more optimizations, see https://github.com/technosaurus/PDMP3)

You can use this in any project, commercial or otherwise without attribution (I'm still working on making this part easy though - patches welcome)
Attachments
pdmp3.zip
Its not letting me add tar.gz files now
(27.76 KiB) Downloaded 173 times
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

musher0
Posts: 14629
Joined: Mon 05 Jan 2009, 00:54
Location: Gatineau (Qc), Canada

#42 Post by musher0 »

Hello, technosaurus.

Surprising little piece of software! :) Oooh, good work, there.

Compiled just fine with "make".

Generally plays ok the mp3's I tried on it.

Except a Japanese recording (see screen cap below) of J. S. Bach's
Goldberg Variations. Something about "Layer 3". Probably you know this
already, but I'm reporting it just in case you don't.

Also -- and this is entirely subjective, please don't go chasing wild geese
on my account -- is it possible that the beat may be off on some songs,
and a male voice could sound "bass-enriched" ? Nah, it's probably this
particular singer! ;)

Anyway, thanks for this. BFN.

musher0
Attachments
Only_layer_3_2015-05-15.jpg
(48.25 KiB) Downloaded 257 times
musher0
~~~~~~~~~~
"You want it darker? We kill the flame." (L. Cohen)

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#43 Post by technosaurus »

If you have a link to a mp3 that won't play, post it ... I'm really sick of /usr/share/audio/ivy.mp3 anyhow. I'm still planning to add id3 tag support (you can try using the id tag stripper from a few posts back ... which is where I will ultimately get the code from)

... you may be right about the sound; while reviewing the code I noticed some things that were "iffy"

the original author of minimp3 on this thread also wrote a mp2 player ... parts of which were released to the public domain... I'm not sure about layer 1 though... not sure if I have ever seen it.
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

Ibidem
Posts: 549
Joined: Wed 26 May 2010, 03:31
Location: State of Jefferson

#44 Post by Ibidem »

technosaurus wrote:If you have a link to a mp3 that won't play, post it ... I'm really sick of /usr/share/audio/ivy.mp3 anyhow. I'm still planning to add id3 tag support (you can try using the id tag stripper from a few posts back ... which is where I will ultimately get the code from)

... you may be right about the sound; while reviewing the code I noticed some things that were "iffy"

the original author of minimp3 on this thread also wrote a mp2 player ... parts of which were released to the public domain... I'm not sure about layer 1 though... not sure if I have ever seen it.
The first mp3 musher0 refers to is the first mp3 of the Open Goldberg Variations (http://www.opengoldbergvariations.org/), which is CC0.
file reports it to be:

Code: Select all

Audio file with ID3 version 2.3.0, contains: MPEG ADTS, layer III, v1, 128 kbps, 44.1 kHz, JntStereo
So it may be the lack of id3 support.

musher0
Posts: 14629
Joined: Mon 05 Jan 2009, 00:54
Location: Gatineau (Qc), Canada

#45 Post by musher0 »

@Ibidem: yep, that's the one.

@technosaurus: The "Aria" track that I mentioned above is here.
It's a "pass-the-hat", "pay-what-you-can" kind of download.

BFN.

musher0
musher0
~~~~~~~~~~
"You want it darker? We kill the flame." (L. Cohen)

Ibidem
Posts: 549
Joined: Wed 26 May 2010, 03:31
Location: State of Jefferson

#46 Post by Ibidem »

Having downloaded those recordings a while ago, I tried it out.
Results:
-Same errors when played without modification
-id3 and id3tool don't recognize the id3 tags, but id3v2 can remove them.
-mp3dec_opt plays the result nicely, at ~25% CPU on my 1.6GHz Atom N270.
-mp3dec plays the result, but runs ~66% CPU.
I'll try out the id3 tag stripper referred to.

UPDATE:
Yup, the id3 tag stripper works (meaning it removes enough); <unistd.h> should be added, though.
It does point out an issue with the PDMP3 code:
the API and code almost seem like they were designed to prevent use with pipes.
- rather than passing a file handle / descriptor, you copy a name to the global

Code: Select all

char filename[256]
(256 is the max length for a file name...without a path!).
- it apparently checks if it has hit the end of the file, via ftell(), rather than whether reading has failed; if ftell() fails, it is treated as an EOF.
- the overuse of globals results in the relevant code being rather well hidden.

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#47 Post by technosaurus »

Ibidem wrote:Having downloaded those recordings a while ago, I tried it out.
Results:
-Same errors when played without modification
-id3 and id3tool don't recognize the id3 tags, but id3v2 can remove them.
-mp3dec_opt plays the result nicely, at ~25% CPU on my 1.6GHz Atom N270.
-mp3dec plays the result, but runs ~66% CPU.
I'll try out the id3 tag stripper referred to.

UPDATE:
Yup, the id3 tag stripper works (meaning it removes enough); <unistd.h> should be added, though.
It does point out an issue with the PDMP3 code:
the API and code almost seem like they were designed to prevent use with pipes.
- rather than passing a file handle / descriptor, you copy a name to the global

Code: Select all

char filename[256]
(256 is the max length for a file name...without a path!).
- it apparently checks if it has hit the end of the file, via ftell(), rather than whether reading has failed; if ftell() fails, it is treated as an EOF.
- the overuse of globals results in the relevant code being rather well hidden.
I am working on those ... as to resource usage, I added lookup tables for the IMDCT cos function which can be enabled with the CFLAG -DIMDCT_NTABLES ... that reduces CPU usage to ~15% after initialization.
Also need to set up a separate initialization function.

Edit:
I have updated https://github.com/technosaurus/PDMP3 with my current code and added a todo list in the readme.md ... For further issues, please add an issue via github.
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

Ibidem
Posts: 549
Joined: Wed 26 May 2010, 03:31
Location: State of Jefferson

#48 Post by Ibidem »

technosaurus wrote: I am working on those ... as to resource usage, I added lookup tables for the IMDCT cos function which can be enabled with the CFLAG -DIMDCT_NTABLES ... that reduces CPU usage to ~15% after initialization.
Also need to set up a separate initialization function.

Edit:
I have updated https://github.com/technosaurus/PDMP3 with my current code and added a todo list in the readme.md ... For further issues, please add an issue via github.
Thanks for the IDMCT bit!
You have a new pull request on github. ;-)

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#49 Post by technosaurus »

Ibidem wrote:Thanks for the IDMCT bit!
You have a new pull request on github. ;-)
Merged. Thanks!
Anytime you see a function that requires #include <math.h>, its a good hint that it could use a lookup table pow*(), sin*(), cos*(), tan*(), etc...
Keep in mind that each chunk of data corresponds to ~20ms, so it needs to be processed very quickly (most programs take longer than 20ms just to load)
I got a bit better cpu load (slightly larger binary) by doing -fprofile-generate (running it) and then -fprofile-use

Edit::Here are the gperf results, Looks like L3_Subband_Synthesis and L3_Reorder alon with reading the data are the hot spots.

Code: Select all

Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls  us/call  us/call  name    
 56.82      0.25     0.25                             L3_Subband_Synthesis
 27.27      0.37     0.12                             L3_Reorder
  6.82      0.40     0.03   437169     0.07     0.07  __do_global_dtors_aux
  4.55      0.42     0.02   181361     0.11     0.11  Read_Header
  2.27      0.43     0.01    78785     0.13     0.13  Get_Bytes
  2.27      0.44     0.01                             Get_Side_Bits
  0.00      0.44     0.00   167430     0.00     0.00  Get_Main_Pos
  0.00      0.44     0.00     9734     0.00     0.00  frame_dummy
  0.00      0.44     0.00     2629     0.00     0.00  Requantize_Pow_43
  0.00      0.44     0.00     1859     0.00     2.29  Read_Audio_L3
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

musher0
Posts: 14629
Joined: Mon 05 Jan 2009, 00:54
Location: Gatineau (Qc), Canada

#50 Post by musher0 »

technosaurus wrote:I reworked Krister Lagerstrom's public domain code a bit... my modifications are also public domain... work is still in progress adding the optimizations in as compile time options, but the big ones are there, (however if you want to add more optimizations, see https://github.com/technosaurus/PDMP3)

You can use this in any project, commercial or otherwise without attribution (I'm still working on making this part easy though - patches welcome)
Thanks again for this, tehcnosaurus!
musher0
~~~~~~~~~~
"You want it darker? We kill the flame." (L. Cohen)

Post Reply