Metode kompresije/pohranjivanja medijskih podataka u WAVE i JPEG formatima, dio 1

Zdravo! Moja prva serija članaka će se fokusirati na proučavanje kompresije slike/audio i metoda skladištenja kao što su JPEG (slika) i WAVE (zvuk), a uključit će i primjere programa koji koriste ove formate (.jpg, .wav) u praksi. U ovom dijelu ćemo pogledati WAVE.

История

WAVE (Waveform Audio File Format) je format datoteke kontejnera za pohranjivanje snimka audio toka. Ovaj kontejner se obično koristi za skladištenje nekomprimovanog zvuka moduliranog impulsnim kodom. (preuzeto sa Wikipedije)

Izmislili su ga i objavili 1991. zajedno sa RIFF-om od strane Microsofta i IBM-a (vodeće IT kompanije tog vremena).

Struktura fajla

Datoteka ima dio zaglavlja, same podatke, ali nema podnožje. Zaglavlje ima ukupno 44 bajta.
Zaglavlje sadrži postavke za broj bitova u uzorku, brzinu uzorkovanja, dubinu zvuka itd. informacije potrebne za zvučnu karticu. (Sve vrijednosti numeričke tablice moraju biti zapisane u Little-Endian redoslijedu)

Naziv bloka
Veličina bloka (B)
Opis/Svrha
Vrijednost (za neke je fiksna

chunkId
4
Definiranje datoteke kao medijskog kontejnera
0x52494646 u Big-Endian (“RIFF”)

chunkSize
4
Veličina cijele datoteke bez chunkId i chunkSize
FILE_SIZE - 8

format
4
Definicija tipa iz RIFF-a
0x57415645 u Big-Endian (“TALAS”)

subchunk1Id
4
Tako da datoteka zauzima više prostora kao nastavak formata
0x666d7420 u Big-Endian (“fmt”)

subchunk1Size
4
Preostalo zaglavlje (u bajtovima)
16 prema zadanim postavkama (za slučaj bez kompresije audio toka)

audioFormat
2
Audio format (ovisi o metodi kompresije i strukturi audio podataka)
1 (za PCM, što razmatramo)

numChannels
2
Broj kanala
1/2, uzet ćemo 1 kanal (3/4/5/6/7... - određeni audio zapis, na primjer 4 za quad zvuk, itd.)

sampleRate
4
Stopa uzorkovanja zvuka (u hercima)
Što je veći, to će zvuk biti bolji, ali što će više memorije biti potrebno za kreiranje audio zapisa iste dužine, preporučena vrijednost je 48000 (najprihvatljiviji kvalitet zvuka)

byteRate
4
Broj bajtova u sekundi
sampleRate numChannels bitsPerSample (dalje)

blockAlign
2
Broj bajtova za 1 uzorak
numChannels * bitsPerSample: 8

bitsPerSample
2
Broj bitova po 1 uzorku (dubina)
Bilo koji broj koji je višestruki od 8. Što je veći broj, to će zvuk biti bolji i teži; od 32 bita nema razlike za ljude

subchunk2Id
4
Referentna oznaka podataka (pošto mogu postojati i drugi elementi zaglavlja u zavisnosti od audioformata)
0x64617461 u Big-Endian ("podaci")

subchunk2Size
4
Veličina područja podataka
veličina podataka u međ

podaci
byteRate * trajanje zvuka
Audio podaci
?

WAVE primjer

Prethodna tabela se lako može prevesti u strukturu u C, ali naš jezik za danas je Python. Najlakše što možete učiniti je koristiti "val" - generator buke. Za ovaj zadatak nam nije potrebna visoka brzina bajtova i kompresija.
Prvo, uvezimo potrebne 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)

Zatim moramo kreirati sve potrebne varijable iz tablice prema njihovim veličinama. Vrijednosti varijable u njemu zavise samo od numSamples (broja uzoraka). Što ih je više, naša buka će trajati duže.

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

Ostaje samo da ih zapišete u traženom redoslijedu (kao u tabeli):

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

I tako, spreman. Da bismo koristili skriptu, moramo dodati potrebne argumente komandne linije:
python3 WAV.py [num of samples] [output]
broj uzoraka - broj. uzorci
output — putanja do izlazne datoteke

Evo linka do probnog audio fajla sa šumom, ali da uštedim memoriju, smanjio sam BPS na 1b/s i smanjio broj kanala na 1 (sa 32-bitnim nekomprimovanim stereo audio streamom na 64kbs, ispostavilo se da je 80M čistog .wav fajla i samo 10): https://instaud.io/3Dcy

Cijeli kod (WAV.py) (Kôd ima puno dupliranih vrijednosti varijabli, ovo je samo skica):

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

Rezultat

Dakle, naučili ste nešto više o digitalnom zvuku i kako se on pohranjuje. U ovom postu nismo koristili kompresiju (audioFormat), ali za razmatranje svakog od najpopularnijih biće potrebno 10 članaka.Nadam se da ste naučili nešto novo za sebe i da će vam to pomoći u budućem razvoju.
Hvala vam!

Izvori

Struktura WAV datoteke
WAV - Wikipedia

izvor: www.habr.com

Dodajte komentar