6个版本
0.1.6 | 2020年3月15日 |
---|---|
0.1.5 | 2019年12月12日 |
#340 in 音频
27 每月下载量
用于 chord-composer
34KB
406 行
Music-Timer
Music Timer是一个音乐时间和计数工具的crate,具有用于在音乐时间中触发事件的回调性能引擎。用Rust编写。
它的目标是允许轻松触发音乐时间中的事件。这个crate不包含任何线程。
性能引擎
要创建具有拍号和bpm的性能引擎,请调用music_timer::create_performance_engine
。
let mut performer = music_timer::create_performance_engine(3, 4, 155.0);
创建一个具有trait MusicTimerState
的struct
,并将其传递给引擎的脉冲。回调将在音乐时间中触发。
struct PerformanceState;
impl MusicTimerState for PerformanceState {
fn on_beat_interval(&mut self, current_time: &MusicTime) {
// Do something on the beat interval
}
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
}
}
let mut performer_state = PerformanceState{};
let mut performer = music_timer::create_performance_engine(3, 4, 155.0);
performer.pulse(&mut performer_state);
未来工作
- 支持不规则的拍号,例如3/5。
- 探讨更高分辨率的节拍间隔的需求。
示例
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);
}
}