Méthodes de compression/stockage de données multimédias aux formats WAVE et JPEG, partie 1

Bonjour! Ma première série d'articles se concentrera sur l'étude des méthodes de compression et de stockage d'image/audio telles que JPEG (image) et WAVE (son), et inclura également des exemples de programmes utilisant ces formats (.jpg, .wav) en pratique. Dans cette partie, nous examinerons WAVE.

histoire

WAVE (Waveform Audio File Format) est un format de fichier conteneur permettant de stocker un enregistrement d'un flux audio. Ce conteneur est généralement utilisé pour stocker de l'audio modulé par impulsions et codes non compressés. (Tiré de Wikipédia)

Il a été inventé et publié en 1991 avec RIFF par Microsoft et IBM (principales sociétés informatiques de l'époque).

Structure du fichier

Le fichier comporte une partie en-tête, les données elles-mêmes, mais pas de pied de page. L'en-tête pèse au total 44 octets.
L'en-tête contient des paramètres pour le nombre de bits dans l'échantillon, la fréquence d'échantillonnage, la profondeur du son, etc. informations nécessaires à la carte son. (Toutes les valeurs numériques du tableau doivent être écrites dans l'ordre Little-Endian)

Nom du bloc
Taille du bloc (B)
Description/Objectif
Valeur (pour certains elle est fixe

ID de morceau
4
Définir un fichier comme conteneur multimédia
0x52494646 en gros-boutiste (« RIFF »)

chunkSize
4
Taille du fichier entier sans chunkId et chunkSize
FILE_SIZE - 8

le format
4
Définition du type à partir de RIFF
0x57415645 en gros-boutiste (« WAVE »)

ID du sous-morceau1
4
Pour que le fichier prenne plus de place en continuation du format
0x666d7420 en gros-boutiste (« fmt »)

sous-morceau1Taille
4
En-tête restant (en octets)
16 par défaut (pour le cas sans compression du flux audio)

format audio
2
Format audio (dépend de la méthode de compression et de la structure des données audio)
1 (pour PCM, ce que nous envisageons)

numCanaux
2
Nombre de canaux
1/2, nous prendrons 1 canal (3/4/5/6/7... - une piste audio spécifique, par exemple 4 pour le son quad, etc.)

taux d'échantillonnage
4
Taux d'échantillonnage audio (en Hertz)
Plus le son est élevé, meilleur sera le son, mais plus il faudra de mémoire pour créer une piste audio de même longueur, la valeur recommandée est de 48000 XNUMX (la qualité sonore la plus acceptable)

taux d'octets
4
Nombre d'octets par seconde
taux d'échantillonnage numCanaux bitsParSample (plus loin)

bloquerAligner
2
Nombre d'octets pour 1 échantillon
numChannels * bitsParSample : 8

bits par échantillon
2
Nombre de bits pour 1 échantillon (profondeur)
Tout nombre multiple de 8. Plus le nombre est élevé, plus l'audio sera de qualité et lourd ; à partir de 32 bits, il n'y a aucune différence pour les humains.

ID du sous-morceau2
4
Marque de référence des données (car il peut y avoir d'autres éléments d'en-tête en fonction de l'audioFormat)
0x64617461 en Big-Endian("données")

sous-morceau2Taille
4
Taille de la zone de données
taille des données en int

données
byteRate * durée audio
Données audio
?

Exemple de VAGUE

Le tableau précédent peut facilement être traduit en structure en C, mais notre langage pour aujourd'hui est Python. La chose la plus simple que vous puissiez faire est d’utiliser une « onde » – un générateur de bruit. Pour cette tâche, nous n'avons pas besoin d'un taux d'octets et d'une compression élevés.
Commençons par importer les modules nécessaires :

# WAV.py

from struct import pack  # перевод py-объектов в базовые типы из C
from os import urandom  # функция для чтения /dev/urandom, для windows:
# from random import randint
# urandom = lambda sz: bytes([randint(0, 255) for _ in range(sz)])  # лямбда под windows, т.к. urandom'а в винде нет
from sys import argv, exit  # аргументы к проге и выход

if len(argv) != 3:  # +1 имя скрипта (-1, если будете замораживать)
    print('Usage: python3 WAV.py [num of samples] [output]')
    exit(1)

Ensuite, nous devons créer toutes les variables nécessaires à partir du tableau en fonction de leurs tailles. Les valeurs des variables qu'il contient dépendent uniquement de numSamples (nombre d'échantillons). Plus il y en aura, plus notre bruit durera longtemps.

numSamples = int(argv[1])
output_path = argv[2]

chunkId = b'RIFF'
Format = b'WAVE'
subchunk1ID = b'fmt '
subchunk1Size = b'x10x00x00x00'  # 0d16
audioFormat = b'x01x00'
numChannels = b'x02x00'  # 2-х каналов будет достаточно (стерео)
sampleRate = pack('<L', 1000)  # 1000 хватит, но если поставить больше, то шум будет слышен лучше. С 1000-ю он звучит, как ветер
bitsPerSample = b'x20x00'  # 0d32
byteRate = pack('<L', 1000 * 2 * 4)  # sampleRate * numChannels * bitsPerSample / 8  (32 bit sound)
blockAlign = b'x08x00'  # numChannels * BPS / 8
subchunk2ID = b'data'
subchunk2Size = pack('<L', numSamples * 2 * 4)  # * numChannels * BPS / 8
chunkSize = pack('<L', 36 + numSamples * 2 * 4)  # 36 + subchunk2Size

data = urandom(1000 * 2 * 4 * numSamples)  # сам шум

Il ne reste plus qu'à les noter dans l'ordre requis (comme dans le tableau) :

with open(output_path, 'wb') as fh:
    fh.write(chunkId + chunkSize + Format + subchunk1ID +
            subchunk1Size + audioFormat + numChannels + 
            sampleRate + byteRate + blockAlign + bitsPerSample +
            subchunk2ID + subchunk2Size + data)  # записываем

Et voilà, prêt. Pour utiliser le script, nous devons ajouter les arguments de ligne de commande nécessaires :
python3 WAV.py [num of samples] [output]
nombre d'échantillons - nombre. échantillons
sortie - chemin d'accès au fichier de sortie

Voici un lien vers un fichier audio de test avec du bruit, mais pour économiser de la mémoire, j'ai réduit le BPS à 1 b/s et le nombre de canaux à 1 (avec un flux audio stéréo non compressé de 32 bits à 64 Ko, il s'est avéré que c'était 80 M de fichier .wav pur, et seulement 10) : https://instaud.io/3Dcy

Le code entier (WAV.py) (le code contient de nombreuses valeurs de variables en double, ce n'est qu'un croquis) :

from struct import pack  # перевод py-объектов в базовые типы из C
from os import urandom  # функция для чтения /dev/urandom, для windows:
# from random import randint
# urandom = lambda sz: bytes([randint(0, 255) for _ in range(sz)])  # лямбда под windows, т.к. urandom'а в винде нет
from sys import argv, exit  # аргументы к проге и выход

if len(argv) != 3:  # +1 имя скрипта (-1, если будете замораживать)
    print('Usage: python3 WAV.py [num of samples] [output]')
    exit(1)

numSamples = int(argv[1])
output_path = argv[2]

chunkId = b'RIFF'
Format = b'WAVE'
subchunk1ID = b'fmt '
subchunk1Size = b'x10x00x00x00'  # 0d16
audioFormat = b'x01x00'
numChannels = b'x02x00'  # 2-х каналов будет достаточно (стерео) 
sampleRate = pack('<L', 1000)  # 1000 хватит, но можно и больше.
bitsPerSample = b'x20x00'  # 0d32
byteRate = pack('<L', 1000 * 2 * 4)  # sampleRate * numChannels * bitsPerSample / 8  (32 bit sound)
blockAlign = b'x08x00'  # numChannels * BPS / 8
subchunk2ID = b'data'
subchunk2Size = pack('<L', numSamples * 2 * 4)  # * numChannels * BPS / 8
chunkSize = pack('<L', 36 + numSamples * 2 * 4)  # 36 + subchunk2Size

data = urandom(1000 * 2 * 4 * numSamples)  # сам шум

with open(output_path, 'wb') as fh:
    fh.write(chunkId + chunkSize + Format + subchunk1ID +
            subchunk1Size + audioFormat + numChannels + 
            sampleRate + byteRate + blockAlign + bitsPerSample +
            subchunk2ID + subchunk2Size + data)  # записываем в файл результат

Total

Vous en savez donc un peu plus sur le son numérique et sur la façon dont il est stocké. Dans cet article, nous n'avons pas utilisé la compression (audioFormat), mais pour examiner chacun des articles les plus populaires, vous aurez besoin de 10 articles. J'espère que vous avez appris quelque chose de nouveau par vous-même et que cela vous aidera dans les développements futurs.
Je vous remercie!

sources

Structure du fichier WAV
WAV — Wikipédia

Source: habr.com

Ajouter un commentaire