FLAC, le format audio est-il vraiment sans perte ?

On nous dit que le format audio FLAC est sans perte. Faut-il prendre la chose littéralement ou bien « c'est presque pareil mais de toute façon tes oreilles n'entendront pas la différence ».

Je n'ai ni la feuille ni le vocabulaire de l'ingénieur du son ou de l'audiophile, on va plutôt raisonner à partir de mesures. On partira d'un fichier wav linéaire qu'on encodera en FLAC puis qu'on redécodera en linéaire, on verra alors si on retrouve le même fichier source au bit près… ou pas.

🏋️ Flexion / Extension

Notre fichier audio d'origine a les caractéristiques suivantes :

 1$ mediainfo sample-src.wav
 2General
 3Complete name                            : sample-src.wav
 4Format                                   : Wave
 5File size                                : 24.6 MiB
 6Duration                                 : 2 min 14 s
 7Overall bit rate mode                    : Constant
 8Overall bit rate                         : 1 536 kb/s
 9
10Audio
11Format                                   : PCM
12Format settings                          : Little / Signed
13Codec ID                                 : 1
14Duration                                 : 2 min 14 s
15Bit rate mode                            : Constant
16Bit rate                                 : 1 536 kb/s
17Channel(s)                               : 2 channels
18Sampling rate                            : 48.0 kHz
19Bit depth                                : 16 bits
20Stream size                              : 24.6 MiB (100%)

Maintenant encodons le en FLAC à l'aide d'ffmpeg :

1$ ffmpeg -i sample-src.wav sample-tmp.flac

Regardons la place gagnée :

1$ ls -l sample-* | awk '{print $5,$9}'
225754856 sample-src.wav
318271243 sample-tmp.flac

Le ratio est de 70.94%, on a gagné presque un tiers, avec la promesse de ne rien perdre, pas si mal si ça se confirme 👌 .

mediainfo nous confirme la validité du nouveau fichier audio compressé :

 1$ mediainfo sample-tmp.flac
 2General
 3Complete name                            : sample-tmp.flac
 4Format                                   : FLAC
 5Format/Info                              : Free Lossless Audio Codec
 6File size                                : 17.4 MiB
 7Duration                                 : 2 min 14 s
 8Overall bit rate mode                    : Variable
 9Overall bit rate                         : 1 090 kb/s
10Writing application                      : Lavf58.76.100
11
12Audio
13Format                                   : FLAC
14Format/Info                              : Free Lossless Audio Codec
15Duration                                 : 2 min 14 s
16Bit rate mode                            : Variable
17Bit rate                                 : 1 089 kb/s
18Channel(s)                               : 2 channels
19Channel layout                           : L R
20Sampling rate                            : 48.0 kHz
21Bit depth                                : 16 bits
22Compression mode                         : Lossless
23Stream size                              : 17.4 MiB (100%)
24Writing library                          : Lavf58.76.100

Reconvertissons le en wav :

1$ ffmpeg -i sample-tmp.flac sample-dst.wav

Note: il existe un paramètre -compression_level compris entre 0 et 12, par défaut à 5. Une étude montre qu'une forte compression ne réduit pas tant que ça la taille mais augmente significativement le temps d'encodage. Bref laissons la valeur par défaut.

Comparons maintenant les fichiers wav source et destination :

1$ diff sample-src.wav sample-dst.wav
2Binary files sample-src.wav and sample-dst-test.wav differ

Aille, c'est un échec, les fichiers diffèrent 🤔.

1$ ls -l sample-*.wav | awk '{print $5,$9}'
225754890 sample-dst.wav
325754856 sample-src.wav

Effectivement il y a 34 octets de différence en taille 🤏.

Regardons de plus près si les données audio sont réellement différentes ou si c'est juste une histoire de métadonnées ajoutées dans l'entête par nos conversions successives…

Dump des premiers octets du fichier source 🤓 :

1$ hexdump -C sample-src.wav | head -n 8
200000000  52 49 46 46 02 fd 88 01  57 41 56 45 66 6d 74 20  |RIFF....WAVEfmt |
300000010  10 00 00 00 01 00 02 00  80 bb 00 00 00 ee 02 00  |................|
400000020  04 00 10 00 4c 49 53 54  1a 00 00 00 49 4e 46 4f  |....LIST....INFO|
500000030  49 53 46 54 0e 00 00 00  4c 61 76 66 35 38 2e 37  |ISFT....Lavf58.7|
600000040  36 2e 31 30 30 00 64 61  74 61 bc fc 88 01 70 0d  |6.100.data....p.|
700000050  93 0f a2 12 fe 08 d7 15  d2 00 df 18 80 fc 46 20  |..............F |
800000060  5c ff 46 29 40 04 a5 29  70 06 c6 20 51 07 8b 17  |\.F)@..)p.. Q...|
900000070  27 08 6b 10 61 08 5e 0b  7b 09 be 0b 44 0c 36 0e  |'.k.a.^.{...D.6.|

Dump des premiers octets du fichier destination 🤓 :

1$ hexdump -C sample-dst.wav | head -n 8
200000000  52 49 46 46 e0 fc 88 01  57 41 56 45 66 6d 74 20  |RIFF....WAVEfmt |
300000010  10 00 00 00 01 00 02 00  80 bb 00 00 00 ee 02 00  |................|
400000020  04 00 10 00 64 61 74 61  bc fc 88 01 70 0d 93 0f  |....data....p...|
500000030  a2 12 fe 08 d7 15 d2 00  df 18 80 fc 46 20 5c ff  |............F \.|
600000040  46 29 40 04 a5 29 70 06  c6 20 51 07 8b 17 27 08  |F)@..)p.. Q...'.|
700000050  6b 10 61 08 5e 0b 7b 09  be 0b 44 0c 36 0e 1c 0c  |k.a.^.{...D.6...|
800000060  62 0c a1 06 7d 09 3a 03  06 0a b8 05 52 09 c4 06  |b...}.:.....R...|
900000070  43 04 c1 02 c0 01 b4 fa  2b 06 51 ec f4 0a 80 dd  |C.......+.Q.....|

L'entête diffère avec le chunk LIST qui est présent dans le fichier destination mais pas le source, l'hypothèse de la réécriture de l'entête par ffmpeg se confirme. Les données audio brutes (après le data) semblent être les mêmes.

Précisons maintenant au convertisseur de ne pas générer de métadonnées particulières :

1$ ffmpeg -i sample-tmp.flac -fflags +bitexact sample-dst.wav

Un rapide contrôle de la taille des fichiers :

1$ ls -l sample-*.wav | awk '{print $5,$9}'
225754856 sample-dst.wav
325754856 sample-src.wav

De bon augure, refaisons la comparaison binaire 🤞 :

1$ diff sample-src.wav sample-dst.wav

🏆 C'est bon, on a bien retrouvé notre fichier d'origine, au bit près ! 🏆

Je ne prends donc même pas la peine de faire une analyse spectrale ou autre, les données sont rigoureusement les mêmes, « ça sonnera pareil ».

Mais on aurait pas pu le zipper ?

Il existe d'autres types de compression générique, sans pertes, comme zip ou gzip, pourquoi ne pas les avoir utilisés ?

1$ zip sample-src.zip sample-src.wav
2  adding: sample-src.wav (deflated 1%)
3$ ls -l sample-src.zip | awk '{print $5,$9}'
425425169 sample-src.zip

Ratio 98.72% 😞

1$ tar zfcv sample-src.tar.gz sample-src.wav
2a sample-src.wav
3$ ls -l sample-src.tar.gz | awk '{print $5,$9}'
425436294 sample-src.tar.gz

Ratio 98.76% 😞

Le gain est quasi nul 😮 ! De plus le temps de décompression préalable à la lecture augmente proportionnellement avec la taille et la durée du fichier. On comprend mieux l'intérêt des formats de compression spécifiques aux fichiers media.

Conclusion

Le format FLAC est bien sans perte ✅. Ses spécifications étant libres et ouvertes, c'est finalement un bon candidat pour l'archivage sonore de votre discothèque 💿.

Ressources

comments powered by Disqus