Discussion:
mp3 VBR histogram?
(too old to reply)
Ian Smith
2009-08-05 05:43:22 UTC
Permalink
Hi,

does anyone know anything that can produce the sort of ASCII histogram
that lame produces while encoding in VBR, from an existing .mp3 file?

I'm interested in analysing the bitrate distribution of frames of a VBR
live stream, though I don't mind saving it to a disk file if necessary.

cheers, Ian
b. f.
2009-08-05 09:51:17 UTC
Permalink
Post by Ian Smith
does anyone know anything that can produce the sort of ASCII histogram
that lame produces while encoding in VBR, from an existing .mp3 file?
I'm interested in analysing the bitrate distribution of frames of a VBR
live stream, though I don't mind saving it to a disk file if necessary.
Any application that can sweep through an mp3 and read the frame
headers should have code that you can adapt for this purpose, and
there are many such pieces of software in Ports (every mp3 decoder,
and many utilities). If you want something ready-made, and efficiency
isn't of paramount importance, you could use, for example,
audio/mp3plot or audio/mp3stat on files.

I've dumped frame bitrates of mp3 files before from the command-line
using audio/mp3_check and something like:

mp3_check -avv sample.mp3 | awk '/BitRate/ { print $2 }' -

audio/py-mad, a python interface to audio/libmad, has some example
code for reading mp3 streams, and could also be used for this purpose.

b.
Ian Smith
2009-08-05 17:05:07 UTC
Permalink
Post by b. f.
Post by Ian Smith
does anyone know anything that can produce the sort of ASCII histogram
that lame produces while encoding in VBR, from an existing .mp3 file?
I'm interested in analysing the bitrate distribution of frames of a VBR
live stream, though I don't mind saving it to a disk file if necessary.
Any application that can sweep through an mp3 and read the frame
headers should have code that you can adapt for this purpose, and
there are many such pieces of software in Ports (every mp3 decoder,
and many utilities). If you want something ready-made, and efficiency
isn't of paramount importance, you could use, for example,
audio/mp3plot or audio/mp3stat on files.
I've dumped frame bitrates of mp3 files before from the command-line
mp3_check -avv sample.mp3 | awk '/BitRate/ { print $2 }' -
192
160
160
320
96
160
112
160
128
160
128
160
160
224

That works well for extracting the raw frame bitrates, might try
scripting up a simple histogram from that, the next rainy day.
Post by b. f.
audio/py-mad, a python interface to audio/libmad, has some example
code for reading mp3 streams, and could also be used for this purpose.
Thanks for the good clues. Speed's not an issue; more about occasional
sampling than realtime monitoring. mp3plot looks good on spec, still
building; compiling boost very nearly ran this old laptop out of swap!

cheers, Ian
b. f.
2009-08-05 22:50:05 UTC
Permalink
...
Post by Ian Smith
Post by b. f.
I've dumped frame bitrates of mp3 files before from the command-line
mp3_check -avv sample.mp3 | awk '/BitRate/ { print $2 }' -
That works well for extracting the raw frame bitrates, might try
scripting up a simple histogram from that, the next rainy day.
Oh, I thought you wanted the numbers. Well, awk is still your friend.
You could use something like:

mp3_check -avv sample.mp3 | awk -v minbr=32 -v maxbr=448 -v
maxwidth=80 -v dispchar="*" '/BitRate/ {
Num=int(($2-minbr)/(maxbr-minbr)*maxwidth); bar=""; for (i=0; i < Num;
i++) bar=bar dispchar; print bar } '

instead (and probably there are more elegant ways to do this if you
know awk well).

b.
b. f.
2009-08-05 23:14:21 UTC
Permalink
Post by b. f.
...
Post by Ian Smith
Post by b. f.
I've dumped frame bitrates of mp3 files before from the command-line
mp3_check -avv sample.mp3 | awk '/BitRate/ { print $2 }' -
That works well for extracting the raw frame bitrates, might try
scripting up a simple histogram from that, the next rainy day.
Oh, I thought you wanted the numbers. Well, awk is still your friend.
mp3_check -avv sample.mp3 | awk -v minbr=32 -v maxbr=448 -v
maxwidth=80 -v dispchar="*" '/BitRate/ {
Num=int(($2-minbr)/(maxbr-minbr)*maxwidth); bar=""; for (i=0; i < Num;
i++) bar=bar dispchar; print bar } '
instead (and probably there are more elegant ways to do this if you
know awk well).
I definitely need that cup of coffee. Histogram, not temporal history
-- right. <gnashes teeth> You can use, for a simple numerical
histogram:

mp3_check -avv sample.mp3 | awk '/BitRate/ { nbr[$2]=nbr[$2]+1 } END {
for (br in nbr) print br, nbr[br] }' | sort -g

b.
Ian Smith
2009-08-06 19:17:22 UTC
Permalink
Post by b. f.
Post by b. f.
...
Post by Ian Smith
Post by b. f.
I've dumped frame bitrates of mp3 files before from the command-line
mp3_check -avv sample.mp3 | awk '/BitRate/ { print $2 }' -
That works well for extracting the raw frame bitrates, might try
scripting up a simple histogram from that, the next rainy day.
Oh, I thought you wanted the numbers. Well, awk is still your friend.
mp3_check -avv sample.mp3 | awk -v minbr=32 -v maxbr=448 -v
maxwidth=80 -v dispchar="*" '/BitRate/ {
Num=int(($2-minbr)/(maxbr-minbr)*maxwidth); bar=""; for (i=0; i < Num;
i++) bar=bar dispchar; print bar } '
instead (and probably there are more elegant ways to do this if you
know awk well).
I now know at least twice as much awk as I did yesterday, thanks :)
Post by b. f.
I definitely need that cup of coffee. Histogram, not temporal history
-- right. <gnashes teeth> You can use, for a simple numerical
mp3_check -avv sample.mp3 | awk '/BitRate/ { nbr[$2]=nbr[$2]+1 } END {
for (br in nbr) print br, nbr[br] }' | sort -g
Before I read this your second message - thought it was the list copy of
your prior, but I'm not getting those for some reason(?) - I'd hacked up
the script below which shows all I need, except maybe the average:

smithi on sola% mp3_check ~/0/music/rf_livin.mp3

FILE_NAME /home/smithi/0/music/rf_livin.mp3
GOOD_FRAMES 12073
BAD_FRAMES 0
LAST_BYTE_CHECKED 6322173
VBR_HIGH 320
VBR_LOW 32
VBR_AVERAGE 160
SONG_LENGTH 05:15.37

USER_TIME 0.18s
SYS_TIME 0.03s

smithi on sola% ./mp3histo ~/0/music/rf_livin.mp3
[ 32] 1
[ 40] 0
[ 48] 0
[ 56] 0
[ 64] 0
[ 80] 2
[ 96] 23
[112] 677 ******
[128] 2526 ************************
[160] 6540 ****************************************************************
[192] 1281 ************
[224] 680 ******
[256] 273 **
[320] 70
[all] 12073

=======
#!/bin/sh # mp3histo v0.5 7/8/9
usage() {
[ "$1" ] && echo $1
echo "usage: `basename $0` filename.mp3"; exit 1
}
[ "$1" ] || usage
[ -r "$1" ] || usage "no file $1" # "$1" may have spaces
stem=${1%.mp3}; [ "${stem}.mp3" = "$1" ] || usage "$1 not *.mp3"
tmpf=/tmp/`basename "$1"` # avoid using subshell

brtab='32 40 48 56 64 80 96 112 128 160 192 224 256 320'
for i in $brtab max all; do eval count_$i=0; done

mp3_check -avv "${stem}.mp3" | awk '/BitRate/ { print $2 }' > $tmpf
while read br; do
[ "${brtab% $br*}" = "$brtab" ] && echo "bad rate $br" && continue
eval count_$br=\$\(\(\$count_$br + 1\)\)
done < $tmpf # ; rm $tmpf

for br in $brtab; do
eval i=\$count_$br
[ $i -gt $count_max ] && count_max=$i
count_all=$(($count_all + $i))
done

[ -f "$stem.histo" ] && rm "$stem.histo"
for br in $brtab; do
[ $br -gt 96 ] && f='' || f=' '
eval echo -n "$br \$count_$br" \
| awk -v max=$count_max -v t=" " -v f="$f" -v width=64 -v ch="*" \
' { len=int($2/max*width); bar=""; OFS="";
for (i=0; i<len; i++) bar=bar ch;
print "[",f,$1,"] ",$2, t bar } ' >> "$stem.histo"
done
echo "[all] $count_all" >> "$stem.histo"

touch -r "$stem.mp3" "$stem.histo"
cat "$stem.histo"
exit 0
=======

thanks again for the awk-foo,

cheers, Ian

Loading...