#!/bin/bash
#
#	IRLP CWID'er by Robert Pectol
#	callsign v3.0 - 12 July 2007
#	http://rob.pectol.com/irlp
#
##########################################
#
# Modified for Debian's version of SOX with bash, not sh - VK2YLD
#


#####   USER CONFIGURABLE SETTINGS    #####
#
# Sets the amplitude of the CW (ranges from a minimum of '.01', to a maximum of '.99')
# A value of approx. '.50' is probably pretty close for most users since you will
# typically want the CW identifier to be, 'subdued' when compared to voice audio level.
volume=".35"

# Sets the pitch of the CW (in Hertz)
pitch="800"

# Sets the characters to be sent in CW.  If, "$CALLSIGN" is specified
# here, it will send the IRLP node's callsign as configured in the IRLP
# environment file.  Most users probably won't need to change this unless
# they want to customize the CW message.
callsign="$CALLSIGN"

# Specifies the location where the callsign wav file will be created.
# (Must end with, '.wav' since it's a wav file that will be created and
# played back.  Also, the full path must be specified as well!)
location="/home/irlp/callsign.wav"

# Specifies the speed of the CW identification string in WPM (words per minute).
# The pre-defined values are 10, 15, and 20 WPM.  Values specified other than
# these will result in a default of 20 WPM.  If you need to tweak the speed of
# the CW identification string to something other than the listed, pre-defined
# values, then change this to, "custom" (ex. id_speed="custom").  Then, you may
# carefully adjust the values for, ditlength, dahlength, ditdahspc, chrspace,
# and wrdspc under the, "CUSTOM CW SPEED, SPACING, ETC." area below.  Be mindful
# of local rules and regulations regarding maximum CW speed for automatically
# identified amateur radio stations, etc.
id_speed="20"
#
###    END USER CONFIG  SETTINGS    ###


####################################################################
#  MODIFICATIONS BELOW THIS LINE ARE NOT NECESSARY FOR MOST USERS  #
####################################################################

# ensure script is run as repeater user
if [ `/usr/bin/whoami` != "repeater" ] ; then
	echo "Script must be run as the, 'repeater' user."
	exit 1
fi

# make sure required binaries are available
check_gawk=`which gawk`
if [ "$check_gawk" = "" ]; then
	echo "The gawk utility could NOT be found and is required!  Exiting..."
	exit 1
fi
check_md5sum=`which md5sum`
if [ "$check_md5sum" = "" ]; then
	echo "The md5sum utility could NOT be found and is required!  Exiting..."
	exit 1
fi
check_play=`which play`
if [ "$check_play" = "" ]; then
	echo "The play utility could NOT be found and is required!  Exiting..."
	exit 1
fi
check_sox=`which sox`
if [ "$check_sox" = "" ]; then
	echo "The sox utility could NOT be found and is required!  Exiting..."
	exit 1
fi

# exit if there is an active instance already executing
if [ -f $LOCAL/cw ] ; then
	exit 1
fi

# ensure the environment file has been sourced
if [ "$RUN_ENV" != "TRUE" ] ; then
	. /home/irlp/custom/environment
fi

if [ "$id_speed" = "custom" ]; then


	#####								#####
	##################  CUSTOM CW SPEED, SPACING, ETC.  #################
	# The following settings affect the CW speed, character spacing, etc.  They
	# produce CW at approx. 25 WPM.  Adjust these values until you get the speed
	# and sound (CW fist) you desire.  These values are very sensitive and can
	# easily cause the generated CW to sound very bad.  Tweak with care!  :-)
	#
	# Sets the length timing for the dits (default is 0.073)
	ditlength="0.073"
	# Sets the lenth timing for the dahs (default is 0.160)
	dahlength="0.160"
	# Sets the space timing between dits and dahs (default is 0.015)
	ditdahspc="0.015"
	# Sets the space timing between characters (default is 0.125)
	chrspc="0.125"
	# Sets the space timing between words (default is 0.180)
	wrdspc="0.180"
	#
	###############  END CUSTOM CW SPEED, SPACING, ETC.  ################
	#####								#####


elif [ "$id_speed" = "20" ]; then
	ditlength="0.075"
	dahlength="0.185"
	ditdahspc="0.030"
	chrspc="0.140"
	wrdspc="0.200"
elif [ "$id_speed" = "15" ]; then
	ditlength="0.085"
	dahlength="0.278"
	ditdahspc="0.045"
	chrspc="0.210"
	wrdspc="0.300"
elif [ "$id_speed" = "10" ]; then
	ditlength="0.150"
	dahlength="0.370"
	ditdahspc="0.060"
	chrspc="0.280"
	wrdspc="0.400"
else
	ditlength="0.075"
	dahlength="0.185"
	ditdahspc="0.030"
	chrspc="0.140"
	wrdspc="0.200"
fi

# set some script vars
dit="/tmp/dit.raw"
dah="/tmp/dah.raw"
wordspace="/tmp/wrdspc.raw"
errtone="/tmp/errtone.raw"
count="0"

# tones synthesizer function
synth ()
{
	sox -n /tmp/di.raw synth $ditlength sine $pitch lowpass $pitch
	sox -n /tmp/da.raw synth $dahlength sine $pitch lowpass $pitch
	sox -n /tmp/dspace.raw synth $ditdahspc sine 0
	sox -n /tmp/chrspace.raw synth $chrspc sine 0
	sox -n /tmp/wrdspc.raw synth $wrdspc sine 0
	sox -n /tmp/et.raw synth 0.75 sine 400-320 lowpass 600
	cat /tmp/di.raw /tmp/dspace.raw > /tmp/dit.raw
	cat /tmp/da.raw /tmp/dspace.raw > /tmp/dah.raw
	cat /tmp/et.raw /tmp/dspace.raw > /tmp/errtone.raw

#	sox -t nul /dev/null -w /tmp/di.raw synth $ditlength sine $pitch lowpass $pitch
#	sox -t nul /dev/null -w /tmp/da.raw synth $dahlength sine $pitch lowpass $pitch
#	sox -t nul /dev/null -w /tmp/dspace.raw synth $ditdahspc sine 0 lowpass 0
#	sox -t nul /dev/null -w /tmp/chrspace.raw synth $chrspc sine 0 lowpass 0
#	sox -t nul /dev/null -w /tmp/wrdspc.raw synth $wrdspc sine 0 lowpass 0
#	sox -t nul /dev/null -w /tmp/et.raw synth 0.75 sine 400-320 lowpass 600
#	cat /tmp/di.raw /tmp/dspace.raw > /tmp/dit.raw
#	cat /tmp/da.raw /tmp/dspace.raw > /tmp/dah.raw
#	cat /tmp/et.raw /tmp/dspace.raw > /tmp/errtone.raw
}

# sanity checking of user config settings
check_location=`echo $location | egrep '\.wav$'`
if [ "$check_location" = "" ]; then
	echo "location must point to a file with a .wav extension!"
fi

# initially create the CW sound files, or re-create
# the CW sound files if, this file has been modified
# since the last time it was executed.
if [ ! -f ${location}script.md5sum ]; then
	touch ${location}script.md5sum
fi
callsign_oldmd5sum=`cat ${location}script.md5sum`
callsign_md5sum=`md5sum $0 | cut -d ' ' -f1`
echo $callsign_md5sum > ${location}script.md5sum
if [ "$callsign_md5sum" != "$callsign_oldmd5sum" ]; then
	echo "generating CW..."
	configured="no"
else
	configured="yes"
fi
if [ "$configured" = "no" ] || [ ! -f $location ]; then
	rm -f $location > /dev/null 2>&1
	synth
fi

# characters build function
character ()
{
	count=$(($count + 1))
	cat $chr /tmp/chrspace.raw > /tmp/letter$count.raw
}

# concatenate letters function
concat ()
{
        lettercount=1
        while [ -f /tmp/letter${lettercount}.raw ]; do
                cat /tmp/letter${lettercount}.raw >> /tmp/callsign.raw
                rm -f /tmp/letter${lettercount}.raw
                lettercount=$(($lettercount + 1))
        done
        sox -r 48000 -c 1 -b 32 -e signed-integer /tmp/callsign.raw -e float $location lowpass $pitch
#        sox -r 44100 -c 2 -s -w /tmp/callsign.raw $location lowpass $pitch
}

# build the callsign file
if ! [ -f $location ] ; then
	# format characters in callsign to allow for spaces, upper/lower-case, etc.
	callsign=`echo $callsign | sed 's/ /_/g'`
	callsign=`echo $callsign | gawk 'BEGIN { FS = "" }{for (i = 1; i <= NF; i = i + 1) print $i}'`
	callsign=`for chrs in $callsign; do chrs=$(echo "$chrs" | tr 'A-Z' 'a-z'); echo $chrs; done`
	# the CW characters are built in a case-statement within a for loop
	for chrs in $callsign; do
		case $chrs in
			a) chr="$dit $dah"; character ;;
			b) chr="$dah $dit $dit $dit"; character ;;
			c) chr="$dah $dit $dah $dit"; character ;;
			d) chr="$dah $dit $dit"; character ;;
			e) chr="$dit"; character ;;
			f) chr="$dit $dit $dah $dit"; character ;;
			g) chr="$dah $dah $dit"; character ;;
			h) chr="$dit $dit $dit $dit"; character ;;
			i) chr="$dit $dit"; character ;;
			j) chr="$dit $dah $dah $dah"; character ;;
			k) chr="$dah $dit $dah"; character ;;
			l) chr="$dit $dah $dit $dit"; character ;;
			m) chr="$dah $dah"; character ;;
			n) chr="$dah $dit"; character ;;
			o) chr="$dah $dah $dah"; character ;;
			p) chr="$dit $dah $dah $dit"; character ;;
			q) chr="$dah $dah $dit $dah"; character ;;
			r) chr="$dit $dah $dit"; character ;;
			s) chr="$dit $dit $dit"; character ;;
			t) chr="$dah"; character ;;
			u) chr="$dit $dit $dah"; character ;;
			v) chr="$dit $dit $dit $dah"; character ;;
			w) chr="$dit $dah $dah"; character ;;
			x) chr="$dah $dit $dit $dah"; character ;;
			y) chr="$dah $dit $dah $dah"; character ;;
			z) chr="$dah $dah $dit $dit"; character ;;
			/) chr="$dah $dit $dit $dah $dit"; character ;;
			,) chr="$dah $dah $dit $dit $dah $dah"; character ;;
			.) chr="$dit $dah $dit $dah $dit $dah"; character ;;
			-) chr="$dah $dit $dit $dit $dit $dah"; character ;;
			0) chr="$dah $dah $dah $dah $dah"; character ;;
			1) chr="$dit $dah $dah $dah $dah"; character ;;
			2) chr="$dit $dit $dah $dah $dah"; character ;;
			3) chr="$dit $dit $dit $dah $dah"; character ;;
			4) chr="$dit $dit $dit $dit $dah"; character ;;
			5) chr="$dit $dit $dit $dit $dit"; character ;;
			6) chr="$dah $dit $dit $dit $dit"; character ;;
			7) chr="$dah $dah $dit $dit $dit"; character ;;
			8) chr="$dah $dah $dah $dit $dit"; character ;;
			9) chr="$dah $dah $dah $dah $dit"; character ;;
			_) chr="$wordspace"; character ;;
			*) chr="$errtone"; character ;;
		esac
	done
	concat
	rm -f /tmp/*.raw > /dev/null 2>&1
fi
touch $LOCAL/cw
aplay $location > /dev/null 2>&1
rm -f $LOCAL/cw
exit 0

