use io_prompt_prototype::prompt; use itertools::Itertools; mod flags; mod play; mod seq; mod syn; mod tone; fn main() { let flags = flags::Flags::new(); if flags.debug { eprintln!("{:?}", flags); } let once = flags.play.iter().filter(|x| x.len() > 0).count() > 0; loop { play_with_flags(&flags); if once { break; } } } fn play_with_flags(flags: &flags::Flags) { let mut syn_seq = seq::new_syn(syn::Syn::new( flags.debug.clone(), flags.sound_font.clone(), flags.sample_rate.clone(), )); let mut i = 0; for p in flags.play.iter() { for p in play::new(p.clone()) { syn_seq.append(i as i32, p); i += 1; } } if i == 0 { let s: String = prompt!("> ").parse().expect("failed to readline"); panic!("not impl"); } play(syn_seq, flags.sample_rate, flags.bpm, true); } 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, }; 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)); } }