[Из песочницы] Методы сжатия/хранения медиа данных в форматах WAVE и JPEG, часть 1

habr.png

Здравствуйте! Моя первая серия статей будет направлена на изучение методов сжатия и хранения изображений/звука, таких как JPEG (изобр.) и WAVE (звук), также в них будут примеры программ с использованием этих форматов (.jpg, .wav) на практике. В этой части мы рассмотрим именно WAVE.


История


WAVE (Waveform Audio File Format) — формат файла-контейнера для хранения записи аудио потока. Этот контейнер, как правило, используется для хранения несжатого звука в импульсно-кодовой модуляции. (Взято из Википедии)

Он был придуман и опубликован в 1991 году вместе в RIFF компаниями Microsoft и IBM (Ведущие IT компании того времени).


Структура файла

У файла есть заголовочная часть, сами данные, но нет футера. Заголовок весит в общем 44 байта.
В хедере находятся настройки количества бит в семпле, частоты дескритизации, глубины звука и т.п. информации, необходимой для звуковой карты. (Все числовые значения таблицы должны быть записаны в Little-Endian порядке)


Пример с WAVE

Предыдущую таблицу можно с легкостью перевести в структуру на C, но наш язык на сегодня — Python. Самое легкое, что можно сделать, используя «волну» — генератор шума. Для этой задачи нам не потребуются высокий byteRate и сжатие.
Для начала импортируем необходимые модули:

# 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)

Далее нам необходимо создать все необходимые переменные из таблицы по их размерам. Непостоянные величины в ней зависят тут только от numSamples (количество семплов). Чем больше их будет, тем дольше будет идти наш шум.

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

chunkId = b'RIFF'
Format = b'WAVE'
subchunk1ID = b'fmt '
subchunk1Size = b'\x10\x00\x00\x00'  # 0d16
audioFormat = b'\x01\x00'
numChannels = b'\x02\x00'  # 2-х каналов будет достаточно (стерео)
sampleRate = pack('

Осталось лишь только записать их в необходимой последовательности (как в таблице):

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

И так, готово. Для использования скрипта, нам нужно добавить необходимые аргументы командной строки:
python3 WAV.py [num of samples] [output]
num of samples — кол. семплов
output — путь к выходному файлу

Вот ссылка на тестовый аудиофайл с шумом, но для экономии памяти я снизил BPS до 1b/s и количество каналов опустил до 1 (с 32 битным несжатым стерео аудиопотоком в 64kbs получилось 80M чистого .wav файла, а так только 10): https://instaud.io/3Dcy

Весь код целиком (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)

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

chunkId = b'RIFF'
Format = b'WAVE'
subchunk1ID = b'fmt '
subchunk1Size = b'\x10\x00\x00\x00'  # 0d16
audioFormat = b'\x01\x00'
numChannels = b'\x02\x00'  # 2-х каналов будет достаточно (стерео) 
sampleRate = pack('


Итог

Вот вы и узнали чуть побольше о цифровом звуке и о том, как его хранят. В этом посте мы не использовали сжатия (audioFormat), но для рассмотра каждого из популярных потребуется статей 10. Надеюсь вы узнали что-то новое для себя и это вам поможет в будущих разработках.
Спасибо!


Источники

Структура WAV файла
WAV — Википедия

© Habrahabr.ru