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
|