WAVE ๋ฐ JPEG ํ˜•์‹์˜ ๋ฏธ๋””์–ด ๋ฐ์ดํ„ฐ๋ฅผ ์••์ถ•/์ €์žฅํ•˜๋Š” ๋ฐฉ๋ฒ•, 1๋ถ€

์•ˆ๋…•ํ•˜์„ธ์š”! ์ฒซ ๋ฒˆ์งธ ๊ธฐ์‚ฌ ์‹œ๋ฆฌ์ฆˆ์—์„œ๋Š” JPEG(์ด๋ฏธ์ง€) ๋ฐ WAVE(์‚ฌ์šด๋“œ)์™€ ๊ฐ™์€ ์ด๋ฏธ์ง€/์˜ค๋””์˜ค ์••์ถ• ๋ฐ ์ €์žฅ ๋ฐฉ๋ฒ•์„ ์—ฐ๊ตฌํ•˜๋Š” ๋ฐ ์ค‘์ ์„ ๋‘˜ ๊ฒƒ์ด๋ฉฐ ์‹ค์ œ๋กœ ์ด๋Ÿฌํ•œ ํ˜•์‹(.jpg, .wav)์„ ์‚ฌ์šฉํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์˜ ์˜ˆ๋„ ํฌํ•จํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋ฒˆ ์‹œ๊ฐ„์—๋Š” WAVE์— ๋Œ€ํ•ด ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด์•ผ๊ธฐ

WAVE(Waveform Audio File Format)๋Š” ์˜ค๋””์˜ค ์ŠคํŠธ๋ฆผ ๋…น์Œ์„ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ ์ปจํ…Œ์ด๋„ˆ ํŒŒ์ผ ํ˜•์‹์ž…๋‹ˆ๋‹ค. ์ด ์ปจํ…Œ์ด๋„ˆ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์••์ถ•๋˜์ง€ ์•Š์€ ํŽ„์Šค ์ฝ”๋“œ ๋ณ€์กฐ ์˜ค๋””์˜ค๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. (์œ„ํ‚คํ”ผ๋””์•„์—์„œ ๊ฐ€์ ธ์˜ด)

1991๋…„์— Microsoft์™€ IBM(๋‹น์‹œ ์ฃผ์š” IT ๊ธฐ์—…)์ด โ€‹โ€‹RIFF์™€ ํ•จ๊ป˜ ๋ฐœ๋ช…ํ•˜๊ณ  ์ถœํŒํ–ˆ์Šต๋‹ˆ๋‹ค.

ํŒŒ์ผ ๊ตฌ์กฐ

ํŒŒ์ผ์—๋Š” ํ—ค๋” ๋ถ€๋ถ„, ์ฆ‰ ๋ฐ์ดํ„ฐ ์ž์ฒด๊ฐ€ ์žˆ์ง€๋งŒ ๋ฐ”๋‹ฅ๊ธ€์€ ์—†์Šต๋‹ˆ๋‹ค. ํ—ค๋”์˜ ๋ฌด๊ฒŒ๋Š” ์ด 44๋ฐ”์ดํŠธ์ž…๋‹ˆ๋‹ค.
ํ—ค๋”์—๋Š” ์ƒ˜ํ”Œ์˜ ๋น„ํŠธ ์ˆ˜, ์ƒ˜ํ”Œ ์†๋„, ์‚ฌ์šด๋“œ ๊นŠ์ด ๋“ฑ์— ๋Œ€ํ•œ ์„ค์ •์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šด๋“œ ์นด๋“œ์— ํ•„์š”ํ•œ ์ •๋ณด์ž…๋‹ˆ๋‹ค. (๋ชจ๋“  ์ˆ˜์น˜ํ‘œ ๊ฐ’์€ Little-Endian ์ˆœ์„œ๋กœ ์ž‘์„ฑ๋˜์–ด์•ผ ํ•จ)

๋ธ”๋ก ์ด๋ฆ„
๋ธ”๋ก ํฌ๊ธฐ(B)
์„ค๋ช…/๋ชฉ์ 
๊ฐ’(์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” ๊ณ ์ •๋˜์–ด ์žˆ์Œ)

์ฒญํฌ ID
4
ํŒŒ์ผ์„ ๋ฏธ๋””์–ด ์ปจํ…Œ์ด๋„ˆ๋กœ ์ •์˜
๋น… ์—”๋””์•ˆ(โ€œRIFFโ€)์˜ 0x52494646

์ฒญํฌ ํฌ๊ธฐ
4
ChunkId ๋ฐ ChunkSize๊ฐ€ ์—†๋Š” ์ „์ฒด ํŒŒ์ผ์˜ ํฌ๊ธฐ
FILE_SIZE - 8

์ฒด์žฌ
4
RIFF์˜ ์œ ํ˜• ์ •์˜
๋น…์—”๋””์•ˆ(โ€œWAVEโ€)์˜ 0x57415645

ํ•˜์œ„ ์ฒญํฌ1ID
4
ํŒŒ์ผ์ด ํ˜•์‹์˜ ์—ฐ์†์œผ๋กœ ๋” ๋งŽ์€ ๊ณต๊ฐ„์„ ์ฐจ์ง€ํ•˜๋„๋ก
๋น…์—”๋””์•ˆ(โ€œfmtโ€)์˜ 0x666d7420

ํ•˜์œ„ ์ฒญํฌ1ํฌ๊ธฐ
4
๋‚จ์€ ํ—ค๋”(๋ฐ”์ดํŠธ)
๊ธฐ๋ณธ์ ์œผ๋กœ 16(์˜ค๋””์˜ค ์ŠคํŠธ๋ฆผ ์••์ถ•์ด ์—†๋Š” ๊ฒฝ์šฐ)

์˜ค๋””์˜ค ํ˜•์‹
2
์˜ค๋””์˜ค ํ˜•์‹(์••์ถ• ๋ฐฉ๋ฒ• ๋ฐ ์˜ค๋””์˜ค ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์— ๋”ฐ๋ผ ๋‹ค๋ฆ„)
1 (์šฐ๋ฆฌ๊ฐ€ ๊ณ ๋ คํ•˜๊ณ  ์žˆ๋Š” PCM์˜ ๊ฒฝ์šฐ)

์ฑ„๋„ ์ˆ˜
2
์ฑ„๋„ ์ˆ˜
1/2, 1๊ฐœ ์ฑ„๋„(3/4/5/6/7... - ํŠน์ • ์˜ค๋””์˜ค ํŠธ๋ž™, ์˜ˆ๋ฅผ ๋“ค์–ด ์ฟผ๋“œ ์˜ค๋””์˜ค์˜ ๊ฒฝ์šฐ 4๊ฐœ ๋“ฑ)์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ƒ˜ํ”Œ๋ ˆ์ดํŠธ
4
์˜ค๋””์˜ค ์ƒ˜ํ”Œ๋ง ์†๋„(Hz)
๋†’์„์ˆ˜๋ก ์‚ฌ์šด๋“œ๋Š” ๋” ์ข‹์•„์ง€์ง€๋งŒ ๋™์ผํ•œ ๊ธธ์ด์˜ ์˜ค๋””์˜ค ํŠธ๋ž™์„ ์ƒ์„ฑํ•˜๋ ค๋ฉด ๋” ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ถŒ์žฅ ๊ฐ’์€ 48000(๊ฐ€์žฅ ์ ํ•ฉํ•œ ์‚ฌ์šด๋“œ ํ’ˆ์งˆ)์ž…๋‹ˆ๋‹ค.

๋ฐ”์ดํŠธ ์†๋„
4
์ดˆ๋‹น ๋ฐ”์ดํŠธ ์ˆ˜
์ƒ˜ํ”Œ๋ ˆ์ดํŠธ ์ฑ„๋„ ์ˆ˜ bitPerSample (์ถ”๊ฐ€)

๋ธ”๋ก์ •๋ ฌ
2
1๊ฐœ ์ƒ˜ํ”Œ์˜ ๋ฐ”์ดํŠธ ์ˆ˜
numChannels * bitPerSample: 8

๋น„ํŠธ๋‹น ์ƒ˜ํ”Œ
2
1์ƒ˜ํ”Œ๋‹น ๋น„ํŠธ์ˆ˜(๊นŠ์ด)
8์˜ ๋ฐฐ์ˆ˜์ธ ๋ชจ๋“  ์ˆซ์ž. ์ˆซ์ž๊ฐ€ ๋†’์„์ˆ˜๋ก ์˜ค๋””์˜ค๊ฐ€ ๋” ์ข‹๊ณ  ๋ฌด๊ฑฐ์›Œ์ง‘๋‹ˆ๋‹ค. 32๋น„ํŠธ์—์„œ๋Š” ์‚ฌ๋žŒ์—๊ฒŒ ์ฐจ์ด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

ํ•˜์œ„ ์ฒญํฌ2ID
4
๋ฐ์ดํ„ฐ ์ฐธ์กฐ ํ‘œ์‹œ(audioFormat์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ํ—ค๋” ์š”์†Œ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ)
๋น…์—”๋””์•ˆ("๋ฐ์ดํ„ฐ")์˜ 0x64617461

ํ•˜์œ„ ์ฒญํฌ2ํฌ๊ธฐ
4
๋ฐ์ดํ„ฐ ์˜์—ญ ํฌ๊ธฐ
int์˜ ๋ฐ์ดํ„ฐ ํฌ๊ธฐ

๋ฐ์ดํ„ฐ
byteRate * ์˜ค๋””์˜ค ์ง€์† ์‹œ๊ฐ„
์˜ค๋””์˜ค ๋ฐ์ดํ„ฐ
?

์›จ์ด๋ธŒ ์˜ˆ์‹œ

์ด์ „ ํ‘œ๋Š” 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๋ฅผ 1b/s๋กœ ๋‚ฎ์ถ”๊ณ  ์ฑ„๋„ ์ˆ˜๋ฅผ 1๋กœ ์ค„์˜€์Šต๋‹ˆ๋‹ค(32kbs์˜ 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)  # ะทะฐะฟะธัั‹ะฒะฐะตะผ ะฒ ั„ะฐะนะป ั€ะตะทัƒะปัŒั‚ะฐั‚

ํ•ฉ๊ณ„

์ง€๊ธˆ๊นŒ์ง€ ๋””์ง€ํ„ธ ์‚ฌ์šด๋“œ์™€ ๋””์ง€ํ„ธ ์‚ฌ์šด๋“œ ์ €์žฅ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์กฐ๊ธˆ ๋” ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒŒ์‹œ๋ฌผ์—์„œ๋Š” ์••์ถ•(audioFormat)์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜์ง€๋งŒ ์ธ๊ธฐ ์žˆ๋Š” ๊ฐ ์••์ถ•์„ ๊ณ ๋ คํ•˜๋ ค๋ฉด 10๊ฐœ์˜ ๊ธฐ์‚ฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์Šค์Šค๋กœ ์ƒˆ๋กœ์šด ๊ฒƒ์„ ๋ฐฐ์› ๊ธฐ๋ฅผ ๋ฐ”๋ผ๋ฉฐ ์ด๊ฒƒ์ด ํ–ฅํ›„ ๊ฐœ๋ฐœ์— ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

์†Œ์Šค

WAV ํŒŒ์ผ ๊ตฌ์กฐ
WAV-์œ„ํ‚คํ”ผ๋””์•„

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€