블로그 이전했습니다. https://jeongzero.oopy.io/
모스신호 wav 파일 생성하기
본문 바로가기
보안/Linux

모스신호 wav 파일 생성하기

728x90


이번에는 문자열을 입력받아 해당 글자에 관한 모스신호에 해당하는 .wav 파일을 만들어내는 프로그램을 만들어 보았다.


위 그림은 구현하려는 파일이 가지고 있는 전체적인 파일 구조를 나타낸다.


해당 프로그램을 파이썬을 이용하여 구현하였으며 구현에 앞서 wav 파일의 헤더를 먼저 공부하였다.




wav 파일 헤더 구조





wav는 헤더는 크게 3가지로 구성되어 있다.


보라색 부분 : 파일의 형식을 나타내고 있는 부분


초록색 부분 : 음성정보를 나타내고 있는 부분


살구색 : 실제 데이터에 관한 정보를 나타내고 있는 부분



wav 파일을 만들때 위 구조의 골격에 맞추어서 코딩을 해야 한다.  각 부분들이 정의하고 있는 부분은 아래의 글에서 자세하게 확인 가능하다.






전체적인 흐름


1. 변환하고 싶은 문자열을 입력한다.

2. 입력받은 문자열을 모스부호로 변환한다.

3. 해당 모스부호에 해당하는 wav 파일을 만들어낸다.


구현을 위해 총 3가지의 모듈을 사용하였다.


1. morse_convert.py    -    메인 모듈로 실행되는 모듈

2. Morse2.py             -    모스부호로 변환하는 모듈

3. make_wave.py        -    wav 파일을 만들어내는 모듈




1. morse_convert.py

import sys
import math
from Morse2 import Morse
from make_wave import waveFile

def make_sin_wave(sample_rate,frequency,duration,amplitude):
data=[]
samples_num=int(duration*sample_rate)
volume=amplitude*32767
for i in range(samples_num):
value=math.sin(2*math.pi*i*frequency/sample_rate)
data.append(int(value*volume))
return data


def convert_text_to_morse_wave(text,filename):
convert_text=Morse().convert(text)
convert_exact_text=Morse('=','===').convert_exact(text)
print(convert_text)

sample_rate=8000 # 8000hz
frequency=600 # 600hz
dot_dur=0.05 # 50ms
volume=0.8 # 80%

wave=waveFile(sample_rate)
wave_duration=0
wave_data=[]
for i in convert_exact_text:
wave_duration=wave_duration+dot_dur
if i !=' ':
wave_data = wave_data + make_sin_wave(sample_rate,frequency,dot_dur,volume)
else:
wave_data = wave_data + make_sin_wave(sample_rate, frequency, dot_dur, 0)

wave.add_data_subchunk(wave_duration,wave_data)
wave.save(filename)

#메인 실행
if __name__ == '__main__':
if len(sys.argv) == 3:
convert_text_to_morse_wave(sys.argv[1], sys.argv[2])
else:
print("Error!! please retry input")


매개변수로 변환할 문자열과 파일이름을 입력해준다.



2. Morse2.py

#Convert Morse_code

class Morse(object):
def __init__(self,dot='.',dash='-'):
self.morse_table=self.MORSE_TABLE
self.dot=dot
self.dash=dash

def convert(self, data):
result=''
for i in data:
result+=self.morse_table.get(i,i) + ' '
result = result[:-1].replace('.', self.dot).replace('-', self.dash)
print(result)
return result

def convert_exact(self,data):
result=''
for i in data:
result += (' '*self.INTER_GAP).join(list(self.morse_table.get(i,i)))+' '*self.LETTERS_GAP
print(result)
result = result[:-self.LETTERS_GAP].replace('.', self.dot).replace('-', self.dash)
print(result)
return result

DOT_DURATION = 1
DAH_DURATION = 3 * DOT_DURATION
INTER_GAP = DOT_DURATION
LETTERS_GAP = 3 * DOT_DURATION
WORDS_GAP = 7 * DOT_DURATION

MORSE_TABLE={
'A': '.-',
'B': '-...',
'C': '-.-.',
'D': '-..',
'E': '.',
'F': '..-.',
'G': '--.',
'H': '....',
'I': '..',
'J': '.---',
'K': '-.-',
'L': '.-..',
'M': '--',
'N': '-.',
'O': '---',
'P': '.--.',
'Q': '--.-',
'R': '.-.',
'S': '...',
'T': '-',
'U': '..-',
'V': '...-',
'W': '.--',
'X': '-..-',
'Y': '-.--',
'Z': '--..',

'a': '.-',
'b': '-...',
'c': '-.-.',
'd': '-..',
'e': '.',
'f': '..-.',
'g': '--.',
'h': '....',
'i': '..',
'j': '.---',
'k': '-.-',
'l': '.-..',
'm': '--',
'n': '-.',
'o': '---',
'p': '.--.',
'q': '--.-',
'r': '.-.',
's': '...',
't': '-',
'u': '..-',
'v': '...-',
'w': '.--',
'x': '-..-',
'y': '-.--',
'z': '--..',

'0': '-----',
'1': '.----',
'2': '..---',
'3': '...--',
'4': '....-',
'5': '.....',
'6': '-....',
'7': '--...',
'8': '---..',
'9': '----.',

'.': '.-.-.-',
',': '--..--',
'?': '..--..',
"'": '.----.',
'!': '-.-.--',
'/': '-..-.',
'(': '-.--.',
')': '-.--.-',
'&': '.-...',
':': '---...',
';': '-.-.-.',
'=': '-...-',
'+': '.-.-.',
'-': '-....-',
'_': '..--.-',
'"': '.-..-.',
'$': '...-..-',
'@': '.--.-.',
}




3. make_wave.py

import struct

class waveFile(object):
def __init__(self,sample_rate):
self.subchunk_size=16 # subchunk data size(16 for PCM)
self.compression_type = 1 # compression (PCM = 1)
self.channels_num=1 # channels (mono =1, stereo =2)
self.bits_per_sample=16
self.block_alignment=int(self.channels_num*self.bits_per_sample / 8)
self.sample_rate=sample_rate
self.byte_rate=int(self.sample_rate*self.channels_num*self.bits_per_sample / 8)
self.duration=0
self.data=[]


def add_data_subchunk(self, duration, data):
self.duration+=duration
self.data+=data


def save(self,filename):
self.samples_num=int(self.duration * self.sample_rate)
self.subchunk2_size=int(self.samples_num * self.channels_num * self.bits_per_sample / 8)

with open(filename,'wb') as f:
# write RIFF header
f.write(b'RIFF')
f.write(struct.pack('<I', 4 + (8 + self.subchunk_size) + (8+self.subchunk2_size)))
f.write(b'WAVE')
# write fmt subchunk1
f.write(b'fmt ')
f.write(struct.pack('<i',self.subchunk_size)) #data size
f.write(struct.pack('<h',self.compression_type)) #compression type
f.write(struct.pack('<h',self.channels_num)) #channels
f.write(struct.pack('<i', self.sample_rate)) # sample rate
f.write(struct.pack('<i', self.byte_rate)) # byte rate
f.write(struct.pack('<h', self.block_alignment)) # block alignment
f.write(struct.pack('<h', self.bits_per_sample)) # sample depth
# write data subchunk2
f.write(b'data')
f.write(struct.pack('<i',self.subchunk2_size))
for i in self.data:
sound=struct.pack('<h',i)
f.write(sound)


728x90

'보안 > Linux' 카테고리의 다른 글

리눅스 부팅 과정  (0) 2019.03.21
xcz 17번 문제  (0) 2019.02.23
network recovery  (0) 2019.02.17
스테가노그라피란?  (0) 2019.02.16
비즈네르 암호문  (0) 2019.02.16