Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
vmagnin committed Oct 28, 2021
1 parent 0e9b430 commit 6c94f98
Show file tree
Hide file tree
Showing 7 changed files with 261 additions and 0 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Changelog
All notable changes to the taptempo project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).


## [TapTempo Fortran 0.9] 2021-10-28
Initial commit.
79 changes: 79 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# TapTempo Fortran

A command line `taptempo` written in modern Fortran and under GNU GPLv3 license. Listen to a song and hit enter key with style and you'll get the corresponding number of beats per minute (BPM). This tool is very useful to quickly find the tempo of a song.

The original TapTempo was written in C++, but lots of porting in other languages have been developed via the [LinuxFr website](https://linuxfr.org/wiki/taptempo). There is even a [TapTempo Federation](https://github.com/Taptempo-Federation).


## Compilation and execution

You need a modern Fortran compiler.

You can easily build and run the project using the Fortran Package Manager fpm (https://github.com/fortran-lang/fpm) at the root of the project directory:

```
$ fpm build
$ fpm run
Hit Enter key for each beat (q to quit).
[Hit enter key one more time to start BPM computation...]
Tempo: 85. BPM
Tempo: 83. BPM
Tempo: 84. BPM
Tempo: 84. BPM
Tempo: 81. BPM
```

To add options, put them after `--`:

```
$ fpm run -- -r 3 -s 8 -p 2
```

Or you can also use the `build.sh` script if you don't have fpm installed, or just simply type:

```
$ gfortran src/taptempo.f90 app/main.f90
```

## Options

```
Usage : taptempo [options]
Options :
-h, --help display this help message
-p, --precision change the number of decimal for the tempo,
the default is 0 decimal places, the max is 5 decimals
-r, --reset-time change the time in seconds to reset the calculation,
the default is 5 seconds
-s, --sample-size change the number of samples needed to calculate the tempo,
the default is 5 samples, the minimum is 2
-v, --version print the version number
```

## Contributing

* Post a message in the GitHub *Issues* tab to discuss the function you want to work on.
* Concerning coding conventions, follow the stdlib conventions:
https://github.com/fortran-lang/stdlib/blob/master/STYLE_GUIDE.md
* When ready, make a *Pull Request*.

## Technical information

* https://en.wikipedia.org/wiki/Tempo

* Introduced by Fortran 90:
* [SYSTEM_CLOCK()](https://gcc.gnu.org/onlinedocs/gfortran/SYSTEM_005fCLOCK.html)

* Introduced by Fortran 2003:
* [COMMAND_ARGUMENT_COUNT()](https://gcc.gnu.org/onlinedocs/gfortran/COMMAND_005fARGUMENT_005fCOUNT.html)
* [GET_COMMAND_ARGUMENT()](https://gcc.gnu.org/onlinedocs/gfortran/GET_005fCOMMAND_005fARGUMENT.html)

* Introduced by Fortran 2008:
* [ISO_FORTRAN_ENV real64 and int64](https://gcc.gnu.org/onlinedocs/gfortran/ISO_005fFORTRAN_005fENV.html)
8 changes: 8 additions & 0 deletions app/main.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
program main
use taptempo, only: manage_command_line, measure_tempo

implicit none

call manage_command_line()
call measure_tempo()
end program main
18 changes: 18 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash

# For a safer script:
set -eu

# Default compiler can be overrided, for example:
# $ GFC='gfortran-8' ./build.sh
# Default:
: ${FC="gfortran"}

# Create (if needed) the build directory:
if [ ! -d build ]; then
mkdir build
fi

rm -f *.mod

"${FC}" -Wall -Wextra -pedantic -std=f2008 -O2 src/taptempo.f90 app/main.f90 -o build/taptempo
14 changes: 14 additions & 0 deletions fpm.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name = "taptempo"
version = "0.9.0"
license = "license"
author = "Vincent Magnin and the Fortran-lang community"
maintainer = "Vincent Magnin"
copyright = "Copyright 2021"

[build]
auto-executables = true
auto-tests = true
auto-examples = true

[install]
library = false
130 changes: 130 additions & 0 deletions src/taptempo.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
module taptempo
! Reals working precision and 64 bits integers:
use, intrinsic :: iso_fortran_env, only: wp=>real64, int64

implicit none

! Tap Tempo Version:
character(len=*), parameter :: version = "0.9.0"

! Default values of the command options:
integer :: s = 5 ! Stack size
integer :: p = 0 ! Precision
integer :: r = 5 ! Reset time in seconds

private

public :: manage_command_line, measure_tempo

contains

subroutine print_version
print '(A)', "TapTempo Fortran "//version
print '(A)', "Copyright (C) 2021 Vincent Magnin and the Fortran-lang community"
print '(A)', "License GPLv3+: GNU GPL version 3 or later <http:https://gnu.org/licenses/gpl.html>"
print '(A)', "This is free software: you are free to change and redistribute it."
print '(A)', "There is NO WARRANTY, to the extent permitted by law."
end subroutine


subroutine print_options
print '(A)'
print '(A)', "Usage : taptempo [options]"
print '(A)'
print '(A)', "Options :"
print '(A)', " -h, --help display this help message"
print '(A)', " -p, --precision change the number of decimal for the tempo,"
print '(A)', " the default is 0 decimal places, the max is 5 decimals"
print '(A)', " -r, --reset-time change the time in seconds to reset the calculation,"
print '(A)', " the default is 5 seconds"
print '(A)', " -s, --sample-size change the number of samples needed to calculate the tempo,"
print '(A)', " the default is 5 samples, the minimum is 2"
print '(A)', " -v, --version print the version number"
end subroutine


subroutine manage_command_line
integer :: i, nb
character(len=100) :: args

nb = command_argument_count()
if (nb == 0) return

i = 0
do while (i <= nb)
i = i + 1
call get_command_argument(i, value=args)

if ((trim(args) == "-h").or.(trim(args) == "--help")) then
call print_version()
call print_options()
stop
else if ((trim(args) == "-p").or.(trim(args) == "--precision")) then
i = i + 1
call get_command_argument(i, value=args)
read(args, *) p
p = min(p, 5)
else if ((trim(args) == "-r").or.(trim(args) == "--reset-time")) then
i = i + 1
call get_command_argument(i, value=args)
read(args, *) r
else if ((trim(args) == "-s").or.(trim(args) == "--sample-size")) then
i = i + 1
call get_command_argument(i, value=args)
read(args, *) s
s = max(2, s)
else if ((trim(args) == "-v").or.(trim(args) == "--version")) then
call print_version()
stop
end if
end do
end subroutine manage_command_line


subroutine measure_tempo
character(len=1) :: key
integer(int64) :: count ! Count of the processor clock
real(wp) :: rate ! Number of clock ticks per second
integer :: i
real(wp), dimension(s) :: t ! Time FIFO stack
character(len=25) :: fmt

! Format used for printing the tempo:
write(fmt, '(A, I1, A)') '("Tempo: ", f8.', p, ', " BPM")'
! Stack initialization:
t = 0.0_wp

print '(A)', "Hit Enter key for each beat (q to quit)."

! Infinite loop:
i = 0
do
read(*, '(a1)') key

if (key == 'q') exit

call system_clock(count, rate)
! Updating the time FIFO stack:
t(2:s) = t(1:s-1)
t(1) = count / rate

i = i + 1

if (i == 1) then
print '(A)', "[Hit enter key one more time to start BPM computation...]"
else
! Verify that the user is actively tapping:
if (t(1) - t(2) <= r) then
print fmt, 60.0_wp / ((t(1) - t(min(i, s))) / (min(i, s)-1))
else
print '(A)', "Time reset"
i = 1
t(2:s) = 0.0_wp
end if
end if
end do

print '(A)', "I don't know why you say goodbye..."
end subroutine measure_tempo

end module taptempo
5 changes: 5 additions & 0 deletions test/check.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
program check
implicit none

print *, "Let It Be is around 72 BPM"
end program check

0 comments on commit 6c94f98

Please sign in to comment.