-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
261 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |