Minimorse - a learning program for interpreting ITU morse

Applications, Games, Tools, User libs and useful stuff coded in PureBasic
gekkonier
User
User
Posts: 78
Joined: Mon Apr 23, 2007 9:42 am

Minimorse - a learning program for interpreting ITU morse

Post by gekkonier »

Hi!

I've written a small program to help learning morse code.
It's not finished, but usablel. It's missing special characters like Á...
Future versions will be edited inside this post here.

It features a REPL (read eval print loop - shell alike) for recognizing commands and text to morse.
It doesn't show you the -.--, instead it shows you the actual character or shorthand while you hear it!
In the end, after using this program for a longer time you should be able to write down what you hear (the morse) without thinking.
Start with only 2-3 chars each day for about 15m. After about 1-3 months (depends on your brain, hehe) you should be able to "see" heard morse code in your head.
If you can write it down on paper without thinking finally, you will be able to morse too. Believe it or not ;)
A special learning modus will be implemented later (dictionary, speed independent,...)


1) get SoundEasy.pbi from http://forum.purebasic.com/english/view ... 12&t=53646
I used it from the very first post in that thread. Thank you BasicallyPure!
2) save the following code aside the pbi and read the comments at the beginning

Code: Select all

; Title:   Minimorse
; Author:  Gekkonier
; Date:    2016-05-13
; Version: 0.2
; OS:      Windows tested
;          Linux and OSX not tested!
; PB ver.  5.42 LTS (x64)
;
; LICENSE:
;
; Do what you want with it, but don't blame me if your ears fall apart or your
; computer starts to act weird!
; This program uses SoundEasy.pbi
; you can find this include here:
; http://forum.purebasic.com/english/viewtopic.php?f=12&t=53646
; I don't know the terms of this include.
;
; Thank you, BasicallyPure for this awesome code!
;
;
; primary purpose:
; this program should help you to learn to correctly hear morse code (ITU)
;
; features:
; repl with help
; you enter text, it displays the transformed text (what is defined as code),
; and then shows you code after code the text and plays the corresponding sequence
; it doesn't show you the actual morse code, it distracts while learning!
;
;
; planned features:
; - change volume, speed and soundfrequency inside repl
; - argc, argv for:
;       minimorse                             for repl
;       minimorse -vol:XX -speed:XX -freq:xx
;       minimorse -say hello world!           for direct playing of strings
;       minimorse -play filename              for playback of a file
;       minimorse hello world!                garbage, abort!
; - in a galaxy far, far away:
;       minimorse -learn and &learn command   for a dedicated learning modus
;                                             you hear morse code, and have to write it down
;                                             but i think i will do this as a gui app
;                                             so i can implement sound or optical morsing



; a simple error "handler"
Procedure handle(value.i, message.s)
  If value = 0
    MessageRequester("ERROR!", message)
    End
  EndIf
EndProcedure

handle(InitSound(), "Could not initialize Sound System!")

; the SoundEasy.pbi is not EnableExplicit compatible!
IncludeFile "SoundEasy.pbi"
; but now we can use it!
EnableExplicit

; speed and freqency settings for the soundoutput
#SPEED = 0.09
#SPEEDMS = #SPEED * 1000
#AMP = 25
#FREQUENZY = 1000

; dit and dah sounds are created with SoundEasy.pbi
Global ditsnd.i = CreateSound(#PB_Any, #FREQUENZY, #SPEED, #AMP, 0, #WF_SineWave, 0, 1)
Global dahsnd.i = CreateSound(#PB_Any, #FREQUENZY, #SPEED * 3, #AMP, 0, #WF_SineWave, 0, 1)

; this is the "AST"
Global NewList Tokens.s()

; these are the morse code values for the different token types
; these values are copied from our glory interwebs.
; missing: accents
; ä, ö, ü, ß are there, because german.
Global NewMap Token.s()
Token(" ") = " "
Token("A") = ".-"
Token("B") = "-..."
Token("C") = "-.-."
Token("D") = "-.."
Token("E") = "."
Token("F") = "..-."
Token("G") = "--."
Token("H") = "...."
Token("I") = ".."
Token("J") = ".---"
Token("K") = "-.-"
Token("L") = ".-.."
Token("M") = "--"
Token("N") = "-."
Token("O") = "---"
Token("P") = ".--."
Token("Q") = "--.-"
Token("R") = ".-."
Token("S") = "..."
Token("T") = "-"
Token("U") = "..-"
Token("V") = "...-"
Token("W") = ".--"
Token("X") = "-..-"
Token("Y") = "-.--"
Token("Z") = "--.."
Token("1") = ".----"
Token("2") = "..---"
Token("3") = "...--"
Token("4") = "....-"
Token("5") = "....."
Token("6") = "-...."
Token("7") = "--..."
Token("8") = "---.."
Token("9") = "----."
Token("0") = "-----"
Token("Ä") = ".-.-"
Token("Ö") = "---."
Token("Ü") = "..--"
Token("ß") = "...--.."
Token("CH") = "----"
Token(".") = ".-.-.-"
Token(",") = "--..--"
Token(":") = "---..."
Token(";") = "-.-.-."
Token("?") = "..--.."
Token("&") = ".-..."
Token("-") = "-....-"
Token("_") = "..--.-"
Token("(") = "-.--."
Token(")") = "-.--.-"
Token("'") = ".----."
Token("=") = "-...-"
Token("+") = ".-.-."
Token("/") = "-..-."
Token("@") = ".--.-."
; shorthands
Token("STARTING SIGNAL") = "-.-.-"
Token("ENDING SIGNAL") = ".-.-."
Token("INVITATION TO TRANSMIT") = "-.-"
Token("UNDERSTOOD") = "...-."
Token("PAUSE") = "-...-"
Token("WAIT") = ".-..."
Token("ERROR") = "........"
Token("NEW PAGE SIGNAL") = ".-.-."
Token("END OF WORK") = "...-.-"

; this can only play one morse symbol
; morse symbols are . - and <space>
Procedure playsymbol(symbol.s)
  Select symbol
    Case "."
      PlaySound(ditsnd)
      Delay(#SPEEDMS * 2)
    Case "-"
      PlaySound(dahsnd)
      Delay(#SPEEDMS * 4)
    Case " "
      Delay(#SPEEDMS * 7)
  EndSelect
EndProcedure

; this uses playsymbol to play a sequence of morse symbols
Procedure playcode(morsecode.s)
  Define i.i
  For i = 1 To Len(morsecode)
    playsymbol(Mid(morsecode, i, 1))
  Next
EndProcedure  

; this feeds the Tokens() List, if the UCase of a char is in the Token() Map
Procedure tokenize(text.s)
  
  text = UCase(text)
  ClearList(Tokens())
  
  Define textlength.i = Len(text)
  
  If textlength = 1
    If Token(text) <> ""
      AddElement(Tokens())
      Tokens() = text
    EndIf
  EndIf
  
  If textlength > 1
    
    Define currentchar.s
    Define nextchar.s
    Define i.i
    For i = 1 To textlength - 1
      currentchar = Mid(text, i, 1)
      nextchar = Mid(text, i + 1, 1)
      If currentchar = "C" And nextchar = "H"
        AddElement(Tokens())
        Tokens() = "CH"
        i = i + 1
      Else
        AddElement(Tokens())
        Tokens() = currentchar
      EndIf
    Next
    
    If i = textlength
      AddElement(Tokens())
      Tokens() = Mid(text, i, 1)
    EndIf
    
  EndIf
  
EndProcedure

; this returns the Tokens() List as a combined string
; for debugging purposes or to see what the process(text.s) will work on
Procedure.s tokens2text()
  Define tokencount = ListSize(Tokens())
  Define text.s
  
  If tokencount > 0
    Define i.i
    For i = 0 To tokencount - 1
      SelectElement(Tokens(), i)
      text = text + Tokens()
    Next
  EndIf
  
  ProcedureReturn text
  
EndProcedure

; print a help for the repl
Procedure help()
  PrintN("")
  PrintN("&help            = this text")
  PrintN("&quit            = quit program")
  ;PrintN("&faster, &slower = change speed")
  ;PrintN("&louder, &lower  = change amp")
  PrintN("")
  PrintN("-- shorcuts --")
  PrintN("&start = starting signal")
  PrintN("&inv   = invitation to transmit")
  PrintN("&ok    = understood")
  PrintN("&wait  = wait")
  PrintN("&pause = pause")
  PrintN("&error = error")
  PrintN("&np    = new page")
  PrintN("&eow   = end of work")
  PrintN("")
EndProcedure

; repl processor - this iterates over the given text.
; first it creates the tokens
; if the tokens2text() returns a commando it will execute that
; if not:
; it prints the token and playes the morsecode of it.
Procedure process(text.s)
  
  Repeat
  
    tokenize(text)
    
    ; special repl syntax
    Select tokens2text()
      ; end the program  
      Case "&QUIT"
        CloseConsole()
        End
      ; print a help
      Case "&HELP"
        help()
        Break
      ; from here: shorthands
      Case "&START"
        Print("STARTING SIGNAL")
        playcode(Token("STARTING SIGNAL"))
        PrintN("")
        Break
      Case "&INV"
        Print("INVITATION TO TRANSMIT")
        playcode(Token("INVITATION TO TRANSMIT"))
        PrintN("")
        Break
      Case "&OK"
        Print("UNDERSTOOD")
        playcode(Token("UNDERSTOOD"))
        PrintN("")
        Break
      Case "&WAIT"
        Print("WAIT")
        playcode(Token("WAIT"))
        PrintN("")
        Break
      Case "&PAUSE"
        Print("PAUSE")
        playcode(Token("PAUSE"))
        PrintN("")
        Break
      Case "&ERROR"
        Print("ERROR")
        playcode(Token("ERROR"))
        PrintN("")
        Break
      Case "&NP"
        PrintN("NEW PAGE")
        playcode(Token("NEW PAGE SIGNAL"))
        PrintN("")
        Break
      Case "&EOW"
        PrintN("END OF WORK")
        playcode(Token("END OF WORK"))
        PrintN("")
        Break
    EndSelect
    
    ; if no command do your job
    ; this needs to be improoved.... spaghetti and silly checks
    Define tokencount.i = ListSize(Tokens())
    Select tokencount
      Case 0
        Break
      Case 1
        FirstElement(Tokens())
        Print(Tokens())
        playcode(Token(Tokens()))
        PrintN("")
        Break
      Default
        PrintN(tokens2text())
        Define i.i
        For i = 0 To tokencount - 1
          SelectElement(Tokens(), i)
          Print(Tokens())
          playcode(Token(Tokens()))
          Delay(#SPEEDMS)
        Next
        PrintN("")
        Break
    EndSelect
  
  ForEver
  
EndProcedure

; our main loop
Procedure repl()
  Define input.s  
  
  OpenConsole()
  PrintN("Welcome to Minimorse")
  PrintN(".-.-.-.-.-.-.-.-.-.-")
  help()
  
  Repeat
    Print("input: ")
    input = Input()
    process(input)
  ForEver
  
EndProcedure

repl()
User avatar
BasicallyPure
Enthusiast
Enthusiast
Posts: 536
Joined: Thu Mar 24, 2011 12:40 am
Location: Iowa, USA

Re: Minimorse - a learning program for interpreting ITU mors

Post by BasicallyPure »

gekkonier wrote:; the SoundEasy.pbi is not EnableExplicit compatible!
I made it compatible now.
Thanks for pointing that out.
BasicallyPure
Until you know everything you know nothing, all you have is what you believe.
Post Reply