I've been trying to create a Morse Code audio decoder for a while now, that would take a Morse Code audio input through a mic and decode it into english, using python. Right now my priority is to be able to recognize the dits and dahs. The way I tried to approach this portion of the decoder is the following:
import pyaudio
import struct
import math
from datetime import datetime
thresh = 0.002
sample_period = 0.01
RATE = 44100
sample_cycles = int(RATE*sample_period)
SHORT_NORMALIZE = (1.0/32768.0)
CHANNELS = 2
FORMAT=pyaudio.paInt16
def rms(sample):
count = len(sample)/2
format = "%dh"%(count)
shorts = struct.unpack( format, sample )
sum_squares = 0.0
for i in shorts:
n = i * SHORT_NORMALIZE
sum_squares += n*n
return math.sqrt( sum_squares / count )
pa=pyaudio.PyAudio()
stream = pa.open(format = FORMAT,
channels = CHANNELS,
rate = RATE,
input = True,
frames_per_buffer = sample_cycles)
thresh_final=thresh
list1=""
counter=0
for i in range(1000):
try:
sample=stream.read(sample_cycles)
except IOError:
print("Error Recording")
amp=rms(sample)
if amp>thresh:
list1+="1"
else:
list1+="0"
list1=list1.split("0")
print(list1)
for i in range(len(list1)):
if len(list1[i])==45:
print ("Dah")
elif len(list1[i])==15:
print("Dit")
Quick Summary of the Code/Target:
- Take audio sample at 0.01s intervals
- Get the amplitude of the sample through RMS
- If the amplitude of the 0.01s samples are greater than a threshold(set just for recognising if there is a beep or no) add '1' to a string else '0'
- Then split the string into a list through the zeros (as these will be the gaps between the beeps)
- Go through the list if the length of the sublists = 15 (15*0.01s=0.15s which is the time I'm using for the dahs) print 'dit', and if the length of the sublists=45 print 'dah'
As you can tell this hasn't been efficient, so any suggestions as to how I could tackle Morse Code audio decoding?
Code Influenced by another post: Detect tap with pyaudio from live mic