use super::source::AudioSource;
use crate::dsl::{ENGINE_VERSION, Node};
use crate::streaming::EffectChain;
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct SourceId(u64);
trait AnySource: AudioSource + std::any::Any {}
impl<T: AudioSource + 'static> AnySource for T {}
struct MixedSource {
id: u64,
source: Box<dyn AnySource + Send>,
gain: f32,
bus: BusId,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct BusId(u32);
impl BusId {
pub const MASTER: BusId = BusId(0);
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
enum BusKind {
Master,
Input,
Fx,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum MixerError {
NotStreamable,
NoSampleRate,
}
impl std::fmt::Display for MixerError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
MixerError::NotStreamable => {
write!(f, "effect chain contains a non-streamable node")
}
MixerError::NoSampleRate => {
write!(f, "mixer has no sample rate; build it with Mixer::new_at")
}
}
}
}
impl std::error::Error for MixerError {}
struct Bus {
name: String,
kind: BusKind,
gain: f32,
to_master: f32,
inserts: Option<(EffectChain, EffectChain)>,
sends: Vec<(u32, f32)>,
}
pub struct Mixer {
sources: Vec<MixedSource>,
buses: Vec<Bus>,
next_id: u64,
sample_rate: Option<u32>,
scratch: Vec<f32>,
master_l: Vec<f32>,
master_r: Vec<f32>,
bus_l: Vec<f32>,
bus_r: Vec<f32>,
fx_in: Vec<(Vec<f32>, Vec<f32>)>,
}
impl Default for Mixer {
fn default() -> Self {
Mixer::new()
}
}
impl Mixer {
pub fn new() -> Self {
Mixer::build(None)
}
pub fn new_at(sample_rate: u32) -> Self {
Mixer::build(Some(sample_rate))
}
fn build(sample_rate: Option<u32>) -> Self {
let master = Bus {
name: "master".into(),
kind: BusKind::Master,
gain: 1.0,
to_master: 1.0,
inserts: None,
sends: Vec::new(),
};
Mixer {
sources: Vec::new(),
buses: vec![master],
next_id: 1,
sample_rate,
scratch: Vec::new(),
master_l: Vec::new(),
master_r: Vec::new(),
bus_l: Vec::new(),
bus_r: Vec::new(),
fx_in: Vec::new(),
}
}
pub fn add(&mut self, source: impl AudioSource + Send + 'static) -> SourceId {
self.add_to(BusId::MASTER, source)
}
pub fn add_to(&mut self, bus: BusId, source: impl AudioSource + Send + 'static) -> SourceId {
let bus = if (bus.0 as usize) < self.buses.len() {
bus
} else {
BusId::MASTER
};
let id = self.next_id;
self.next_id += 1;
self.sources.push(MixedSource {
id,
source: Box::new(source),
gain: 1.0,
bus,
});
SourceId(id)
}
pub fn bus(&mut self, name: impl Into<String>) -> BusId {
self.push_bus(name.into(), BusKind::Input, None)
}
pub fn fx_bus(
&mut self,
name: impl Into<String>,
effects: Vec<Node>,
) -> Result<BusId, MixerError> {
let inserts = self.build_chain(&effects)?;
Ok(self.push_bus(name.into(), BusKind::Fx, inserts))
}
fn push_bus(
&mut self,
name: String,
kind: BusKind,
inserts: Option<(EffectChain, EffectChain)>,
) -> BusId {
let id = self.buses.len() as u32;
self.buses.push(Bus {
name,
kind,
gain: 1.0,
to_master: 1.0,
inserts,
sends: Vec::new(),
});
BusId(id)
}
pub fn bus_named(&self, name: &str) -> Option<BusId> {
self.buses
.iter()
.position(|b| b.name == name)
.map(|i| BusId(i as u32))
}
pub fn set_bus_effects(&mut self, bus: BusId, effects: Vec<Node>) -> Result<(), MixerError> {
let inserts = self.build_chain(&effects)?;
if let Some(b) = self.buses.get_mut(bus.0 as usize) {
b.inserts = inserts;
}
Ok(())
}
pub fn master_effects(&mut self, effects: Vec<Node>) -> Result<(), MixerError> {
self.set_bus_effects(BusId::MASTER, effects)
}
pub fn set_send(&mut self, from: BusId, to_fx: BusId, level: f32) {
let valid = matches!(
self.buses.get(from.0 as usize).map(|b| b.kind),
Some(BusKind::Input)
) && matches!(
self.buses.get(to_fx.0 as usize).map(|b| b.kind),
Some(BusKind::Fx)
);
if !valid {
return;
}
let level = level.max(0.0);
let bus = &mut self.buses[from.0 as usize];
if let Some(s) = bus.sends.iter_mut().find(|s| s.0 == to_fx.0) {
s.1 = level;
} else {
bus.sends.push((to_fx.0, level));
}
}
pub fn set_bus_gain(&mut self, bus: BusId, gain: f32) {
if let Some(b) = self.buses.get_mut(bus.0 as usize) {
b.gain = gain.max(0.0);
}
}
pub fn set_bus_dry(&mut self, bus: BusId, level: f32) {
if bus != BusId::MASTER
&& let Some(b) = self.buses.get_mut(bus.0 as usize)
{
b.to_master = level.max(0.0);
}
}
fn build_chain(
&self,
effects: &[Node],
) -> Result<Option<(EffectChain, EffectChain)>, MixerError> {
if effects.is_empty() {
return Ok(None);
}
let sr = self.sample_rate.ok_or(MixerError::NoSampleRate)?;
let build = || EffectChain::try_new(effects, sr, ENGINE_VERSION);
let l = build().ok_or(MixerError::NotStreamable)?;
let r = build().ok_or(MixerError::NotStreamable)?;
Ok(Some((l, r)))
}
pub fn set_gain(&mut self, id: SourceId, gain: f32) {
if let Some(s) = self.sources.iter_mut().find(|s| s.id == id.0) {
s.gain = gain.max(0.0);
}
}
pub fn get_mut<T: AudioSource + 'static>(&mut self, id: SourceId) -> Option<&mut T> {
let s = self.sources.iter_mut().find(|s| s.id == id.0)?;
let any: &mut dyn std::any::Any = s.source.as_mut();
any.downcast_mut::<T>()
}
pub fn remove(&mut self, id: SourceId) {
self.sources.retain(|s| s.id != id.0);
}
pub fn source_count(&self) -> usize {
self.sources.len()
}
pub fn contains(&self, id: SourceId) -> bool {
self.sources.iter().any(|s| s.id == id.0)
}
}
fn grow(v: &mut Vec<f32>, n: usize) {
if v.len() < n {
v.resize(n, 0.0);
}
}
impl AudioSource for Mixer {
fn fill(&mut self, out: &mut [f32]) -> usize {
let frames = out.len() / 2;
let mut scratch = std::mem::take(&mut self.scratch);
let mut master_l = std::mem::take(&mut self.master_l);
let mut master_r = std::mem::take(&mut self.master_r);
let mut bus_l = std::mem::take(&mut self.bus_l);
let mut bus_r = std::mem::take(&mut self.bus_r);
let mut fx_in = std::mem::take(&mut self.fx_in);
grow(&mut scratch, frames * 2);
grow(&mut master_l, frames);
grow(&mut master_r, frames);
grow(&mut bus_l, frames);
grow(&mut bus_r, frames);
if fx_in.len() < self.buses.len() {
fx_in.resize_with(self.buses.len(), || (Vec::new(), Vec::new()));
}
for (l, r) in fx_in.iter_mut() {
grow(l, frames);
grow(r, frames);
}
master_l[..frames].fill(0.0);
master_r[..frames].fill(0.0);
for (l, r) in fx_in.iter_mut() {
l[..frames].fill(0.0);
r[..frames].fill(0.0);
}
let scr = &mut scratch[..frames * 2];
for s in self.sources.iter_mut().filter(|s| s.bus == BusId::MASTER) {
s.source.fill(scr);
for f in 0..frames {
master_l[f] += scr[f * 2] * s.gain;
master_r[f] += scr[f * 2 + 1] * s.gain;
}
}
for bi in 1..self.buses.len() {
if self.buses[bi].kind != BusKind::Input {
continue;
}
bus_l[..frames].fill(0.0);
bus_r[..frames].fill(0.0);
let bus_id = bi as u32;
for s in self.sources.iter_mut().filter(|s| s.bus.0 == bus_id) {
s.source.fill(scr);
for f in 0..frames {
bus_l[f] += scr[f * 2] * s.gain;
bus_r[f] += scr[f * 2 + 1] * s.gain;
}
}
if let Some((cl, cr)) = &mut self.buses[bi].inserts {
cl.process(&mut bus_l[..frames]);
cr.process(&mut bus_r[..frames]);
}
let fader = self.buses[bi].gain;
let dry = fader * self.buses[bi].to_master;
for f in 0..frames {
master_l[f] += bus_l[f] * dry;
master_r[f] += bus_r[f] * dry;
}
for &(target, level) in &self.buses[bi].sends {
let k = target as usize;
if k < fx_in.len() {
let g = fader * level;
let (fl, fr) = &mut fx_in[k];
for f in 0..frames {
fl[f] += bus_l[f] * g;
fr[f] += bus_r[f] * g;
}
}
}
}
#[allow(clippy::needless_range_loop)]
for bi in 1..self.buses.len() {
if self.buses[bi].kind != BusKind::Fx {
continue;
}
let bus_id = bi as u32;
let (fl, fr) = &mut fx_in[bi];
for s in self.sources.iter_mut().filter(|s| s.bus.0 == bus_id) {
s.source.fill(scr);
for f in 0..frames {
fl[f] += scr[f * 2] * s.gain;
fr[f] += scr[f * 2 + 1] * s.gain;
}
}
}
#[allow(clippy::needless_range_loop)]
for bi in 1..self.buses.len() {
if self.buses[bi].kind != BusKind::Fx {
continue;
}
let (fl, fr) = &mut fx_in[bi];
if let Some((cl, cr)) = &mut self.buses[bi].inserts {
cl.process(&mut fl[..frames]);
cr.process(&mut fr[..frames]);
}
let ret = self.buses[bi].gain * self.buses[bi].to_master;
for f in 0..frames {
master_l[f] += fl[f] * ret;
master_r[f] += fr[f] * ret;
}
}
if let Some((cl, cr)) = &mut self.buses[0].inserts {
cl.process(&mut master_l[..frames]);
cr.process(&mut master_r[..frames]);
}
let master_gain = self.buses[0].gain;
for f in 0..frames {
out[f * 2] = master_l[f] * master_gain;
out[f * 2 + 1] = master_r[f] * master_gain;
}
self.scratch = scratch;
self.master_l = master_l;
self.master_r = master_r;
self.bus_l = bus_l;
self.bus_r = bus_r;
self.fx_in = fx_in;
frames
}
fn reset(&mut self) {
for s in self.sources.iter_mut() {
s.source.reset();
}
}
}