I. Introduction▲
Je développe depuis 2005 maintenant un éditeur de tag gratuit du nom de MetatOGGerSite officiel de MetatOGGer. Comme son nom l'indique, il a été conçu à la base pour prendre en charge les fichiers Ogg et contribuer ainsi aux efforts de la fondation XiphSite officiel de la fondation Xiph visant à développer un ensemble de briques multimédias gratuites et exempt de brevet (codec, conteneur, etc.). Le support des fichiers MP3 (tags ID3), Musepack, Windows Media, WavPack et Monkey's Audio a été ajouté par la suite. En fait, n'importe quel format peut être ajouté par le biais de plugin.
MetatOGGer est développé en C# (l'interface utilise l'API WPF depuis la version 3). Il me fallait
donc une librairie .NET pour gérer les tags au format Vorbis Comment des fichiers Ogg. Ne trouvant
pas ce qu'il me fallait sur internet, j'ai décidé de développer ma propre librairie.
II. Un peu de théorie▲
II-A. Le format de tags des fichiers Ogg et FLAC natifs : Vorbis Comment▲
Les tags des fichiers Ogg (Vorbis, FLAC et Speex), ainsi que des fichiers FLAC natifs sont stockés au format Vorbis Comment. Les spécifications(1) de ce format sont disponibles iciSpécifications du format Vorbis Comment. Chaque tag au format Vorbis Comment est composé d'une paire clef-valeur sous la forme "TAG_NAME=Tag Value". La clef est une chaîne de caractère codée en ASCII (à l'exception du caractère "=", exclu car il sert à délimiter le nom du tag de sa valeur) et insensible à la casse (même si le nom du tag est souvent formaté en majuscule par convention). La valeur du tag est une chaîne de caractère codée en UTF8.
Le format Vorbis Comment définit quinze tags standards :
Nom du tag | Description |
---|---|
TITLE | Le titre du morceau |
VERSION | Permet de distinguer plusieurs versions d'un même morceau : remix, live, etc. |
ALBUM | Le titre de l'album |
TRACKNUMBER | Le numéro de piste dans un album |
ARTIST | Le nom de l'artiste ou de l'auteur |
PERFORMER | Le nom de l'interprète, orchestre, etc. |
COPYRIGHT | Les informations de copyright |
LICENSE | La licence applicable au morceau : Creative Commons, tous droits réservés, etc. |
ORGANIZATION | Organisation ayant produit le morceau comme le nom de la maison de disque |
DESCRIPTION | Une description ou un commentaire quelconque sur le contenu |
GENRE | Le genre du morceau : rock, pop, etc. |
DATE | La date ou l'année d'enregistrement du morceau |
LOCATION | Le lieu où le morceau a été enregistré |
CONTACT | Une information de contact de l'auteur ou du distributeur |
ISRC | Numéro ISRC du morceau |
Au-delà de ces tags standards, tout tag arbitraire peut bien évidemment être ajouté. Le risque étant
que les lecteurs audio ne sachent comment interpréter ces tags non standards.
Les tags Vorbis Comment peuvent être définis un nombre de fois illimité. Par exemple, il est tout à fait possible de définir plusieurs fois le tag ARTIST : "ARTIST=John Lennon" et "ARTIST=Paul McCartney".
II-B. Le support des tags binaires▲
Le standard Vorbis Comment ne prévoit pas le stockage de contenu autre que textuel. Ceci est problématique pour le stockage de contenu binaire comme les images.
Le développeur du codec FLAC ayant souhaité ajouter le support des images dans son format, il a prévu la possibilité d'ajouter un "bloc image" comparable à la frame APICSpécifications id3v2.4 du standard ID3v2 du format MP3.
III. L'implémentation du standard Vorbis Comment▲
Les deux classes principales de la librairie sont les classes OggTagger et FlacTagger. Elles permettent respectivement la lecture des informations dans les fichiers Ogg (.ogg, .oga) et FLAC natifs (.flac, .fla).
III-A. La lecture des tags textuels▲
Le constructeur des classes OggTagger et FlacTagger prend en paramètre une chaîne de caractère correspondant au chemin du fichier. Les tags du fichier sont alors immédiatement lus.
Il est possible de forcer la lecture des tags d'un autre fichier sans avoir à instancier un nouvel objet en utilisant la méthode ReadMetadata.
OggTagger ogg =
new
OggTagger
(
@"C:\Song.ogg"
);
ogg.
ReadMetadata
(
@"C:\Song2.ogg"
);
Les tags sont stockés dans un objet de type SortedList<string, List<string>> pour gérer
les tags multiples. Il est possible de récupérer l'intégralité des tags du fichier avec la méthode
GetAllTags.
string
artist =
ogg.
Artist;
// == tags["ARTIST"][0] || null
ReadOnlyCollection<
string
>
artists =
tags[
"ARTIST"
];
ogg.
Title =
"My Immortal"
;
ogg.
AddTag
(
"LYRICS"
,
"I am singing in the rain..."
);
ogg.
SetTag
(
"LYRICS"
,
"I am not singing in the rain..."
);
ogg.
RemoveTag
(
"LYRICS"
);
Pour enregistrer les tags dans le fichier, il suffit d'appeler la méthode SaveMetadata.
ogg.
SaveMetadata
(
);
III-B. La prise en charge des tags "images"▲
Les tags "images" ne sont prises en charge que dans les fichiers Ogg FLAC ou FLAC natifs. Les images sont encapsulées dans des objets de type System.Windows.Media.Imaging.BitmapFrame (classe disponible dans l'assemblage PresentationCore.dll de l'API WPF).
OggTagger ogg =
new
OggTagger
(
@"C:\SongFLAC.ogg"
);
Collection<
ID3PictureFrame>
arts =
ogg.
FlacArts;
BitmapFrame cover =
null
;
foreach
(
ID3PictureFrame picture in
arts)
{
if
(
picture.
PictureType ==
ID3PictureType.
FrontCover)
cover =
picture.
Picture;
}
III-C. Le lecture des informations techniques▲
La librairie ne se limite pas à l'accès aux tags mais permet de récupérer de nombreuses informations techniques sur les fichiers.
Voici la liste des informations auxquelles la classe OggTagger permet d'accéder :
Propriétés | Type de retour | Commentaire |
---|---|---|
Codec | OggCodec (énumération) | Codec du fichier Ogg : Vorbis, Speex ou FLAC |
SpeexBand | SpeexBand (énumération) | Largeur de bande utilisée pour le fichier Speex : Narrowband (8 000 Hz), WideBand (16 000 Hz) ou UltraWideband (32 000 Hz) |
Channels | byte | Nombre de canaux |
MinimumVorbisBitrate | int | Bitrate minimum du fichier Ogg Vorbis |
SampleRate | int | Taux d'échantillonnage |
MaximumVorbisBitrate | int | Bitrate maximum du fichier Ogg Vorbis |
VorbisSpeexNominalBitrate | int | Bitrate nominal du fichier Ogg Vorbis et Speex |
IsVariableBitrate | bool | Indique si le fichier est encodé en débit variable |
VorbisQuality | float | Niveau de qualité du fichier Ogg Vorbis, de 0 (64 kb/s) à 1 (500 kb/s) |
CodecVersion | string | Version du codec utilisé |
Samples | long | Nombre d'échantillons |
Duration | float | Durée du morceau en secondes |
AverageBitrate | int | Débit moyen calculé |
Ratio | float | Taux de compression du fichier |
FlacBitsPerSample | byte | Taille de l'échantillon du fichier Ogg Flac |
UncompressedFileLength | long | Taille calculé du fichier sans compression |
Voici la liste des informations auxquelles la classe FlacTagger permet d'accéder :
Propriétés | Type de retour | Commentaire |
---|---|---|
Channels | byte | Nombre de canaux |
SampleRate | int | Taux d'échantillonnage |
CodecVersion | string | Version du codec utilisé |
Samples | long | Nombre d'échantillons |
Duration | float | Durée du morceau en secondes |
AverageBitrate | int | Débit moyen calculé |
Ratio | float | Taux de compression du fichier |
BitsPerSample | byte | Taille de l'échantillon |
UncompressedFileLength | long | Taille calculée du fichier sans compression |
III-D. La gestion du bloc "padding" dans les fichiers FLAC natifs▲
Les tags Vorbis Comment sont enregistrés au début du fichier ce qui suppose la réécriture complète du fichier en cas de modification. Toutefois, les développeurs du format FLAC ont prévu la possibilité d'insérer un bloc "padding" au début de fichier pour servir de variable d'ajustement pour l'écriture des métadonnées. Ainsi, ce bloc peut être réduit pour laisser plus de place aux tags ou au contraire agrandit pour prendre la place des tags supprimés. Il est alors possible d'éviter la longue reconstruction du fichier, très lente dans le cas du FLAC, un format de compression sans perte dont les fichiers font souvent plusieurs dizaines de mégaoctets par morceaux.
La librairie gère le bloc "padding". Par défaut, ce bloc servira donc autant que faire se peut de variable d'ajustement pour accélérer la sauvegarde des modifications sur les tags. Il est toutefois possible de placer la propriété OptimizeFileSizeWhenSaving à vraie, ce qui aura pour effet de mettre la taille du bloc "padding" à 0 et de récupérer l'espace disque éventuellement laissé vacant par la suppression des tags.
Lorsque que la reconstruction du fichier est nécessaire parce que la taille du bloc "padding" n'est pas suffisante pour enregistrer les tags, ou lorsque la propriété OptimizeFileSizeWhenSaving est vraie, le développeur a la possibilité d'indiquer la taille du bloc "padding" qu'il souhaite voir insérer dans le fichier à l'occasion de sa reconstruction. Pour cela, il convient de définir la propriété DesiredPaddingSize (la valeur par défaut est fixée à 4 Ko).
III-E. Diagrammes des classes OggTagger et FlacTagger▲
IV. Exemple d'utilisation de la librairie▲
Le code source de la librairie est livré avec un projet WPF montrant comment utiliser la classe FlacTagger dans le cadre d'une application cliente.
Après avoir choisi un fichier FLAC en cliquant sur l'unique bouton, un objet FlacTagger est instancié et passé à la propriété DataContext de ma fenêtre WPF.
OpenFileDialog open =
new
OpenFileDialog
(
);
open.
Filter =
"Fichiers FLAC (*.flac)|*.flac"
;
if
(!
open.
ShowDialog
(
).
Value) return
;
FlacTagger flac =
new
FlacTagger
(
open.
FileName);
DataContext =
flac;
Il suffit ensuite d'utiliser les capacités avancées de Data Binding de WPF pour récupérer les valeurs
des tags côté interface.
<TextBlock
Text
=
"{Binding Artist}"
/>
<TextBlock
Text
=
"{Binding Title}"
Grid.
Row
=
"1"
/>
<TextBlock
Text
=
"{Binding Album}"
Grid.
Row
=
"2"
/>
<TextBlock
Text
=
"{Binding TrackNumber}"
Grid.
Row
=
"3"
/>
<TextBlock
Text
=
"{Binding Genre}"
Grid.
Row
=
"4"
/>
<TextBlock
Text
=
"{Binding Date}"
Grid.
Row
=
"5"
/>
<Image
Source
=
"{Binding Arts[0].Picture}"
MaxWidth
=
"{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Source.PixelWidth}"
MaxHeight
=
"{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Source.PixelHeight}"
Stretch
=
"Uniform"
Grid.
Row
=
"6"
Grid.
Column
=
"1"
/>
Voici le code XAML pour "binder" les informations techniques du fichier FLAC. Remarquez l'utilisation
de la propriété StringFormat de la classe Binding (disponible dans le Framework .NET 3.5 SP1) pour
formater la chaîne.
<TextBlock
Text
=
"{Binding Channels}"
/>
<TextBlock
Text
=
"{Binding SampleRate, StringFormat={}{0:N0} Hertz}"
Grid.
Row
=
"1"
/>
<TextBlock
Text
=
"{Binding CodecVersion, StringFormat={}FLAC {0}}"
Grid.
Row
=
"2"
/>
<TextBlock
Text
=
"{Binding Duration, StringFormat={}{0:N0} secondes}"
Grid.
Row
=
"3"
/>
<TextBlock
Text
=
"{Binding AverageBitrate, StringFormat={}{0:N0} bits par seconde}"
Grid.
Row
=
"4"
/>
<TextBlock
Text
=
"{Binding Ratio, StringFormat={}{0:P}}"
Grid.
Row
=
"5"
/>
<TextBlock
Text
=
"{Binding BitsPerSample, StringFormat={}{0} bits}"
Grid.
Row
=
"6"
/>
V. Téléchargements et liens▲
Codes sources de l'assemblage Luminescence.XiphCodes sources de l'assemblage Luminescence.Xiph
Site officiel Luminescence SoftwareSite officiel Luminescence Software
VI. Conclusions▲
La librairie Luminescence.Xiph permet d'accéder facilement aux tags des fichiers Ogg et FLAC natifs. Le code est entièrement documenté et livré avec une batterie de tests unitaires. Les sources sont sous LGPL, ce qui permet à l'assemblage d'être utilisé dans des applications propriétaires.
VII. Remerciements▲
Je remercie l'équipe .NET pour leurs relectures de ce document.