
Voici quelques portions de codes pour vous aider à comprendre le fonctionnement des Tags ID3:
Déclaration de la chaine des genres
Déclaration des structures simples Id3
1) Retouner le genre à partir de son numéro et de la chaine
PROCEDURE Zid3_RetourneGenre(xGenre)
// Procédure permettant de retourner le genre en clair pour les tags
id3 en version 1.x uniquement
// L'index du genre +1
SI Asc(xGenre)+1>126 ALORS
RENVOYER ""
SINON
RENVOYER ExtraitChaîne(gpMp3Genre,Asc(xGenre)+1)
FIN
2) Lire simplement les 128 Bytes des tags 1.x
PROCEDURE Zid3_LireTagv1(xFichier)
// Procédure permettant d'extraire un tag id3 en version 1.0 ou 1.1
// Déclarations
cNumFic est un entier
cChaine est une chaîne
cLigne est une chaîne
cVersion est un entier
// Ouverture du fichier et lecture des 128 derniers octets
cNumFic=fOuvre(xFichier,foLecture)
SI cNumFic=-1 ALORS RENVOYER ""
GOTO LBFIN
FIN
SI fPositionne(cNumFic,-128,fpFin)=-1 ALORS
fFerme(cNumFic)
GOTO LBFIN
FIN
cLigne=fLit(cNumFic,128)
fFerme(cNumFic)
// Check si la chaine extraite est bien un tag en version 1.x
SI cChaine[[1 A 3]]<>"TAG" ALORS
GOTO LBFIN
SINON
cChaine=cLigne
FIN
LBFIN:
RENVOYER cChaine
3) Calcul de la taille d'un Tag
PROCEDURE Zid3_CalculTaille(xTailleCodee,xNombreOctet)
// Prodédure permettant de renvoyer la taille d'un tag
// Les tailles sont codées avec suppression du 7ème bit soit sous
la forme :
// %0xxxxxx %0xxxxxxx %0xxxxxxx (%0xxxxxxx)
// Déclarations
cTaille est un entier
cTailleOctet1A,cTailleOctet2A,cTailleOctet3A,cTailleOctet4A sont des chaînes
fixes sur 8
cTailleOctet1B,cTailleOctet2B,cTailleOctet3B,cTailleOctet4B sont des chaînes
fixes sur 8
cRes1,cRes2,cRes3,cRes4 sont des chaînes fixes sur 2
// Suivant la codification de la taille
SELON xNombreOctet
CAS 3:
cTailleOctet1A=Zid3_C2Bin(xTailleCodee[[1]])
cTailleOctet2A=Zid3_C2Bin(xTailleCodee[[2]])
cTailleOctet3A=Zid3_C2Bin(xTailleCodee[[3]])
cTailleOctet1B="000"+cTailleOctet2A[[2 A 6]]
cTailleOctet2B=cTailleOctet2A[[7 A 8]]+cTailleOctet3A[[2 A 7]]
cTailleOctet3B=cTailleOctet3A[[8 A 8]]+cTailleOctet4A[[2 A 8]]
cRes1=Zid3_Bin2C(cTailleOctet1B)
cRes2=Zid3_Bin2C(cTailleOctet2B)
cRes3=Zid3_Bin2c(cTailleOctet3B)
cTaille=Val(cRes1+cRes2+cRes3,"x")
CAS 4:
cTailleOctet1A=Zid3_C2Bin(xTailleCodee[[1]])
cTailleOctet2A=Zid3_C2Bin(xTailleCodee[[2]])
cTailleOctet3A=Zid3_C2Bin(xTailleCodee[[3]])
cTailleOctet4A=Zid3_C2Bin(xTailleCodee[[4]])
cTailleOctet1B="0000"+cTailleOctet1A[[2 A 5]]
cTailleOctet2B=cTailleOctet1A[[6 A 8]]+cTailleOctet2A[[2 A 6]]
cTailleOctet3B=cTailleOctet2A[[7 A 8]]+cTailleOctet3A[[2 A 7]]
cTailleOctet4B=cTailleOctet3A[[8 A 8]]+cTailleOctet4A[[2 A 8]]
cRes1=Zid3_Bin2C(cTailleOctet1B)
cRes2=Zid3_Bin2C(cTailleOctet2B)
cRes3=Zid3_Bin2c(cTailleOctet3B)
cRes4=Zid3_Bin2c(cTailleOctet4B)
cTaille=Val(cRes1+cRes2+cRes3+cRes4,"x")
FIN
RENVOYER cTaille
4) Décrypter une entête de Tag 2.2 et 2.3
PROCEDURE Zid3_DecrypteEntete(xFichier,xOuvre=Vrai,xLigne="")
// Procédure permettante d'extraire et de décrypter une entête
de TAG Id3 en version 2.2 et 2.3
// 01>03= Constante soit dans tous les cas (ID3)
// 04>05= Version du TAG soit 2.(2/3.x)
// 06>06 Flags %ab000000 en 2.2 et %abc00000 en 2.3
// A=Bit de désynchronisation
// B=Bit de compression
// C=Bit d'utilisation expérimental
// 07->10=Taille du TAG (sans les 10 octets de l'entête )
// Chaque 7ème bit est décalé soit %0xxxxxxx %0xxxxxxx
%0xxxxxxx %0xxxxxxx
// Taille_TAG= (A<<21|B<<14|C<<7|D)+10)
// Déclarations
cNumFic est un entier
cTagDE est une gpEnteteTagId3v2
cBin8 est une chaîne fixe de 8
// Si l'ouverture du fichier est demandée
SI xOuvre ALORS
cNumFic = fOuvre(xFichier,foLecture)
SI cNumFic=-1 ALORS
GOTO LBFIN
FIN
xLigne = fLit(cNumFic,10)
fFerme(cNumFic)
FIN
// Check si l'entête est lisible
SI xLigne[[1 sur 3]]<>"ID3" ALORS
GOTO LBFIN
FIN
// Extraction des données
cTagDE:Tag=xLigne[[1 sur 3]]
cTagDE:VersionMajeur=Asc(xLigne[[4]])
cTagDE:VersionMineur=Asc(xLigne[[5]])
SELON cTagDE:VersionMajeur
CAS 2,3:
AUTRE CAS: GOTO LBFIN
FIN
cBin8=Zid3_C2Bin(xLigne[[6]])
cTagDE:BitDesynchro=Asc(cBin8[[1]])
cTagDE:BitCompression=Asc(cBin8[[2]])
SI cTagDE:VersionMajeur=3 ALORS
cTagDE:BitExperimental=Asc(cBin8[[3]])
FIN
cTagDE:TailleTag=ZId3_CalculTaille(xLigne[[7 sur 4]],4)
// Fin de traitement
LBFIN:
RENVOYER cTagDE
5) Décrypter l'entête Mpeg
PROCEDURE Zid3_DecrypteMpegHeader(xEnteteMpeg)
// Procédure permettante de decrypter l'entête Mpeg Audio
// Déclarations
cMpegDMH est une gpMpegAudioHeader
cBin1 est une chaîne fixe de 8
cBin2 est une chaîne fixe de 8
cBin3 est une chaîne fixe de 8
cBin4 est une chaîne fixe de 8
cBin4=Zid3_C2Bin(xEnteteMpeg[[1]])
cBin3=Zid3_C2Bin(xEnteteMpeg[[2]])
cBin2=Zid3_C2Bin(xEnteteMpeg[[3]])
cBin1=Zid3_C2Bin(xEnteteMpeg[[4]])
cMpegDMH:Emphasis=cBin1[[7 A 8]]
cMpegDMH:Original=cBin1[[6]]
cMpegDMH:Copyright=cBin1[[5]]
cMpegDMH:ModeExtension=cBin1[[3 A 4]]
cMpegDMH:ChannelMode=cBin1[[1 A 2]]
cMpegDMH:PrivateBit=cBin2[[8]]
cMpegDMH:PaddingBit=cBin2[[7]]
cMpegDMH:SamplingRate=cBin2[[5 A 6]]
cMpegDMH:Bitrate=cBin2[[1 A 4]]
cMpegDMH:ProtectionBit=cBin3[[8]]
cMpegDMH:Layer=cBin3[[6 A 7]]
cMpegDMH:MpegVersion=cBin3[[4 A 5]]
// Mode en clair
cMode est une chaîne
SELON cMpegDMH:ChannelMode
CAS "00": cMode="Stereo"
CAS "01": cMode="Joint stereo (Stereo)"
SELON cMpegDMH:ModeExtension
CAS "00":
CAS "01":
CAS "10":
CAS "11":
FIN
CAS "10": cMode="Dual channel (Stereo)"
CAS "11": cMode="Single channel (Mono)"
FIN
cMpegDMH:PMode=cMode
// Fréquence en clair
cFréquence est une chaîne
SELON cMpegDMH:SamplingRate
CAS "00":
SELON cMpegDMH:MpegVersion
CAS "00": cFréquence="11.025 kHz"
CAS "01": // Reserved
CAS "10": cFréquence="22.05 kHz"
CAS "11": cFréquence="44.1 kHz"
FIN
CAS "01":
SELON cMpegDMH:MpegVersion
CAS "00": cFréquence="12 kHz"
CAS "01": // Reserved
CAS "10": cFréquence="24 kHz"
CAS "11": cFréquence="48 kHz"
FIN
CAS "10":
SELON cMpegDMH:MpegVersion
CAS "00": cFréquence="8 kHz"
CAS "01": // Reserved
CAS "10": cFréquence="16 kHz"
CAS "11": cFréquence="32 kHz"
FIN
CAS "11": // Reserved
SELON cMpegDMH:MpegVersion
CAS "00":
CAS "01": // Reserved
CAS "10":
CAS "11":
FIN
FIN
cMpegDMH:PFréquence=cFréquence
// Compression en clair
cCompression est une chaîne
SELON cMpegDMH:MpegVersion
CAS "00": cCompression="MPEG-2.5"
CAS "01": // Reserved
CAS "10": cCompression="MPEG-2"
CAS "11": cCompression="MPEG-1"
FIN
SELON cMpegDMH:Layer
CAS "00": // Reserved
CAS "01": cCompression=cCompression+" Layer III"
CAS "10": cCompression=cCompression+" Layer II"
CAS "11": cCompression=cCompression+" Layer I"
FIN
cMpegDMH:PCompression=cCompression
// Bitrate en clair
cBitrate est une chaîne
SELON cMpegDMH:Bitrate
CAS "0000":
CAS "0001":
SELON cMpegDMH:MpegVersion
CAS "00","10":
SELON cMpegDMH:Layer
CAS "01": cBitrate=8
CAS "10": cBitrate=8
CAS "11": cBitrate=32
FIN
CAS "11":
SELON cMpegDMH:Layer
CAS "01": cBitrate=32
CAS "10": cBitrate=32
CAS "11": cBitrate=32
FIN
FIN
CAS "0010":
SELON cMpegDMH:MpegVersion
CAS "00","10":
SELON cMpegDMH:Layer
CAS "01": cBitrate=16
CAS "10": cBitrate=16
CAS "11": cBitrate=48
FIN
CAS "11":
SELON cMpegDMH:Layer
CAS "01": cBitrate=40
CAS "10": cBitrate=48
CAS "11": cBitrate=64
FIN
FIN
CAS "0011":
SELON cMpegDMH:MpegVersion
CAS "00","10":
SELON cMpegDMH:Layer
CAS "01": cBitrate=24
CAS "10": cBitrate=24
CAS "11": cBitrate=56
FIN
CAS "11":
SELON cMpegDMH:Layer
CAS "01": cBitrate=48
CAS "10": cBitrate=56
CAS "11": cBitrate=96
FIN
FIN
CAS "0100":
SELON cMpegDMH:MpegVersion
CAS "00","10":
SELON cMpegDMH:Layer
CAS "01": cBitrate=32
CAS "10": cBitrate=32
CAS "11": cBitrate=64
FIN
CAS "11":
SELON cMpegDMH:Layer
CAS "01": cBitrate=56
CAS "10": cBitrate=64
CAS "11": cBitrate=128
FIN
FIN
CAS "0101":
SELON cMpegDMH:MpegVersion
CAS "00","10":
SELON cMpegDMH:Layer
CAS "01": cBitrate=40
CAS "10": cBitrate=40
CAS "11": cBitrate=80
FIN
CAS "11":
SELON cMpegDMH:Layer
CAS "01": cBitrate=64
CAS "10": cBitrate=80
CAS "11": cBitrate=160
FIN
FIN
CAS "0110":
SELON cMpegDMH:MpegVersion
CAS "00","10":
SELON cMpegDMH:Layer
CAS "01": cBitrate=48
CAS "10": cBitrate=48
CAS "11": cBitrate=96
FIN
CAS "11":
SELON cMpegDMH:Layer
CAS "01": cBitrate=80
CAS "10": cBitrate=96
CAS "11": cBitrate=192
FIN
FIN
CAS "0111":
SELON cMpegDMH:MpegVersion
CAS "00","10":
SELON cMpegDMH:Layer
CAS "01": cBitrate=56
CAS "10": cBitrate=56
CAS "11": cBitrate=112
FIN
CAS "11":
SELON cMpegDMH:Layer
CAS "01": cBitrate=96
CAS "10": cBitrate=112
CAS "11": cBitrate=224
FIN
FIN
CAS "1000":
SELON cMpegDMH:MpegVersion
CAS "00","10":
SELON cMpegDMH:Layer
CAS "01": cBitrate=64
CAS "10": cBitrate=64
CAS "11": cBitrate=128
FIN
CAS "11":
SELON cMpegDMH:Layer
CAS "01": cBitrate=112
CAS "10": cBitrate=128
CAS "11": cBitrate=256
FIN
FIN
CAS "1001":
SELON cMpegDMH:MpegVersion
CAS "00","10":
SELON cMpegDMH:Layer
CAS "01": cBitrate=80
CAS "10": cBitrate=80
CAS "11": cBitrate=144
FIN
CAS "11":
SELON cMpegDMH:Layer
CAS "01": cBitrate=128
CAS "10": cBitrate=160
CAS "11": cBitrate=288
FIN
FIN
CAS "1010":
SELON cMpegDMH:MpegVersion
CAS "00","10":
SELON cMpegDMH:Layer
CAS "01": cBitrate=96
CAS "10": cBitrate=96
CAS "11": cBitrate=160
FIN
CAS "11":
SELON cMpegDMH:Layer
CAS "01": cBitrate=160
CAS "10": cBitrate=192
CAS "11": cBitrate=320
FIN
FIN
CAS "1011":
SELON cMpegDMH:MpegVersion
CAS "00","10":
SELON cMpegDMH:Layer
CAS "01": cBitrate=112
CAS "10": cBitrate=112
CAS "11": cBitrate=176
FIN
CAS "11":
SELON cMpegDMH:Layer
CAS "01": cBitrate=192
CAS "10": cBitrate=224
CAS "11": cBitrate=352
FIN
FIN
CAS "1100":
SELON cMpegDMH:MpegVersion
CAS "00","10":
SELON cMpegDMH:Layer
CAS "01": cBitrate=128
CAS "10": cBitrate=128
CAS "11": cBitrate=192
FIN
CAS "11":
SELON cMpegDMH:Layer
CAS "01": cBitrate=224
CAS "10": cBitrate=256
CAS "11": cBitrate=384
FIN
FIN
CAS "1101":
SELON cMpegDMH:MpegVersion
CAS "00","10":
SELON cMpegDMH:Layer
CAS "01": cBitrate=144
CAS "10": cBitrate=144
CAS "11": cBitrate=224
FIN
CAS "11":
SELON cMpegDMH:Layer
CAS "01": cBitrate=256
CAS "10": cBitrate=320
CAS "11": cBitrate=416
FIN
FIN
CAS "1110":
SELON cMpegDMH:MpegVersion
CAS "00","10":
SELON cMpegDMH:Layer
CAS "01": cBitrate=160
CAS "10": cBitrate=160
CAS "11": cBitrate=256
FIN
CAS "11":
SELON cMpegDMH:Layer
CAS "01": cBitrate=320
CAS "10": cBitrate=384
CAS "11": cBitrate=448
FIN
FIN
CAS "1111":
FIN
SI cBitrate<>"" ALORS
cMpegDMH:PBitrateC=cBitrate+ " kbit/s"
cMpegDMH:PBitrateN=cBitrate
FIN
RENVOYER cMpegDMH
6) Décoder les bits d'un octet
PROCEDURE Zid3_Bin2C(xBin)
// Conversion d'une chaine binaire au format %00000000 en 1 caractère
// Déclarations
cRes est une chaîne fixe sur 2
cCpt est un entier
BOUCLE
cCpt++
SELON Milieu(xBin,(4*(cCpt-1))+1,4)
CAS "0000":
cRes[[cCpt]]="0"
CAS "0001":
cRes[[cCpt]]="1"
CAS "0010":
cRes[[cCpt]]="2"
CAS "0011":
cRes[[cCpt]]="3"
CAS "0100":
cRes[[cCpt]]="4"
CAS "0101":
cRes[[cCpt]]="5"
CAS "0110":
cRes[[cCpt]]="6"
CAS "0111":
cRes[[cCpt]]="7"
CAS "1000":
cRes[[cCpt]]="8"
CAS "1001":
cRes[[cCpt]]="9"
CAS "1010":
cRes[[cCpt]]="A"
CAS "1011":
cRes[[cCpt]]="B"
CAS "1100":
cRes[[cCpt]]="C"
CAS "1101":
cRes[[cCpt]]="D"
CAS "1110":
cRes[[cCpt]]="E"
CAS "1111":
cRes[[cCpt]]="F"
FIN
SI cCpt=2 ALORS SORTIR
FIN
RENVOYER cRes
7) Codé un caractère en %
PROCEDURE Zid3_C2Bin(xCar)
// Procédure permettant de convertir un caractère en chaine binaire
%xxxxxxxx
// Déclarations
cCar est entier sur 1 octet sans signe=Asc(xCar)
cHexa est une chaîne fixe sur 2 = NumériqueVersChaine(cCar,"02X")
cRes est une chaîne fixe sur 8
cCpt est un entier
// Conversion du charactère en chaine binaire %00000000
BOUCLE
cCpt++
SELON cHexa[[cCpt]]
CAS 0:
cRes[[(4*(cCpt-1))+1 A (4*cCpt)]]="0000"
CAS 1:
cRes[[(4*(cCpt-1))+1 A (4*cCpt)]]="0001"
CAS 2:
cRes[[(4*(cCpt-1))+1 A (4*cCpt)]]="0010"
CAS 3:
cRes[[(4*(cCpt-1))+1 A (4*cCpt)]]="0011"
CAS 4:
cRes[[(4*(cCpt-1))+1 A (4*cCpt)]]="0100"
CAS 5:
cRes[[(4*(cCpt-1))+1 A (4*cCpt)]]="0101"
CAS 6:
cRes[[(4*(cCpt-1))+1 A (4*cCpt)]]="0110"
CAS 7:
cRes[[(4*(cCpt-1))+1 A (4*cCpt)]]="0111"
CAS 8:
cRes[[(4*(cCpt-1))+1 A (4*cCpt)]]="1000"
CAS 9:
cRes[[(4*(cCpt-1))+1 A (4*cCpt)]]="1001"
CAS "A":
cRes[[(4*(cCpt-1))+1 A (4*cCpt)]]="1010"
CAS "B":
cRes[[(4*(cCpt-1))+1 A (4*cCpt)]]="1011"
CAS "C":
cRes[[(4*(cCpt-1))+1 A (4*cCpt)]]="1100"
CAS "D":
cRes[[(4*(cCpt-1))+1 A (4*cCpt)]]="1101"
CAS "E":
cRes[[(4*(cCpt-1))+1 A (4*cCpt)]]="1110"
CAS "F":
cRes[[(4*(cCpt-1))+1 A (4*cCpt)]]="1111"
FIN
SI cCpt=2 ALORS SORTIR
FIN
RENVOYER cRes
8) Supprimer un tag 1.x
PROCEDURE Zid3_SupprimeTag1(xRepertoire, xNom, xChange, xplCompteur)
// Procédure permettant de supprimer le tag v1 d'un fichier mp3
// Déclarations
cUneligne est une chaîne
cNumFic est un entier
cPosition est un entier
// Chargement du fichier
cUneligne=fChargeTexte(xRepertoire+xNom)
cPosition=Taille(cUneligne)
// Recherche du tag id3v1
SI cPosition>(10+128+3) ALORS
SI cUneligne[[cPosition-127 A (cPosition-127+2)]]<>"TAG" ALORS
RENVOYER Faux
FIN
SINON
RENVOYER Faux
FIN
// Réecriture fichier
cNumFic=fOuvre(xRepertoire+xNom, foCréation+foEcriture)
SI cNumFic=-1 ALORS
RENVOYER Faux
FIN
fEcrit(cNumFic,cUneligne[[1 A cPosition-128]])
fFerme(cNumFic)
RENVOYER Vrai
9) Ajouter un Tag 1.x
PROCEDURE Zid3_AjouteTag1(xFichier,xRemplacer,xTag)
// Procédure permettant d'ajouter un tag v1 dans un fichier mp3
// Déclarations
cNumFic est un entier
cPosition est un entier
cModif est un booléen=Faux
// Ouverture du fichier
cNumFic=fOuvre(xFichier, foLectureEcriture)
SI cNumFic=-1 ALORS
GOTO LBFIN
FIN
// Recherche du tag existant
SI fPositionne(cNumFic,-128,fpFin)=-1 ALORS
GOTO LBFIN
FIN
SI fLit(cNumFic,3)="TAG" ALORS
SI xRemplacer=Faux ALORS
GOTO LBFIN
SINON
SI fPositionne(cNumFic,-128,fpFin)=-1 ALORS
GOTO LBFIN
FIN
FIN
SINON
SI fPositionne(cNumFic,0,fpFin)=-1 ALORS
GOTO LBFIN
FIN
FIN
fEcrit(cNumFic,xTag)
cModif=Vrai
LBFIN:
fFerme(cNumFic)
RENVOYER cModif
10) Base de travail pour l'extraction des tags (non finie sur la gestion des trames)
PROCEDURE Zid3_ExtraireTag(xRepertoire, xNom, xChange, xplCompteur)
// Procédure permettant d'extraire les informations Id3 d'un fichier
// Déclarations
cNumFic est un entier
cOffset est un entier
cDurée est un entier
cLigne est une chaîne
cData est une chaîne
cFichier est une chaîne=xRepertoire+xNom
cFlagv1 est un booléen=Faux
cFlagv2 est un booléen=Faux
// Structures pour la manipulation des id3
cTagERD est une gpTagId3
cEnteteERD est une gpEnteteTagId3v2
cMpegERD est une gpMpegAudioHeader
cTrame22 est une gpTrameId3v22
cTrame23 est une gpTrameId3v23
// -------------------------------------------------------------------------------------------------------------------------------------------
// Ouverture du fichier
// -------------------------------------------------------------------------------------------------------------------------------------------
// Ouverture du fichier
cNumFic=fOuvre(cFichier,foLecture)
SI cNumFic=-1 ALORS
EcritMessage(gcThreadId3,"Impossible d'ouvrir le fichier "+cFichier)
GOTO LBFIN
FIN
// Initialisation de l'offset
cOffset=1
// Extraction de la taille du fichier
cTagERD:TailleFichier=fTaille(cFichier)/(1024*1024)
// Nom du fichier
cTagERD:Fichier=cFichier
// -------------------------------------------------------------------------------------------------------------------------------------------
// TAG[1] --> Lecture du tag (128 derniers octets du fichier mp3)
// -------------------------------------------------------------------------------------------------------------------------------------------
// Positionnement à -128
SI fPositionne(cNumFic,-128,fpFin)=-1 ALORS
EcritMessage(gcThreadId3,"Erreur de positionnement %-128% (T1) pour "+cFichier)
GOTO LBFIN
FIN
// Lecture des données
cLigne=fLit(cNumFic,128)
// Check si la chaine extraite est bien un tag en version 1.x
SI cLigne[[1 sur 3]]="TAG" ALORS
// Activation du flag
cFlagv1=Vrai
// Informations générales
SELON Asc(cLigne[[126]])
CAS 0:
cTagERD:Version=11
cTagERD:Titre=cLigne[[4 A 33]]
cTagERD:Artiste=cLigne[[34 A 63]]
cTagERD:Album=cLigne[[64 A 93]]
cTagERD:Année=cLigne[[94 A 97]]
cTagERD:Commentaire=cLigne[[98 A 125]]
cTagERD:Piste=Asc(cLigne[[127]])
SI Val(cTagERD:Piste)>99 ALORS
cTagERD:Piste=0
FIN
AUTRE CAS:
cTagERD:Version=10
cTagERD:Titre=cLigne[[4 A 33]]
cTagERD:Artiste=cLigne[[34 A 63]]
cTagERD:Album=cLigne[[64 A 93]]
cTagERD:Année=cLigne[[94 A 97]]
cTagERD:Commentaire=cLigne[[98 A 127]]
FIN
// Conversion du genre
cTagERD:Genre=Zid3_RetourneGenre(cLigne[[128]])
FIN
// -------------------------------------------------------------------------------------------------------------------------------------------
// TAG[2.x] --> Lecture de l'entête (10 premiers octets du fichier)
// -------------------------------------------------------------------------------------------------------------------------------------------
// Positionnement au début du fichier
SI fPositionne(cNumFic,0,fpDébut)=-1 ALORS
EcritMessage(gcThreadId3,"Erreur de positionnement %+0% (T2) pour "+cFichier)
GOTO LBFIN
FIN
// Lecture des 10 premiers octets
cLigne=fLit(cNumFic,10)
SI CLigne="" ALORS
EcritMessage(gcThreadId3,"Format de fichier non reconnu pour "+cFichier)
GOTO LBFIN
FIN
// La présence du tag est indiqué par <ID3> dans les 3
premiers octets
SI cLigne[[1 sur 3]]="ID3" ALORS
// Décryptage de l'entête de Tag
cEnteteERD=Zid3_DecrypteEntete(cFichier,Faux,cLigne)
// On ne traite pas le tag si le bit expérimental est à 1
SI cEnteteERD:BitExperimental=1 ALORS
EcritMessage(gcThreadId3,"Flag expérimental activé pour "+cFichier)
GOTO LBFIN
FIN
// Mise à jour les infos sur le numéro de version du tag sa taille
cTagERD:Version=20+cEnteteERD:VersionMajeur+(cEnteteERD:VersionMineur/10)
cTagERD:TailleTag=cEnteteERD:TailleTag
// Activation du flag
SI cTagERD:Version>20 ALORS
cFlagv2=Vrai
FIN
FIN
// -------------------------------------------------------------------------------------------------------------------------------------------
// TAG[2.x] --> Extraction des trames ( base de travail, à compléter
)
// -------------------------------------------------------------------------------------------------------------------------------------------
// Si le tag 2.x existe
SI cFlagv2=Vrai ALORS
// La taille d'un tag normal ne devant pas exéceder 1 ou 2Ko on le lit
d'un coup
cLigne=fLit(cNumFic,cTagERD:TailleTag)
// Boucle tant qu'il y a des trames à lire
BOUCLE
// Si la ligne n'est pas valide
SI cLigne="" ALORS SORTIR
// Si l'offset est hors secteur
SI cOffset>=cTagERD:TailleTag ALORS SORTIR
// Selon la version du tag l'entête de trame n'est pas la même
SELON cTagERD:Version
// Cas du Tag en version 2.2 -> l'entête de trame fait 6 octets
CAS 22:
cTrame22:Nom=cLigne[[cOffset sur 3]]
cOffset+=3
cTrame22:TailleTrame=Zid3_CalculTaille(cLigne[[cOffset sur 3]],3)
SI cTrame22:TailleTrame=0 ALORS SORTIR
cOffset+=3
cData=cLigne[[cOffset A (cOffset+cTrame22:TailleTrame-1)]]
SI cTrame22:TailleTrame>1 ALORS
cData=Droite(cData,Taille(cData)-Position(cData,Caract(0x00),DepuisFin))
FIN
cOffset+=cTrame22:TailleTrame
// Cas du Tag en version 2.3 -> l'entête de trame fait 10 octets
CAS 23:
cTrame23:Nom=cLigne[[cOffset sur 4]]
cOffset+=4
cTrame23:TailleTrame=Zid3_CalculTaille(cLigne[[cOffset sur 4]],4)
SI cTrame23:TailleTrame=0 ALORS SORTIR
cOffset+=(4+2)
cData=cLigne[[cOffset A (cOffset+cTrame23:TailleTrame-1)]]
SI cTrame23:TailleTrame>1 ALORS
cData=Droite(cData,Taille(cData)-Position(cData,Caract(0x00),DepuisFin))
FIN
cOffset+=cTrame23:TailleTrame
FIN
FIN
FIN
// -------------------------------------------------------------------------------------------------------------------------------------------
// MPEG[H] --> Lecture de l'entête Mpeg Audio pour la 1ère frame
(les 4 octets qui suivent le tag 2)
// Attention :
// On n'a pas forcément de Tag [2] dans un fichier mp3...
// Un fichier Mpeg n'a pas forcément qu'une seule frame (normalement
1 mp3 en bitrate fixe-->1)
// -------------------------------------------------------------------------------------------------------------------------------------------
// Positionnement sur le fichier : dépend si un Tag [2] est présent
ou non
SI cFlagv2=Vrai ALORS
SI fPositionne(cNumFic,cTagERD:TailleTag+10,fpDébut)=-1 ALORS
EcritMessage(gcThreadId3,"Erreur de positionnement %+10% (Mpeg Audio) pour
"+cFichier)
GOTO LBFIN
FIN
SINON
SI fPositionne(cNumFic,0,fpDébut)=-1 ALORS
EcritMessage(gcThreadId3,"Erreur de positionnement %+T% (Mpeg Audio) pour
"+cFichier)
GOTO LBFIN
FIN
FIN
// Lecture des 4 octets de l'entête Mpeg
cLigne=fLit(cNumFic,4)
SI cLigne="" ALORS
EcritMessage(gcThreadId3,"Format d'entête Mpeg Audio non reconnue
pour "+cFichier)
GOTO LBFIN
FIN
fFerme(cNumFic)
// Décryptage de l'entête
cMpegERD=Zid3_DecrypteMpegHeader(cLigne)
cTagERD:Compression=cMpegERD:PCompression
cTagERD:Bitrate=cMpegERD:PBitrateC
cTagERD:Fréquence=cMpegERD:PFréquence
cTagERD:Mode=cMpegERD:PMode
// Extraction de la durée du fichier
// Le calcul dépend si on est un bitrate fixe ou variable
// Birate fixe avec Tag [1] = 8* [TailleFichier-128-TailleTag[2]-10 ] / BitRate
// Birate fixe sans Tag [1] = 8* [TailleFichier-TailleTag[2]-10 ] / BitRate
// Bitrate variable = Faire la somme pour chaque frame
SI cMpegERD:PBitrateN<>0
SI cFlagv1 ALORS
cDurée=8*((cTagERD:TailleFichier*1024*1024)-128-cTagERD:TailleTag-10)/cMpegERD:PBitrateN
SINON
cDurée=8*((cTagERD:TailleFichier*1024*1024)-cTagERD:TailleTag-10)/cMpegERD:PBitrateN
FIN
cTagERD:Durée..Heure=modulo(PartieEntière(cDurée/(1000*60*60)),60)
cTagERD:Durée..Minute=modulo(PartieEntière(cDurée/(1000*60)),60)
cTagERD:Durée..Seconde=modulo(PartieEntière(cDurée/(1000)),60)
cTagERD:Durée..Milliseconde=PartieDécimale(cDurée/(1000))*1000
FIN
// -------------------------------------------------------------------------------------------------------------------------------------------
// FIN --> Ajout d'une ligne dans la zone mémoire
// -------------------------------------------------------------------------------------------------------------------------------------------
// Complémentation automatique des zones si gAutoId3v1 et pas de Tag
en version 2.x
SI cTagERD:Version<20 ET gAutoId3v1=1 ET cFlagv1=Vrai ALORS
cTagERD:Compression=gLayer
cTagERD:Bitrate=gBitrate
cTagERD:Fréquence=gFrequency
cTagERD:Mode=gMode
FIN
cLigne=...
SansEspace(cTagERD:Artiste)+TAB+...
SansEspace(cTagERD:Titre)+TAB+...
SansEspace(cTagERD:Album)+TAB+...
SansEspace(cTagERD:TailleFichier)+TAB+...
SansEspace(cTagERD:Année)+TAB+...
SansEspace(cTagERD:Piste)+TAB+...
SansEspace(cTagERD:Genre)+TAB+...
""+TAB+... // Note
SansEspace(cTagERD:Commentaire)+TAB+...
SansEspace(cTagERD:Durée)+TAB+...
SansEspace(cTagERD:Compression)+TAB+...
SansEspace(cTagERD:Bitrate)+TAB+...
SansEspace(cTagERD:Fréquence)+TAB+...
SansEspace(cTagERD:Mode)+TAB+...
""+TAB+... // Site web
SansEspace(cFichier)+TAB+...
SansEspace(xNom)+TAB+...
ComplèteRep(xRepertoire)+TAB+...
cTagERD:Version/10
MemAjoute(gcThreadId3_F,MemOccurrence(gcThreadId3_F)+1,cLigne)
// -------------------------------------------------------------------------------------------------------------------------------------------
// Fin du traitement
SI cTagERD:Version=0 ALORS
EcritMessage(gcThreadId3,"Pas d'informations Id3 dans le fichier "+cFichier)
FIN
LBFIN:
fFerme(cNumFic)