6 ###--------------------------------------------------------------------------
7 ### CD identification algorithms.
11 ### CCLLLLNN [NTRACK TRACK-START... LENGTH]
13 ### CC is a checksum of the track start times; LLLL is the offset of the
14 ### leadout track, in seconds (rounded down), and NN is the total number of
15 ### tracks. All of these are in hexadecimal, and include the 150-frame (2
16 ### second) pre-gap. All of these are in hexadecimal. Since a CD can have
17 ### at most 99 tracks, and can contain no more than 90 minutes of audio (!),
18 ### the other two items fit without needing reduction.
20 ### The checksum is the sum of the decimal digits of the track start times,
21 ### in seconds, reduced modulo 255.
23 ### NTRACK is the number of tracks; LENGTH is the offset of the leadout in
24 ### seconds. These are the same as in the checksum, so repeating them is
25 ### pointless, but it's done anyway. The TRACK-STARTs are the track start
26 ### offsets, in frames.
33 ### CDDBID is the CDDB id as described above. DA1 is simply the sum of the
34 ### track starts, including the lead-out track; DA2 is the sum of the
35 ### products TRACKNO * OFFSET for the audio tracks only, but including the
36 ### final lead-out -- so a data track makes the last audio track look very
37 ### long. Another wrinkle: the OFFSET for the first track is forced to 1 if
38 ### it's zero (to avoid the entry being lost, I presume, though I'm not sure
39 ### why this is ever so useful).
44 ### The MusicBrainz identification is a base64-encoded SHA-1 hash of the
45 ### table of contents. The base64 encoding uses `.', `_' and `-' in place of
46 ### `+', `/' and `=', because the standard characters /all/ have special
47 ### meanings in URL query strings. (Duh. And I'm not quite sure why we
48 ### still need the trailing marker.)
50 ### The message to be hashed is FIRST LAST LENGTH TRACK-START..., where FIRST
51 ### and LAST are the first and last track numbers, LENGTH is the offset of
52 ### the lead-out, in frames, and the TRACK-STARTs are the start offsets of
53 ### the tracks, in order, also in frames. The track numbers are two
54 ### uppercase hex digits; the frame offsets are eight. All of these are
55 ### simply concatenated together.
57 ### MusicBrainz only concerns itself with the audio tracks. If there's a
58 ### data track, then we ignore it, and the lead-out is considered to be 11400
59 ### frames before the data track.
61 ###--------------------------------------------------------------------------
65 while getopts "acCm" opt
; do
67 a
) format
=accuraterip
;;
69 C
) format
=cddb-tracks
;;
70 m
) format
=musicbrainz
;;
80 if [ -r
"$1/.discid" ]; then
83 exec < <($JBDIR/bin
/flaccrip-toc
"$1")
87 echo >&2 "Usage: $0 [-acCm] [DIRECTORY]"
92 ###--------------------------------------------------------------------------
102 ## Wander through the table of contents picking up unconsidered trifles.
103 while read type offset
; do
105 ## Bump the track numbers here. Most things want 1-based numbering, so
106 ## this is right. Don't bump for the end marker. Those who care
107 ## (AccurateRip) will sort it out for themselves.
109 T
) nt
=$
((nt
+ 1)) nat
=$
((nat
+ 1));;
113 ## Update the CDDB state. This is common to several formats.
118 cddbtracks
="${cddbtracks:+$cddbtracks }$o"
121 ?
*) cddbck
=$
((cddbck
+ ${s:0:1})); s
=${s#?} ;;
131 ## Update other bits of information.
135 db
=$
((db
+ nat
*(offset
> 0 ? offset
: 1)))
136 mbtracks
="$mbtracks$(printf "%08X
" $((offset + 150)))"
139 mbfinal
=$
((offset
- 11250))
143 db
=$
((db
+ (nat
+ 1)*(offset
> 0 ? offset
: 1)))
144 case "${mbfinal+t}" in
146 *) mbfinal
=$
((offset
+ 150)) ;;
152 ## Sort out the CDDB id.
153 cddbid
=$
(printf "%02x%04x%02x" $
((cddbck
%255)) $
((final
/75)) $nt)
155 ###--------------------------------------------------------------------------
156 ### Produce the answer.
163 echo "$cddbid $nt $cddbtracks $((final/75 + 2))"
166 printf "%03d-%08x-%08x-%s\n" $nat $da $db $cddbid
169 mb
=$
(printf "%02X%02X%08X%s" 1 $nat $mbfinal $mbtracks)
170 for ((i
= nat
; i
< 99; i
++)); do
174 openssl dgst
-sha1
-binary |
175 openssl base64 |
tr '+/=' '._-'