Metodes om mediadata in WAVE- en JPEG-formate saam te druk/berg, deel 1

Hallo! My eerste reeks artikels sal fokus op die bestudering van beeld-/klankkompressie- en bergingsmetodes soos JPEG (beeld) en WAVE (klank), en sal ook voorbeelde insluit van programme wat hierdie formate (.jpg, .wav) in die praktyk gebruik. In hierdie deel gaan ons na WAVE kyk.

Story

WAVE (Waveform Audio File Format) is 'n houerlêerformaat vir die stoor van 'n opname van 'n oudiostroom. Hierdie houer word tipies gebruik om ongecomprimeerde pulskode-gemoduleerde oudio te stoor. (Geneem uit Wikipedia)

Dit is in 1991 saam met RIFF deur Microsoft en IBM (Leading IT-maatskappye van daardie tyd) uitgevind en gepubliseer.

Lêerstruktuur

Die lêer het 'n kopskrif, die data self, maar geen voetskrif nie. Die kopskrif weeg altesaam 44 grepe.
Die kop bevat instellings vir die aantal bisse in die monster, monstertempo, klankdiepte, ens. inligting benodig vir die klankkaart. (Alle numeriese tabelwaardes moet in Little-Endian volgorde geskryf word)

Blok naam
Blokgrootte (B)
Beskrywing/Doel
Waarde (vir sommige is dit vas

stukId
4
Definieer 'n lêer as 'n mediahouer
0x52494646 in Big-Endian ("RIFF")

brokkie Grootte
4
Grootte van die hele lêer sonder chunkId en chunkSize
FILE_SIZE - 8

formaat
4
Tik definisie van RIFF
0x57415645 in Big-Endian ("WAVE")

subchunk1Id
4
Sodat die lêer meer spasie opneem deur die formaat voort te sit
0x666d7420 in Big-Endian ("fmt")

subchunk1 Grootte
4
Oorblywende kopskrif (in grepe)
16 by verstek (vir die geval sonder klankstroomkompressie)

oudioformaat
2
Oudioformaat (hang af van kompressiemetode en oudiodatastruktuur)
1 (vir PCM, dit is wat ons oorweeg)

aantal kanale
2
Aantal kanale
1/2, ons sal 1 kanaal neem (3/4/5/6/7... - 'n spesifieke oudiosnit, byvoorbeeld 4 vir quad-klank, ens.)

sampleRate
4
Oudio-steekproeftempo (in Hertz)
Hoe hoër, hoe beter sal die klank wees, maar hoe meer geheue benodig word om 'n oudiosnit van dieselfde lengte te skep, die aanbevole waarde is 48000 (die mees aanvaarbare klankgehalte)

byteKoerus
4
Aantal grepe per sekonde
sampleRate aantal kanale bitsPerSample (verder)

blokBelyn
2
Aantal grepe vir 1 monster
aantal kanale * stukkies per monster: 8

bitsPerSample
2
Aantal bisse per 1 monster (diepte)
Enige getal wat 'n veelvoud van 8 is. Hoe hoër die getal, hoe beter en swaarder sal die klank wees; van 32 bisse is daar geen verskil vir mense nie

subchunk2Id
4
Dataverwysingsmerk (aangesien daar ander kopelemente kan wees, afhangende van die oudioformaat)
0x64617461 in Big-Endian("data")

subchunk2 Grootte
4
Data area grootte
datagrootte in int

data
byteRate * oudio duur
Oudio data
?

GOLF voorbeeld

Die vorige tabel kan maklik in 'n struktuur in C vertaal word, maar ons taal vir vandag is Python. Die maklikste ding wat jy kan doen is om 'n "golf" te gebruik - 'n geraasgenerator. Vir hierdie taak het ons nie hoë byteRate en kompressie nodig nie.
Kom ons voer eers die nodige modules in:

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

Vervolgens moet ons al die nodige veranderlikes uit die tabel volgens hul groottes skep. Die veranderlike waardes daarin hang slegs af van numSamples (aantal steekproewe). Hoe meer van hulle daar is, hoe langer sal ons geraas aanhou.

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

Al wat oorbly is om dit in die vereiste volgorde neer te skryf (soos in die tabel):

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

En so, gereed. Om die skrif te gebruik, moet ons die nodige opdragreëlargumente byvoeg:
python3 WAV.py [num of samples] [output]
aantal monsters - tel. monsters
uitvoer - pad na die uitvoerlêer

Hier is 'n skakel na 'n toetsklanklêer met geraas, maar om geheue te bespaar het ek die BPS na 1b/s verlaag en die aantal kanale verlaag na 1 (met 'n 32-bis ongecomprimeerde stereo klankstroom op 64kbs, het dit geblyk te wees 80M suiwer .wav-lêer, en slegs 10): https://instaud.io/3Dcy

Die hele kode (WAV.py) (Die kode het baie duplikaat veranderlike waardes, dit is net 'n skets):

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

Totale

So jy het 'n bietjie meer geleer oor digitale klank en hoe dit gestoor word. In hierdie pos het ons nie kompressie (audioFormat) gebruik nie, maar om elkeen van die gewildes te oorweeg, sal 10 artikels vereis word.Ek hoop jy het iets nuuts vir jouself geleer en dit sal jou help in toekomstige ontwikkelings.
Dankie!

bronne

WAV-lêerstruktuur
WAV - Wikipedia

Bron: will.com

Voeg 'n opmerking