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