Table of content d'un CD audio

La TOC, ou Table of Content (table des matières) est le nom d'une zone de données située au début de chaque CD Audio. La TOC contient la liste des plages du CD. Si le CD est multi-sessions, chaque session possède une TOC. Une session est composée du lead-in, de la program area, et du lead-out (qui doit contenir au moins 90 secondes de silence).

La TOC d'un CD Audio joue le même rôle que le répertoire racine d'un disque dur conventionnel. Les différences sont les suivantes :

  • Le nombre d'entrées, donc de titres, est limité.
  • les plages ne sont pas nommées, le CD Audio ne contient donc pas les titres des plages.
  • la TOC contient l'offset de chaque plage à partir du début du CD, mais pas leur longueur qui doit être calculée.
  • pas de notion de sous-répertoires.

Une TOC est dimensionnée pour contenir le numéro et la position de 100 plages. Physiquement la TOC se situe dans le lead-in, donc au début du CD (diamètre 23 mm à diamètre 25 mm). Les plages doivent être numérotées incrémentalement, mais rien n'oblige de commencer à la plage 1. Ainsi, dans le cas d'un coffret de 2 CD, si le premier contient 10 plages, il est possible de commencer la numérotation du deuxième CD à 11. Pour être sûr d'être compatible avec tous les lecteurs du marché, il est cependant recommandé de commencer à 1.

La structure de la TOC ainsi que la limite sur le nombre de plages sont définis par le Red Book.

Structure de la TOC modifier

La TOC est composée de deux types d'informations :

  • information sur le disque : longueur de la TOC, numéros de la première et de la dernière plage
  • informations sur les plages musicales

La TOC contient les informations sur 100 plages : les 99 plages musicales autorisées sur un CD Audio, et le lead-out.

Lors de l'implémentation logicielle des deux structures décrites après, le compilateur ne doit pas ajouter d'octet de padding pour aligner les champs. Avec GCC il faut utiliser l'option PACKED.

Structure de l'information sur une plage modifier

Cette structure d'une taille de 8 octets est connue sous le nom de TOCTRACK.

  • Reserved1 : 1 octet
  • ADR : 1 octet. Si le bit 2 est à 1, alors il s'agit d'une plage DATA
  • Track : 1 octet pour le numéro de la plage. Si ce numéro vaut 0xAA, alors cette plage est le lead-out
  • Reserved2 : 1 octet
  • Addr : 4 octets pour la position de la plage

Le contenu de Addr peut être au format MSF ou au format LBA :

  • le format MSF : Minute/Second/Frame. Dans ce cas min=Addr[1], sec=Addr[2], fr=Addr[3] (champ 0 inutilisé)
  • Le format LBA : Logical Block Adressing. Addr donne la position absolue sur 4 octets, Addr[0] est le poids fort.

Le code-source donné montre comment activer le mode MSF.

Structure de la TOC modifier

Cette structure d'une taille de 804 octets ((8*100)+4) est connue sous le nom de TOC.

  • TocLen : 2 octets pour la taille de la TOC, en octets
  • FirstTrack : 1 octet pour le numéro de la première plage (souvent 1, voir plus haut)
  • LastTrack : 1 octet pour le numéro de la dernière plage
  • tocTrack : 100 structures de type TOCTRACK (voir ci-dessus)

Comment lire la TOC ? modifier

GNU/Linux modifier

Sous Linux on peut facilement lire les premiers secteurs du CD avec l'utilitaire dd, il faut alors interpréter soi-même les données brutes lues sur le disque. Une méthode plus simple consiste à utiliser cdrdao, avec l'option read-toc, afin de récupérer directement les informations en clair.

Windows modifier

Sous Windows on ne peut pas accéder directement au contenu du CD, donc on n'a pas accès à la TOC. Pour accéder physiquement aux secteurs du CD il faut utiliser une couche d'interface logicielle permettant l'envoi de commandes SCSI au lecteur ou graveur. On peut par exemple utiliser ASPI, de la société Adaptec, voir l'exemple ci-dessous. La documentation fournie avec la bibliothèque ASPI liste les include à ajouter, ainsi que pour les define qui dépendent du compilateur (Borland C++ Builder, Microsoft Visual C++, GCC).

TOC toc; // définir une structure en fonction des informations données plus haut
SRB_ExecSCSICmd SRBexec;
DWORD dwASPIStatus;
HANDLE hEvent;
 
memset(&SRBexec, 0, sizeof(SRB_ExecSCSICmd));
hEventSRB = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!heventSRB)
{
   // ERREUR : sortir
}

SRBexec.SRB_Cmd = SC_EXEC_SCSI_CMD;
SRBexec.SRB_HaID = haId; // numéro de l'interface
SRBexec.SRB_Target = id; // identifiant du périphérique
SRBexec.SRB_Lun = lun; // unité logique
SRBexec.SRB_Flags = SRB_DIR_IN; // sens du transfert
SRBexec.SRB_BufLen = sizeof(TOC); // taille des données à transférer (la TOC)
SRBexec.SRB_BufPointer = &toc;
SRBexec.SRB_SenseLen = 0x0e;
SRBexec.SRB_CDBLen = 0x0A;
SRBexec.SRB_CDBByte[0] = 0x43; // numéro de la commande "read TOC"
SRBexec.SRB_CDBByte[1] = 0x02; // pour le format du champ Addr (mode MSF = Minute/Second/Frame)
SRBexec.SRB_CDBByte[7] = 0x03; // poids-fort de la taille du buffer (804=0x324)
SRBexec.SRB_CDBByte[8] = 0x24; // poids-faible de la taille du buffer (804=0x324)
SRBexec.SRB_PostProc = hEventSRB; // on bloque sur cet objet, pour attendre la fin de la commande
ResetEvent(hEventSRB); // reset l'événement avant de l'utiliser

dwASPIStatus = SendASPI32Command((LPSRB)&srbExec);

if (dwASPIStatus == SS_PENDING) // commande acceptée, en cours d'exécution
{
   WaitForSingleObject(heventSRB, 15000);  // attendre au maximum 15 secondes
}
else
{
   // ERREUR 
   CloseHandle(hEventSRB);                 // libérer la ressource avant de sortir
   // sortir
}
 
CloseHandle(hEventSRB); // libérer la ressource avant de sortir

if (srbExec.SRB_Status != SS_COMP)
{
  // ERREUR pendant l'exécution, sortir
}
 
// commande terminée sans erreur, la TOC est dans la structure toc.

Une autre solution est d'utiliser les fichiers CDA fournis par Windows à l'insertion du CD. Le problème avec cette solution est quelle ne donne pas la position du lead-out, et ne permet donc pas de calculer le DiscId.