Wolfram Language

Computational Audio

Create and Decode a Morse Code Signal

Create a dictionary for Morse code.

show complete Wolfram Language input
In[1]:=
Click for copyable input
code = <|"a" -> ".-", "b" -> "-...", "c" -> "-.-.", "d" -> "-..", "e" -> ".", "f" -> "..-.", "g" -> "--.", "h" -> "....", "i" -> "..", "j" -> ".---", "k" -> "-.-", "l" -> ".-..", "m" -> "--", "n" -> "-.", "o" -> "---", "p" -> ".--.", "q" -> "--.-", "r" -> ".-.", "s" -> "...", "t" -> "-", "u" -> "..-", "v" -> "...-", "w" -> ".--", "x" -> "-..-", "y" -> "-.--", "z" -> "--..", "1" -> ".----", "2" -> "..---", "3" -> "...--", "4" -> "....-", "5" -> ".....", "6" -> "-....", "7" -> "--...", "8" -> "---..", "9" -> "----.", "0" -> "-----", "." -> ".-.-.-", "," -> "--..--", "!" -> "-.-.--", "?" -> "..--.."|> withgaps = Map[StringRiffle[Characters[#], "_"] &, code]; withpauses = Map[StringInsert[#, "___", -1] &, withgaps]; withspace = AssociateTo[withpauses, " " -> "_______"]; replacements = Map[StringReplace[#, {"-" -> "111", "." -> "1", "_" -> "0"}] &, withspace];
Out[1]=

Create a function to translate a message to an audio signal using the dictionary.

In[2]:=
Click for copyable input
createMorseSignal[s_String, t_] := Module[{events = Characters[StringReplace[ToLowerCase[s], Normal@replacements]], ts, amps}, ts = TimeSeries[ToExpression@events, {0, (Length[events] - 1)*t, t}]; amps = AudioGenerator[ts, SampleRate -> 1000]; AudioGenerator[{"Sin", 800}, Duration@amps, SampleRate -> 8000] amps ]

Encode a string into an audio signal.

In[3]:=
Click for copyable input
morse = createMorseSignal["hello world", .07]
Out[3]=

Decode the Morse signal without making any assumption on its timing.

In[4]:=
Click for copyable input
inversecode = AssociationThread[Values[code], Keys[code]]
Out[4]=
show complete Wolfram Language input
In[5]:=
Click for copyable input
decodeMorseSignal[audio_] := Module[{rms, rounded, crossings, transients, shifted, dit}, rms = AudioLocalMeasurements[audio, "RMSAmplitude", PartitionGranularity -> {.01, .002}]; rounded = Round[rms/Max@rms]; crossings = TimeSeriesInsert[ TimeSeries[ CrossingDetect[rounded["Values"] - .5, CornerNeighbors -> True], {rounded["Times"]}], {0, 1}]; transients = TimeSeries@Select[Normal@crossings, #[[2]] == 1 &]; shifted = TimeSeriesShift[transients, -transients["FirstTime"]]; dit = MinimumTimeIncrement[shifted]; StringSplit[ StringJoin[ Table[{Differences[shifted["Times"]][[i]], Mod[i, 2]}, {i, Length@Differences[shifted["Times"]]}] /. {{x_, 1} /; .5 dit < x < 1.5 dit -> ".", {x_, 1} /; 2.5 dit < x < 3.5 dit -> "-", {x_, 0} /; 2.5 dit < x < 3.5 dit -> "/", {x_, 0} /; .5 dit < x < 1.5 dit -> Nothing, {x_, 0} /; 5 dit < x < 12 dit -> "/_/"}], "/"] /. "_" -> " " ]
In[6]:=
Click for copyable input
decoded = decodeMorseSignal[morse]
Out[6]=
In[7]:=
Click for copyable input
StringJoin[decoded /. inversecode]
Out[7]=

Related Examples

de es fr ja ko pt-br ru zh