#!/bin/bash

bpm=$1
(( i = bpm? 6000/bpm-1: 74, sec = i/100, ms = i%100, bpm )) || bpm=80
printf -v interval "%i.%02i" $sec $ms

help="  + - or (pg)up,dn to adjust tempo
       any key to enter a numeric tempo
       h for help
       q to quit"

printf '\e[?25l\e[11;1]\e[H\e[2J%i bpm' $bpm

[ $TERM = linux ] || printf '\n\n%s' \
'consider switching to plain linux console'
       # the escape for changing bell length only works there, leading to
       # inaccuracy when some terms have a long bleat -- not to mention
       # some don't even have a bell at all

amixer -q set Beep unmute  # or the equivalent command for non-alsa setups, if needed

# if still mute, try (as root) modprobe pcspkr

trap 'amixer -q set Beep mute; exit' INT

while [ "$input" ] || printf '\a'; do
       unset input
       read -sn1 -t $interval input || continue

       case "$input" in
       +|A|5)
               (( bpm++ ))
       ;;
       -|B|6)
               (( bpm-- ))
       ;;
       $'\E'|[|\~)
               # up/down keys need this, despite WORKING FINE JUST A SECOND AGO
       ;;
       q)
               amixer -q set Beep mute
               printf '\e[?25h\e[H\e[JGood job %s for practicing.\n' "$USER"
               exit
       ;;
       h)
               printf '\e[H\e[J%s\n\n\t%s' "$help" "press any key"
               read -n 1
       ;;
       *)
               printf '\e[H\e[JEnter a tempo: '
               old=$bpm
               read bpm
       ;;
       esac

       if (( i=6000/bpm-1, sec = i/100, ms = i%100, bpm )); then
               printf -v interval "%i.%02i" $sec $ms
               # HA, goodbye numfmt, my last external process
       else bpm=$old; fi

       printf '\e[H\e[J%i bpm' $bpm
done