# Tap Tempo, a toy project 🥁

## Here Comes the Sun

The Tap Tempo project was born in February 2018, as the first C++ version was posted by François Mazen on the famous LinuxFr.org website, alias Da Linux French Page, created in 1998. It follows KISS, not the band, but the Keep It Simple Stupid principle: you hit the Enter key at each beat of the song, and taptempo computes the beats per minute (BPM). For the greatest benefit of mankind, it was published under the GNU GPLv3+ license and is even available as a Debian package.

It soon became a game to adapt taptempo in as many languages as possible, as it is more interesting than the boring classical Hello World: Ada, Avanced Brainfuck, APL, Arduino Uno, Awk, Bash, basic Amstrad CPC, brainfuck, C, C#, C++, Chisel3, Clojure, Clojure (v2), CMake, COBOL, Crystal-Lang, Elixir, emacs lisp, Forth, Golang, GOTO++, Haskell, Java, Javascript, Kotlin, Linotte, OCaml, Perl, Perl6, PHP, PWA, Python 2.7, Python 3, Python web, Python WUY, Reason, Rust, Scala, Scratch, STM32F469i-Discovery, Tcl, VBA, Verilog, VHDL, Wren, ZX81… Following that planetary success, a TapTempo-Federation was founded on GitHub, with the glorious goal of “promoting the use and adoption of Taptempo, and defines related standards.”

## A T. Rex version

As I found no Fortran version, I decided to write my own: an obvious reason for that enterprise, apart the admirable science behind the computation of the tempo, is that, like Elvis Presley, Fortran began its career in 1954. But before announcing to the world that major event, I decided of course to submit my work to the Fortran-lang community as an fpm project:

Any comments and ideas to improve the quality of that 0.9.0 version are welcome, as I would like it still runs when I am sixty-four.

## What I learned

Interestingly, my first idea was to use cpu_time() but I soon realised that the process was idle while the read(*, '(a1)') key was waiting for an input! That’s why I finally used system_clock().

8 Likes

Very fun idea. I just knew I had to test it with a very fast-paced tune, Gansuvd - Sarnai. Over 140 BPM! This song is kind of annoying, but still nice to listen to during aerobic exercise (cycling, etc.) because of its fast beat.

My only idea would be to add some sort of ASCII x/y-plot that displays the BPM vs. time. Maybe it could be shown when the user exits the program?

1 Like

Thanks for feedback! I have also found ~138 bpm on the beginning of that song! (but did not try aerobic )

My only idea would be to add some sort of ASCII x/y-plot that displays the BPM vs. time. Maybe it could be shown when the user exits the program?

That’s an interesting idea. Could be shown in ASCII, or the data could be saved in a file for plotting with Gnuplot.

The original post (French) about the C++ TapTempo shows a graph about the tempo deviation during Stairway to Heaven. It comes from that blog where you will find the same thing for a few other songs:

I have also realized TapTempo can be used to measure your heart rate : (gently!) put one hand around your throat and tap the enter key at each beat.

GNU GPL v3 :

16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM…

Vincent @vmagnin, very nice toy project.

After my poor keyboard (ENTER) interpretation, here some tests.

I added some lines to plot data with gnuplot (set the multiplot mode)

open(10,file=output,status='unknown')
write(10,'(a)') '#
...
write(10,'(i0,f10.1)') iter, 60 / ((t(1) - t(oldest)) / (oldest - 1))

2 Likes

Thanks Asdrubal @alozada , you showed that even if there is noise in our tapping we can see tempo variations in a piece of music. I hope you keyboard is not dead… (did you really tap Enter for 1700 seconds ?!) Once again I plead the GNU GPL v3 Limitation of Liability clause

Remark: there is an anomaly in your data, as 200 BPM would be already a very fast song. Wikipedia says: " Prestissimo – even faster than presto (200 bpm and over)". Therefore 350 BPM seems odd. Maybe you tapped 2 or 4 times per beat?

1 Like

yes. I found it fun

the keyboard still lives.

I think it would be interesting to use the mouse click
is there a way to use the mouse click as input for Fortran programs?

3 Likes

Killing mouses is a more serious moral problem… I don’t know if the GPL covers that.

I don’t think Fortran could access the mouse click without using a C library (or any other language). It could be a kind of Hello world example for gtk-fortran (or Tcl/Tk for @Arjen), with just one button and the display of the beats per minute. That display could even be in the button text. If someone wish to learn gtk-fortran, it is a good toy introduction!

1 Like

I discovered that if you press continuously the Enter key in your terminal, the BPM is peaking at 1500 BPM in the case of bash under Linux, and ~1900 BPM with MSYS2/MINGW64 under Windows 10. The bash value was exactly the same with the C++ TapTempo, it’s therefore a feature of the shell. And it is not related to scrolling, as it does not depend on the height of the terminal window. So leave all hope behind, you won’t even approach the GBPM with your 3 GHz processor…

Updated: that 1500 BPM limit is in fact coming from the KDE settings. The defaut repetition rate of the keyboard is 25 Hz, and 25 \times 60=1500. In KDE, the maximum value is 100 Hz (6000 BPM).

Keeping a mouse alive can also be a problem. I once read a problem report where a long simulation was running on a PC with periodic graphics output to the screen, and the user wanted to know how to prevent Windows from going into Sleep mode. One recommendation given was to place the PC mouse on a hard surface and to keep a small fan continuously blowing air on the mouse.

1 Like

I implemented a simple click counter in Tcl/Tk, just for fun. You can also change the colour of specific graphical items. In Tcl/Tk you assign actions to various events that happen in the windows under its control. Various toolkits for building GUIs offer different methods. (If you want to catch all mouse clicks that happen on the display, you will have to use low-level methods, as the mouse clicks are usually mapped to some window.)

Here is the code - just for fun as I said.

# cntclicks.tcl --
#     Count mouse clicks
#

#
# Create a canvas widget: clicks inside the widget will be counted
#
grid [canvas .c -bg white]                                   -                                       -sticky news
grid [label  .l1 -text "Count: " -anchor w]                 [label .lcount -textvariable count]     -sticky news
grid [label  .l2 -text "Frequency (count/min): " -anchor w] [label .lfreq  -textvariable frequency] -sticky news

.c create text       20  20 -text "Click in the window ..." -anchor nw
.c create rectangle  40  45 300 100 -fill green -tag rectangle
.c create rectangle  40 240 300 300 -fill green -tag rectangle
.c create text 50 50 -text "Click here to change the colour" -anchor nw

#
# Two types of bindings:
# - One specific to canvas items (items with a tag "rectangle")
# - One for the canvas as a whole
#

.c bind rectangle <Button-1> {changeColour}

bind .c <Button-1> {countClick}

#
# Fancy: set some options for resizing
#
grid rowconfigure    . 0 -weight 1
grid columnconfigure . 1 -weight 1

#
# Initialilise a few global variables
#
set count      0      ;# Number of mouse clicks
set frequency  0.0    ;# Frequency of the clicks
set startTime [clock milliseconds]  ;# Start time, so we can display the frequency

set colours [list black blue cyan green lime yellow orange red magenta]

#
# Action to be taken with each click
#
proc countClick {} {
global count
global frequency
global startTime

incr count
set currentTime [clock milliseconds]
set frequency   [expr {($count * 60000) / double($currentTime - $startTime)}] } # # Action to change the colour # proc changeColour {} { global count global colours set colour [expr {$count % [llength $colours]}] .c itemconfigure rectangle -fill [lindex$colours \$colour]
}

1 Like
1 Like

At 600 BPM, it sounds quite like my old 56 kbit/s modem…
You did not say in your first post he was the guy playing your Für Elise and Turkish March shred versions…

Happily TapTempo can be used up to 1500 BPM… You just have to find a shred keyboard… Be careful with tendonitis!

1 Like

@vmagnin, @alozada, here is a song which will mess with your perception:

(Hint: the bpm is supposedly close to 154.78; if you struggle to find it watch this video)

1 Like