2 |
- |
1 |
|
|
|
2 |
CDDB DISCID
|
|
|
3 |
-----------
|
|
|
4 |
|
|
|
5 |
Both forms of CDDB access require that the software compute a "disc
|
|
|
6 |
ID" which is an identifier that is used to access the CDDB. The disc
|
|
|
7 |
ID is a 8-digit hexadecimal (base-16) number, computed using data from
|
|
|
8 |
a CD's Table-of-Contents (TOC) in MSF (Minute Second Frame) form. The
|
|
|
9 |
algorithm is listed below in Appendix A.
|
|
|
10 |
|
|
|
11 |
It is crucial that your software compute the disc ID correctly. If it
|
|
|
12 |
does not generate the correct disc ID, it will not be compatible with CDDB.
|
|
|
13 |
Moreover, if your software submits CDDB entries with bad disc IDs to the
|
|
|
14 |
CDDB archives, it could compromise the integrity of the CDDB.
|
|
|
15 |
|
|
|
16 |
[...]
|
|
|
17 |
|
|
|
18 |
APPENDIX A - CDDB DISCID ALGORITHM
|
|
|
19 |
----------------------------------
|
|
|
20 |
|
|
|
21 |
The following is a C code example that illustrates how to generate the
|
|
|
22 |
CDDB disc ID. [...] A text description
|
|
|
23 |
of the algorithm follows, which should contain the necessary information
|
|
|
24 |
to code the algorithm in any programming language.
|
|
|
25 |
|
|
|
26 |
|
|
|
27 |
struct toc {
|
|
|
28 |
int min;
|
|
|
29 |
int sec;
|
|
|
30 |
int frame;
|
|
|
31 |
};
|
|
|
32 |
|
|
|
33 |
struct toc cdtoc[100];
|
|
|
34 |
|
|
|
35 |
int
|
|
|
36 |
read_cdtoc_from_drive(void)
|
|
|
37 |
{
|
|
|
38 |
/* Do whatever is appropriate to read the TOC of the CD
|
|
|
39 |
* into the cdtoc[] structure array.
|
|
|
40 |
*/
|
|
|
41 |
return (tot_trks);
|
|
|
42 |
}
|
|
|
43 |
|
|
|
44 |
int
|
|
|
45 |
cddb_sum(int n)
|
|
|
46 |
{
|
|
|
47 |
int ret;
|
|
|
48 |
|
|
|
49 |
/* For backward compatibility this algorithm must not change */
|
|
|
50 |
|
|
|
51 |
ret = 0;
|
|
|
52 |
|
|
|
53 |
while (n > 0) {
|
|
|
54 |
ret = ret + (n % 10);
|
|
|
55 |
n = n / 10;
|
|
|
56 |
}
|
|
|
57 |
|
|
|
58 |
return (ret);
|
|
|
59 |
}
|
|
|
60 |
|
|
|
61 |
unsigned long
|
|
|
62 |
cddb_discid(int tot_trks)
|
|
|
63 |
{
|
|
|
64 |
int i,
|
|
|
65 |
t = 0,
|
|
|
66 |
n = 0;
|
|
|
67 |
|
|
|
68 |
/* For backward compatibility this algorithm must not change */
|
|
|
69 |
|
|
|
70 |
i = 0;
|
|
|
71 |
|
|
|
72 |
while (i < tot_trks) {
|
|
|
73 |
n = n + cddb_sum((cdtoc[i].min * 60) + cdtoc[i].sec);
|
|
|
74 |
i++;
|
|
|
75 |
}
|
|
|
76 |
|
|
|
77 |
t = ((cdtoc[tot_trks].min * 60) + cdtoc[tot_trks].sec) -
|
|
|
78 |
((cdtoc[0].min * 60) + cdtoc[0].sec);
|
|
|
79 |
|
|
|
80 |
return ((n % 0xff) << 24 | t << 8 | tot_trks);
|
|
|
81 |
}
|
|
|
82 |
|
|
|
83 |
main()
|
|
|
84 |
{
|
|
|
85 |
int tot_trks;
|
|
|
86 |
|
|
|
87 |
tot_trks = read_cdtoc_from_drive();
|
|
|
88 |
printf("The discid is %08x", cddb_discid(tot_trks));
|
|
|
89 |
}
|
|
|
90 |
|
|
|
91 |
|
|
|
92 |
This code assumes that your compiler and architecture support 32-bit
|
|
|
93 |
integers.
|
|
|
94 |
|
|
|
95 |
The cddb_discid function computes the discid based on the CD's TOC data
|
|
|
96 |
in MSF form. The frames are ignored for this purpose. The function is
|
|
|
97 |
passed a parameter of tot_trks (which is the total number of tracks on
|
|
|
98 |
the CD), and returns the discid integer number.
|
|
|
99 |
|
|
|
100 |
It is assumed that cdtoc[] is an array of data structures (records)
|
|
|
101 |
containing the fields min, sec and frame, which are the minute, second
|
|
|
102 |
and frame offsets (the starting location) of each track. This
|
|
|
103 |
information is read from the TOC of the CD. There are actually
|
|
|
104 |
tot_trks + 1 "active" elements in the array, the last one being the
|
|
|
105 |
offset of the lead-out (also known as track 0xAA).
|
|
|
106 |
|
|
|
107 |
The function loops through each track in the TOC, and for each track
|
|
|
108 |
it takes the (M * 60) + S (total offset in seconds) of the track and
|
|
|
109 |
feeds it to cddb_sum() function, which simply adds the value of each digit
|
|
|
110 |
in the decimal string representation of the number. A running sum of this
|
|
|
111 |
result for each track is kept in the variable n.
|
|
|
112 |
|
|
|
113 |
At the end of the loop:
|
|
|
114 |
1. t is calculated by subtracting the (M * 60) + S offset of the lead-out
|
|
|
115 |
minus the (M * 60) + S offset of first track (yielding the length of
|
|
|
116 |
the disc in seconds).
|
|
|
117 |
|
|
|
118 |
2. The result of (n modulo FFh) is left-shifted by 24 bits.
|
|
|
119 |
|
|
|
120 |
3. t is left shifted by 8.
|
|
|
121 |
|
|
|
122 |
The bitwise-OR operation of result 2., 3. and the tot_trks number is
|
|
|
123 |
used as the discid.
|
|
|
124 |
|
|
|
125 |
The discid is represented in hexadecimal form for the purpose of
|
|
|
126 |
xmcd cddb file names and the DISCID= field in the xmcd cddb file itself.
|
|
|
127 |
If the hexadecimal string is less than 8 characters long, it is
|
|
|
128 |
zero-padded to 8 characters (i.e., 3a8f07 becomes 003a8f07). All
|
|
|
129 |
alpha characters in the string should be in lower case, where
|
|
|
130 |
applicable.
|
|
|
131 |
|
|
|
132 |
Important note for clients using the MS-Windows MCI interface:
|
|
|
133 |
|
|
|
134 |
The Windows MCI interface does not provide the MSF location of the
|
|
|
135 |
lead-out. Thus, you must compute the lead-out location by taking the
|
|
|
136 |
starting position of the last track and add the length of the last track
|
|
|
137 |
to it. However, the MCI interface returns the length of the last track
|
|
|
138 |
as ONE FRAME SHORT of the actual length found in the CD's TOC. In most
|
|
|
139 |
cases this does not affect the disc ID generated, because we truncate
|
|
|
140 |
the frame count when computing the disc ID anyway. However, if the
|
|
|
141 |
lead-out track has an actual a frame count of 0, the computed quantity
|
|
|
142 |
(based on the MSF data returned from the MCI interface) would result in
|
|
|
143 |
the seconds being one short and the frame count be 74. For example,
|
|
|
144 |
a CD with the last track at an offset of 48m 32s 12f and having a
|
|
|
145 |
track length of 2m 50s 63f has a lead-out offset of 51m 23s 0f. Windows
|
|
|
146 |
MCI incorrectly reports the length as 2m 50s 62f, which would yield a
|
|
|
147 |
lead-out offset of 51m 22s 74f, which causes the resulting truncated
|
|
|
148 |
disc length to be off by one second. This will cause an incorrect disc
|
|
|
149 |
ID to be generated. You should thus add one frame to the length of the
|
|
|
150 |
last track when computing the location of the lead-out.
|
|
|
151 |
|
|
|
152 |
The easiest way for Windows clients to compute the lead-out given information
|
|
|
153 |
in MSF format is like this:
|
|
|
154 |
|
|
|
155 |
(offset_minutes * 60 * 75) + (offset_seconds * 75) + offset_frames +
|
|
|
156 |
(length_minutes * 60 * 75) + (length_seconds * 75) + length_frames + 1 = X
|
|
|
157 |
|
|
|
158 |
Where X is the offset of the lead-out in frames. To find the lead-out in
|
|
|
159 |
seconds, simply divide by 75 and discard the remainder.
|