Newsgroup: it.comp.lang.delphi
Titolo: Problema nella lettura dell'ID3TAG di un MP3

Salve a tutti,
ho letto che negli ultimi 128 bytes di un file MP3 c'è l'ID3TAG che
contine ele informazioni su cantante, titolo della canzone, ecc. ed ho
provato a leggerlo con questo pezzo di codice
procedure TForm1.Button1Click(Sender: TObject);
type
  ID3TAG=record
           tag:string[3];
           Title:string[30];
           Author:string[30];
           Album:string[30];
           Year:string[4];
           Comment:string[30];
           Genre:char;
         end;
var
  f:file;
  Mp3Tag:ID3TAG;
  size:longint;
begin
  If OpenDialog1.execute then
  begin
    AssignFile(f,OpenDialog1.filename);
    reset(f);
    size:=Filesize(f)-128;
    seek(f, size);
    BlockRead(F, Mp3Tag, sizeof(Mp3Tag));
    closefile(f);
  end;
end;
La lettura non mi dà errori, però quando tento di visualizzare quello
che ho salvato nel record mi vengono fuori le peggio cose: caratteri
incomprensibili, spazi vuoti.
Dove ho sbagliato?
Ringrazio in anticipo

 Dove ho sbagliato?
Ciao,
            l'errore sta nel record. Le specifiche MP3 danno una tabella dei
valori da leggere a partire dagli ultimi 128 bytes:
[la formattazione della tabella andrà a farsi benedire, credo grazie ad
Outlook]
   Field       Length            offsets
   -------------------------------------
   Tag           3                0-2
   Songname     30                3-32
   Artist       30                33-62
   Album        30                63-92
   Year          4                93-96
   Comment      30                97-126
   Genre         1                127
Cmq, in sostanza il tuo record è + grande di 128 bit (mi pare fossero 134,
ora non ricordo)... Questo accade perchè usi delle stringhe e, nelle
stringhe Pascal c'è sempre un carattere in + [il primo, in cui viene
memorizzata la dimensione]...
Avevi 6 stringhe: uno sforamento di 6 bytes...
Basta rimpiazzare il record con questo e funziona tutto:
[io ho usato i TfileStream ma puoi benissimo mantenere la BlockWrite]
procedure TForm1.Button1Click(Sender: TObject);
type
  ID3TAG=record
           tag:array[0..2] of char;
           Title:array [0..29] of char;
           Author:array [0..29] of char;
           Album:array [0..29] of char;
           Year:array [0..3] of char;
           Comment:array [0..29] of char;
           Genre:char;
         end;
var
  Mp3Tag:ID3TAG;
  f:TfileStream;
begin
  If OpenDialog1.execute then
  begin
//    FillChar(mp3tag,sizeof(mp3tag),#0); // questa andrebbe per sicurezza,
potrebbe servirti + avanti...
    f:=TfileStream.create(opendialog1.filename,fmOpenReadWrite);
    f.Seek(f.size-sizeof(mp3tag),0);
    f.read(mp3tag,sizeof(mp3tag));
    f.Free;
  listbox1.items.clear;
  listbox1.items.add('tag='+mp3tag.tag);
  listbox1.items.add('titolo='+mp3tag.title);
  listbox1.items.add('autore='+mp3tag.author);
  listbox1.items.add('album='+mp3tag.album);
  listbox1.items.add('anno='+mp3tag.year);
  listbox1.items.add('commento='+mp3tag.comment);
  listbox1.items.add('genere='+inttostr(ord(mp3tag.genre)));
  end;
end;
Sta' attento anche al fatto che non è automatico che un MP3 abbia un IDTag
negli ultimi 128 bytes... alcuni l'hanno, altri potrebbero non averlo...
Non ricordo bene cosa dicono le specifiche, ma mi pare che si potesse fare
un controllo in base al campo TAG del record: se Mp3Tag.Tag='TAG' allora
tutto ok, altrimenti l'mp3 in questione non ha l'IDTag...
[gli IDTags si possono creare anche da winAmp ma, per esempio, quando avevo
fatto io le prove per un programma che serviva ad un mio amico per
archiviare i brani della sua band registrati da microfono (quindi si faceva
un utilizzo _legale_ dell'MP3) tutti gli mp3 creati non avevano un IDTag e
si è dovuto crearli a manina, non saprei se gli MP3 che trovi in giro per il
Web sono in genere forniti di IdTags o meno...]
Ciao :-)
--
(¯`·.¸¸.·´¯`·.¸¸.-> Andrea <-.¸¸.·´¯`·.¸¸.·´¯)
Ps: se possibile, cerca di evitare il cross-posting...
AntiSpam: rimuovere il trattino basso dall'indirizzo per rispondere
AntiSpam: remove the underscore from the e-mail address to reply

 wrote in message
94909822...@melissa.energy.it...


 questo non è più semplice ?
[Premessa importante: non voglio passare per quello che sostiene
                                        che il suo codice è migliore di
quello degli altri.
Mi permetto di correggerti solo perchè questo è un Ng pubblico, quindi penso
che se tu non avessi voluto esporti a commenti non avresti postato...]
Detto questo, direi che no, il tuo codice non è + semplice.
Anzi,
- è decisamente + lenta (circa 20 volte)
- hai dimenticato una CloseFile (va beh, una svista)
- Fallisce se il file è read-only [per es. su un CD] (io non l'avevo
considerato perchè si trattava anche di scrivere)
- usi variabili che potresti evitare... (male!)
- leggi un byte alla volta dal disco (il che implica lentezza in esecuzione)
Il codice qui sotto è una versione un po' ritoccata ;-)
Procedure Lettura_Tag2(Mp3file:string;var
titolo,artista,album,anno,commento:String);
Var
  MP3 : File of char;
  Tag:array[1..128] of char;
  i:Byte;
begin
 titolo:='';   Artista:='';
 Album:='';    Anno:='';
 commento:='';
 AssignFile(MP3,MP3file);
  FileMode:=0; // non fallisce se in ReadOnly
  Reset(MP3);
 seek(MP3,filesize(MP3)-sizeof(tag));
 BlockRead(Mp3,tag,sizeof(tag));
 CloseFile(MP3);
  if tag[1]='T' then
     begin
      for i:= 4 to  33 do Titolo:=Titolo+tag[i];
      for i:=34 to  63 do Artista:=artista+tag[i];
      for i:=64 to  93 do album:=album+tag[i];
      for i:=94 to  97 do Anno:=Anno+tag[i];
      for i:=98 to 127 do Commento:=Commento+tag[i];
     { questi cicli for non mi piacciono neanche un po'... }
     end;
end;
Ma che ci trovi di drammatico nel mio codice?
Una volta definito il record
type
  ID3TAG=record
           tag:array[0..2] of char;
           Title:array [0..29] of char;
           Author:array [0..29] of char;
           Album:array [0..29] of char;
           Year:array [0..3] of char;
           Comment:array [0..29] of char;
           Genre:char;
         end;
non ti restano che 4 righe di codice...
var
  Mp3Tag:ID3TAG;
  f:TfileStream;
begin
    f:=TfileStream.create(NomeFile,fmOpenRead);
    f.Seek(f.size-sizeof(mp3tag),0);
    f.read(mp3tag,sizeof(mp3tag));
    f.Free;
Ciao :-)
--
(¯`·.¸¸.·´¯`·.¸¸.-> Andrea <-.¸¸.·´¯`·.¸¸.·´¯)
AntiSpam: rimuovere il trattino basso dall'indirizzo per rispondere


       AssignFile(MP3,MP3file);
