music_timer/
lib.rs

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