Métode pikeun ngompres/nyimpen data média dina format WAVE sareng JPEG, bagian 1

Halo! Séri artikel munggaran kuring bakal difokuskeun diajar komprési gambar / audio sareng metode panyimpen sapertos JPEG (gambar) sareng WAVE (sora), sareng ogé bakal kalebet conto program anu nganggo format ieu (.jpg, .wav) dina praktékna. Dina bagian ieu urang bakal ningali WAVE.

dongeng

WAVE (Waveform Audio File Format) nyaéta format file wadahna pikeun nyimpen rékaman aliran audio. Wadah ieu biasana dianggo pikeun nyimpen audio modulasi kode pulsa anu teu dikomprés. (Dicutat tina Wikipedia)

Éta diciptakeun sareng diterbitkeun taun 1991 sareng RIFF ku Microsoft sareng IBM (Pausahaan IT terkemuka waktos éta).

Struktur file

file ngabogaan bagian lulugu, data sorangan, tapi euweuh footer. lulugu ngabogaan beurat total 44 bait.
Lulugu ngandung setélan pikeun jumlah bit dina sampel, laju sampel, jero sora, jsb. informasi diperlukeun pikeun kartu sora. (Sadaya nilai tabel numerik kudu ditulis dina urutan Little-Endian)

Ngaran blok
Ukuran blok (B)
Katerangan / Tujuan
Nilai (pikeun sababaraha éta tetep

chunkId
4
Nangtukeun file salaku wadah media
0x52494646 dina Big-Endian ("RIFF")

chunkSize
4
Ukuran sakabéh file tanpa chunkId na chunkSize
UKURAN_FILE - 8

wujud jeung ukuran
4
Tipe harti tina RIFF
0x57415645 dina Big-Endian ("GELOMBANG")

subchunk1Id
4
Sangkan file nyokot leuwih spasi salaku tuluyan tina format
0x666d7420 dina Big-Endian ("fmt")

subchunk1Ukuran
4
Sésana lulugu (dina bait)
16 sacara standar (pikeun kasus tanpa komprési aliran audio)

audioFormat
2
Format audio (gumantung kana metode komprési sareng struktur data audio)
1 (pikeun PCM, anu kami pertimbangkeun)

numChannels
2
Jumlah saluran
1/2, urang bakal nyandak 1 saluran (3/4/5/6/7... - lagu audio husus, contona 4 pikeun sora quad, jsb)

sampleRate
4
Laju sampling audio (dina Hertz)
Langkung luhur, langkung saé sorana, tapi langkung seueur mémori anu diperyogikeun pikeun nyiptakeun lagu audio anu panjangna sami, nilai anu disarankeun nyaéta 48000 (kualitas sora anu paling ditarima).

byteRate
4
Jumlah bait per detik
sampleRate numChannels bitPerSample (salajengna)

blockAlign
2
Jumlah bait pikeun 1 sampel
numChannels * bitPerSample: 8

bitPerSample
2
Jumlah bit per 1 sampel (jero)
Sakur angka nu mangrupa kelipatan 8. Nu leuwih luhur jumlahna, nu hadé tur beurat audio bakal jadi; ti 32 bit teu aya bédana pikeun manusa.

subchunk2Id
4
Tanda rujukan data (sabab meureun aya elemen lulugu séjén gumantung kana audioFormat)
0x64617461 dina Big-Endian("data")

subchunk2Ukuran
4
Ukuran wewengkon data
ukuran data dina int

data
byteRate * durasi audio
Data audio
?

conto WAVE

Tabél saméméhna tiasa gampang ditarjamahkeun kana struktur dina C, tapi basa urang ayeuna nyaéta Python. Hal panggampangna anu anjeun tiasa laksanakeun nyaéta ngagunakeun "gelombang" - generator noise. Pikeun tugas ieu kami henteu peryogi byteRate sareng komprési anu luhur.
Mimiti, hayu urang ngimpor modul anu diperyogikeun:

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

Salajengna, urang kedah nyiptakeun sadaya variabel anu diperyogikeun tina méja dumasar kana ukuranana. Nilai variabel di jerona ngan ukur gumantung kana numSamples (jumlah sampel). Beuki loba di antarana, beuki lila noise urang bakal nuluykeun.

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

Sadaya anu tetep nyaéta nyerat aranjeunna dina urutan anu diperyogikeun (sapertos dina tabél):

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

Janten, siap. Pikeun nganggo naskah, urang kedah nambihan argumen baris paréntah anu diperyogikeun:
python3 WAV.py [num of samples] [output]
jumlah sampel - cacah. sampel
output - jalur ka file output

Ieu mangrupikeun tautan kana file audio tés kalayan sora, tapi pikeun ngahémat mémori kuring nurunkeun BPS ka 1b / s sareng ngirangan jumlah saluran ka 1 (kalayan aliran audio stereo 32-bit anu henteu dikomprés dina 64kbs, tétéla janten 80M file .wav murni, sareng ngan 10): https://instaud.io/3Dcy

Sakabéh kode (WAV.py) (Kodena ngagaduhan seueur nilai variabel duplikat, ieu ngan ukur sketsa):

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

hasil

Janten anjeun parantos diajar sakedik ngeunaan sora digital sareng kumaha disimpenna. Dina postingan ieu kami henteu nganggo komprési (audioFormat), tapi pikeun nganggap unggal anu populér, bakal diperyogikeun artikel 10. Abdi ngarepkeun anjeun diajar anu énggal pikeun diri anjeun sareng ieu bakal ngabantosan anjeun dina kamajuan anu bakal datang.
Hatur nuhun!

sumber

Struktur file WAV
WAV - Wikipédia

sumber: www.habr.com

Tambahkeun komentar