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