use rodio::{source::SineWave, OutputStream, Source}; use std::sync::atomic::{AtomicU8, Ordering}; use std::thread; use std::time::{Duration, Instant}; static SOUND_TIMER: AtomicU8 = AtomicU8::new(0); static DELAY_TIMER: AtomicU8 = AtomicU8::new(0); pub enum Type { Delay, Sound, } pub struct Timer; impl Timer { pub fn start_thread() { thread::spawn(|| { let duration = Duration::from_nanos(1e+9 as u64 / 60); let mut start = Instant::now(); let mut has_beeped = false; loop { if Instant::now().duration_since(start) > duration { Timer::tick(&mut has_beeped); start = Instant::now(); } } }); } fn tick(has_beeped: &mut bool) { // Sound Timer let remaining = SOUND_TIMER.load(Ordering::Relaxed); match (remaining, *has_beeped) { (0, false) => { Self::beep(); *has_beeped = true; } (0, true) => {} _ => { if *has_beeped { *has_beeped = false; } SOUND_TIMER.store(remaining - 1, Ordering::Release) } } // Delay Timer let remaining = DELAY_TIMER.load(Ordering::Relaxed); if remaining != 0 { DELAY_TIMER.store(remaining - 1, Ordering::Release); } } pub fn get(timer: Type) -> u8 { match timer { Type::Delay => DELAY_TIMER.load(Ordering::Acquire), Type::Sound => SOUND_TIMER.load(Ordering::Acquire), } } pub fn set(secs: u8, timer: Type) { match timer { Type::Delay => DELAY_TIMER.store(secs, Ordering::Relaxed), Type::Sound => SOUND_TIMER.store(secs, Ordering::Relaxed), } } fn beep() { const BEEP_FREQ: f32 = 440.0; // Hz (Middle A) const BEEP_LENGTH: u64 = 150; // ms let beep = SineWave::new(BEEP_FREQ).take_duration(Duration::from_millis(BEEP_LENGTH)); let (_stream, stream_handle) = OutputStream::try_default().expect("find output stream"); stream_handle.play_raw(beep).expect("play sine wave"); } }