PDA

View Full Version : [C] Modificare attributi file mp3


VegetaSSJ5
30-10-2004, 18:33
Salve a tutti! Vorrei fare un programmino in c che mi permetta di modificare gli attributi ID3v1 di alcuni file mp3 (titolo, artista, anno, genere...). Ho fatto una ricerchina veloce ma mi appaiono tutti siti di mp3 da scaricare...:rolleyes:
Qualcuno mi sa dare una mano???

Blackat
31-10-2004, 09:05
ID3.ORG (http://www.id3.org/)

VegetaSSJ5
01-11-2004, 18:13
per quanto riguarda il C/C++ quel sito mi rimanda a questa (http://id3lib.sourceforge.net/) pagina da dove ho scaricato la versione 3.8.3.
tuttavia qualsiasi documentazione reperibile su quel sito si riferisce al c++ e non al c.
non so dove cercare...

SnakePlissken
01-11-2004, 19:10
Ma ti serve il programma già fatto oppure solo delle indicazioni su come farlo?

VegetaSSJ5
02-11-2004, 00:06
no, voglio farmi un programmino che mi sistemi gli id3 in un certo formato. sono stanco di farlo sempre io a mano!;) (anch perchè altrimenti dovrei farmi 17 cd e non è bello...:eek: almeno così imparo come gestire (mi basta anche in modo basilare) gli id3 in c.

SnakePlissken
02-11-2004, 20:08
Avevo fatto un programmino a suo tempo, ma dovrei vedere se me lo ritrovo in qualche floppy ...il mio disco rigido l'anno scorso ha tolto del fumo....

Comunque vedrò di spiegarti qualcosa, per quanto mi ricordo.

Innanzitutto esistono due tipi principali di tag ID3, la versione 1.0/1.1 e la 2.4 (questa mi pare sia l'ultima... o almeno lo era quando mi interessavo di tag qualche annetto fa).

Esistono differenze sostanziali tra le due.
Innanzitutto la 1.1 (che si differenzia dalla 1.0 solo perché permette l'inserimento del numero di traccia... mi pare:)) è molto semplice, mentre la 2.4 è veramente complessa, e nelle sue ultime varianti permette addirittura l'inserimento di immagini e testi. Guarda quel sito che ti hanno suggerito per renderti conto tu stesso. Ovviamente sarebbe difficile anche farsi un programma che gestisca tutti i suoi campi...

Perciò meglio pensare al tag ID3v1.
Questo occupa gli ultimi 128 byte del file MP3. Per "prelevarlo" quindi puoi andare a colpo sicuro posizionandoti 128 byte prima della fine del file e leggendoli. Per identificarlo controlla la presenza della sequenza di caratteri "tag" o "TAG" tra i primi tre di tutto questo blocco. Seguono quindi i pochi campi, 6 in tutto. Ecco lo schema completo del blocco:
Identificatore 3
Titolo 30
Autore 30
Album 30
Anno 4
Commento 30
Genere 1
TOTALE = 128 bytes
Una serie di piccole aggiunte.

La prima: questa è la struttura del 1.0. L'1.1 permette anche la memorizzazione del numero di traccia, tuttavia mantiene la totale compatibilità col 1.0: non cambia infatti la dimensione del tag. Sfruttando la relativa inutilità di un campo commento di soli 30 caratteri, infatti, si era stabilito che il numero di traccia fosse inserito proprio come ultimo byte del commento. Ma per essere identificato e non confuso col commento stesso, è preceduto da un carattere 0x00 che lo
delimita, cosicché il campo riservato al commento si riduce a 28 bytes. Se manca il numero di traccia, comunque, il commento può prendersi tutti i 30 bytes.

La seconda: I campi sono fissi, non puoi cambiare la loro dimensione e in caso non li occupi tutti, devi riempirli con 0x00 (meglio fare così che utilizzare gli spazi 0x20).

Terza: l'anno va memorizzato come stringa (di quattro caratteri).

Quarta: per il genere si utilizza una tabella bella lunga con un 150 generi ad ognuno dei quali corrisponde un numero ... purtoppo anche questa dovrei vedere se me la ritrovo da qualche parte. Faccio una ricerchina e domani ti riferisco.

Buona programmazione!

Ciao!

VegetaSSJ5
02-11-2004, 23:53
SnakePlissken meriti tutto il mio rispetto!!!:)
sei stato veramente chiaro nella spiegazione! ho però una domanda che riguarda il genere.
la tabella l'ho trovata a questo sito: http://www.mp3-howto.com/mp3-howto-22.html, non so come viene memorizzato il genere visto che non può essere come stringa perchè occupa un solo byte (secondo le indicazioni che mi hai fornito, e che ho anche visto sul sito www.id3.org), ma come fa a rappresentare i numeri fino a 128?

VegetaSSJ5
03-11-2004, 16:34
ho trovato da solo la risposta: sia il genere che il track sono due char.

SnakePlissken
03-11-2004, 19:59
Originariamente inviato da VegetaSSJ5
SnakePlissken meriti tutto il mio rispetto!!!:)
:eek:
non so come viene memorizzato il genere visto che non può essere come stringa perchè occupa un solo byte, ma come fa a rappresentare i numeri fino a 128?
In realtà un solo byte potrebbe memorizzare numeri da 0 fino al 255, in tutto 256 = 2^8 = (base binaria)^(bit a disposizione). Non devi vederlo come un char, ma considerarlo come un piccolo (unsigned) intero.
ho trovato da solo la risposta
:cool: Ma sì che le sai queste cose... :D
sia il genere che il track sono due char
ricorda però che il genere c'è sempre, mentre la track no (è un'intrusa!:D)!

VegetaSSJ5
06-11-2004, 15:37
Originariamente inviato da SnakePlissken
La seconda: I campi sono fissi, non puoi cambiare la loro dimensione e in caso non li occupi tutti, devi riempirli con 0x00 (meglio fare così che utilizzare gli spazi 0x20).
come faccio ad inserire in una stringa il carattere 0x00??

per caso è così??char stringa[30];
.
.
stringa[i]= (char) 0x00;oppure è semplicementestringa[i]= (char) 0;

SnakePlissken
06-11-2004, 18:55
Queste notazioni sono tutte valide:
stringa[i] = 0x00; // esadecimale (1 byte)
stringa[i] = 0; // decimale
stringa[i] = 00; // ottale
stringa[i] = '\0'; // codice ASCII del carattere

e puoi utilizzarle con o senza cast.
Io preferisco utilizzare 0x00 perché è intrinseca la specificazione di singolo byte, tu puoi fare come di più ti piace!:D

;)

cikko
07-11-2004, 12:17
Ciao,
stavo facendo qualcosa di simile in C++, senza usare alcuna libreria esterna.
Siccome devo corregere un po' di errori nella scrittura dei tag ID3, posto solo il codice per la lettura:

<code>
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;

int main(int argc, char** argv)
{
if (argc == 1) {
cout << "Devi specificare un file .mp3!\n";
exit(EXIT_FAILURE);
}

fstream fin;

char buf[129];

fin.open(argv[1], ios::in | ios::binary); // apertura file in modalità binaria
fin.seekg(-128, ios::end); // posizionamento 128 byte prima di EOF
fin.read(buf, 128); // memorizzo questi 128 byte nel buffer di byte

//controllo se è presente la stringa TAG
if (strncmp(buf, "TAG", 3)) {
cout << "TAG ID3 mancanti o file non valido!" << endl;
exit(EXIT_FAILURE);
}

/* stampa artista traccia, byte 33..62 */
cout << "ARTISTA: ";
for (int i = 33; i <= 62; i++)
if ((buf[i] == ' ') && (buf[i+1] == ' '))
break;
else
cout << buf[i];
/* stampa album, byte 63..92 */
cout << "\nALBUM: ";
for (int i = 63; i <= 92; i++)
if ((buf[i] == ' ') && (buf[i+1] == ' '))
break;
else
cout << buf[i];
/* stampa traccia, byte 3..32 */
cout << "\nTITOLO: ";
for (int i = 3; i <= 32; i++)
if ((buf[i] == ' ') && (buf[i+1] == ' '))
break;
else
cout << buf[i];
</code>

VegetaSSJ5
07-11-2004, 13:26
il codice per la lettura l'ho finito (in c), ora devo perfezionare quello per la scrittura ma purtroppo in questi giorni non ho molto tempo da dedicarci...

VegetaSSJ5
07-11-2004, 23:55
scusate ho fatto una domanda idiota...:cry: :cry: :muro: :muro:

VegetaSSJ5
10-11-2004, 00:01
ragazzi ho terminato la prima versione del mio programmino che permette di editare i tag id3v1.1. va migliorato sicuramente cmq intanto lo allego.:)

Allegato a pagina 2

VegetaSSJ5
10-11-2004, 18:00
mi raccomando non vi accalcate a scaricare il file giusto per darmi un parere...

accetto qualsiasi critica, anche "è inutile ed è programmato male", ma almeno scrivete qualcosa...:cry: :cry: :cry: ;)

DanieleC88
10-11-2004, 18:34
[non l'ho compilato e provato per davvero ma] Sembra ben scritto. Bravo.
L'unica cosa che a me non piace e' che non vai a capo all'inizio di un nuovo blocco, nemmeno quando inizi una routine... e poi io avrei evitato una initgenreV ed avrei usato valori costanti in una static array. Per il resto mi sembra niente male.

P.S.: oltre ad id3.org e gli altri link, guardati il sito di LAME, l'ottimo encoder open source. Puoi prendere spunti da li se vuoi anche il supporto id3v2.

VegetaSSJ5
10-11-2004, 19:11
non ho mai usato array statici, per questo non mi è venuta l'idea. cmq ho provato ad inizializzare l'array al di fuori del codice delle funzioni (nella dichiarazione delle variabili globali) ma il compilatore mi dava errore. usando l'array statico come potrei inizializzarlo anche fuori dalle funzioni??L'unica cosa che a me non piace e' che non vai a capo all'inizio di un nuovo blocco, nemmeno quando inizi una routine...il fatto è che ormai mi ci sono abituato a programmare così e non mi ci vedo proprio a scrivere codice nell'altro modo.

per quanto riguarda il sito di lame tu a quale ti riferisci? io sono andato qui http://lame.sourceforge.net ma non ho trovato alcuna info...

VegetaSSJ5
10-11-2004, 19:19
bug dl programma:
se l'anno è di 4 cifre, quando si visualizzano le informazioni, la riga Year:... è di questo formato:

Year: <anno><commento>

come mai stampa il commento a fianco all'anno? eppure nella struttura id3v1 l'anno è dichiarato array di 5 caratteri...:confused:

DanieleC88
11-11-2004, 12:47
Forse quando l'anno è più corto di quattro cifre trova la char[] riempita con caratteri nulli (0) e quindi si ferma, altrimenti no... comunque, usa \n alla [/i]fine[/i] di ogni printf, non all'inizio: in alcuni casi printf non stampa sullo schermo fino al prossimo \n, e quindi alcuni messaggi potrebbero non vedersi mai.

Per l'array statico, basta usare:static char * genreV[125] = {"blues", "classic rock", "...", "e così fino alla fine"};

accetto qualsiasi critica, anche "è inutile ed è programmato male"
Nessun programma è inutile per il programmatore, visto che è comunque un modo di migliorare le proprie capacità. E poi, si, ci sono alcune cose che potrebbero essere migliori, ma alla fine basta che sia bug-free...

DanieleC88
11-11-2004, 12:48
Dimenticavo:
http://lame.sourceforge.net/download/download.html

VegetaSSJ5
27-12-2004, 10:48
allegato: