3

I'm new to Linux and have recently started working on my very first (very simple) project - a morse code generator. I've been able to get the translation working, and now I want to take the next step.

What would be the best way to go about replacing the character "." with a beep and "-" with a slightly longer beep? I would like to be able to actually produce audible morse code.

Which way would you more advanced users go about doing this? If you have any ideas, please explain in as simple terms as you can.

NOTE: My code is here on pastebin: http://pastebin.com/K5Ap3p4S.

echo
echo "What would you like to translate today?"
read transmission
clear
echo $transmission | sed 's/.\{1\}/& /g' | sed 's/a/.-/g;
s/b/-.../g;
s/c/-.-./g;
  • 1
    Can you please show us what you have so far in code? You're asking how to expand a . to a beep, without seeing your code your question is then a bit too broad to answer ATM. If you're looking to do a search/replace in Bash, you can either use sed to accomplish this or Bash's native regex facilities. – slm Mar 31 '16 at 07:21
  • I tried, but it exceeds the character limit. Essentially what it does is read the input of "transmission", then echos "transmission" and pipes the result through sed commands that replace the letters with dashes and dots. Sorry for the difficulties in explaining this, I'm still getting the hang of this, and this forum. – nosferatwo Mar 31 '16 at 07:34
  • 2
    I think I would tackle this in a slightly different way, why not construct the audio sequences as you need them and then skip the whole translation to dot/dash and play the appropriate audio sequence for a given letter instead? This code shows exactly how I would approach this: http://crunchbang.org/forums/viewtopic.php?id=31657. – slm Mar 31 '16 at 07:49
  • That was actually my original plan. The dots and dashes thing was mostly just an exercise with sed. I figured I could simplify everything to two characters and then play the appropriate sounds. I figured that would be easier since I'm so inexperienced. I'm like Linux/Unix 101 new. I'm open to suggestions though. – nosferatwo Mar 31 '16 at 07:53
  • 1
    No harm in experimenting, but it's always been my experience to do direct mappings when you can from one thing to another then to create middle translations. – slm Mar 31 '16 at 07:55
  • On that note, do you know of any good resources that would teach the methods one would use to do this in a more streamlined fashion? Also, would it make a difference if I was using Putty instead of an actual Linux system? – nosferatwo Mar 31 '16 at 07:58
  • 1
    PuTTY is just a terminal emulator that you're using to gain access to a remote Linux system, it's does have anything to do with what you're trying to accomplish here 8-). I would figure out how to convert a letter to a sequence of appropriate sounds to start. Once you know how to do this, then it's a matter of repeating it 25 more times. I'd also look into how to play a sequence of sounds in a shell as it's own task and see if any support being given a series of commands to play a tone, or can read from a file and do this. – slm Mar 31 '16 at 08:07
  • I'll have to look a bit more into this, and perhaps ask my instructor for some hands on advice. Thank you very much for your input. – nosferatwo Mar 31 '16 at 08:20
  • 1
    This CLI tool, cwwav will take text files in and create custom .wav files in morse code dot/dash. Might be useful here. I also always take a look at Rosetta for stuff like this: https://www.rosettacode.org/wiki/Morse_code. Here they show Morse Code implementations in every programming language that matters 8-). – slm Mar 31 '16 at 08:33
  • Also note that your sed script contains completely unnecessary curly braces. s/.\{1\}/& /g should just be s/./& /g. – Wildcard Apr 03 '16 at 07:49

3 Answers3

5

In the end: I will not exactly answer your question, but help is under way.

You do need a program to generate the sounds. The command beep may help.

And you may try to code all the details as this guy also tried using beep. Like sending a 1000 Hz tone for 2 seconds to the speaker (debug will show exactly what is being done):

beep --debug -f 1000 -l 2000

But beep only use the pc speaker to generate tones.
And your computer may not have an speaker installed.

However, it is actually very easy to generate a sound in linux: send it to /dev/audio

$ echo "test" > /dev/audio

Of course, "test" is a very poor sound wave, it will sound as a simple "bump".

To actually generate an useful tone you need to create all the values in a sinewave in a file, and then send the file to /dev/audio. And here is a crude example of exactly this idea.


Actually, all that has been already coded in a command designed for morse: cw.
In debian derivatives, install it with: apt-get cw.

Then execute this:

echo "test" | cw

And that is the reason for the "I will not exactly answer your question", because cw does all the work for you. It converts characters to dash and dot, create a sound wave for each and send it to the sound card.

In fact, the amount of help available in Linux to Ham radio is overwhelming:

https://radio.linux.org.au/?sectpat=morse

And that is only for morse.

  • 1
    +1 , nice set of alternatives , OP should be able to select a suitable solution to implement in his bash script. – Prem Apr 01 '16 at 07:08
0

You could replace them with bell character. You'd just replace '.' with one bell character, and '-' with two characters. Note that because of that the string would have to expand, but that shouldn't be too hard - for example, you could just copy the string, character by character, placing two bell characters where appropriate.

Note, however, that the bell character sometimes "doesn't work"(you don't hear it); for more robust solution you might want to write something like a trivial parser that would play sound using external command(e.g. mpg123) to play the sound when you encounter a '.' or '-', and wait command(or even playing 'no sound' track! :)) otherwise.

The pseudocode would look something like this:

For every character in string:
   If character is '.':
     play "shortBeep"
   else if character is '-'
     play "shortBeep"
     play "shortBeep" # or play "longBeep"
   else
     play "noBeep" # or wait
MatthewRock
  • 6,986
  • I actually tried to do this, but couldn't find a simple enough explanation for how to replace the dashes and dots with the commands that produce the bell sounds. What is the method one would use to replace a character with a command? – nosferatwo Mar 31 '16 at 07:39
  • @nosferatwo use sed. store character in variable. Expand variable using $ in "". – MatthewRock Mar 31 '16 at 07:51
  • If I recall the technical details of morse code correctly, I believe that a dash is supposed to last three times as long as a dot, not just twice as long. – Wildcard Mar 31 '16 at 23:14
0

You have been able to convert the given text to morse code, and now want to convert that morse code to audio beeps.

Download (or create) two files for the two sounds (DOT.wav having short beep for dot & DASH.wav having long beep for dash) and then iterate over the signals, using speaker-test or sox inside the loop , for generating the sound matching the current signal.

By using the various command-line options, you may not even require the 2 files, and can generate the sound specifying the frequency and the duration.

References:
http://manpages.ubuntu.com/manpages/trusty/man1/speaker-test.1.html
http://sox.sourceforge.net/

Check your installation for alternatives to speaker-test or sox , you might be able to find tools like play, beep, siggen, tonegen, etc. Check out https://en.wikipedia.org/wiki/List_of_Linux_audio_software for more.

Prem
  • 3,342
  • 1
    The performance for this is probably going to be lousy, since he's going to be calling sox or whatever a bunch of times for every dot/dash sound. – slm Mar 31 '16 at 07:41
  • @slm , here OP has tagged with bash & scripting, so performance will necessarily be lousy. I would probably use some C Libraries and generate the output with functions calls in a C program. Hey, maybe the end result would be a new binary tool morsecode -string ". - . .. -" -output morse.mp3 ! – Prem Mar 31 '16 at 07:48
  • @slm , I see that you suggest "Bash Morse code Generator" at http://crunchbang.org/forums/viewtopic.php?id=31657 which also iterates over the signals but it says it requires sudo apt-get install beep, whereas my answer might require sudo apt-get sox, so it is essentially the same as my answer, and only the tool for single sound generation is changed. Would not that also be lousy ? – Prem Mar 31 '16 at 08:01
  • I highlighted crunchbang only to show that he should skip the mid-level translation and think of solving the problem by mapping alphabet -> sounds instead of alpha -> dot/dash -> sounds since the dot/dash are of no actual value and over complicate the task. I still would not recommend doing the play/sox/beep or whatever each time through since that's a ridiculous way to construct something like this, even in bash. The crunchbang example also demonstrates how to setup arrays which would be of use for this particular problem and so it was a good example to showcase that type of approach. – slm Mar 31 '16 at 08:04
  • @slm , I get your point , but OP said "What would be the best way to go about replacing the character "." with a beep and "-" with a slightly longer beep?" and I only answered that part, and I hope I answered it correctly within the parameters of the question (even though somebody felt it necessary to downvote). Any cli tool which takes the raw input text and gives the audio output would work, but it would not match the given tags of bash and scripting. – Prem Mar 31 '16 at 08:53
  • 1
    The thing is, you didn't actually answer any part. You gave a general direction the OP can follow but not an actual answer. Where do you help the OP "replace . with beep and - with a slightly longer beep"? How would the OP code this? All you are saying is basically "get two appropriate sound files and use that", you're not helping the OP do the actual translation of symbols to sounds. – terdon Mar 31 '16 at 09:01
  • @terdon , "...iterate over the signals, using speaker-test or sox inside the loop , for generating the sound matching the current signal." , If OP asked for code, I could have added it (downvote gives no clue on what I should do more) , but anyway my terse answer says : "iterate over the signals" meaning "for D in (...) ; do ... done" ; "generate the sound matching the current signal" meaning "if $D=. play DOT.wav else play DASH.wav endif" , and OP should have all that he requires. If somebody had given such terse instructions to me, I would have been happy; else I would ask for details – Prem Mar 31 '16 at 09:25
  • 1
    @Prem well that's just it. We expect answers to actually answer the question here. Your answer doesn't actually mention the for loop and, more importantly, it doesn't mention anything about what to do inside the for loop. That (...) in your previous comment is what it's all about. If $D= what? That is exactly what the OP is asking: "how can I replace . with beep". Your answer is, basically, "just replace . with a beep". – terdon Mar 31 '16 at 09:29