[Sub0] - 26/05/03

Conversion 16 bits stéréo en 16 bits mono

 

Les données du sample 16 bits stéréo possèdent 4 octets: 2 octets pour la voie de gauche, et 2 octets pour la voie de droite. Pour convertir en mono, nous allons retirer 2 octets sur les 4. Nous avons donc le choix de mixer les deux voies, ou prendre uniquement soit la voie de gauche, ou de droite. Par défaut, c'est la conversion par mixage qui est la plus "normale", mais c'est aussi la plus compliquée. Ce mixage se fait par une moyenne des amplitudes...

1) Convertir les données signées en données non signées.
2) Calculer la moyenne des deux voies.
3) Reconvertir le résultat en données signées.
4) Modifier l'en-tête du fichier pour le nouveau format.

Pour convertir les données en données non-signées, il faut soustraire $8000 (32768). Si le résultat est inférieur à zéro, alors il faut additionner $10000 (65536) au résultat. Pour calculer la moyenne, il faut additionner les deux valeurs, et diviser la somme par deux. Ensuite, pour convertir la donnée en valeurs signées, il faut additionner $8000. Si le résultat est supérieure ou égal à $10000, il faut soustraire $10000.

Le code suivant est un exemple de conversion d'une seule donnée. Il est destiné à vous expliquer la méthode utilisée. Dans le cas d'un fichier entier, il faudra placer ce code dans une boucle, pour traiter chaque donnée du sample.

VAR voieL,voieR,voieM: Longint;

BEGIN
voieL:=voieL-
$8000; IF(voieL<0)THEN voieL:=voieL+$10000;
voieR:=voieR-
$8000; IF(voieR<0)THEN voieR:=voieR+$10000;
voieM:=(voieL
+voieR)DIV 2;
voieM:=voieM+
$8000;
IF(voieM>=$10000)THEN voieM:=voieM-$10000;
Result:=word(VoieM);
END;


En ce qui concerne l'en-tête du fichier, il faut apporter les modifications suivantes:
-
Filesize est divisée par deux.
-
Format ne change pas.
-
Mode passe de stéréo (2) à mono (1).
- Cela va donc modifier
BytePerSec et NbrByte.


 

Réalisation du programme: Le programme d'exemple pour Delphi nous servira de base pour les autres conversions... Il pourra être facilement porté sur d'autres compilateurs Pascal comme TP ou BPW. Voici l'explication des principales fonctions utilisées:


FUNCTION CreateHeader (size,mode,format,freq: longint): boolean;

C'est
une fonction permettant de créer l'en-tête. Cette fonction retourne TRUE si tout s'est bien déroulé, et FALSE dans le cas contraire (si les paramètres d'entrée sont invalides); En théorie, size doit-être supérieur à 116, et encore! **. Le paramètre mode doit-être égal à 1 (mono) ou à 2 (stéréo). Le paramètre format doit-être égal à 8 ou à 16 (bits). Et la fréquence (freq) doit-être comprise entre 5000 et 96000 (Hz).  La fonction modifie les octets de la variable HEADER:Array[0..43]of byte. C'est-à-dire qu'après l'appel de la fonction CreateHeader, le tableau HEADER contient la nouvelle en-tête du fichier.


FUNCTION Make16ST_MO (Source,Dest: string): boolean; 

Au final, je peux regrouper le tout dans une seule fonction: Avec en paramètre d'entrée, le nom du fichier source et le nom du fichier destination. La fonction retourne
TRUE si tout s'est bien déroulé, et FALSE dans le cas contraire. En ce qui concerne l'accès au fichier, j'utilise les procédures BlockRead et BlockWrite pour réaliser la copie -> Les données sont d'abord copiées dans un buffer (source), puis traîtées une par une. Le résultat est placé dans un autre buffer (destination) qui sera copié dans le nouveau fichier de destination... Ce procédé se fait en plusieurs fois pour éviter d'avoir à charger la totalité du fichier en mémoire avant le traitement. Je n'ai pas utilisé le type STREAM pour que le code soit compris de tous programmeurs Pascal.


** Remarques: Mon code fonctionne parfaitement en théorie, étant donné que ce n'est que de la logique. Seulement quand je convertis un fichier 16 bits stéréo en mono, et que je l'ouvre ensuite avec SndForge, ce dernier m'avertit qu'il trouve une erreur dans ce fichier. Après des recherches assez poussées, je me suis apperçu que SndForge enlèvait 72 octets à la fin du fichier pour le corriger!
72 = 116 - 44. J'ai donc rajouter une fonction pour supprimer ces 72 octets superflus à la fin de la procédure Make16ST_MO, juste avant la sauvegarde finale du fichier. Comme ça, SndForge est content! Voici ce code:

Seek(Fdest,size2-72);
Truncate(Fdest);
 

SOURCE DU PROGRAMME