Մեդիա տվյալների WAVE և JPEG ձևաչափերով սեղմելու/պահպանելու մեթոդներ, մաս 1

Բարեւ Ձեզ! Իմ առաջին հոդվածների շարքը կկենտրոնանա պատկերի/ձայնի սեղմման և պահպանման մեթոդների ուսումնասիրության վրա, ինչպիսիք են JPEG (պատկեր) և WAVE (ձայն), ինչպես նաև կներառեն այս ձևաչափերը (.jpg, .wav) գործնականում օգտագործող ծրագրերի օրինակներ: Այս մասում մենք կանդրադառնանք WAVE-ին:

Պատմություն

WAVE (Waveform Audio File Format) կոնտեյներային ֆայլի ձևաչափ է՝ աուդիո հոսքի ձայնագրությունը պահելու համար: Այս բեռնարկղը սովորաբար օգտագործվում է չսեղմված իմպուլսային կոդով մոդուլավորված աուդիո պահելու համար: (վերցված է Վիքիպեդիայից)

Այն հորինվել և հրատարակվել է 1991 թվականին RIFF-ի հետ միասին՝ Microsoft-ի և IBM-ի (այն ժամանակվա առաջատար ՏՏ ընկերություններ):

Ֆայլի կառուցվածքը

Ֆայլն ունի վերնագրի մաս, տվյալներն ինքնին, բայց ոչ ստորագիր: Վերնագիրն ընդհանուր առմամբ կշռում է 44 բայթ:
Վերնագիրը պարունակում է նմուշի բիթերի քանակի կարգավորումներ, նմուշի արագություն, ձայնի խորություն և այլն: ձայնային քարտի համար անհրաժեշտ տեղեկատվություն. (Բոլոր թվային աղյուսակի արժեքները պետք է գրվեն Little-Endian կարգով)

Արգելափակման անունը
Բլոկի չափը (B)
Նկարագրություն/Նպատակ
Արժեքը (ոմանց համար այն ամրագրված է

chunkId
4
Ֆայլի սահմանում որպես մեդիա կոնտեյներ
0x52494646 Big-Endian-ում («RIFF»)

chunkSize
4
Ամբողջ ֆայլի չափը՝ առանց chunkId-ի և chunkSize-ի
FILE_SIZE - 8

ֆորմատ
4
Տիպի սահմանումը RIFF-ից
0x57415645 Big-Endian («ԱԼԻՔ»)

subchunk1Id
4
Որպեսզի ֆայլը ավելի շատ տեղ զբաղեցնի՝ շարունակելով ձևաչափը
0x666d7420 Big-Endian («fmt»)

subchunk1 Չափ
4
Մնացած վերնագիր (բայթերով)
16 լռելյայն (առանց աուդիո հոսքի սեղմման դեպքի համար)

աուդիո ձևաչափ
2
Աուդիո ձևաչափ (կախված է սեղմման մեթոդից և ձայնային տվյալների կառուցվածքից)
1 (PCM-ի համար, ինչը մենք դիտարկում ենք)

numChannels
2
Channelsանցերի քանակը
1/2, մենք կվերցնենք 1 ալիք (3/4/5/6/7... - կոնկրետ աուդիո ուղի, օրինակ 4 քառաձայն ձայնի համար և այլն)

ընտրանքի չափը
4
Ձայնային նմուշառման արագություն (հերցով)
Որքան բարձր է, այնքան լավ կլինի ձայնը, բայց որքան ավելի շատ հիշողություն կպահանջվի նույն երկարության աուդիո ուղու ստեղծման համար, առաջարկվող արժեքը 48000 է (ձայնի առավել ընդունելի որակը)

բայթերի արագություն
4
Բայթերի քանակը վայրկյանում
ընտրանքի չափը numChannels bitsPerSample (հետագա)

բլոկՀավասարեցում
2
Բայթերի քանակը 1 նմուշի համար
numChannels * bitsPerSample՝ 8

bitsPerSample
2
Բիթերի քանակը 1 նմուշի համար (խորությունը)
Ցանկացած թիվ, որը 8-ի բազմապատիկ է: Որքան մեծ է թիվը, այնքան լավ և ծանր կլինի ձայնը, 32 բիթից մարդկանց համար տարբերություն չկա:

subchunk2Id
4
Տվյալների հղման նշան (քանի որ կարող են լինել վերնագրի այլ տարրեր՝ կախված աուդիոՖորմատից)
0x64617461 Big-Endian («տվյալներ»)

subchunk2 Չափ
4
Տվյալների տարածքի չափը
տվյալների չափը int

տվյալներ
byterRate * ձայնի տևողություն
Աուդիո տվյալներ
?

WAVE օրինակ

Նախորդ աղյուսակը հեշտությամբ կարելի է թարգմանել C-ով կառուցվածքի, բայց մեր այսօրվա լեզուն Python-ն է: Ամենահեշտ բանը, որ դուք կարող եք անել, «ալիք» օգտագործելն է՝ աղմուկի գեներատոր: Այս առաջադրանքի համար մեզ պետք չեն բարձր բայթերատիվ և սեղմում:
Նախ, եկեք ներմուծենք անհրաժեշտ մոդուլները.

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

Հաջորդը, մենք պետք է աղյուսակից ստեղծենք բոլոր անհրաժեշտ փոփոխականները՝ ըստ դրանց չափերի: Դրա մեջ փոփոխական արժեքները կախված են միայն numSamples-ից (նմուշների քանակից): Ինչքան շատ լինեն, այնքան մեր աղմուկը կշարունակվի։

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

Մնում է դրանք գրել անհրաժեշտ հաջորդականությամբ (ինչպես աղյուսակում).

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

Եվ այսպես, պատրաստ։ Սցենարն օգտագործելու համար մենք պետք է ավելացնենք հրամանի տողի անհրաժեշտ փաստարկները.
python3 WAV.py [num of samples] [output]
Նմուշների քանակը - հաշվարկ: նմուշներ
ելք — ճանապարհ դեպի ելքային ֆայլ

Ահա աղմուկով փորձնական աուդիո ֆայլի հղումը, բայց հիշողությունը խնայելու համար ես իջեցրեցի BPS-ը մինչև 1բ/վ և իջեցրեցի ալիքների թիվը մինչև 1-ի (32-բիթանոց չսեղմված ստերեո աուդիո հոսքով 64 կբբ, պարզվեց. 80M մաքուր .wav ֆայլ և ընդամենը 10): https://instaud.io/3Dcy

Ամբողջ կոդը (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)

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

Լրիվ

Այսպիսով, դուք մի փոքր ավելին իմացաք թվային ձայնի և այն պահելու մասին: Այս գրառման մեջ մենք չենք օգտագործել սեղմում (աուդիոֆորմատ), բայց հանրաճանաչներից յուրաքանչյուրը դիտարկելու համար կպահանջվի 10 հոդված: Հուսով եմ, որ դուք ինքներդ նոր բան սովորեցիք, և դա կօգնի ձեզ հետագա զարգացումներում:
Thank you!

Տեղեկատվության աղբյուրներ

WAV ֆայլի կառուցվածքը
WAV - Վիքիպեդիա

Source: www.habr.com

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