Class: Vizcore::Analysis::TapTempo

Inherits:
Object
  • Object
show all
Defined in:
lib/vizcore/analysis/tap_tempo.rb

Overview

Estimates a fixed BPM from manual tap timestamps.

Constant Summary collapse

DEFAULT_MIN_BPM =
40.0
DEFAULT_MAX_BPM =
240.0
DEFAULT_HISTORY_SIZE =
4
DEFAULT_RESET_AFTER_MS =
2_500.0

Instance Method Summary collapse

Constructor Details

#initialize(min_bpm: DEFAULT_MIN_BPM, max_bpm: DEFAULT_MAX_BPM, history_size: DEFAULT_HISTORY_SIZE, reset_after_ms: DEFAULT_RESET_AFTER_MS) ⇒ TapTempo

Returns a new instance of TapTempo.



12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/vizcore/analysis/tap_tempo.rb', line 12

def initialize(
  min_bpm: DEFAULT_MIN_BPM,
  max_bpm: DEFAULT_MAX_BPM,
  history_size: DEFAULT_HISTORY_SIZE,
  reset_after_ms: DEFAULT_RESET_AFTER_MS
)
  @min_bpm = Float(min_bpm)
  @max_bpm = Float(max_bpm)
  @history_size = Integer(history_size).clamp(1, 16)
  @reset_after_ms = Float(reset_after_ms)
  @last_tap_ms = nil
  @intervals = []
end

Instance Method Details

#tap(timestamp_ms:) ⇒ Float?

Returns estimated BPM after at least two taps.

Parameters:

  • timestamp_ms (Numeric)

    tap timestamp in milliseconds

Returns:

  • (Float, nil)

    estimated BPM after at least two taps



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/vizcore/analysis/tap_tempo.rb', line 28

def tap(timestamp_ms:)
  current = Float(timestamp_ms)
  reset_if_stale(current)
  return remember_first_tap(current) unless @last_tap_ms

  interval = current - @last_tap_ms
  @last_tap_ms = current
  return nil unless valid_interval?(interval)

  @intervals << interval
  @intervals.shift while @intervals.length > @history_size
  bpm_from_intervals
rescue ArgumentError, TypeError
  nil
end