This question is related to my other recent questions. In the last question, I learned that I should filter about 4 * WPM (words per minute) around the carrier frequency if I want to recover Morse code. One problem is, learning the words per minute. I filter because I want to differentiate times when the system is keyed, to times that are just noise. Filtering requires WPM, WPM seems to require filtering.

Now I am simply going through the whole audio, and if a window has an element above a certain threshold, the whole window is marked as being 'on' or 'keyed'. The window is big enough for a whole alternation of the carrier to be examined (sampling frequency over carrier freq, or fs/fc).

Are there better ways to approach this? I have been working on this for awhile now. I am doing this in Python.


1 Answer 1


The recommendation to use 4* WPM just means that you should estimate the upper limit of the WPM that you expect to receive. High speed CW starts around 40 WPM (usually too fast to write or type the decoded signal.) So, 50WPM would be a good upper limit which means you could use a bandwidth of 200Hz.

As an alternative to what you are doing, you could use the goertzel algorithm. That algorithm works like a narrow bandpass with a signal level detector. You run your signal through it, and it delivers a number that tells you how strong the signal is at the center frequency that you gave the goertzel method.

This web site gives a clear example of how to write a goertzel method to do what you are trying to accomplish. Use the tandem goertzel to work in real time. The example is in C, but it should be clear enough that you can translate it to python.

Varying the RESETSAMPLES value will allow you to change how narrow the filter is. The higher RESETSAMPLES is, the narrower the filter will be. The article suggests 200 samples, so I would start there. If your signal is too noisy and you get a lot of bad morse code symbols, then you can make the number larger. What I usually do is make it some multiple of the wave length of the frequency I am trying to detect in samples. So, to detect 1kHz using 44100Hz sampling, I would first try 44 (44100/1000.) If that is too "loose" then 88, then 132 and so forth until I get a filter that is narrow enough. If you go too high, though, you will start "smearing" the morse code symbols and won't be able to tell when one ends and the next begins.

  • $\begingroup$ Thanks. After filtering, how can I efficiently determine whether or not I am in noise, or the low level CW signal? Now I am trying to average a window (fs/fc), and if the avg of that window is above a tolerance, I call it on... $\endgroup$ Aug 13, 2014 at 21:21
  • $\begingroup$ Would this be a good place to use RMS instead of just avg? $\endgroup$ Aug 13, 2014 at 21:22
  • 1
    $\begingroup$ Average would not be good. RMS would be much more reasonable. The average would give you zero if you had one or more complete cycles perfectly in your averaging window. Since that will (almost) never happen, your average is basically proportional to how poorly your cycles fit your window. RMS will give to a true indication of the strength of the signal in your window. $\endgroup$
    – JRE
    Aug 13, 2014 at 21:27
  • $\begingroup$ I was doing the averages of the absolute values. Another thing I tried was to mark the entire window as 'on' if any point in the window was above the tolerance. Are both of these reasonable (or unreasonable) approaches? $\endgroup$ Aug 13, 2014 at 21:37
  • 1
    $\begingroup$ Averaging the absolute value should be OK, it will give numbers about as high as the RMS values, but different. Counting the whole window as on if any point is on would work, but I'd expect a lot of false detections. It also reduces the time accuracy of the detector - the smallest time unit is the length of your window. If the filter is reducing the strength of your signal, then the center frequency of your filter is probably wrong. Check and see if you have the correct value for the frequency of the cw signal. $\endgroup$
    – JRE
    Aug 14, 2014 at 7:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.