Multimedia datuak WAVE eta JPEG formatuetan konprimitzeko/biltegiratzeko metodoak, 1. zatia

Kaixo! Nire lehen artikulu sorta JPEG (irudia) eta WAVE (soinua) bezalako irudi/audio konpresioa eta biltegiratze metodoak aztertzera bideratuko dira, eta formatu hauek (.jpg, .wav) praktikan erabiltzen dituzten programen adibideak ere jasoko ditu. Zati honetan Uhina aztertuko dugu.

Story

WAVE (Waveform Audio File Format) audio-korronte baten grabaketa gordetzeko edukiontzi-fitxategi formatua da. Edukiontzi hau pultsu-kode modulatu gabeko audioa gordetzeko erabiltzen da normalean. (Wikipediatik hartua)

1991n RIFFrekin batera asmatu eta argitaratu zuten Microsoftek eta IBMk (orduko IT konpainia nagusiak).

Fitxategien egitura

Fitxategiak goiburuko zati bat du, datuak berak, baina oin-oinik ez. Goiburuak 44 byte pisatzen ditu guztira.
Goiburuak laginaren bit kopurua, lagin-abiadura, soinu-sakonera, etab. soinu-txartelerako behar den informazioa. (Taula zenbakizko balio guztiak Little-Endian ordenan idatzi behar dira)

Blokearen izena
Blokearen tamaina (B)
Deskribapena/Helburua
Balioa (batzuentzat finkoa da

chunkId
4
Fitxategi bat multimedia edukiontzi gisa definitzea
0x52494646 Big-Endian ("RIFF")

chunkSize
4
Fitxategi osoaren tamaina chunkId eta chunkSize gabe
FILE_SIZE - 8

formatuan
4
Mota definizioa RIFF-tik
0x57415645 Big-Endian ("WAVE")

azpitxanda1Id
4
Fitxategiak leku gehiago har dezan formatuaren jarraipena gisa
0x666d7420 Big-Endian ("fmt")

azpitxukun1Tamaina
4
Gainerako goiburua (bytetan)
16 lehenespenez (audio-korrontearen konpresiorik gabeko kasurako)

audioFormat
2
Audio formatua (konpresio metodoaren eta audio-datuen egituraren araberakoa da)
1 (PCMrako, hau da, kontuan hartzen ari garen)

numChannels
2
Kanal kopurua
1/2, kanal 1 hartuko dugu (3/4/5/6/7... - audio pista zehatz bat, adibidez 4 soinu laukoentzat, etab.)

laginTasa
4
Audio-laginketa-tasa (Hertz-tan)
Zenbat eta handiagoa, orduan eta soinu hobea izango da, baina zenbat eta memoria gehiago beharko da luzera bereko audio-pista sortzeko, gomendatutako balioa 48000 da (soinu-kalitate onargarriena)

byteRate
4
Segundoko byte kopurua
laginTasa numChannels bitsPer Sample (gehiago)

blockAlign
2
Lagin baterako byte kopurua
numChannels * bitsPer Sample: 8

bitsPerSample
2
Lagin bakoitzeko bit kopurua (sakonera)
8ren multiploa den edozein zenbaki. Zenbat eta handiagoa izan, orduan eta hobea eta astunagoa izango da audioa; 32 bitetik aurrera ez dago desberdintasunik gizakientzat.

azpitxanda2Id
4
Datu-erreferentzia marka (audioFormat-aren arabera goiburuko beste elementu batzuk egon daitezkeelako)
0x64617461 Big-Endian("datuak")

azpitxukun2Tamaina
4
Datu-eremuaren tamaina
datuen tamaina int

datuak
byteRate * audioaren iraupena
Audio datuak
?

WAVE adibidea

Aurreko taula erraz itzul daiteke egitura batera C-n, baina gaurko hizkuntza Python da. Egin dezakezun gauzarik errazena "uhin" bat erabiltzea da - zarata-sorgailu bat. Zeregin honetarako ez dugu byteRate eta konpresio handirik behar.
Lehenik eta behin, inporta ditzagun beharrezko moduluak:

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

Ondoren, taulatik beharrezko aldagai guztiak sortu behar ditugu haien tamainaren arabera. Bertan dauden balio aldagaiak numSamples (lagin kopurua) soilik araberakoak dira. Zenbat eta gehiago izan, orduan eta luzeagoa izango da gure zarata.

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

Beharrezko sekuentzian idaztea besterik ez da geratzen (taulan bezala):

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

Eta horrela, prest. Scripta erabiltzeko, beharrezko komando lerroko argumentuak gehitu behar ditugu:
python3 WAV.py [num of samples] [output]
lagin kopurua - zenbatu. laginak
output — irteera fitxategirako bidea

Hona hemen zarata duen probako audio fitxategi baterako esteka, baina memoria aurrezteko BPS 1b/s-ra jaitsi nuen eta kanal-kopurua 1era jaitsi nuen (32 biteko konprimitu gabeko audio-korronte estereoarekin 64 kb-tan, izan zen. .wav fitxategi hutseko 80M, eta 10 bakarrik): https://instaud.io/3Dcy

Kode osoa (WAV.py) (Kodeak balio aldagai bikoiztu asko ditu, hau zirriborro bat besterik ez da):

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

Guztira

Beraz, pixka bat gehiago ikasi duzu soinu digitalari buruz eta nola gordetzen den. Post honetan ez dugu konpresiorik erabili (audioFormat), baina ezagunak diren bakoitza kontuan hartzeko, 10 artikulu beharko dira.Espero dut zuk zeuk zerbait berria ikasi izana eta honek etorkizuneko garapenetan lagunduko dizula.
Eskerrik asko!

iturri

WAV fitxategien egitura
WAV - Wikipedia

Iturria: www.habr.com

Gehitu iruzkin berria