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 |