7
$\begingroup$

Trying to make a function to convert text into morse code and play the sound. Have it pretty much completed, but I cannot get mathematica to emit no sound so I can have a pause between the dots and dashes. I have defined each letter in terms of dots and dashes, with spaces in between. For example:

a := {dot, ps, dash, lps};
b := {dash, ps, dot, ps, dot, ps, dot, lps};
c := {dash, ps, dot, ps, dash, ps, dot, lps};

ps is a pause between dots and dashes, while lps is a pause between letters. Currently they are defined as:

ps = EmitSound[Play[Sin[400 t], {t, 0, .2}]]
lps := EmitSound[Play[Sin[1/200 t], {t, 0, .5}]];

This emits a small beat sound, but I want to get away to have that just be silence. For spaces in between words I have used

space := EmitSound[Sound[None]];

and used StringReplace to replace " " with "space", and that works, but it doesn't work when trying to define ps and lps.

$\endgroup$
0

3 Answers 3

6
$\begingroup$

You're close. For the silences, just multiply the amplitude of the sine waves by 0.

dot := EmitSound[Play[Sin[2000 t], {t, 0, 0.2}, SampleRate -> 22050]];
dash := EmitSound[Play[Sin[2000 t], {t, 0, 0.5}, SampleRate -> 22050]];
ps := EmitSound[0 Play[Sin[2000 t], {t, 0, 0.2}, SampleRate -> 22050]];
lps := EmitSound[0 Play[Sin[2000 t], {t, 0, 0.5}, SampleRate -> 22050]];

Now you can set up the letters:

a := {dot, ps, dash, lps};

a

(sound pattern out)
$\endgroup$
2
  • 2
    $\begingroup$ Or use Piecewise to make a sound that ends before the sound finishes playing. Since the pause is actually part of the dot or dash, I think that could be a better approach. $\endgroup$ Commented Dec 14, 2015 at 2:00
  • 1
    $\begingroup$ I don't think this actually works. If you crank up the upper limit for t to something like 10 seconds, it doesn't change the break between the tones. $\endgroup$ Commented Jan 27, 2016 at 21:30
2
$\begingroup$

Play seems to have the property that it autoscales the volume to some constant level, regardless of the specified amplitude. The following code should play two tones, the first one loud and the second one quiet:

louddot := Play[Sin[2000 t], {t, 0, 1}, SampleRate -> 22050];
quietdot := Play[0.01 Sin[2000 t], {t, 0, 1}, SampleRate -> 22050];
EmitSound[{louddot, quietdot}]

On my system, this results in two tones that have the same volume. The fact that it does this means that trying to feed silence into Play fails (without throwing an error message!):

pause = Play[0, {t, 0, 1}, SampleRate -> 22050]

(* Sound[SampledSoundFunction[CompiledFunction[Argument count: 1; Argument types: {_Integer}],4410,22050]] *)

This is probably because Mathematica is trying to normalize the input signal to some common maximum level, which (for a zero signal) would result in a divide-by-zero error.

To actually get silence, you can use Sound and SoundNote instead, which accept the SoundVolume option:

dot := Play[Sin[2000 t], {t, 0, 0.2}, SampleRate -> 22050];
dash := Play[Sin[2000 t], {t, 0, 0.5}, SampleRate -> 22050];
ps := Sound[SoundNote[0, 0.2, SoundVolume -> 0]];
lps := Sound[SoundNote[0, 0.5, SoundVolume -> 0]];
EmitSound[{dot, ps, dot, ps, dash, ps, dot, lps, dash, lps, dot, ps, dash, ps, dash}]

This is kludgey as hell, but I couldn't find another way to do it. Trying to combine Sound objects with different volumes doesn't seem to work (it yields silence), and trying to create a silent sound with ListPlay gave an error.

$\endgroup$
0
$\begingroup$

I will give the morse code - generating part of this question another go:

First let's query Wolfram Alpha for some morse code:

query[letter_]:= WolframAlpha["morse code " <> letter, "PodPlaintext"][[2]]

and create an Association for easy lookup

charToMorse = query ~AssociationMap~ CharacterRange["A","Z"]

The following function translates a given string into a list of ., -, S, C and W where . and _ are your typical morse symbols, S is a space between to morse symbols, C is a space between characters and W is the space between two words. For better understanding just out-comment it from top to bottom to see what every operation does.

morseCode[string_]:= string 
                     //ToUpperCase 
                     //StringSplit 
                     //Characters  
                     //ReplaceAll[charToMorse]
                     //Map[Riffle[#,"C"]&]  (*character spaces*)
                     //Riffle[#,head@"W"]& //ReplaceAll[head->List] (*word spaces*)
                     //Map[Characters] 
                     //Flatten[#, 1]& 
                     //Map[Riffle[#, "S"]&] (*symbol spaces*)
                     //Flatten

Lets test:

"an apple" //morseCode
(* {.,S,-,C,-,S,.,W,.,S,-,C,.,S,-,S,-,S,.,C,.,S,-,S,-,S,.,C,.,S,-,S,.,S,.,C,.} *)

and compare to:

WolframAlpha["morse code an apple" , "PodCells"][[2]]

wolfram alpha result

Now you can use replacement rules in the fashion bill showed you in his answer to translate the morse symbols and spacings into sound.

$\endgroup$
1
  • $\begingroup$ I would have added numbers and special characters to my lookup-table of morse codes but I couldn't convince W|A to reliably accept queries like WolframAlpha["morse code 1"] $\endgroup$
    – Sascha
    Commented Jan 27, 2016 at 21:24

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.