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

Zdravo! Moja prva serija članaka usredotočit će se na proučavanje metoda kompresije slike/audija i pohrane kao što su JPEG (slika) i WAVE (zvuk), a također će uključivati ​​primjere programa koji koriste te formate (.jpg, .wav) u praksi. U ovom dijelu ćemo pogledati WAVE.

Priča

WAVE (Waveform Audio File Format) je format datoteke spremnika za pohranjivanje snimke audio streama. Ovaj se spremnik obično koristi za pohranu nekomprimiranog audio moduliranog pulsnog koda. (Preuzeto s Wikipedije)

Izmislili su ga i objavili 1991. zajedno s RIFF-om Microsoft i IBM (vodeće IT tvrtke tog vremena).

Struktura datoteke

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

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

chunkId
4
Definiranje datoteke kao medijskog spremnika
0x52494646 u Big-Endianu ("RIFF")

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

format
4
Definicija tipa iz RIFF-a
0x57415645 u Big-Endianu ("WAVE")

subchunk1Id
4
Tako da datoteka zauzima više prostora nastavljajući format
0x666d7420 u Big-Endianu ("fmt")

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

audioFormat
2
Audio format (ovisi o metodi kompresije i strukturi audio podataka)
1 (za PCM, što je ono š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 audio, itd.)

uzorak stope
4
Brzina uzorkovanja zvuka (u hercima)
Što je veći, to će zvuk biti bolji, ali što će više memorije biti potrebno za stvaranje zvučnog zapisa iste duljine, preporučena vrijednost je 48000 (najprihvatljivija kvaliteta zvuka)

byteRate
4
Broj bajtova u sekundi
uzorak stope 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šekratnik broja 8. Što je veći broj, zvuk će biti bolji i teži; od 32 bita nema razlike za ljude

subchunk2Id
4
Referentna oznaka podataka (budući da mogu postojati drugi elementi zaglavlja ovisno o audioFormatu)
0x64617461 u Big-Endianu ("podaci")

subchunk2Size
4
Veličina područja podataka
veličina podataka u int

datum
byteRate * trajanje zvuka
Audio podaci
?

Primjer VALA

Prethodna tablica se lako može prevesti u strukturu u C-u, ali naš jezik za danas je Python. Najjednostavnije što možete učiniti je koristiti "val" - generator buke. Za ovaj zadatak ne trebamo visoku brzinu bajtova i kompresiju.
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 ovise samo o numSamples (broj uzoraka). Što ih je više, to će naša buka 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 traženim redoslijedom (kao u tablici):

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, spremni. Da bismo koristili skriptu, moramo dodati potrebne argumente naredbenog retka:
python3 WAV.py [num of samples] [output]
broj uzoraka - broj. uzorci
izlaz — put do izlazne datoteke

Ovdje je poveznica na testnu audio datoteku sa šumom, ali da uštedim memoriju spustio sam BPS na 1b/s i broj kanala na 1 (s 32-bitnim nekomprimiranim stereo audio streamom na 64kbs pokazalo se da je 80M čiste .wav datoteke, a samo 10): https://instaud.io/3Dcy

Cijeli kod (WAV.py) (Kod ima puno duplih 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)  # записываем в файл результат

Ukupan

Dakle, naučili ste nešto više o digitalnom zvuku i kako se pohranjuje. U ovom postu nismo koristili kompresiju (audioFormat), ali za razmatranje svakog od popularnih bit ć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

WAV struktura datoteke
WAV - Wikipedia

Izvor: www.habr.com

Dodajte komentar