Skip to content

Instantly share code, notes, and snippets.

@Thann
Last active February 9, 2023 05:11
Show Gist options
  • Save Thann/d56ffc0d8cc0690e960a to your computer and use it in GitHub Desktop.
Save Thann/d56ffc0d8cc0690e960a to your computer and use it in GitHub Desktop.
Beats per minute calculator for the command line.
#!/bin/sh
# Calculates Beats per Minute and confidence.
# Trigger function on ctrl+c
trap ctrl_c_handler INT
function ctrl_c_handler() {
echo -e "\n -> $index beats in $(echo "scale=2; $delta_sum /1"| bc) seconds. "
exit 0
}
if [[ $1 == '-q' ]]; then
q_to_quit='true'
fi
index=0
delta_sum="0.0"
delta_sum_sq="0.0"
confidence="%100 "
if [[ -n $q_to_quit ]]; then
msg="Start tapping any key to calculate BPM, press \"Q\" to stop."
else
msg="Start tapping any key to calculate BPM, press Ctrl+C to stop."
fi
cols=$(tput cols) # terminal width
echo -ne ${msg:0:$cols} # truncate msg to fit terminal.
read -n 1 -s # get character
read -t 0.00001 -s # flush
msg=" BPM: ... "
echo -ne "\r${msg:0:$cols}"
while true; do
start_time=$(date +%s.%N)
read -n 1 -s "char" # get character
end_time=$(date +%s.%N)
read -t 0.00001 -s # flush
if [[ -n $q_to_quit ]] && [[ $char == "q" || $char == "Q" ]]; then
ctrl_c_handler
fi
((index++))
delta_time=$(echo "$end_time - $start_time"| bc)
delta_sum=$(echo "$delta_sum + $delta_time"| bc)
delta_sum_sq=$(echo "$delta_sum_sq + ($delta_time * $delta_time)"| bc)
if [ $index -gt 1 ]; then
# Use naïve algorithm for calculating variance.
# from https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Na.C3.AFve_algorithm
variance=$(echo "scale=10; ($delta_sum_sq - ($delta_sum * $delta_sum) / $index) / ($index - 1)"| bc)
# Calculate confidence: abs(x - v) / x
diff=$(echo "$delta_time - $variance"| bc)
if [ ${diff:0:1} == '-' ]; then diff=${diff:1}; fi # abs( diff )
confidence=$(echo "scale=5; $diff / $delta_time * 100"| bc)
if [ `echo "$confidence < 100"| bc` -eq 1 ]; then
confidence="%${confidence:0:4}"
else # when confidence was less than -100
confidence="%00.0"
fi
fi
BPM=$(echo "scale=2; ($index / $delta_sum) * 60"| bc)
echo -ne "\r BPM: $BPM $confidence "
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment