Metòd pou konpresyon / estoke done medya nan fòma WAVE ak JPEG, pati 1

Bonjou! Premye seri atik mwen an pral konsantre sou etid konpresyon imaj/odyo ak metòd depo tankou JPEG (imaj) ak WAVE (son), epi yo pral gen ladan tou egzanp pwogram ki itilize fòma sa yo (.jpg, .wav) nan pratik. Nan pati sa a nou pral gade nan WAVE.

Istwa

WAVE (Waveform Audio File Format) se yon fòma dosye veso pou estoke yon anrejistreman yon kouran odyo. Veso sa a anjeneral itilize pou estoke odyo ki pa konprese kòd batman. (Te pran nan Wikipedia)

Li te envante epi pibliye an 1991 ansanm ak RIFF pa Microsoft ak IBM (Leading IT konpayi yo nan tan sa a).

Estrikti dosye

Fichye a gen yon pati header, done nan tèt li, men pa gen okenn pye. Tèt la peze yon total de 44 octets.
Tèt la gen paramèt pou kantite bit nan echantiyon an, pousantaj echantiyon, pwofondè son, elatriye. enfòmasyon ki nesesè pou kat son an. (Tout valè tablo nimerik yo dwe ekri nan lòd Little-Endian)

Non blòk
Gwosè blòk (B)
Deskripsyon / Objektif
Valè (pou kèk li fiks

chunkId
4
Defini yon dosye kòm yon veso medya
0x52494646 nan Big-Endian ("RIFF")

chunkSize
4
Gwosè tout fichye a san chunkId ak chunkSize
FILE_SIZE - 8

fòma
4
Kalite definisyon soti nan RIFF
0x57415645 nan Big-Endian ("WAVE")

subchunk1Id
4
Se konsa ke dosye a pran plis espas kòm yon kontinyasyon nan fòma a
0x666d7420 nan Big-Endian ("fmt")

subchunk1Size
4
Tèt ki rete (an byte)
16 pa default (pou ka a san konpresyon kouran odyo)

odyoFormat
2
Fòma odyo (depann sou metòd konpresyon ak estrikti done odyo)
1 (pou PCM, ki se sa n ap konsidere)

numChannels
2
Nimewo nan chanèl
1/2, nou pral pran 1 chanèl (3/4/5/6/7... - yon tras odyo espesifik, pou egzanp 4 pou son kwadwilatè, elatriye)

sampleRate
4
To echantiyon odyo (nan Hertz)
Plis pi wo, pi bon son an pral, men plis memwa yo pral oblije kreye yon track odyo ki gen menm longè, valè rekòmande a se 48000 (bon jan kalite son ki pi akseptab)

byteRate
4
Kantite byte pou chak segonn
sampleRate numChannels bitsPerSample (plis)

blockAlign
2
Kantite byte pou 1 echantiyon
numChannels * bitsPerSample: 8

bitsPerSample
2
Kantite Bits pou chak echantiyon 1 (pwofondè)
Nenpòt nimewo ki se yon miltip nan 8. Plis nimewo a pi wo, se pi bon ak pi lou odyo a, soti nan 32 bit pa gen okenn diferans pou moun.

subchunk2Id
4
Done referans mak (piske ka gen lòt eleman header depann sou odyoFormat la)
0x64617461 nan Big-Endian ("done")

subchunk2Size
4
Gwosè zòn done
gwosè done nan int

done
byteRate * dire odyo
Done odyo
?

Egzanp WAVE

Tablo anvan an ka fasilman tradui nan yon estrikti nan C, men lang nou jodi a se Python. Bagay ki pi fasil ou ka fè se sèvi ak yon "vag" - yon dèlko bri. Pou travay sa a nou pa bezwen gwo byteRate ak konpresyon.
Premyèman, ann enpòte modil ki nesesè yo:

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

Apre sa, nou bezwen kreye tout varyab ki nesesè yo nan tab la selon gwosè yo. Valè yo varyab nan li depann sèlman de numSamples (kantite echantiyon). Plis yo genyen, se plis bri nou an ap kontinye.

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

Tout sa ki rete se ekri yo nan sekans ki nesesè yo (tankou nan tablo a):

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

Se konsa, pare. Pou itilize script la, nou bezwen ajoute agiman liy lòd ki nesesè yo:
python3 WAV.py [num of samples] [output]
kantite echantiyon - konte. echantiyon
pwodiksyon - chemen nan dosye pwodiksyon an

Isit la se yon lyen ki mennen nan yon dosye odyo tès ak bri, men pou konsève pou memwa mwen bese BPS a 1b / s ak bese kantite chanèl yo a 1 (ak yon kouran odyo stereo 32-bit dekonprese nan 64kbs, li te tounen soti yo dwe 80M nan pi bon kalite .wav dosye, ak sèlman 10): https://instaud.io/3Dcy

Tout kòd la (WAV.py) (Kòd la gen anpil valè varyab kopi, sa a se jis yon chema):

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

Total

Se konsa, ou te aprann yon ti kras plis sou son dijital ak ki jan li estoke. Nan pòs sa a nou pa t 'sèvi ak konpresyon (audioFormat), men yo konsidere chak nan sa yo popilè yo, yo pral mande 10 atik.Mwen espere ou te aprann yon bagay nouvo pou tèt ou e sa ap ede ou nan devlopman nan lavni.
Mèsi!

Sous

Estrikti dosye WAV
WAV - Wikipedya

Sous: www.habr.com

Add nouvo kòmantè