FLAC bitrate histogram (shell script) |
FLAC bitrate histogram (shell script) |
Nov 25 2012, 04:39
Post
#1
|
|
![]() Group: Members (Donating) Posts: 1983 Joined: 4-January 04 From: Austin, TX Member No.: 10933 |
In the meantime, does anyone know of a program that displays a histogram of bitrates from flac and hopefully some of the other more popular lossless formats? No, but I vaguely recall wanting precisely this sort of information before. It's a holiday weekend, and I was bored, so I OCD'd out and hacked this together. Obviously, this probably requires a Unix system of some sort. CODE #!/bin/bash set -e if [ ! -f "$1" -o $# != "2" ]; then echo "Usage: $0 <flac> <histogram-png>" >&2 exit 1 fi FLAC_PATH=$1 FLAC_FILE=`basename "$FLAC_PATH"` # uncomment this to autodect #HISTOGRAM=`sed -e 's/\(.*\)\.flac/histogram-\1\.png/' <<< "$FLAC_FILE"` HISTOGRAM=$2 BITS_ORIG=/tmp/bits-orig.txt BITS=/tmp/bits.txt read minblk maxblk origminframe origmaxframe channels bps rate <<< \ `metaflac --show-min-blocksize --show-max-blocksize \ --show-min-framesize --show-max-framesize \ --show-channels --show-bps --show-sample-rate "$FLAC_PATH"` # $blocksize is as reported by metaflac. Must be constant for entire file if [ "$minblk" != "$maxblk" ]; then echo "ERROR: min/max blocksizes differ ($minblk, $maxblk)." >&2 exit 1 fi blocksize=$minblk # $rawblocksize: uncompressed size of block, in bits, including all channels rawblocksize=$(($blocksize*$channels*$bps)) # Analyze FLAC, extract "bits=" property of each frame flac -sa "$FLAC_PATH" -o- \ | grep "blocksize=$BLOCKSIZE" \ | sed -e 's/.*bits=\([0-9]*\).*/\1/' \ >& $BITS_ORIG # The "actual" minimum/maximum frame sizes appear to be outliers; e.g. for one # FLAC with average frame size of roughly 70kb, the very first frame was 203kb # and was nearly 2x the size of the next largest frame; the 2nd and 3rd frame # were 112 bits long and were 135x smaller than the next smallest frame. For the # sake of the histogram, drop those out. echo "Dropping min frame size $(($origminframe*8))" \ "and first frame size `head -1 $BITS_ORIG`." tail -n +2 $BITS_ORIG | grep -v "^$(($origminframe*8))$" > $BITS #cat $BITS_ORIG > $BITS # uncomment this to include min/max frame sizes read minframesize maxframesize <<< \ `awk -e 'BEGIN { max=0; min=999999; } min > $0 {min=$0} \ max < $0 {max=$0} END { print min " " max }' \ < $BITS` gnuplot <<EOF bin(x,width)=width*floor(x/width) binwidth=25 # in kbits/s set xlabel "Frame effective bitrate (kbps)" set ylabel "frequency (frames)" set xrange [$minbits:$maxbits] # comment this out to display gnuplot window instead of writing to png set term png size 500, 300 font "DejaVu Sans,8" set output "$HISTOGRAM" set yrange [0.0:] plot "$BITS" using (bin(\$1/(1.e3*$blocksize/$rate),binwidth)):(1.0) title "$FLAC_FILE" smooth freq with boxes # if commenting out above png output lines, uncomment this # pause mouse EOF echo "Done, output in $HISTOGRAM" rm -f $BITS $BITS_ORIG Sample output... Tame Impala, "Elephant": ![]() Merzbow, "I Lead You Towards Glorious Times": ![]() Autechre & Hafler Trio, "æ³o": ![]() I'm not aware of any way to get this sort of information from a format-independent utility like sox. Which is unfortunate. This post has been edited by Axon: Nov 25 2012, 04:48 |
|
|
|
![]() |
Nov 25 2012, 10:02
Post
#2
|
|
![]() Group: Members Posts: 1058 Joined: 4-May 04 From: France Member No.: 13875 |
Nice
-------------------- Save my friend from going homeless: http://outpost.fr/url/308w
|
|
|
|
Nov 25 2012, 13:48
Post
#3
|
|
![]() Group: Members Posts: 1465 Joined: 30-November 06 Member No.: 38207 |
Yeah nice. If it could also specify file average and 1-second peak?
I have posted this a few timed, but Merzbow: I Lead You Towards Glorious Times is the least-compressible piece of music I have ever come across. FLAC -8 doesn't manage to get it below 1395, which in the very least beats TAK, which even at -p4m returns more than 100 percent of uncompressed filesize. (WavPack extra high saves some 7 percent I think.) -------------------- geocities.com/hydrogenaudio: http://goo.gl/tqYZj
|
|
|
|
Nov 25 2012, 16:37
Post
#4
|
|
![]() Group: Members Posts: 607 Joined: 16-January 09 Member No.: 65630 |
Like it too
Then made Windows version. I doubt what to do for histogram, then I guess ascii is universal. It accepts optional parameter for number of bins (default 32), unlike binwidth in Axon's version. Path to executables should be set according user preferance. Example: CODE C:\>cscript flachist.vbs "10 - Hysteria.flac" Microsoft (R) Windows Script Host Version 5.7 Copyright (C) Microsoft Corporation. All rights reserved. 10 - Hysteria.flac 0: 36> 36: 73> 73: 110> 110: 147> 147: 183> 183: 220> 220: 257> 257: 294> 294: 330> 330: 367> 367: 404> 404: 441> * 441: 478> * 478: 514> * 514: 551> * 551: 588> * 588: 625> * 625: 661> ** 661: 698> *** 698: 735> ***** 735: 772> ********** 772: 808> ************* 808: 845> ************** 845: 882> *************************** 882: 919> ************************************* 919: 956> ******************************************************* 956: 992> ************************************************************* 992:1029> ******************************************************************** 1029:1066> ********************************************************* 1066:1103> ************************ 1103:1139> **** 1139:1176> flachist.vbs CODE ' Path to executables
flac = "C:\Program Files\foobar2000\tools\flac.exe" metaflac = "C:\Program Files\foobar2000\tools\metaflac.exe" Set WshShell = CreateObject("WScript.Shell") Set fso = CreateObject("Scripting.FileSystemObject") If WScript.Arguments.Count And fso.FileExists(WScript.Arguments(0)) Then flacArgs = " -asc " metaflacArgs = " --show-min-blocksize --show-max-blocksize --show-min-framesize" &_ " --show-max-framesize --show-channels --show-bps --show-sample-rate " q = Chr(34) : flac = q & flac & q : metaflac = q & metaflac & q Set cmd = WshShell.exec(metaflac & metaflacArgs & q & WScript.Arguments(0) & q) info = Split(cmd.StdOut.ReadAll(), vbCrLf) If info(0) <> info(1) Then WScript.Echo "ERROR: min/max blocksizes differ: " & info(0) & "<>" & info(1) WScript.Quit Else blocksize = info(0) : origminframe = info(2) : rate = info(6) End If ' Write bits info data to csv file Set csv = fso.CreateTextFile(WScript.Arguments(0) & ".csv") Set cmd = WshShell.exec(flac & flacArgs & q & WScript.Arguments(0) & q) Do While cmd.StdOut.AtEndOfStream <> True readline = cmd.StdOut.ReadLine If InStr(readline, "blocksize=" & blocksize) Then bits = Split(Split(readline, vbTab)(2), "=")(1) If Int(bits) <> origminframe*8 Then csv.WriteLine(bits) End If Loop ' Read csv Set csv = fso.OpenTextFile(WScript.Arguments(0) & ".csv") lines = Split(csv.ReadAll(), vbCrLf) max = 0 : bins = 32 If WScript.Arguments.Count > 1 Then bins = CInt(WScript.Arguments(1)) For Each line In lines If line <> "" Then If Int(line) > max Then max = Int(line) Next ' Print ascii histogram bin = Array() : ReDim bin(bins) maxbin = 0 For Each line In lines If line <> "" Then idx = Fix(bins*Int(line)/(max+1)) : bin(idx) = bin(idx) + 1 If bin(idx) > maxbin Then maxbin = bin(idx) Next WScript.Echo WScript.Arguments(0) & vbCrLf m = max*rate/bins/blocksize/1000 For i=0 To bins-1 WScript.Echo Right(" " & Int(i*m), 4) & ":" &_ Right(" " & Int((i+1)*m), 4) & "> " &_ String(Int(bin(i)*68/maxbin), "*") Next Else WScript.Echo "Usage: cscript flachist.vbs flac-file-path [bins]" End If This post has been edited by romor: Nov 25 2012, 17:28 -------------------- Scripts (mainly foobar2000 related): http://goo.gl/yje3h
|
|
|
|
![]() ![]() |
|
Lo-Fi Version | Time is now: 18th May 2013 - 10:50 |