Mga pamamaraan para sa pag-compress/pag-imbak ng data ng media sa mga format na WAVE at JPEG, bahagi 1

Kamusta! Ang aking unang serye ng mga artikulo ay tututuon sa pag-aaral ng image/audio compression at mga paraan ng pag-iimbak gaya ng JPEG (image) at WAVE (tunog), at magsasama rin ng mga halimbawa ng mga program na gumagamit ng mga format na ito (.jpg, .wav) sa pagsasanay. Sa bahaging ito ay titingnan natin ang WAVE.

Kuwento

Ang WAVE (Waveform Audio File Format) ay isang container file format para sa pag-iimbak ng recording ng isang audio stream. Ang lalagyan na ito ay karaniwang ginagamit upang mag-imbak ng hindi naka-compress na pulse code na modulated na audio. (Nakuha mula sa Wikipedia)

Ito ay naimbento at nai-publish noong 1991 kasama ng RIFF ng Microsoft at IBM (Nangungunang mga kumpanya ng IT noong panahong iyon).

Istraktura ng file

Ang file ay may bahagi ng header, ang data mismo, ngunit walang footer. Ang header ay tumitimbang ng kabuuang 44 bytes.
Ang header ay naglalaman ng mga setting para sa bilang ng mga bit sa sample, sample rate, sound depth, atbp. impormasyong kailangan para sa sound card. (Ang lahat ng mga numeric na halaga ng talahanayan ay dapat na nakasulat sa Little-Endian order)

Block name
Laki ng block (B)
Paglalarawan/Layunin
Halaga (para sa ilan ito ay naayos

chunkId
4
Pagtukoy sa isang file bilang isang lalagyan ng media
0x52494646 sa Big-Endian (“RIFF”)

chunkSize
4
Sukat ng buong file na walang chunkId at chunkSize
FILE_SIZE - 8

format
4
Uri ng kahulugan mula sa RIFF
0x57415645 sa Big-Endian (“WAVE”)

subchunk1Id
4
Upang ang file ay tumatagal ng mas maraming espasyo sa pamamagitan ng pagpapatuloy sa format
0x666d7420 sa Big-Endian (“fmt”)

subchunk1Size
4
Natitirang header (sa bytes)
16 bilang default (para sa kaso na walang audio stream compression)

AudioFormat
2
Format ng audio (depende sa paraan ng compression at istraktura ng data ng audio)
1 (para sa PCM, na aming isinasaalang-alang)

numChannels
2
Bilang ng mga channel
1/2, kukuha kami ng 1 channel (3/4/5/6/7... - isang partikular na audio track, halimbawa 4 para sa quad sound, atbp.)

sampleRate
4
Rate ng pagsa-sample ng audio (sa Hertz)
Kung mas mataas, mas magiging maganda ang tunog, ngunit mas maraming memory ang kakailanganin upang lumikha ng audio track na may parehong haba, ang inirerekomendang halaga ay 48000 (ang pinakakatanggap-tanggap na kalidad ng tunog)

byteRate
4
Bilang ng mga byte bawat segundo
sampleRate numChannels bitsPerSample (karagdagang)

blockAlign
2
Bilang ng mga byte para sa 1 sample
numChannels * bitsPerSample: 8

bitsPerSample
2
Bilang ng mga bit bawat 1 sample (depth)
Anumang numero na multiple ng 8. Kung mas mataas ang numero, mas maganda at mas mabigat ang audio; mula sa 32 bits ay walang pagkakaiba para sa mga tao

subchunk2Id
4
Sangguniang marka ng data (dahil maaaring may iba pang elemento ng header depende sa audioFormat)
0x64617461 sa Big-Endian("data")

subchunk2Size
4
Laki ng lugar ng data
laki ng data sa int

data
byteRate * tagal ng audio
Data ng audio
?

Halimbawa ng WAVE

Ang nakaraang talahanayan ay madaling isalin sa isang istraktura sa C, ngunit ang aming wika para sa ngayon ay Python. Ang pinakamadaling bagay na maaari mong gawin ay gumamit ng "alon" - isang generator ng ingay. Para sa gawaing ito hindi namin kailangan ng mataas na byteRate at compression.
Una, i-import natin ang mga kinakailangang module:

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

Susunod, kailangan nating lumikha ng lahat ng kinakailangang mga variable mula sa talahanayan ayon sa kanilang mga sukat. Ang mga variable na halaga dito ay nakasalalay lamang sa numSamples (bilang ng mga sample). Kung mas marami sila, mas tumatagal ang ingay natin.

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)  # сам шум

Ang natitira na lang ay isulat ang mga ito sa kinakailangang pagkakasunud-sunod (tulad ng sa talahanayan):

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

At kaya, handa na. Upang magamit ang script, kailangan nating magdagdag ng mga kinakailangang argumento ng command line:
python3 WAV.py [num of samples] [output]
bilang ng mga sample - bilang. mga sample
output — landas patungo sa output file

Narito ang isang link sa isang pagsubok na audio file na may ingay, ngunit upang makatipid ng memorya ay ibinaba ko ang BPS sa 1b/s at ibinaba ang bilang ng mga channel sa 1 (na may 32-bit na hindi naka-compress na stereo audio stream sa 64kbs, ito ay naging 80M ng purong .wav file, at 10 lang): https://instaud.io/3Dcy

Ang buong code (WAV.py) (Ang code ay may maraming mga dobleng variable na halaga, ito ay isang sketch lamang):

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)  # записываем в файл результат

Kabuuan

Kaya natuto ka ng kaunti pa tungkol sa digital sound at kung paano ito iniimbak. Sa post na ito hindi kami gumamit ng compression (audioFormat), ngunit upang isaalang-alang ang bawat isa sa mga sikat, kakailanganin ang 10 artikulo. Sana ay may natutunan kang bago para sa iyong sarili at makakatulong ito sa iyo sa mga susunod na pag-unlad.
Salamat sa iyo!

pinagmumulan

istraktura ng WAV file
WAV - Wikipedia

Pinagmulan: www.habr.com

Magdagdag ng komento