123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- CDDB DISCID
- -----------
- Both forms of CDDB access require that the software compute a "disc
- ID" which is an identifier that is used to access the CDDB. The disc
- ID is a 8-digit hexadecimal (base-16) number, computed using data from
- a CD's Table-of-Contents (TOC) in MSF (Minute Second Frame) form. The
- algorithm is listed below in Appendix A.
- It is crucial that your software compute the disc ID correctly. If it
- does not generate the correct disc ID, it will not be compatible with CDDB.
- Moreover, if your software submits CDDB entries with bad disc IDs to the
- CDDB archives, it could compromise the integrity of the CDDB.
- [...]
- APPENDIX A - CDDB DISCID ALGORITHM
- ----------------------------------
- The following is a C code example that illustrates how to generate the
- CDDB disc ID. [...] A text description
- of the algorithm follows, which should contain the necessary information
- to code the algorithm in any programming language.
- struct toc {
- int min;
- int sec;
- int frame;
- };
- struct toc cdtoc[100];
- int
- read_cdtoc_from_drive(void)
- {
- /* Do whatever is appropriate to read the TOC of the CD
- * into the cdtoc[] structure array.
- */
- return (tot_trks);
- }
- int
- cddb_sum(int n)
- {
- int ret;
- /* For backward compatibility this algorithm must not change */
- ret = 0;
- while (n > 0) {
- ret = ret + (n % 10);
- n = n / 10;
- }
- return (ret);
- }
- unsigned long
- cddb_discid(int tot_trks)
- {
- int i,
- t = 0,
- n = 0;
- /* For backward compatibility this algorithm must not change */
- i = 0;
- while (i < tot_trks) {
- n = n + cddb_sum((cdtoc[i].min * 60) + cdtoc[i].sec);
- i++;
- }
- t = ((cdtoc[tot_trks].min * 60) + cdtoc[tot_trks].sec) -
- ((cdtoc[0].min * 60) + cdtoc[0].sec);
- return ((n % 0xff) << 24 | t << 8 | tot_trks);
- }
- main()
- {
- int tot_trks;
- tot_trks = read_cdtoc_from_drive();
- printf("The discid is %08x", cddb_discid(tot_trks));
- }
- This code assumes that your compiler and architecture support 32-bit
- integers.
- The cddb_discid function computes the discid based on the CD's TOC data
- in MSF form. The frames are ignored for this purpose. The function is
- passed a parameter of tot_trks (which is the total number of tracks on
- the CD), and returns the discid integer number.
- It is assumed that cdtoc[] is an array of data structures (records)
- containing the fields min, sec and frame, which are the minute, second
- and frame offsets (the starting location) of each track. This
- information is read from the TOC of the CD. There are actually
- tot_trks + 1 "active" elements in the array, the last one being the
- offset of the lead-out (also known as track 0xAA).
- The function loops through each track in the TOC, and for each track
- it takes the (M * 60) + S (total offset in seconds) of the track and
- feeds it to cddb_sum() function, which simply adds the value of each digit
- in the decimal string representation of the number. A running sum of this
- result for each track is kept in the variable n.
- At the end of the loop:
- 1. t is calculated by subtracting the (M * 60) + S offset of the lead-out
- minus the (M * 60) + S offset of first track (yielding the length of
- the disc in seconds).
- 2. The result of (n modulo FFh) is left-shifted by 24 bits.
- 3. t is left shifted by 8.
- The bitwise-OR operation of result 2., 3. and the tot_trks number is
- used as the discid.
- The discid is represented in hexadecimal form for the purpose of
- xmcd cddb file names and the DISCID= field in the xmcd cddb file itself.
- If the hexadecimal string is less than 8 characters long, it is
- zero-padded to 8 characters (i.e., 3a8f07 becomes 003a8f07). All
- alpha characters in the string should be in lower case, where
- applicable.
- Important note for clients using the MS-Windows MCI interface:
- The Windows MCI interface does not provide the MSF location of the
- lead-out. Thus, you must compute the lead-out location by taking the
- starting position of the last track and add the length of the last track
- to it. However, the MCI interface returns the length of the last track
- as ONE FRAME SHORT of the actual length found in the CD's TOC. In most
- cases this does not affect the disc ID generated, because we truncate
- the frame count when computing the disc ID anyway. However, if the
- lead-out track has an actual a frame count of 0, the computed quantity
- (based on the MSF data returned from the MCI interface) would result in
- the seconds being one short and the frame count be 74. For example,
- a CD with the last track at an offset of 48m 32s 12f and having a
- track length of 2m 50s 63f has a lead-out offset of 51m 23s 0f. Windows
- MCI incorrectly reports the length as 2m 50s 62f, which would yield a
- lead-out offset of 51m 22s 74f, which causes the resulting truncated
- disc length to be off by one second. This will cause an incorrect disc
- ID to be generated. You should thus add one frame to the length of the
- last track when computing the location of the lead-out.
- The easiest way for Windows clients to compute the lead-out given information
- in MSF format is like this:
- (offset_minutes * 60 * 75) + (offset_seconds * 75) + offset_frames +
- (length_minutes * 60 * 75) + (length_seconds * 75) + length_frames + 1 = X
- Where X is the offset of the lead-out in frames. To find the lead-out in
- seconds, simply divide by 75 and discard the remainder.
|