#music #trigger #state #time

music-timer

music-timer是一个音乐时间和计数工具的crate,具有用于在音乐时间中触发事件的回调性能引擎。用Rust编写。

6个版本

0.1.6 2020年3月15日
0.1.5 2019年12月12日

#340 in 音频

27 每月下载量
用于 chord-composer

MIT 协议

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 MusicTimerStatestruct,并将其传递给引擎的脉冲。回调将在音乐时间中触发。

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);
    }
}

无运行时依赖