[Sub0] - 26/05/03

conversion 16 bits mono en stéréo

 

Les données du sample 16 bits mono ne possèdent que 2 octets. Le sample stéréo, 4 octets: 2 octets pour la voie de gauche, et 2 octets pour la voie de droite. Pour convertir le mono en stéréo, il suffit d'ajouter 2 octets de plus, et de modifier l'en-tête du fichier pour le nouveau format. Autrement dit, nous pouvons copier tout simplement la piste mono existante (gauche) sur une nouvelle piste (droite). Ainsi, nous obtiendrons un sample stéréo, mais mono à l'écoute... Il est aussi possible (et facile), d'ajouter des effets à la 2ème piste, pour différencier les deux voies! Ces effets sont obtenues par différentes méthodes de calcul (transformation des données). Cependant, nous n'en verrons ici, pour l'instant!

Donc, pour cette conversion du
mono vers stéréo, aucun calcul compliqué ne sera vraiment nécessaire. J'en profiterai donc pour m'attarder davantage sur l'explication de la gestion de la copie des données...


Réalisation du programme: Ce qui est important à mon avis, ce sont les vérifications et la gestion des erreurs pour la copie du fichier! Pour commencer, je vérifie que l'ouverture du fichier source est bien possible avec la fonction FileExists. Cette fonction me dit si ce fichier est bien présent sur le disque ou non. Puis, j'ouvre ce fichier source, et je copie l'en-tête du fichier (44 octets) dans le buffer nommé BufS. Ce buffer servira à obtenir et vérifier le format du sample (par la suite). Pour le moment, je vérifie la taille, et d'éventuelles erreurs d'accès, grâce à IOResult et à la directive de compilation {$I+}. Le fichier est refermé avant l'affichage des éventuelles erreurs. Nous le réouvrirons après si aucune erreur n'est décelée.

IF NOT(FileExists(Source))THEN
  BEGIN
ShowMessage('Impossible d''ouvrir '+Source);EXIT;END;
{$I-} AssignFile(Fsour,Source);
      Filemode:=
2;
      Reset(Fsour,
1);
      Size:=FileSize(Fsour);
      BlockRead(Fsour,BufS,
44,res);
      CloseFile(Fsour);
{$I+} IF(IOResult<>0)OR(Size<116)THEN {$I-}
  
BEGIN ShowMessage('Impossible d''ouvrir '+Source);EXIT;END;



J
e vais maintenant vérifier la validité de son format, en contrôlant quelques octets de son en-tête, en particulier le format (16 bits), le mode (mono), et la fréquence. La fonction CreateHeader permet un test supplémentaire (à peu près identique). Cette fonction renvoie FALSE si la création d'une en-tête avec ses paramètres poserait un problème. Cela permet aussi de s'assurer que la copie de l'en-tête s'est bien déroulée:

Freq:=(bufS[
27]*$1000000)+(bufS[26]*$10000)+(bufS[25]*$100)+bufS[24];
IF(BufS[22]<>1)OR(BufS[34]<>16)OR
  (
NOT CreateHeader(Size,BufS[22],bufS[34],Freq))THEN
  BEGIN
ShowMessage('Format de '+source+' invalide');EXIT;END;



Une fonction spéciale est mise en place pour permettre de connaître la taille disponible sur le lecteur. Si l'espace libre est insuffisant pour copier le nouveau fichier destination, un message d'erreur est affiché, et la processus s'interrompt. La détection d'espace libre est faite avec la fonction GetDiskFreeSpaceEx de Delphi. Il existe un équivalent pour les autres compilateurs... Etant donné que cette fonction a besoin de plusieurs variable pour fonctionner, j'ai simplifier en regroupant tout dans une fonction appellée GetDiskSize:

FUNCTION getdisksize(lecteur:string):int64;
VAR Drive:array[0..255]of char; TailleDisque:int64;
BEGIN TRY
 
TailleDisque:=0; strPCopy(Drive,lecteur);
 GetDiskFreeSpaceEx(Drive,Result,TailleDisque,
nil);
EXCEPT Result:=0;END; END;

Je m'en sert comme ceci:

IF(getdisksize( copy(ExpandFilename(dest),1,3))<Size2)THEN
  BEGIN
ShowMessage('Espace insuffisant pour la copie');EXIT;END;



Un dernier test est nécessaire, celui de la création du fichier de destination. Pendant ce test, je profite que le fichier est ouvert pour créer et copier la nouvelle en-tête (16 bits stéréo), à condition de connaître à l'avance la taille finale qu'aura le fichier (Size2). Dans le cas actuel (mono vers stéréo), il suffit de multiplier par deux la taille du fichier source, et d'ajouter la taille de l'en-tête (44 octets):

{$I-} AssignFile(Fdest,Dest);
      Filemode:=
2;
      Rewrite(Fdest,
1);
      CreateHeader(Size2,
2,16,Freq);
      BlockWrite(Fdest,Header,
44,res2);
      CloseFile(Fdest);
{$I+} IF(IOResult<>0)THEN {$I-}
  
BEGIN ShowMessage('Impossible de créer '+dest);EXIT;END;

 

Une fois tous ces tests réalisés avec succès, il est possible de traîter le sample... En résumé:

  1. Test si le fichier source existe
  2. Test d'ouverture du fichier source
  3. Lecture et test du format du sample source
  4. Test de l'espace libre pour la copie
  5. Test de création du fichier destination

SOURCE DU PROGRAMME