demorse is a non-interactive command line tool for decoding Morse code signals into text. demorse detects the "dihs" and "dahs" that make a Morse code character via the computer's sound card, which can be connected to a radio receiver tuned to a CW Morse code transmission or to a tone generator. The input signal is processed by a Goertzel tone detector which produces "mark" or "space" (signal/no signal) outputs and the resulting stream of Morse code "elements" is decoded into an ASCII character for printing to the screen. Currently demorse is a non- interactive command line tool for the console and decoded Morse signals are sent to stdout.
demorse [-c<capture level>][-d<detector threshold>][-f<fixed speed>] [-l<level device>][-m<mixer device>][-p<dsp device>] [-r<recording source>][-s<initial speed>][-u<channel>] [-w<line length>][-hiv] -c<capture level>: Capture/Recording source level. Value should be 0-100, default is 50. -d<detector threshold>: Tone/No-tone detector threshold. Value should be 0-100, default is 60. -f<fixed-speed>: Fixed speed in w.p.m at which to expect and to decode a Morse coded signal. Valid range is 10-30 words per minute. -l<level device>: Input level device. Default is "igain". -m<mixer device>: Mixer device. Default is "/dev/mixer". -p<dsp device>: DSP device. Default is "/dev/dsp". -r<recording source>: Recording/Capture source. Default is "line". -s<initial speed>: Initial speed in w.p.m at start-up, at which to expect and to decode a Morse code signal. Actual decoding speed then adapts to the incoming Morse signal, limited to the range 10-30 words per minute. -u<channel>: Channel to use. Value should be left|right. Default is "right". -w<line length>: Line length in columns beyond which word wrapping is performed. Maximum is LINE_LENGTH columns. -h: Print this usage information and exit. -i: Display information for setting up signal input. -v: Print version number and exit.
demorse was designed from the beginning to be simple and efficient, decoding Morse code using (almost) only integer arithmetic and simple processing methods. It uses the computer's sound card to read the "dit" and "dah" elements that make the Morse coded characters by implementing a Goertzel detector of the level of sound signals from a radio receiver or tone generator. This software detector is centered on a nominal frequency of 500 Hz, which is lower than the more common 700-800 Hz BFO setting, because my PSK31 applications have to work with a 500 Hz audio tone due to various limitations. I have chosen to run my Morse decoding applications on the same BFO setting, to avoid regular changes to my receiver.
Error and noise
demorse has a certain level of tolerance towards operator errors (bad "fist") regarding deviation from the standard duration of the various elements that make up the Morse code. It can also reject to some extend the effects of interference and noise by ignoring marks or spaces shorter than a certain fraction of the unit Morse code element. Below is a table of the basic Morse code elements and the range of durations that demorse can deal with:
Morse Element Duration demorse ------------------------------------------------- dit 1 units 1/2-2 units dah 3 units 2-4 units Inter-elem space 1 units 1/2-2 units Inter-char space 3 units 2-4 units Inter-word space > 5 units > 4 unitsThe Morse code characters, punctuation marks and special signals that demorse can currently recognize are in the file Morsecode.txt. Extra characters etc can be added to the collection by inserting the hex equivalent of the decoded Morse code character in the demorse.h header file before compilation. Please see detailed explanation in that file.
demorse automatically sets up the sound card and tries to set the input and recording/capture level to the #define RECORD_LEV entry in demorse.h or the value given by the -c option. If it fails it will give an appropriate warning and the mixer levels for line input and recording level must be set up manually using a mixer app like 'aumix'.
For proper operation the level of the input audio signal must be adjusted from the receiver or the tone generator by starting demorse with the -i option. This causes demorse to print the maximum value of the dsp sound samples and a simple bar graph of this at regular intervals so that the input signal level can be adjusted to a value of about 90-100. To do this with for the radio receiver, it should be tuned to some stable carrier signal with no am modulation (narrow-band rtty signals will probably do) while the af volume control is adjusted for the correct input to the sound card. If the audio signal is taken from an outlet that provides a fixed audio level (such as a TNC connector), then the input level control (IGain on my system) must be adjusted using a mixer app like aumix so that the bar graph is around 90% of maximum. #define RECORD_LEV entry in demorse.h will need to be edited to set it to the value of level control and then demorse must be recompiled to make this value the default, see below.
Before compiling demorse, it may be necessary to customize some entries in the header file demorse.h. There are seven items that may need editing, the mixer and dsp device names, the recording source name, the recording level device, the default input/capture gain, the Stereo/Mono mode and the Left/Right channel selection if stereo mode is selected. Stereo mode allows the computer's sound card to be connected to two audio sources without the need to move plugs or switch audio. In my case this allows me to feed audio from my ham radio receiver and a weather satellite receiver to the sound card.
The default devices are "/dev/mixer", "/dev/dsp", "line" and "igain". These will more likely be correct for most sound installations and may be left unchanged. (Look in # /usr/include/soundcard.h (search for SOUND_DEVICE_NAMES) to find valid # device names).The default input/capture gain is 50 (decimal) and the acceptable range is usually 0-100. Also the Morse characters table can be edited to include extra characters if needed, according to the instructions given in demorse.h
Compilation is very simple, just run 'make' in the demorse
source directory to produce the executable binary 'demorse'. This
can then be copied to a suitable location, usually /usr/local/bin
or /usr/bin. There is only this hypertext documentation file which
you can copy to a location of your choice.
You can also type 'make install' to install the 'demorse' binary into /usr/local/bin and this hypertext documentation in /usr/local/doc.
Type 'make uninstall' to remove the 'demorse' binary and the 'demorse.html' documentation file.
Type 'make clean' to remove all files produced by compilation except for the 'demorse' binary, from the source directory.
Type 'make distclean' to remove all but the files that were included in the original source directory.
4. Command line
demorse is a non-interactive command-line tool and can be invoked with a number of option combinations, depending on the mode of operation:
-c<capture level>: Capture/Recording source level. Value should be 0-100, default is 50. The correct value can be found by using the -i option to display the input signal level and adjusting the capture level by using a mixer application like "aumix". On my system the relevant control is "IGain".
-d<detector threshold>: Tone/No-tone detector threshold. Value should be 0-100, default is 60. This sets a threshold above which the Tone (signal) detector will signal a "mark" tone, e.g. a "dit" or a "dah". Higher values tighten the detection of mark signals but reduce sensitivity.
-f<fixed-speed>: Fixed speed in w.p.m at which demorse should expect and decode a Morse coded signal. Valid range is 10-30 words per minute. demorse has some tolerance to operator errors (bad "fist") and so it will copy signals with about +/- 30% deviation from the specified speed.
-s<initial-speed>: Initial speed in w.p.m at start-up, at which demorse should expect and a Morse coded signal. Actual decoding speed then adapts to the incoming Morse signal but limited within the range of 10-30 words per minute.
-l<level device>: Input level control device. Default is "igain" on my system but it may be necessary to use a mixer app to find the right device.
-p<dsp device>: DSP device. Default is "/dev/dsp" on my system but other device names may be relevant on different platforms.
-r<recording source>: Recording/Capture source. Default is "line" on my system but again other values may be relevant on different platforms.
-u<channel>: Channel to use. Value should be left|right. Default is "right" on my machine but this depends on what connections are available on the sound card.
-w<line-length>: Line length in characters beyond which demorse should perform word-wrapping of the decoded text. Maximum is LINE_LENGTH characters as defined in the demorse.h header file.
-h: Print this usage information and exit.
-i: Display information for setting up signal input. demorse prints the max value of the dsp sound samples and a simple bar graph of this at regular intervals so that the input signal level can be adjusted to a value of about 90-100.
-v: Print version number and exit.
Before demorse is used to decode Morse signals the input level to the sound card must be set up correctly. For this the radio receiver or tone generator must be connected to the "line" input of the sound card with a suitable cable and connectors, with either the left or right channel connected to the receiver's o/p if in stereo mode, or if in mono mode usually the left channel input should be used. When working with a radio receiver it will be necessary to tune to a stable carrier with no AM modulation and with the BFO set for a tone of about 500 Hz. A MW broadcast station can be used with the receiver in CW mode and using very narrow IF/AF filters to block modulation. Then demorse should be started with the -i option and the level of audio signal input to the sound card adjusted using the AF volume control of the receiver so that a reading of about 90-100 is printed on the screen. If the audio signal is taken from an outlet that provides a fixed audio level (such as a TNC connector), then the input level control (IGain on my system) must be adjusted using a mixer app like aumix so that the bar graph is around 90% of maximum. #define RECORD_LEV entry in demorse.h will need to be edited to set it to the value of level control and then demorse must be recompiled to make this value the default.
By default when no command line options are given, Morse code speed is set to 20 wpm and speed tracking is enabled. Word wrapping is disabled.
To decode Morse code from a communications receiver, set the BFO so that the tone of the CW signal is near to 500 Hz and then start demorse from the console or xterm command line: demorse should then start decoding Morse characters. Alternately if demorse is already running, tune the receiver so that the BFO tone is near 500 Hz and until the CW Morse signals begin to be printed on the screen. The -i option can be used to tune in a station but demorse must be restarted to copy the code.
A maximum tuning step of 1 Hz should be selected on digital receivers and tuning should be slow. A narrow CW filter is an advantage although very narrow (less than 300-400 Hz) IF or dsp/AF filters tend to ring and cause spurious characters, mainly E's to be printed on the screen. Surely a tuning aid would be useful but since demorse is a non-interactive command line tool in its current form, this is difficult to implement.
Again by default, demorse starts with the Morse decoding speed set to 20 wpm and speed tracking enabled. demorse estimates the sending speed by measuring the length of dots, dashes, inter-element spaces and inter-character spaces and adjusts its decoding speed setting accordingly at the end of each word. Speed tracking is limited to 10-30 wpm and the first word to be received may be decoded incorrectly if the sending speed is far from the nominal 20 wpm. The command line option -s can be used to specify a different starting speed if a slow transmission like a ham band beacon is to be monitored, while the -f option specifies a fixed speed and also disables speed tracking. However demorse has some built-in tolerance to errors (bad "fists") so it can decode signals about +/- 30% away from the nominal speed.
Generally demorse has a fairly wide tolerance of sending errors (bad fists or noise) but in practice it has proved to be difficult to correctly decode CW signals on the amateur bands, with the main problem appearing to be bad keying habits. Sometimes inter-character spacing is too small so two or more characters are taken as one and therefore cannot be decoded correctly. Characters not recognized by demorse are indicated by an asterisk * on the screen. Word spacing also seems to be inconsistent with many hams resulting in fragmented or fused words.
Finally a list of all characters, punctuation marks and special signals recognized by demorse are listed in the Morse-code.txt file. Additional characters can be entered in two tables in the demorse.h header file before compilation, following the instructions in there.
6. Bugs and annoyances
I have fixed whatever bugs I came across testing demorse but there may be some hiding, waiting for the right conditions to appear.
The Morse code decoding algorithm may need further improvements to make it more tolerant to errors and noise and the mark/space detection process may need to be improved to reduce spurious output due to noise interference.
Version 0.1: First beta release of the basic Morse decoding command line tool.
Version 0.2: Changed the software PLL tone detector for
more stability and more effectiveness in tone detection.
Modified the Morse code decoding algorithm to improve performance in weak signal/interference conditions.
Version 0.3: Added the ability to work in either stereo or mono mode so that more than one audio sources can be connected to the sound card without switching or removing plugs.
Version 0.4 Minor bug fixes.
Version 0.5: Changed the detector scheme from a software PLL to a fixed-center-frequency synchronous detector running at 500Hz, since the PLL detector did not show any significant advantages and tended to drift. Simplified the signal/no-signal detection scheme to make it more reliable.
Version 0.6: Changed the detection scheme so that the slope of the detector's output is used to determine a Mark or Space signal. This appears to be more effective that using the signal level itself, since changes in the level are a more reliable indicator of key-down/key-up conditions.
Version 0.7: Changed the detector scheme to a Mark/Space transition (edge) detector. This seems to work better than the previous slope detection scheme.
Version 0.8: Changed the detector scheme to a Mark/Space transition (edge) detector which works by counting the number of consecutive signal samples (steps) that change by more than 5% in the same direction (up or down). If the number of steps is more than a given threshold (default 60% of the Morse element duration) then this is taken to indicate a rising or falling edge. This seems to work better than the previous slope detection scheme. Also added a few extra command line options to specify parameters for demorse's operation.
Version 0.9 After a bug report from Juha Vierinen regarding seg faulting of xnec2c, my graphical adaptation of NEC2, I changed all "sprintf" commands to "snprintf" to avoid buffer overruns. Following on the above changes, I revised all similar situations in demorse source code and changed all "sprintf" commands to "snprintf" just in case. While going through the demorse source code, I also fixed some minor bugs like typos and tidied error messages.
Version 1.0 Changed the sound functions from OSS to ALSA as OSS is no longer properly supported and I had reports from users of demorse that they could not get it to work with their sound card. I also checked the code with cppcheck and clang analyzer and fixed warnings, mainly about style.
8. Copying This software package is released under the GNU Public License. Please see the COPYING file for more details.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details:August 16 2002.
Last modified: Mon Mar 31 10:25:16 EEST 2003