use crate::beep::instrument::Instrument; use crate::beep::tween::Tween; use std::time::Duration; use crate::beep::sample::StereoSample; use crate::beep::hack::StableClamp; /// A set of instruments pub struct Orchestra { pub instruments: Vec, /// Normalize the output to produce constant amplitude of 1.0 (instead of clipping) normalize: bool, /// Sample rate, used to calculate time based effects sample_rate : f32, /// Master gain gain: Tween, } impl Orchestra { pub fn new(instruments: Vec, sample_rate: f32) -> Self { let mut o = Self { instruments, normalize: false, sample_rate, gain: Tween { actual: 1.0, target: 1.0, step: None, min: 0.0, max: 1.0, sample_rate } }; o } pub fn normalize(&mut self, normalize: bool) { self.normalize = normalize; } pub fn get_amp(&self) -> f32 { self.gain.actual() } pub fn set_amp(&mut self, amp : f32) { self.gain.set_immediate(amp); } pub fn fade_amp(&mut self, amp : f32, time: Duration) { self.gain.fade(amp, time); } fn calc_gain(&self) -> f32 { (if self.normalize { 1.0 / ( self.instruments.iter() .fold(0.0, |acc, item| acc + item.get_peak_amplitude()) ) } else { 1.0 }) * self.gain.actual } pub fn sample_stereo(&mut self) -> StereoSample { let gain = self.calc_gain(); self.instruments .iter_mut() .fold(StereoSample::default(), |mut acc, item| { let s = item.sample() * gain; acc.left += s * item.ratio_left; acc.right += s * item.ratio_left; acc }) .clip() } pub fn sample_mono(&mut self) -> f32 { let gain = self.calc_gain(); self.instruments .iter_mut() .fold(0.0, |mut acc, item| { acc + item.sample() * gain }) .clamp_(0.0, 1.0) } }