M000
M000

Reputation: 23

Morse Audio Decoding Using Python

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

Upvotes: 2

Views: 11462

Answers (1)

Anil_M
Anil_M

Reputation: 11453

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.

Upvotes: 3

Related Questions