I found a fun little tool that converts text into Morse Code with audio.
nimit2801 / MorseCodeMessenger
This Project will currently let you convert your text into Encrypted Morse Code with audio!
I have a little bit of experience making command line tools, but I have never worked with sound before. My plan to tackle this issue was:
- figure out how to read a wav file
- create a wav file from multiple smaller ones
- figure out how to find patterns in a wav file
After a little bit of research I found that a straightforward way to read a wav file was to use scipy.io.wavfile.read. The method takes a file location to a wav file and returns a sample rate as an integer and a numpy array. The opposite method scipy.io.wavfile.write takes a file location, a sample rate and a numpy array and creates a wav file. After playing around with these functions for a while, I was able to read the dot and dash wav files and create a large numpy array by appending copies of the dot and dash arrays.
dt = np.dtype('uint8')
blank = np.array([0] * 800, dt) # 0.1s
padding = np.array([0] * 240, dt) # 0.03s
samplerate, dot = wavfile.read(DOT)
samplerate, dash = wavfile.read(DASH)
dot = np.append(dot, padding.copy())
dash = np.append(dash, padding.copy())
wav_data = np.empty((0,0), dt)
for tune in self.encoded:
np_data = dot.copy() if tune == '.' else dash.copy() if tune == '-' else blank.copy()
wav_data = np.append(wav_data.copy(), np_data)
location = f'{self.filename}.wav'
wavfile.write(location, samplerate, wav_data)
The last thing I needed the tool to do was read a wav file and recognize patterns, specifically a dot, a dash, or blank silence. Perhaps there is a better method, but I decided that I would have the program read the wav file and look for specific values in the returned array at specific locations. This isn't a particularly elegant solution as it mainly involved checking an arbitrary location.
samplerate, wav = wavfile.read(f'{self.filename}.wav')
end = wav.shape[0]
self.encoded = ''
ptr = 0
while ptr < end:
if wav[ptr] == 0:
ptr += 800 # size of blank array
self.encoded += ' '
elif wav[ptr + 800] == 128:
ptr += 1120 # size of dot array
self.encoded += '.'
else:
ptr += 2080 # size of dash array
self.encoded += '-'
The result is a string of dots, dashes and spaces which could be passed to the original functions of the tool.
The last thing I wanted to do, was give the user a way to specify which functions to call from the command line. So I turned to argparse and implemented the following flags:
Optional flags | Purpose | Example |
---|---|---|
-w --wav
|
Create a Morse Code audio file | At the prompts, enter a message Hello World and a name hi. An audio file will be created and saved as hi.wav
|
-p --play
|
Play a Morse Code audio file | At the prompt, enter hi and if hi.wav exists, the audio will be played |
-r --read
|
Decipher a Morse Code audio file | At the prompt, enter hi and if hi.wav exists, the text Hello World will be displayed |
This was a fun little project and I was really happy to have my PR merged.
Top comments (0)