Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
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.