mp3 id3 z cddb
iko
iko na kamarad.cz
Čtvrtek Červen 19 08:29:49 CEST 2003
ked uz nikto iny, tak ja to teda spravim... ak bude niekedy dost casu
Patrik Skovajsa wrote:
> Zdravim vsetkych v konfere, mp3 id3 z cddb je zaujmavy problem o ktorom
> som i ja v minulosti rozmyslal avsak vtedy to bolo na mna dost. Robil
> som nejake pokusy s vypalovanim AudioCD z Mp3 a nasledne vyskusat dane
> CD na CDDB/FREEDB a zakazdym to fungovalo ako z originalneho CD. Ako
> MP3compresor som pouzil bladeenc i lame. Usudil som, ze z MP3 sa urcite
> bude dat vygenerovat discid. Tymto sa vas chcem opytat ci by niekto
> nemal zaujem napisat program (napr. v C) ktory by riesil dany problem.
> Mohol by
> fungovat napr. tak, ze mu zadame vstupny adresar z MP3, ktore musia
> byt samozrejme riadne ocislovane napr. 01xxx.mp3 az 25xxx.mp3.
> Program spli ulohu a zapise id3tag. Keby sa do pisania programu
> zapojilo viac ludi som si isty, ze by to ani dlho netrvalo. Tu je
> discid algoritmus z freedb.org:
>
> CDDB/FREEDB DISCID ALGORITHM
> ----------------------------
>
> The following is a C code example that illustrates how to generate the
> CDDB/freedb disc ID. Examples in other programming languages may be
> found on
> the freedb web site at http://www.freedb.org in the developers-section.
> 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.
>
> -----------------
>
> Tu je trochu iny sposob:
>
> /* Code to get discid for a cddb query.
>
> *** Linux Version ***
>
> $Id: discid.c,v 1.3 2001/04/14 17:54:53 jzawodn Exp $
>
> Copyright (c) 1998-2000 Jeremy D. Zawodny <Jeremy na Zawodny.com>
>
> This software is covered by the GPL.
>
> Is is based on code found in:
>
> To: code-review na azure.humbug.org.au
> Subject: CDDB database reader
> From: Byron Ellacott <rodent na route-qn.uqnga.org.au>
> Date: Fri, 5 Jun 1998 17:32:40 +1000
>
> */
>
> /* Stripped net code, 'cause I only care about the discid */
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <fcntl.h>
> #include <stdarg.h>
> #include <errno.h>
> #include <netdb.h>
> #include <unistd.h>
> #include <string.h>
> #include <sys/ioctl.h>
> #include <sys/types.h>
>
> #include <linux/cdrom.h>
>
> struct toc {
> int min, sec, frame;
> } cdtoc[100];
>
> int read_toc(void) {
> int drive = open("/dev/cdrom", O_RDONLY | O_NONBLOCK);
> struct cdrom_tochdr tochdr;
> struct cdrom_tocentry tocentry;
> int i;
>
> ioctl(drive, CDROMREADTOCHDR, &tochdr);
> for (i = tochdr.cdth_trk0; i <= tochdr.cdth_trk1; i++) {
> tocentry.cdte_track = i;
> tocentry.cdte_format = CDROM_MSF;
> ioctl(drive, CDROMREADTOCENTRY, &tocentry);
> cdtoc[i-1].min = tocentry.cdte_addr.msf.minute;
> cdtoc[i-1].sec = tocentry.cdte_addr.msf.second;
> cdtoc[i-1].frame = tocentry.cdte_addr.msf.frame;
> cdtoc[i-1].frame += cdtoc[i-1].min*60*75;
> cdtoc[i-1].frame += cdtoc[i-1].sec*75;
> }
> tocentry.cdte_track = 0xAA;
> tocentry.cdte_format = CDROM_MSF;
> ioctl(drive, CDROMREADTOCENTRY, &tocentry);
> cdtoc[tochdr.cdth_trk1].min = tocentry.cdte_addr.msf.minute;
> cdtoc[tochdr.cdth_trk1].sec = tocentry.cdte_addr.msf.second;
> cdtoc[tochdr.cdth_trk1].frame = tocentry.cdte_addr.msf.frame;
> cdtoc[tochdr.cdth_trk1].frame += cdtoc[tochdr.cdth_trk1].min*60*75;
> cdtoc[tochdr.cdth_trk1].frame += cdtoc[tochdr.cdth_trk1].sec*75;
> close(drive);
> return tochdr.cdth_trk1;
> }
>
> unsigned int cddb_sum(int n) {
> unsigned int ret;
>
> ret = 0;
> while (n > 0) {
> ret += (n % 10);
> n /= 10;
> }
> return ret;
> }
>
> unsigned long cddb_discid(int tot_trks) {
> unsigned int i, t = 0, n = 0;
>
> 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);
> }
>
> void main(void) {
> unsigned long discid;
> int tracks, i;
>
> tracks = read_toc();
> discid = cddb_discid(tracks);
> printf("%08x %d", discid, tracks);
> for (i = 0; i < tracks; i++) printf(" %d", cdtoc[i].frame);
> printf(" %d\n", (cdtoc[tracks].frame)/75);
> printf("\n");
> exit(0);
> }
>
> --
> Skuska:
>
> [cracken na cracken_house linux]$ ./discid
> 3b127718 24 150 1460 15858 32207 45639 58258 73874 86336 101453 116466
> 129933 143651 154810 169153 183098 198923 210750 225482 240652 258799
> 277872 298870 315703 335409 4729
>
> [cracken na cracken_house linux]$ ./discid
> bb119f0e 14 150 17777 36809 65584 87314 107183 127639 151099 172946
> 191136 214565 254729 273463 317543 4513
>
> [cracken na cracken_house linux]$ ./discid
> b70b820e 14 150 15089 30965 46570 62487 80643 96460 110721 126593 144242
> 159270 171706 187078 203099 2948
> --
> A takto z tychto cisel dostanme co chceme.
> http://freedb.freedb.org/~cddb/cddb.cgi?cmd=cddb+query+7c0b8b0b+11+150+23115+
> 42165+60015+79512+101560+118757+136605+159492+176067+198875+2957&hello=
> user+
> hostname+program+version&proto=3
>
> ---------
> Dufam, ze sa tento problem vyriesi a ospravedlnujem sa za dlhy nudny mail.
Další informace o konferenci Linux