///|
pub(all) struct Source {
samples : Array[Double]
keyframes : Array[Keyframe]
start : Int32
gain : Double
}
// Bounded offline mixing. Each source has an independent convolution history.
// Summation is unclipped; clipping is measured before optional PCM quantization.
///|
pub fn render_mix(
sources : Array[Source],
measurements : Array[Measurement],
sample_rate : Int32,
hrir_rate : Int32,
fade_samples : Int32,
) -> SceneResult raise AudioError {
if sources.is_empty() || sources.length() > 16 || measurements.is_empty() {
raise InvalidAudio
}
let taps = measurements[0].hrir.left.length()
let mut work = 0L
let mut length = 0
for s in sources {
if s.start < 0 || s.start > 240000 || !finite(s.gain) || s.gain.abs() > 16.0 {
raise InvalidAudio
}
work += s.samples.length().to_int64() * taps.to_int64()
if work > 64000000L || s.samples.length() > 240000 {
raise InvalidAudio
}
let end = s.start + s.samples.length() + taps - 1
if end > length {
length = end
}
}
if length > 480000 {
raise InvalidAudio
}
let result : Stereo = {
left: Array::make(length, 0.0),
right: Array::make(length, 0.0),
}
for s in sources {
let audio = render_scene(
s.samples,
measurements,
s.keyframes,
sample_rate,
hrir_rate,
fade_samples,
).audio
for i in 0.. peak {
peak = x.abs()
}
if x.abs() > 1.0 {
clipped += 1
}
}
}
{ audio: result, peak, clipped_samples: clipped, }
}