You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
86 lines
2.2 KiB
86 lines
2.2 KiB
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<Instrument>,
|
|
/// 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<Instrument>, 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)
|
|
}
|
|
}
|
|
|
|
|