1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//!
//! _Music Timer_ is a crate with music time and counting utilities featuring a callback performance engine to help with triggering events in music time. Written in Rust.
//!
//! # Example
//! ```
//! use music_timer::{
//! music_time::MusicTime,
//! music_timer_engine::MusicTimerState,
//! };
//!
//! struct PerformanceState {
//! is_playing: bool,
//! performance_end: MusicTime,
//! events: Vec<MusicTime>,
//! event_head: usize,
//! }
//!
//! impl MusicTimerState for PerformanceState {
//! fn on_beat_interval(&mut self, current_time: &MusicTime) {
//! let event_triggered =
//! self.event_head < self.events.len() && *current_time == self.events[self.event_head];
//!
//! // Advance the event head
//! if event_triggered {
//! self.event_head += 1;
//! }
//!
//! // Print out esoteric data
//! println!(
//! "{:02}.{}.{} = {}",
//! current_time.get_bar(),
//! current_time.get_beat(),
//! current_time.get_beat_interval(),
//! event_triggered
//! );
//!
//! // Check to end the performance
//! self.is_playing = *current_time < self.performance_end;
//! }
//! fn on_beat(&mut self, _current_time: &MusicTime) {
//! // Do something on the beat
//! }
//! fn on_bar(&mut self, _current_time: &MusicTime) {
//! // Do something on the bar
//! }
//! }
//!
//! fn main() {
//! use std::thread;
//!
//! // Create the performer_state with bunch of events
//! let mut performer_state = PerformanceState {
//! is_playing: true,
//! performance_end: MusicTime::new(4, 3, 8),
//! events: vec![
//! MusicTime::new(1, 1, 1),
//! MusicTime::new(2, 2, 5),
//! MusicTime::new(4, 3, 8),
//! ],
//! event_head: 0,
//! };
//!
//! // Run our main loop
//! let mut performer = music_timer::create_performance_engine(3, 4, 155.0);
//!
//! // We can set the delay to be half the trigger target. This will give
//! // us a reasonable cycle speed with enough buffer to keep an accurate time.
//! // This of course is not needed if the application is managing thread sleeping.
//! // The shorter the sleep duration of the thread, the more accurate the
//! // time triggering will be. In most cases setting the sleep to 60fps is recommended for
//! // < 180bpm @ 4/4.
//! let sleep_duration = performer.get_beat_interval_duration() / 2;
//! println!("SLEEP_DURATION: {:?}", sleep_duration);
//!
//! while performer_state.is_playing {
//! // Pass in our performance state to trigger our on event callback functions
//! performer.pulse(&mut performer_state);
//! thread::sleep(sleep_duration);
//! }
//! }
//! ```
/// Creates a new music timer performance engine.
///
/// # Arguments
///
/// * `numerator` - The upper part of a time signature. Must be none 0.
/// * `denominator` - The lower part of a time signature. Only 2, 4, 8, 16, 32 are supported.
/// * `bpm` - The beats per minute.
///
/// # Example
///
/// ```
/// let mut performer = music_timer::create_performance_engine(3, 4, 155.0);
/// ```