Բարեւ Ձեզ! Իմ առաջին հոդվածների շարքը կկենտրոնանա պատկերի/ձայնի սեղմման և պահպանման մեթոդների ուսումնասիրության վրա, ինչպիսիք են 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):
Ամբողջ կոդը (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!
Տեղեկատվության աղբյուրներ
Source: www.habr.com