Aðferðir til að þjappa/geyma miðlunargögn á WAVE og JPEG sniðum, hluti 1

Halló! Fyrsta greinaröð mín mun fjalla um að rannsaka mynd/hljóð þjöppun og geymsluaðferðir eins og JPEG (mynd) og WAVE (hljóð), og mun einnig innihalda dæmi um forrit sem nota þessi snið (.jpg, .wav) í reynd. Í þessum hluta munum við skoða WAVE.

Story

WAVE (Waveform Audio File Format) er gámaskráarsnið til að geyma upptöku af hljóðstraumi. Þetta ílát er venjulega notað til að geyma óþjappað hljóðbreytt púlskóða. (Tekið af Wikipedia)

Það var fundið upp og gefið út árið 1991 ásamt RIFF af Microsoft og IBM (Leiðandi upplýsingatæknifyrirtæki þess tíma).

Uppbygging skráa

Skráin hefur haushluta, gögnin sjálf, en enginn fótur. Hausinn vegur samtals 44 bæti.
Hausinn inniheldur stillingar fyrir fjölda bita í sýninu, sýnishraða, hljóðdýpt osfrv. upplýsingar sem þarf fyrir hljóðkortið. (Öll töluleg töflugildi verða að vera skrifuð í Little-Endian röð)

Nafn blokk
Stærð blokk (B)
Lýsing/tilgangur
Gildi (fyrir suma er það fast

klumpur
4
Að skilgreina skrá sem miðlunarílát
0x52494646 í Big-Endian ("RIFF")

klumpurStærð
4
Stærð allrar skráarinnar án chunkId og chunkSize
FILE_SIZE - 8

snið
4
Tegundarskilgreining frá RIFF
0x57415645 í Big-Endian („WAVE“)

subchunk1Id
4
Svo að skráin tekur meira pláss með því að halda áfram sniðinu
0x666d7420 í Big-Endian ("fmt")

subchunk1Stærð
4
Eftirstandandi haus (í bætum)
16 sjálfgefið (fyrir tilvikið án hljóðstraumsþjöppunar)

hljóðsnið
2
Hljóðsnið (fer eftir þjöppunaraðferð og uppbyggingu hljóðgagna)
1 (fyrir PCM, sem er það sem við erum að íhuga)

numChannels
2
Fjöldi rása
1/2, við munum taka 1 rás (3/4/5/6/7... - ákveðið hljóðlag, til dæmis 4 fyrir quad hljóð, osfrv.)

sampleRate
4
Hljóðsýnishraðni (í Hertz)
Því hærra, því betra verður hljóðið, en því meira minni sem þarf til að búa til hljóðlag af sömu lengd, ráðlagt gildi er 48000 (viðunandi hljóðgæði)

bætahlutfall
4
Fjöldi bæta á sekúndu
sampleRate numChannels bitsPerSample (nánar)

blockAlign
2
Fjöldi bæta fyrir 1 sýni
fjöldiRásar * bitsPerSample: 8

bitsPerSample
2
Fjöldi bita á 1 sýni (dýpt)
Sérhver tala sem er margfeldi af 8. Því hærri sem talan er, því betra og þyngra verður hljóðið, frá 32 bitum er enginn munur fyrir menn

subchunk2Id
4
Gagnaviðmiðunarmerki (þar sem það geta verið aðrir hausþættir eftir hljóðsniði)
0x64617461 í Big-Endian ("gögn")

subchunk2Stærð
4
Gagnasvæðisstærð
gagnastærð í int

gögn
byteRate * hljóðlengd
Hljóðgögn
?

WAVE dæmi

Hægt er að þýða fyrri töfluna yfir í uppbyggingu í C, en tungumálið okkar í dag er Python. Það auðveldasta sem þú getur gert er að nota „bylgju“ - hávaðagjafa. Fyrir þetta verkefni þurfum við ekki háan bætihraða og þjöppun.
Fyrst skulum við flytja inn nauðsynlegar einingar:

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

Næst þurfum við að búa til allar nauðsynlegar breytur úr töflunni í samræmi við stærðir þeirra. Breytugildin í því eru aðeins háð numSamples (fjöldi sýna). Því fleiri sem þeir eru, því lengur mun hávaði okkar halda áfram.

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

Allt sem er eftir er að skrifa þau niður í tilskildri röð (eins og í töflunni):

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

Og svo, tilbúinn. Til að nota handritið þurfum við að bæta við nauðsynlegum skipanalínurökum:
python3 WAV.py [num of samples] [output]
fjöldi sýna - telja. sýnishorn
úttak — slóð að úttaksskránni

Hér er hlekkur á prufuhljóðskrá með hávaða, en til að spara minni lækkaði ég BPS niður í 1b/s og lækkaði fjölda rása niður í 1 (með 32 bita óþjappað steríó hljóðstraum á 64kbs reyndist það vera 80M af hreinni .wav skrá og aðeins 10): https://instaud.io/3Dcy

Allur kóðinn (WAV.py) (Kóðinn hefur mikla tvítekningu á breytugildum, þetta er bara skissa):

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

Samtals

Þannig að þú hefur lært aðeins meira um stafrænt hljóð og hvernig það er geymt. Í þessari færslu notuðum við ekki þjöppun (audioFormat), en til að íhuga hverja vinsælustu, þarf 10 greinar. Ég vona að þú hafir lært eitthvað nýtt fyrir sjálfan þig og þetta mun hjálpa þér í framtíðinni.
Þakka þér!

Heimildir

Uppbygging WAV skráar
WAV - Wikipedia

Heimild: www.habr.com

Bæta við athugasemd