#![warn(missing_docs)]
pub const MAX_RATIO: u64 = 1 << 20;
pub const MAX_FRAME: u64 = 4000;
#[allow(non_camel_case_types)]
type fixed_t = u64;
#[allow(non_camel_case_types)]
type enum_t = usize;
#[allow(non_camel_case_types)]
type buf_t = i32;
const PRE_SHIFT: enum_t = 32;
const TIME_BITS: enum_t = PRE_SHIFT + 20;
const TIME_UNIT: fixed_t = (1 as fixed_t) << TIME_BITS;
const BASS_SHIFT: enum_t = 9;
const END_FRAME_EXTRA: enum_t = 2;
const HALF_WIDTH: enum_t = 8;
const BUF_EXTRA: enum_t = HALF_WIDTH * 2 + END_FRAME_EXTRA;
const PHASE_BITS: enum_t = 5;
const PHASE_COUNT: enum_t = 1 << PHASE_BITS;
const DELTA_BITS: enum_t = 15;
const DELTA_UNIT: enum_t = 1 << DELTA_BITS;
const FRAC_BITS: enum_t = TIME_BITS - PRE_SHIFT;
pub struct BlipBuf {
factor: fixed_t,
offset: fixed_t,
integrator: i32,
avail: usize,
samples: Vec<buf_t>,
}
unsafe impl Send for BlipBuf {}
impl BlipBuf {
pub fn new(sample_count: u32) -> Self {
let sample_count = sample_count as usize;
const FACTOR: u64 = TIME_UNIT / MAX_RATIO;
Self {
factor: FACTOR,
offset: FACTOR / 2,
integrator: 0,
avail: 0,
samples: vec![0; sample_count + BUF_EXTRA],
}
}
pub fn set_rates(&mut self, clock_rate: f64, sample_rate: f64) -> Result<(), &'static str> {
let factor: f64 = (TIME_UNIT as f64) * sample_rate / clock_rate;
let factor_int = factor as fixed_t;
let in_bounds = 0.0 <= factor - factor_int as f64 && factor - (factor_int as f64) < 1.0;
if !in_bounds {
return Err("clock_rate exceeds maximum, relative to sample_rate");
}
self.factor = factor.ceil() as fixed_t;
Ok(())
}
pub fn clear(&mut self) {
self.offset = self.factor / 2;
self.avail = 0;
self.integrator = 0;
self.samples.fill(0);
}
pub fn add_delta(&mut self, clock_time: u32, delta: i32) -> Result<(), &'static str> {
let time = clock_time as fixed_t;
let fixed = ((time * self.factor + self.offset) >> PRE_SHIFT) as usize;
let out_index = self.avail + (fixed >> FRAC_BITS);
if out_index + 16 > self.samples.len() {
return Err("buffer size was exceeded");
}
const PHASE_SHIFT: usize = FRAC_BITS - PHASE_BITS;
let phase = fixed >> PHASE_SHIFT & (PHASE_COUNT - 1);
let phase_rev = PHASE_COUNT - phase;
let interp = (fixed >> (PHASE_SHIFT - DELTA_BITS) & (DELTA_UNIT - 1)) as i32;
let delta2 = (delta * interp) >> DELTA_BITS;
let delta1 = delta - delta2;
for i in 0..8 {
self.samples[out_index + i] +=
BL_STEP[phase][i] * delta1 + BL_STEP[phase + 1][i] * delta2;
}
for i in 0..8 {
self.samples[out_index + 8 + i] +=
BL_STEP[phase_rev][7 - i] * delta1 + BL_STEP[phase_rev - 1][7 - i] * delta2;
}
Ok(())
}
pub fn add_delta_fast(&mut self, clock_time: u32, delta: i32) -> Result<(), &'static str> {
let time = clock_time as fixed_t;
let fixed = ((time * self.factor + self.offset) >> PRE_SHIFT) as usize;
let out_index = self.avail + (fixed >> FRAC_BITS);
if out_index + 8 > self.samples.len() {
return Err("buffer size was exceeded");
}
let interp = (fixed >> (FRAC_BITS - DELTA_BITS) & (DELTA_UNIT - 1)) as i32;
let delta2 = delta * interp;
self.samples[out_index + 7] += delta * (DELTA_UNIT as i32) - delta2;
self.samples[out_index + 8] += delta2;
Ok(())
}
pub fn clocks_needed(&self, sample_count: u32) -> Result<u32, &'static str> {
if self.avail + sample_count as usize > self.samples.len() {
return Err("can't hold that many more samples");
}
let needed = sample_count as fixed_t * TIME_UNIT;
if needed < self.offset {
return Ok(0);
}
let res = (needed - self.offset + self.factor - 1) / self.factor;
Ok(res as u32)
}
pub fn end_frame(&mut self, clock_duration: u32) -> Result<(), &'static str> {
let off = (clock_duration as fixed_t) * self.factor + self.offset;
let avail = self.avail + (off >> TIME_BITS) as usize;
if avail > self.samples.len() {
return Err("buffer size was exceeded");
}
self.avail = avail;
self.offset = off & (TIME_UNIT - 1);
Ok(())
}
pub fn samples_avail(&self) -> u32 {
self.avail as u32
}
fn remove_samples(&mut self, count: usize) {
let remain = (self.avail + BUF_EXTRA).saturating_sub(count);
self.avail = self.avail.saturating_sub(count);
self.samples.copy_within(count..count + remain, 0);
self.samples[remain..].fill(0);
}
pub fn read_samples(&mut self, buf: &mut [i16], stereo: bool) -> usize {
let count = buf.len().min(self.avail);
if count > 0 {
let step = if stereo { 2 } else { 1 };
let mut sum = self.integrator;
for i in 0..count {
let s = clamp_to_i16(sum >> DELTA_BITS);
buf[i * step] = s as i16;
sum += self.samples[i];
sum -= s << (DELTA_BITS - BASS_SHIFT);
}
self.integrator = sum;
self.remove_samples(count);
}
count
}
}
#[inline]
fn clamp_to_i16(n: i32) -> i32 {
n.clamp(i16::MIN.into(), i16::MAX.into())
}
#[cfg(test)]
mod test {
use super::BlipBuf;
#[test]
fn basics() {
let mut blipbuf = BlipBuf::new(44100);
blipbuf.set_rates((1 << 22) as f64, 44100f64).unwrap();
drop(blipbuf);
}
#[test]
fn check_assumptions() {
use super::*;
const MAX_SAMPLE: i32 = i16::MAX as i32;
const MIN_SAMPLE: i32 = i16::MIN as i32;
let mut n: i32;
assert!((-3 >> 1) == -2);
n = MAX_SAMPLE * 2;
n = clamp_to_i16(n);
assert!(n == MAX_SAMPLE);
n = MIN_SAMPLE * 2;
n = clamp_to_i16(n);
assert!(n == MIN_SAMPLE);
assert!(MAX_RATIO as fixed_t <= TIME_UNIT);
assert!(MAX_FRAME as fixed_t <= !1 >> TIME_BITS);
}
}
const BL_STEP: &[[i32; 8]] = &[
[43, -115, 350, -488, 1136, -914, 5861, 21022],
[44, -118, 348, -473, 1076, -799, 5274, 21001],
[45, -121, 344, -454, 1011, -677, 4706, 20936],
[46, -122, 336, -431, 942, -549, 4156, 20829],
[47, -123, 327, -404, 868, -418, 3629, 20679],
[47, -122, 316, -375, 792, -285, 3124, 20488],
[47, -120, 303, -344, 714, -151, 2644, 20256],
[46, -117, 289, -310, 634, -17, 2188, 19985],
[46, -114, 273, -275, 553, 117, 1758, 19675],
[44, -108, 255, -237, 471, 247, 1356, 19327],
[43, -103, 237, -199, 390, 373, 981, 18944],
[42, -98, 218, -160, 310, 495, 633, 18527],
[40, -91, 198, -121, 231, 611, 314, 18078],
[38, -84, 178, -81, 153, 722, 22, 17599],
[36, -76, 157, -43, 80, 824, -241, 17092],
[34, -68, 135, -3, 8, 919, -476, 16558],
[32, -61, 115, 34, -60, 1006, -683, 16001],
[29, -52, 94, 70, -123, 1083, -862, 15422],
[27, -44, 73, 106, -184, 1152, -1015, 14824],
[25, -36, 53, 139, -239, 1211, -1142, 14210],
[22, -27, 34, 170, -290, 1261, -1244, 13582],
[20, -20, 16, 199, -335, 1301, -1322, 12942],
[18, -12, -3, 226, -375, 1331, -1376, 12293],
[15, -4, -19, 250, -410, 1351, -1408, 11638],
[13, 3, -35, 272, -439, 1361, -1419, 10979],
[11, 9, -49, 292, -464, 1362, -1410, 10319],
[9, 16, -63, 309, -483, 1354, -1383, 9660],
[7, 22, -75, 322, -496, 1337, -1339, 9005],
[6, 26, -85, 333, -504, 1312, -1280, 8355],
[4, 31, -94, 341, -507, 1278, -1205, 7713],
[3, 35, -102, 347, -506, 1238, -1119, 7082],
[1, 40, -110, 350, -499, 1190, -1021, 6464],
[0, 43, -115, 350, -488, 1136, -914, 5861],
];