Sound Byte Libs 29c5ff3
C++ firmware library for audio applications on 32-bit ARM Cortex-M processors
Loading...
Searching...
No Matches
beat_clock.hpp
Go to the documentation of this file.
1// sbl/patterns/timing/beat_clock.hpp — Tick-based beat clock
2//
3// Simple BPM-driven clock for sequencers, LED pulse, and gate timing.
4// Call advance() once per control tick (e.g., 200 Hz timer ISR).
5// The clock tracks bar and beat boundaries and provides a configurable
6// gate-off point within each bar.
7//
8// Not tied to any hardware — pure tick counting with integer math.
9// For audio-rate timing, use PhaseAccumulator instead.
10//
11// Usage:
12// sbl::patterns::timing::BeatClock clock(200); // 200 Hz tick rate
13// clock.set_bpm(120); // 120 BPM, 4/4 time
14// // In your control ISR:
15// bool new_bar = clock.advance();
16// if (clock.at_beat()) { /* flash LED */ }
17// if (clock.at_gate_off()) { /* release gate */ }
18
19#pragma once
20
21#include <cstdint>
22
23namespace sbl {
24namespace patterns {
25namespace timing {
26
27class BeatClock {
28public:
29 /// Construct with tick rate (Hz) and time signature.
30 explicit BeatClock(uint16_t tick_rate_hz, uint8_t beats_per_bar = 4)
31 : tick_rate_hz_(tick_rate_hz)
32 , beats_per_bar_(beats_per_bar)
33 {
34 set_bpm(120);
35 }
36
37 /// Set tempo. Recalculates all derived tick counts.
38 void set_bpm(uint16_t bpm) {
39 if (bpm == 0) bpm = 1;
40 bpm_ = bpm;
41 ticks_per_bar_ = (static_cast<uint32_t>(tick_rate_hz_) * 60 * beats_per_bar_) / bpm_;
42 ticks_per_beat_ = ticks_per_bar_ / beats_per_bar_;
43 gate_off_tick_ = (ticks_per_bar_ * gate_percent_) / 100;
44 }
45
46 /// Set gate duration as percentage of bar (0-100). Default 75%.
47 void set_gate_percent(uint8_t percent) {
48 if (percent > 100) percent = 100;
49 gate_percent_ = percent;
50 gate_off_tick_ = (ticks_per_bar_ * gate_percent_) / 100;
51 }
52
53 /// Advance one tick. Returns true on bar boundary (tick wraps to 0).
54 bool advance() {
55 if (++tick_ >= ticks_per_bar_) {
56 tick_ = 0;
57 return true;
58 }
59 return false;
60 }
61
62 /// True when current tick is on a beat boundary.
63 bool at_beat() const {
64 return ticks_per_beat_ > 0 && (tick_ % ticks_per_beat_) == 0;
65 }
66
67 /// True at the gate-off point within the bar.
68 bool at_gate_off() const { return tick_ == gate_off_tick_; }
69
70 /// Reset tick counter to start of bar.
71 void reset() { tick_ = 0; }
72
73 // Read-only accessors
74 uint16_t bpm() const { return bpm_; }
75 uint32_t tick() const { return tick_; }
76 uint32_t ticks_per_bar() const { return ticks_per_bar_; }
77 uint32_t ticks_per_beat() const { return ticks_per_beat_; }
78 uint8_t beats_per_bar() const { return beats_per_bar_; }
79
80private:
81 uint16_t tick_rate_hz_;
82 uint8_t beats_per_bar_;
83 uint8_t gate_percent_ = 75;
84 uint16_t bpm_ = 120;
85 uint32_t tick_ = 0;
86 uint32_t ticks_per_bar_ = 0;
87 uint32_t ticks_per_beat_ = 0;
88 uint32_t gate_off_tick_ = 0;
89};
90
91} // namespace timing
92} // namespace patterns
93} // namespace sbl
bool at_gate_off() const
True at the gate-off point within the bar.
void reset()
Reset tick counter to start of bar.
BeatClock(uint16_t tick_rate_hz, uint8_t beats_per_bar=4)
Construct with tick rate (Hz) and time signature.
void set_gate_percent(uint8_t percent)
Set gate duration as percentage of bar (0-100). Default 75%.
bool advance()
Advance one tick. Returns true on bar boundary (tick wraps to 0).
bool at_beat() const
True when current tick is on a beat boundary.
void set_bpm(uint16_t bpm)
Set tempo. Recalculates all derived tick counts.
Root namespace for all Sound Byte Libs functionality.
Definition aliases.hpp:24