Compact Disc Audio track

.cda est une extension de nom de fichier désignant un petit fichier conforme à la spécification RIFF Le format de fichier CDA est un format Microsoft, .

Les fichiers CDA (Compact Disc Audio) sont générés par Windows lorsque ce système d'exploitation accède à un CD Audio. Chaque titre du CD Audio est alors vu comme un fichier de 44 octets, et d'extension ".cda". Les fichiers sont nommés "Track01.cda", "Track02.cda", etc.

Le fichier .cda copié sur l'ordinateur est inutile sans le CD, puisqu'il ne s'agit que d'un raccourci vers le CD. Les fichiers .cda ne contiennent pas les données sonores, mais indiquent où commence et s'arrête chaque piste sur le disque. Si le fichier est "copié" du CD vers un ordinateur, il ne peut pas être utilisé seul car il ne s'agit que d'un raccourci vers une partie du disque. Toutefois, certains programmes d'édition audio et de création de CD chargeront, du point de vue de l'utilisateur, les fichiers .cda comme s'il s'agissait de véritables fichiers de données audio, et permettront à l'utilisateur de les écouter.

Organisation d'un fichier CDA

modifier
offset longueur contenu
0x00 4 les 4 caractères ASCII "RIFF"
0x04 4 la taille du chunk suivant : toujours 36 (44 - 8), sur 4 octets (ordre Intel)
0x08 4 identifiant du chunk : les 4 caractères ASCII "CDDA"
0x0C 4 les 3 caractères ASCII "fmt" suivi d'un espace :
0x10 4 longueur du chunk : toujours 24, sur 4 octets (ordre Intel)
0x14 2 version du format CD, sur 2 octets (ordre Intel). En , vaut toujours 1.
0x016 2 numéro de la plage, sur 2 octets (ordre Intel). La première plage a le numéro 1.
0x18 4 identifiant calculé par Windows pour cdplayer.exe.
0x1c 4 offset de la plage, en nombre de frames (ordre Intel)
0x20 4 durée de la plage, en nombre de frames (ordre Intel)
0x24 1 position de la plage : frames
0x25 1 position de la plage : secondes
0x26 1 position de la plage : minutes
0x27 1 un octet nul (valeur binaire 0)
0x28 1 durée de la plage : frames
0x29 1 durée de la plage : secondes
0x2a 1 durée de la plage : minutes
0x2b 1 un octet nul (valeur binaire 0)

La taille d'un fichier CDA étant fixe, ainsi que son organisation, il n'y a toujours qu'un seul et unique chunk, nommé "CDDA" (signifiant Compact Disc for Digital Audio).

L'identifiant créé par Windows est utilisé par le lecteur de CD de Windows 95 et Windows 98 (cdplayer.exe). Ce lecteur ne sait pas se connecter à FreeDB ou CDDB. Pour qu'il puisse afficher le nom de l'artiste et le titre des morceaux, il faut entrer manuellement ces informations dans le fichier cdplayer.ini (dans le répertoire d'installation de Windows), dans une section nommée d'après cet identifiant. Cet identifiant n'a aucun rapport avec le DiscId utilisé par FreeDB ou CDDB, c'est une création purement Microsoft, pour l'usage précité.

La position et la longueur des plages utilisent des frames comme unité. Il y a 75 frames par seconde. C'est le plus petit bloc de données qui peut être lu depuis un CD audio, correspondant à un secteur du CD.

Toutes les informations qui nécessitent plusieurs octets sont codées avec l'order-byte Intel (petit boutiste).

Exemple d'analyse d'un fichier CDA, en Perl

modifier

Le programme de démonstration fourni est un script Perl. Il faut lancer le script avec un paramètre : le chemin vers le répertoire ou le disque contenant les fichiers CDA.

#! /bin/perl -w 
 
use strict;

my $path_cda;	# chemin vers les CDA (paramètre du script)
my $data_cda;	# contenu d'un fichier CDA
my @liste_cda;	# la liste des fichiers CDA du répertoire
my $fic_cda;	# le nom du fichier CDA courant
my $mins;
my $secs;
my $frames;

# tester qu'un argument a été fourni 
$path_cda = shift;
die("argument: le nom du répertoire") if (!defined($path_cda));

# ouvrir, lire, puis refermer le fichier CDA 
opendir(DIR_CDA, $path_cda) or die ("impossible d'ouvrir le répertoire $path_cda");
@liste_cda = grep /.*cda$/i, readdir(DIR_CDA);
closedir(DIR_CDA);

print "plage début   durée   début                  durée\n";
print "      frames  frames  min:sec:frm            min:sec:frm\n";
foreach $fic_cda (@liste_cda)
{
    # charger le contenu du fichier CDA dans une variable
    open(CDA,  "<:raw", $path_cda.$fic_cda) or die("impossible d'ouvrir le fichier $fic_cda");
    $data_cda = <CDA>;
    close(CDA);
    
    # vérifier la taille du fichier, et le header
    die "taille invalide" if (length($data_cda) != 44);
    die "entête invalide" if (substr($data_cda, 0, 0x0f) ne "RIFF\$\x00\x00\x00CDDAfmt");
    
    # afficher le numéro de la plage
    printf sprintf("%02d    ", ord(substr($data_cda, 0x16, 1)));
    
    # afficher les informations sur la plage : position en frames
    $frames = unpack("V", substr($data_cda, 0x1c, 4));
    printf sprintf("%06d  ", $frames);
    
    # afficher les informations sur la plage : durée en frames
    $frames = unpack("V", substr($data_cda, 0x20, 4));
    printf sprintf("%06d  ", $frames);
    
    # afficher les informations sur la plage : position min:sec:frames
    ($frames, $secs, $mins) = unpack("CCC", substr($data_cda, 0x24, 3));
    printf sprintf("%02d:%02d:%02d = %06d frm  ", $mins, $secs, $frames, ((($mins * 60) + $secs) * 75) + $frames);
    
    # afficher les informations sur la plage : durée min:sec:frames
    ($frames, $secs, $mins) = unpack("CCC", substr($data_cda, 0x28, 3));
    printf sprintf("%02d:%02d:%02d = %06d frm", $mins, $secs, $frames, ((($mins * 60) + $secs) * 75) + $frames);
    
    print "\n";
}

Dans les colonnes affichant la position et la durée au format minutes:secondes:frames, le script ajoute le nombre de frames équivalent à cette durée. La position dans les deux systèmes devrait être identique. Dans la pratique on observe pourtant une différence de 150 frames, correspondant aux 2 secondes de prégap (voir le Red Book).

Résultats du script

modifier

Le script ci-dessus a été lancé sur l'album « Some Great Reward » du groupe Depeche Mode. Les résultats sont recopiés ci-dessous, une colonne « durée pochette » contenant la durée indiquée sur la pochette a été ajoutée.

plage début   durée   début                  durée                   durée pochette
      frames  frames  min:sec:frm            min:sec:frm
01    000032  017015  00:02:32 = 000182 frm  03:46:65 = 017015 frm   3:46
02    017047  022780  03:49:22 = 017197 frm  05:03:55 = 022780 frm   5:03
03    039827  017398  08:53:02 = 039977 frm  03:51:73 = 017398 frm   3:51
04    057225  021387  12:45:00 = 057375 frm  04:45:12 = 021387 frm   4:45
05    078612  014570  17:30:12 = 078762 frm  03:14:20 = 014570 frm   3:14
06    093182  020045  20:44:32 = 093332 frm  04:27:20 = 020045 frm   4:27
07    113227  018970  25:11:52 = 113377 frm  04:12:70 = 018970 frm   4:12
08    132197  021068  29:24:47 = 132347 frm  04:40:68 = 021068 frm   4:40
09    153265  028952  34:05:40 = 153415 frm  06:26:02 = 028952 frm   6:26

On retrouve la différence de deux secondes entre les deux champs « position ».
La durée affichée par une platine CD ou par les logiciels de lecture peut être :

  • la durée indiquée dans le fichier CDA, le nombre de frames ayant été ignoré
  • la durée indiquée dans le fichier CDA, avec arrondi à la seconde la plus proche.