Autor Beitrag
Icarus666
Hält's aus hier
Beiträge: 9



BeitragVerfasst: Sa 11.03.06 13:32 
Hallo!

Ich will ein kleines Programm in C# schreiben, was mir die von einer CD die ID gemäß den Vorgaben von freedb.org liefert, und eben dann auch die CD-Daten.
Mein derzeitiges Problem bezieht sich auf die Berechnung der ID.

auf freedb.org gibt es folgenden C Beispielcode:
ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
/*
The following is a C code example that illustrates how to generate the
CDDB/freedb 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.*/


Daraus habe ich folgenden Code fabriziert:
ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
private struct toc {
  public int  min;
  public int  sec;
  public int  frame;
};

private toc[] cdtoc = new toc[100];

ulong cddb_sum(int n)
{
  ulong ret = 0;
  while (n > 0) {
    ret = ret + (ulong)(n % 10);
    n /= 10;
  }
 return (ret);
}

int cddb_discid()
{
  int Tracks = CD.GetNumTracks();  //Anzahl der Tracks auf CD
  for (int i = 0; i <= Tracks; i++) {
    double Offset = 150;
    for (int k = 1; k <= i; k++) {
      Offset += CD.TrackSize(k) / 2352 + 1;
    }
    double f = Offset;  
    double m = Math.Floor(f / 75 / 60);
    double s = Math.Round(f / 75 - m * 60);
    cdtoc[i].frame = (int)f;  // Track-Array füllen
    cdtoc[i].min = (int)m;
    cdtoc[i].sec = (int)s;
  }
       
  int t = 0, n = 0;
  for (int i = 0; i < Tracks; i++) {
    n += (int)cddb_sum((cdtoc[i].min * 60) + cdtoc[i].sec);
  }
  t = (int)((cdtoc[Tracks].min * 60) + cdtoc[Tracks].sec) -
      ((cdtoc[0].min * 60) + cdtoc[0].sec);
  return ((n % 0xff) << 24 | t << 8 | Tracks);
}


das was cd_discid zurückliefert in Hexadezimaler schreibweise ist die Disc-ID.

Das Füllen des CD-Arrays stimmt. Habe ich anhand eines kleinen Tools, auch von freedb.org überprüft.
Lediglich bei der Disc-ID (8 Stellen Hex) scheinen bei manchen CDs die ersten beiden Stellen nicht zu stimmen.

Ich denke, dass es vielleicht mit der Genauigkeit der verwendeten Variablen zusammenhängt. Stehe aber im Moment auf'em Schlauch