2

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:

  1. Take audio sample at 0.01s intervals
  2. Get the amplitude of the sample through RMS
  3. 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'
  4. Then split the string into a list through the zeros (as these will be the gaps between the beeps)
  5. 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

Community
  • 1
  • 1
M000
  • 23
  • 2
  • 5

1 Answers1

3

If you are still looking for an answer, I found a python based library called morse-to-text - default which converts a .wav morse code file to text.

If you have an mp3, first convert it to wav.
You can use built in python wave , ffmpeg or a external wrapper library pydub.
Below is an example using pydub as its very easy to use.

from pydub import AudioSegment

codefile_mp3 = "sampleMorseCode.mp3"
codefile_wav = "sampleMorseCode.wav"
mcode = AudioSegment.from_mp3(codefile_mp3)
mcode.export(codefile_wav , format="wav")

Once morse code file is converted to wav , you can run morse-to-text.py commandline as follows , or call within a python script.

C:\morse-to-text>morse-to-text.py sampleMorseCode.wav

Output:

.-.. .- | .-. . ... .--. ..- . ... - .- | -.. . | . ... - . | -. .. ...- . .-..
| . ... | .- .-.. ..-. .-. . -.. | ...- .- .. .-..
LA RESPUESTA DE ESTE NIVEL ES ALFRED VAIL

It also produces lots of data on signal such as spectrogram, fft, frequency, filter etc (if you are interested.

Usage: C:\morse-to-text\morse-to-text.py soundfile.wav [--report[=pdf|=png]]

I just got a sample morse code file from web. Hence its not in English.
Hope this helps.

Anil_M
  • 10,893
  • 6
  • 47
  • 74
  • Regretfully, after using your (morse-to-text.py) code with any of the samples included in your [Googlecode archive](https://code.google.com/archive/p/morse-to-text/source/default/source) (az, tppds and wikipedia) I got the following error: TypeError: 'numpy.float64' object cannot be interpreted as an integer... Any suggestions? – José Luis Martínez Nov 15 '20 at 21:41
  • Your data is interpreted as 'numpy.float64' , you may have to convert to 'integer' first before running through morse-to-text.py. Try that, else post your question separately with data and let me know. I can take a look then. – Anil_M Nov 17 '20 at 07:16
  • For anyone who's using Python3, add braces to `print`, change `min` to `int(min)` in line 87, change line 242 to `if code in self.dic:` – 김선달 Dec 25 '21 at 18:41