WAVE və JPEG formatlarında media məlumatlarının sıxılması/saxlanması üsulları, 1-ci hissə

Salam! İlk məqalələr silsiləsi JPEG (şəkil) və WAVE (səs) kimi şəkil/audionun sıxılması və saxlama üsullarının öyrənilməsinə yönəldiləcək və praktikada bu formatlardan (.jpg, .wav) istifadə edən proqramların nümunələrini də əhatə edəcək. Bu hissədə WAVE-a baxacağıq.

Hekayə

WAVE (Waveform Audio File Format) audio axınının qeydini saxlamaq üçün konteyner fayl formatıdır. Bu konteyner adətən sıxılmamış impuls kodu modulyasiya edilmiş səsi saxlamaq üçün istifadə olunur. (Vikipediyadan götürülmüşdür)

1991-ci ildə RIFF ilə birlikdə Microsoft və IBM (o dövrün aparıcı İT şirkətləri) tərəfindən icad edilmiş və nəşr edilmişdir.

Fayl strukturu

Faylın başlıq hissəsi, verilənlərin özü var, lakin altbilgi yoxdur. Başlığın ümumi çəkisi 44 baytdır.
Başlıq nümunədəki bitlərin sayı, nümunə sürəti, səs dərinliyi və s. parametrləri ehtiva edir. səs kartı üçün lazım olan məlumat. (Bütün rəqəmli cədvəl dəyərləri Little-Endian qaydasında yazılmalıdır)

Blok adı
Blok ölçüsü (B)
Təsvir/Məqsəd
Dəyər (bəziləri üçün sabitdir

chunkID
4
Faylın media konteyneri kimi təyin edilməsi
Big-Endian dilində 0x52494646 (“RIFF”)

parça ölçüsü
4
chunkId və chunkSize olmadan bütün faylın ölçüsü
FILE_SIZE - 8

format
4
RIFF-dən tip tərifi
Big-Endian dilində 0x57415645 (“WAVE”)

subchunk1Id
4
Beləliklə, fayl formatın davamı olaraq daha çox yer tutur
Big-Endian dilində 0x666d7420 (“fmt”)

subchunk1Size
4
Qalan başlıq (baytla)
Varsayılan olaraq 16 (səs axınının sıxılmaması halı üçün)

audioformat
2
Audio formatı (sıxılma metodundan və audio məlumat strukturundan asılıdır)
1 (PCM üçün, biz bunu nəzərdən keçiririk)

numChannels
2
Kanalların sayı
1/2, biz 1 kanal götürəcəyik (3/4/5/6/7... - xüsusi audio trek, məsələn, dörd səs üçün 4 və s.)

nümunə dərəcəsi
4
Audio seçmə dərəcəsi (Hertz ilə)
Nə qədər yüksək olsa, səs bir o qədər yaxşı olacaq, lakin eyni uzunluqda audio trek yaratmaq üçün daha çox yaddaş tələb olunacaq, tövsiyə olunan dəyər 48000-dir (ən məqbul səs keyfiyyəti)

byteRate
4
Saniyədə bayt sayı
nümunə dərəcəsi numChannels bitsPerSample (bundan sonra)

blockAlign
2
1 nümunə üçün bayt sayı
numChannels * bitsPerSample: 8

bitsPerSample
2
1 nümunə üçün bit sayı (dərinlik)
8-in qatı olan istənilən rəqəm. Nömrə nə qədər çox olsa, səs bir o qədər yaxşı və ağır olacaq; 32 bitdən insanlar üçün heç bir fərq yoxdur

subchunk2Id
4
Məlumat istinad işarəsi (çünki audioFormatdan asılı olaraq başqa başlıq elementləri ola bilər)
Big-Endian dilində 0x64617461("data")

subchunk2Size
4
Məlumat sahəsinin ölçüsü
int-də verilənlərin ölçüsü

məlumat
byteRate * audio müddəti
Audio data
?

WAVE nümunəsi

Əvvəlki cədvəl asanlıqla C-də struktura çevrilə bilər, lakin bugünkü dilimiz Python-dur. Edə biləcəyiniz ən asan şey "dalğa" - səs-küy generatorundan istifadə etməkdir. Bu tapşırıq üçün bizə yüksək byteRate və sıxılma lazım deyil.
Əvvəlcə lazımi modulları idxal edək:

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

Sonra, cədvəldən ölçülərinə görə bütün lazımi dəyişənləri yaratmalıyıq. İçindəki dəyişən dəyərlər yalnız numSamples (nümunələrin sayı) asılıdır. Onlar nə qədər çox olsa, səsimiz bir o qədər uzun sürəcək.

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

Onları tələb olunan ardıcıllıqla yazmaq qalır (cədvəldəki kimi):

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

Və beləliklə, hazır. Skriptdən istifadə etmək üçün lazımi əmr satırı arqumentlərini əlavə etməliyik:
python3 WAV.py [num of samples] [output]
nümunələrin sayı - saymaq. nümunələri
çıxış — çıxış faylına gedən yol

Budur səs-küylü sınaq audio faylına keçid, lakin yaddaşa qənaət etmək üçün BPS-ni 1b/s-ə endirdim və kanalların sayını 1-ə endirdim (32kbs-də 64-bit sıxılmamış stereo audio axını ilə, belə çıxdı). 80M təmiz .wav faylı və yalnız 10): https://instaud.io/3Dcy

Bütün kod (WAV.py) (Kodda çoxlu dublikat dəyişən dəyərlər var, bu sadəcə eskizdir):

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

Ümumi

Beləliklə, siz rəqəmsal səs və onun necə saxlanılması haqqında bir az daha çox öyrəndiniz. Bu yazıda sıxılmadan (audioFormat) istifadə etmədik, lakin populyar olanların hər birini nəzərdən keçirmək üçün 10 məqalə tələb olunacaq.Ümid edirəm ki, özünüz üçün yeni bir şey öyrəndiniz və bu, gələcək inkişaflarda sizə kömək edəcəkdir.
Təşəkkür edirik!

İnformasiya qaynaqları

WAV fayl strukturu
WAV - Vikipediya

Mənbə: www.habr.com

Добавить комментарий