Le sample WAV
L'amplitude: Un sample est composé
d'une courbe continue ayant une valeur bi-polaire. Le 1er élément
d'un son est l'amplitude: C'est le point le plus élevé
(et le plus bas) de la courbe. Plus l'amplitude est élevée,
plus le son est fort, bruyant. L'unité de grandeur de l'amplitude
est le décibel (dB). "C'est une mesure logarithmique
donnant le degré d'amplification d'une vibration." Nous
n'irons pas plus loin dans la description du décibel, puisque
ce n'est pas indispensable dans la programmation. L'amplitude est
digitalisée avec l'ADC de la carte son. Par exemple, en 8
bits, l'amplitude possède une résolution de 256 valeurs.
En 16 bits, 65536 valeurs, etc... Il existe aussi le 24 et 32 bits.
Plus la résolution est élevée, plus l'échantillon
est proche du son original. Dans les images ci-dessus, l'amplitude
digitalisée est illustrée en vert.
La
fréquence: En bleu, c'est la fréquence d'échantillonnage,
le nombre de valeurs définissant l'amplitude pour une
seconde d'enregistrement. Ainsi 44100 Hz signifie 44100 échantillons
pour une seconde de son mémorisé. Plus la fréquence
du son est élevée, plus le son est aigu.
Plus la fréquence d'échantillonnage est élevée,
meilleure est la qualité du sample, plus les données
digitales sont proches de l'original.
Le
débit:
On peut calculer le "débit" (ko/s) d'un sample
avec ces paramètres: L'amplitude (format 8 ou 16 bits), le
mode (mono ou stéréo) et la fréquence. Par
exemple, en 8 bits mono 44100Hz, cela nous donne pour une seconde
d'enregistrement: 44100 octets (1 octet=8 bits). En stéréo,
c'est le double. En 16 bits stéréo, c'est le quadruple.
Ainsi, avec la qualité du CD audio (16 bits stéréo
44,1 kHz), on obtient 176400 octets par seconde. A partir de la
taille du fichier (donnée par fileSize), et les caractéristiques
du sample, il est facile de calculer le temps total en secondes
(ou ms) de lecture d'un sample...
Le
format PCM:
C'est le format de fichier "standard" pour les samples,
car les données sont brutes, c'est-à-dire qu'elles
ne sont ni modifiées, ni compressées depuis l'ADC.
Le fichier possède une en-tête de 44 octets, permettant
de connaître le type du sample: Son format, sa fréquence,
le nombre de voies, etc... En 8 bits, la valeur de l'amplitude est
non signée, et en 16 bits, l'amplitude est signée.
Cela complique un peu les choses, par exemple, pour convertir un
sample 16 bits en 8 bits, il ne suffit pas de diviser la valeur
de l'amplitude par 256, il faut aussi penser à soustraire
(ou à ajouter) ce décalage. Cette manip est expliquée
un peu plus bas dans ce document... Le format WAV possède
aussi d'autres particularités. Par exemple, voici l'en-tête
d'un sample 16 bits mono 44,1 kHz:
CONST HEADER:ARRAY[0..43]OF
BYTE=(
$52,$49,$46,$46, $00,$00,$00,$00, $57,$41,$56,$45, $66,$6D,$74,$20,
$10,$00,$00,$00, $01,$00,$01,$00, $44,$AC,$00,$00, $88,$58,$01,$00,
$02,$00,$10,$00, $64,$61,$74,$61, $00,$00,$00,$00);
TYPE
THEAD=RECORD
Tag1 : ARRAY[1..4]OF CHAR;
{ 00..03 Constante "RIFF"
}
Size1 :
LONGINT;
{ 04..07 Filesize-8
}
Tag2 : ARRAY[1..14]OF CHAR;
{ 08..21 Constante "WAVEfmt..."
}
Mode :
WORD; { 22..23 Mono or Stereo }
Freq :
LONGINT; { 24..27 Frequence (Hz) }
BytePerSec :
LONGINT; { 28..31 Freq*NbrByte }
NbrByte :
WORD; { 32..33 (Format div 8)*Mode }
Format :
WORD;
{ 34..35
8 or 16 bits }
Tag3 : ARRAT[1..4]OF CHAR; { 36..39 Constante "data"
}
Size2 :
LONGINT; { 40..43 Filesize-116 }
END;
Accéder
aux octets - Méthode:
Le type Longint possède 4 octets, tandis qu'un Word, en possède
2.
TYPE LongRec=RECORD lo,hi:WORD;END;
WordRec=RECORD lo,hi:BYTE;END;
LongRec permet de décomposer
un LONGINT en 2 WORD (lo & hi), et WordRec permet de décomposer un WORD en
2 BYTES (lo & hi). Par exemple, pour obtenir les 4 octets du
longint size:
VAR
s1,s2,s3,s4:BYTE;
size:LONGINT;
BEGIN
s1:=WordRec(LongRec(size).lo).lo;
s2:=WordRec(LongRec(size).lo).hi;
s3:=WordRec(LongRec(size).hi).lo;
s4:=WordRec(LongRec(size).hi).hi;
Pour
l'opération inverse, je fais la somme des octets multipliés
par leur poids:
size:=(s4*$1000000)+(s3*$10000)+(s2*$100)+s1;
END;
L'ordre
des données:
Après les 44 octets de l'en-tête, viennent les données.
Les données ont un ordre bien défini. Dans le cas
d'un sample 8
bits mono,
c'est 1 seul octet par sample, donc
les données se suivent normalement. Pour un sample 8 bits stéréo, ce sont 2 octets par sample, l'octet de la voie de gauche,
puis l'octet de la voie de droite: L,R, L,R, L,R, etc... Dans le
cas d'un sample
16 bits mono,
ce sont 2 octets par sample, l'octet
de poids faible, puis l'octet de poids fort. Par exemple pour
une donnée qui vaudrait 15000, nous aurions: $98 $3A (les
octets sont toujours inversés). Dans le cas d'un sample 16 bits stéréo, ce sont 4 octets par sample; Deux octets pour la voie de gauche,
et deux pour la voie de droite: L,L,R,R, L,L,R,R, L,L,R,R, etc...
Le format
des données: Le sample 8
bits (mono
ou stéréo) possède des données non-signées,
c'est-à-dire que le point (l'amplitude) le plus bas vaut
zéro, le point du milieu vaut
127, et le point le plus haut
vaut 255. Avec un sample 16 bits, les choses sont différentes,
les données sont signées: Le point le plus bas vaut
-32268, le point du milieu vaut
zéro, et le point le plus au
vaut 32767. Voici une illustration
de l'amplitude d'un sample 16 bits: A gauche, le format d'origine
des données (signées), et à droite, les valeurs
lorsque les données seront converties en données non-signées:
Pour pouvoir travailler sur
les données 16 bits, par exemple pour modifier le volume
du sample, ou le mixer avec un autre, etc... les données
16 bits signées doivent-être converties en données
16 bits non-signées avant le traitement, puis reconverties
en données signées après le traitement afin
d'être prêtes à la lecture. Voici donc la méthode
que j'utilise pour transformer une donnée 16 bits signée
en non-signée. La variable nommée "donnée"
est du type Integer (avec Delphi) ou Longint (avec TP):
Voici l'opération de conversion (signée -> non-signée):
donnee:=donnee-$8000;
IF(donnee<0)THEN donnee:=donnee+$10000;
Voici l'opération inverse (non-signée -> signée):
donnee:=donnee+$8000;
IF(donnee>=$10000)THEN donnee:=donnee-$10000;
Difficile de faire plus simple!
Attention! Toutes ces explications ne sont valables que pour le
format PCM, car il existe d'autres
types de compression pour les samples WAV! Cependant, le format PCM est le plus utilisé pour le traitement des samples...
Les exemples proposés dans ce tutoriel, ont été
réalisés et testés avec Delphi 6 (voir sommaire).
|