/****************************************************************************** * Compilation: javac CDDB.java * Execution: java CDDB * * % java CDDB * 970ada0c * * Note: Pearl Jam's album Vs. has N = 12 tracks. The first track * starts at frames[0] = 150, the second at frames[1] = 14672, * the twelfth at frames[11] = 185792, and the disc ends at * frames[N] = 208500. Its disc id is 970ADA0C. * * The disc id is a 32-bit integer, which we represent using 8 * hex digits XXYYYYZZ. * * - XX is the checksum. The checksum is computed as follows: * for each starting frame[i], we convert it to seconds by * dividing by the frame rate 75; then we sum up the decimal * digits. E.g., if frame[i] = 7500600, this corresponds to * 100008 seconds whose digit sum is 1 + 8 = 9. * XX is the total sum of all of these digit sums mod 255. * - YYYY is the length of the album tracks in seconds. It is * computed as (frames[N] - frames[0]) / 75 and output in hex. * - ZZ is the number of tracks N expressed in hex. * ******************************************************************************/ public class CDDB { // return sum of decimal digits in n public static int sumOfDigits(int n) { int sum = 0; while (n > 0) { sum = sum + (n % 10); n = n / 10; } return sum; } public static void main(String[] args) { int FRAMES_PER_SECOND = 75; int[] frames = { 150, 14672, 27367, 45030, 60545, 76707, 103645, 116430, 137730, 156887, 171577, 185792, 208500 }; int n = frames.length - 1; // 12 // a somewhat unusual definition, but consistent with freedb int totalLength = frames[n] / FRAMES_PER_SECOND - frames[0] / FRAMES_PER_SECOND; // note the integer division before summing up the digits int checkSum = 0; for (int i = 0; i < n; i++) checkSum += sumOfDigits(frames[i] / FRAMES_PER_SECOND); int xx = checkSum % 255; int yyyy = totalLength; int zz = n; // xxyyyyzz int discID = ((xx << 24) | (yyyy << 8) | zz); StdOut.println(Integer.toHexString(discID)); } }