Skip to content

Instantly share code, notes, and snippets.

@ahti
Last active August 9, 2018 04:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ahti/6c2e659dda4dfe20d955b897d9806521 to your computer and use it in GitHub Desktop.
Save ahti/6c2e659dda4dfe20d955b897d9806521 to your computer and use it in GitHub Desktop.
Hex Fiend binary template to read mp3 frames, very rough and needs hexf>=2.10
# This is a binary template for inspecting mp3 files in HexFiend
# http://ridiculousfish.com/hexfiend/
#
# https://www.mp3-tech.org/programmer/frame_header.html
# http://id3.org/id3v2.3.0
set count 0
proc : {args} {lindex $args 0}
proc remaining {} {expr {[len] - [pos]}}
proc getbr {bitstr} {
switch $bitstr {
"0000" {: free}
"0001" {: 32}
"0010" {: 40}
"0011" {: 48}
"0100" {: 56}
"0101" {: 64}
"0110" {: 80}
"0111" {: 96}
"1000" {: 112}
"1001" {: 128}
"1010" {: 160}
"1011" {: 192}
"1100" {: 224}
"1101" {: 256}
"1110" {: 320}
"1111" {: bad}
}
}
proc getsr {bitstr} {
switch $bitstr {
"00" {: 44100}
"01" {: 48000}
"10" {: 32000}
"11" {: reserved}
}
}
proc framesize {br sr pad} {
# is this right? http://id3.org/mp3Frame says yes,
# http://www.mp3-converter.com/mp3codec/frames.htm
# says it should be 144 * $br / ($sr + $pad).
expr { (144 * $br * 1000 / $sr) + $pad }
}
#while {![expr [end] || { $count > 200000 }]} {
while {[remaining] >= 2} {
set b [hex 2]
# sync + mpeg v1 layer 3 non-crc = FFFB
if {$b == "FFFB"} {
section "mp3 frame $count" {
move -2
hex 2 "sync"
# hex 2 "Raw"
# move -2
# analyze the first two bytes
set rest [bytes 2]
move -2
binary scan $rest B16 bits
binary scan $bits "a4a2a1a1a2a2aaa2" br_b sr_b pad priv channel mode_ext copy orig emph
set br [getbr $br_b]
set sr [getsr $sr_b]
# display the results
bytes 1 "bitrate: ${br}kbps"
move -1
bytes 1 "sampling: ${sr}hz"
move -1
bytes 1 "padded: $pad"
move -1
if [expr {[string is integer $br] && [string is integer $sr]}] {
set len [framesize $br $sr $pad]
bytes 1 "length: $len bytes"
move -1
}
bytes 1 "private: $priv"
bytes 1 "channels: $channel"
move -1
bytes 1 "mode_ex: $mode_ext"
move -1
bytes 1 "copyright: $copy"
move -1
bytes 1 "original: $orig"
move -1
bytes 1 "emphasis: $emph"
bytes [expr { min($len - 4, [remaining]) }] "samples"
}
set count [expr $count + 1]
} elseif {$b == "4944"} {
# "ID"
set three [ascii 1]
if {$three != 3} {
move -2
continue
}
section "ID3" {
move -3
ascii 3 "file identifier"
hex 2 "version"
hex 1 "flags"
set size [bytes 4]
binary scan $size B32 size_b
binary scan $size_b xa7xa7xa7xa7 a b c d
set bytes [expr { "0b${a}${b}${c}${d}" }]
move -4
bytes 4 "size: $bytes"
bytes $bytes "data"
}
} else {
# we read two bytes but didn't match,
# so take one step back and try again
move -1
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment