diff --git a/src/main.rs b/src/main.rs index 6ef66ca..2cf0b14 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,8 @@ use io_prompt_prototype::prompt; use itertools::Itertools; mod flags; -mod play; +mod parse; +mod player; mod seq; mod syn; mod tone; @@ -14,15 +15,16 @@ fn main() { } let once = flags.play.iter().filter(|x| x.len() > 0).count() > 0; + let mut player = player::new(flags.sample_rate.clone(), flags.bpm.clone()); loop { - play_with_flags(&flags); + play_with_flags(&flags, &mut player); if once { break; } } } -fn play_with_flags(flags: &flags::Flags) { +fn play_with_flags(flags: &flags::Flags, player: &mut player::Player) { let mut syn_seq = seq::new_syn(syn::Syn::new( flags.debug.clone(), flags.sound_font.clone(), @@ -31,7 +33,7 @@ fn play_with_flags(flags: &flags::Flags) { let mut i = 0; for p in flags.play.iter() { - for p in play::new(p.clone()) { + for p in parse::new(p.clone()) { syn_seq.append(i as i32, p); i += 1; } @@ -60,41 +62,14 @@ fn play_with_flags(flags: &flags::Flags) { }; } - for p in play::new(payload.join("\n")) { + for p in parse::new(payload.join("\n")) { syn_seq.append(i as i32, p); i += 1; } } - play(syn_seq, flags.sample_rate, flags.bpm, sync); -} - -fn play(mut s: seq::SynSeq, sample_rate: usize, bpm: usize, sync: bool) { - let samples_per_beat = sample_rate / bpm * 60; - let params = tinyaudio::prelude::OutputDeviceParameters { - channels_count: 2, - sample_rate: sample_rate, - channel_sample_count: samples_per_beat, + match sync { + true => player.play(syn_seq), + false => player.play_async(syn_seq), }; - let beats = s.beats() + 3; - let duration = 60 * beats / bpm; - - let sample_count = (params.channel_sample_count) as usize; - let mut left: Vec = vec![0_f32; sample_count]; - let mut right: Vec = vec![0_f32; sample_count]; - - let _device = tinyaudio::prelude::run_output_device(params, { - move |data| { - s.render(&mut left[..], &mut right[..]); // put in a state of rendering the next loop of these notes - for (i, value) in left.iter().interleave(right.iter()).enumerate() { - data[i] = *value; - } - } - }) - .unwrap(); - - if sync { - // Wait it out - std::thread::sleep(std::time::Duration::from_secs(duration as u64)); - } } diff --git a/src/play.rs b/src/parse.rs similarity index 100% rename from src/play.rs rename to src/parse.rs diff --git a/src/player.rs b/src/player.rs new file mode 100644 index 0000000..ec727b8 --- /dev/null +++ b/src/player.rs @@ -0,0 +1,61 @@ +use itertools::Itertools; + +use crate::seq; + +pub struct Player { + bpm: usize, + params: tinyaudio::OutputDeviceParameters, + device: Option, +} + +pub fn new(sample_rate: usize, bpm: usize) -> Player { + let samples_per_beat = sample_rate / bpm * 60; + Player { + bpm: bpm, + params: tinyaudio::prelude::OutputDeviceParameters { + channels_count: 2, + sample_rate: sample_rate, + channel_sample_count: samples_per_beat, + }, + device: None, + } +} + +impl Player { + pub fn play(&mut self, s: seq::SynSeq) { + self.play_with_sync(s, true); + } + + pub fn play_async(&mut self, s: seq::SynSeq) { + self.play_with_sync(s, false); + } + + fn play_with_sync(&mut self, mut s: seq::SynSeq, sync: bool) { + let sample_count = (self.params.channel_sample_count) as usize; + let mut left: Vec = vec![0_f32; sample_count]; + let mut right: Vec = vec![0_f32; sample_count]; + + let beats = s.beats() + 3; + let duration = 60 * beats / self.bpm; + + if self.device.is_some() { + self.device.as_mut().expect("lost device").close(); + } + self.device = Some( + tinyaudio::prelude::run_output_device(self.params, { + move |data| { + s.render(&mut left[..], &mut right[..]); // put in a state of rendering the next loop of these notes + for (i, value) in left.iter().interleave(right.iter()).enumerate() { + data[i] = *value; + } + } + }) + .unwrap(), + ); + + if sync { + // Wait it out + std::thread::sleep(std::time::Duration::from_secs(duration as u64)); + } + } +}