Skip to content

Commit

Permalink
Cleanup core::write module
Browse files Browse the repository at this point in the history
  • Loading branch information
PolyMeilex committed Dec 28, 2024
1 parent b9f8115 commit 2363911
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 166 deletions.
4 changes: 2 additions & 2 deletions oxisynth/src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub struct Synth {
pub settings: Settings,

#[cfg(feature = "i16-out")]
dither_index: usize,
i16_output: write::i16_write::I16OutputState,
}

impl Default for Synth {
Expand Down Expand Up @@ -108,7 +108,7 @@ impl Synth {
settings,

#[cfg(feature = "i16-out")]
dither_index: 0,
i16_output: write::i16_write::I16OutputState::default(),
};

if synth.settings.drums_channel_active {
Expand Down
130 changes: 4 additions & 126 deletions oxisynth/src/core/write.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use crate::core::Synth;

#[cfg(feature = "i16-out")]
pub(crate) mod i16_write;

impl Synth {
/// clean the audio buffers
fn clear_buffers(&mut self) {
Expand Down Expand Up @@ -65,7 +68,7 @@ impl Synth {
}
}

self.ticks = self.ticks.wrapping_add(64);
self.ticks += 64;
}

#[inline]
Expand All @@ -79,129 +82,4 @@ impl Synth {
self.cur += 1;
out
}

#[inline]
pub fn write<F: FnMut(usize, f32, f32)>(&mut self, len: usize, incr: usize, mut cb: F) {
for i in 0..len {
let next = self.read_next();

cb(i * incr, next.0, next.1);
}
}

#[inline]
pub fn write_f32(
&mut self,
len: usize,
left_out: &mut [f32],
loff: usize,
lincr: usize,
right_out: &mut [f32],
roff: usize,
rincr: usize,
) {
for i in 0..len {
let next = self.read_next();

left_out[loff + i * lincr] = next.0;
right_out[roff + i * rincr] = next.1;
}
}

#[inline]
pub fn write_f64(
&mut self,
len: usize,
left_out: &mut [f64],
loff: usize,
lincr: usize,
right_out: &mut [f64],
roff: usize,
rincr: usize,
) {
for i in 0..len {
let next = self.read_next();

left_out[loff + i * lincr] = f64::from(next.0);
right_out[roff + i * rincr] = f64::from(next.1);
}
}

#[cfg(feature = "i16-out")]
#[inline]
pub fn write_i16(
&mut self,
len: usize,
loff: usize,
lincr: usize,
roff: usize,
rincr: usize,
mut cb: impl FnMut((usize, i16), (usize, i16)),
) {
let mut di = self.dither_index;

let mut cur = self.cur;
let mut i: usize = 0;
let mut j = loff;
let mut k = roff;

while i < len {
// fill up the buffers as needed
if cur == 64 {
self.one_block(false);
cur = 0;
}

// Converts stereo floating point sample data to signed 16 bit data with
// dithering.

let mut left_sample = f32::round(self.left_buf[0][cur] * 32766.0 + RAND_TABLE[0][di]);
let mut right_sample = f32::round(self.right_buf[0][cur] * 32766.0 + RAND_TABLE[1][di]);

di += 1;
if di >= 48000 {
di = 0;
}

// digital clipping
left_sample = left_sample.clamp(-32768.0, 32767.0);
right_sample = right_sample.clamp(-32768.0, 32767.0);

cb(
(j, left_sample as i16),
(k, right_sample as i16),
//
);

i += 1;
cur += 1;
j += lincr;
k += rincr
}

self.cur = cur;
// keep dither buffer continuous
self.dither_index = di;
}
}

#[cfg(feature = "i16-out")]
use std::sync::LazyLock;

#[cfg(feature = "i16-out")]
static RAND_TABLE: LazyLock<[[f32; 48000]; 2]> = LazyLock::new(|| {
let mut rand: [[f32; 48000]; 2] = [[0.; 48000]; 2];

for c in 0..2 {
let mut dp = 0.0;
for i in 0..(48000 - 1) {
let r: i32 = rand::random();
let d = r as f32 / 2147483647.0 - 0.5;
rand[c][i] = d - dp;
dp = d;
}
rand[c][48000 - 1] = 0.0 - dp;
}

rand
});
85 changes: 85 additions & 0 deletions oxisynth/src/core/write/i16_write.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
use std::sync::LazyLock;

use crate::core::Synth;

static RAND_TABLE: LazyLock<[[f32; 48000]; 2]> = LazyLock::new(|| {
let mut rand: [[f32; 48000]; 2] = [[0.0; 48000]; 2];

for c in rand.iter_mut() {
let mut dp = 0.0;

for i in c.iter_mut().take(48000 - 1) {
let r: i32 = rand::random();
let d = r as f32 / 2147483647.0 - 0.5;
*i = d - dp;
dp = d;
}

c[48000 - 1] = 0.0 - dp;
}

rand
});

/// Stored in [`Synth::i16_output`]
#[derive(Default)]
pub(crate) struct I16OutputState {
dither_index: usize,
}

#[inline]
pub fn write_i16(
synth: &mut Synth,
len: usize,
loff: usize,
lincr: usize,
roff: usize,
rincr: usize,
mut cb: impl FnMut((usize, i16), (usize, i16)),
) {
let mut di = synth.i16_output.dither_index;

let mut cur = synth.cur;
let mut i = 0;
let mut j = loff;
let mut k = roff;

while i < len {
// fill up the buffers as needed
if cur == 64 {
synth.one_block(false);
cur = 0;
}

// Converts stereo floating point sample data to signed 16 bit data with
// dithering.

let mut left_sample = f32::round(synth.left_buf[0][cur] * 32766.0 + RAND_TABLE[0][di]);
let mut right_sample = f32::round(synth.right_buf[0][cur] * 32766.0 + RAND_TABLE[1][di]);

di += 1;
if di >= 48000 {
di = 0;
}

// digital clipping
left_sample = left_sample.clamp(-32768.0, 32767.0);
right_sample = right_sample.clamp(-32768.0, 32767.0);

cb(
(j, left_sample as i16),
(k, right_sample as i16),
//
);

i += 1;
cur += 1;
j += lincr;
k += rincr
}

synth.cur = cur;

// keep dither buffer continuous
synth.i16_output.dither_index = di;
}
70 changes: 32 additions & 38 deletions oxisynth/src/synth/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,24 +70,24 @@ impl IsSamples for &mut [f64] {
}
}

/**
Synthesizer plugin
*/
impl Synth {
/**
Write sound samples to the sample data buffer
*/
/// Write sound samples to the sample data buffer
#[inline(always)]
pub fn write<S: IsSamples>(&mut self, samples: S) {
samples.write_samples(self)
}

#[inline(always)]
pub fn read_next(&mut self) -> (f32, f32) {
self.core.read_next()
}

#[inline(always)]
pub fn write_cb<F: FnMut(usize, f32, f32)>(&mut self, len: usize, incr: usize, cb: F) {
self.core.write(len, incr, cb)
pub fn write_cb<F: FnMut(usize, f32, f32)>(&mut self, len: usize, incr: usize, mut cb: F) {
for i in 0..len {
let (left, right) = self.core.read_next();
cb(i * incr, left, right);
}
}

/// Write samples as 16-bit signed integers
Expand All @@ -109,54 +109,48 @@ impl Synth {
rincr: usize,
cb: impl FnMut((usize, i16), (usize, i16)),
) {
self.core.write_i16(len, loff, lincr, roff, rincr, cb);
crate::core::write::i16_write::write_i16(&mut self.core, len, loff, lincr, roff, rincr, cb);
}

/**
Write samples as 32-bit floating-point numbers
# Safety
The `len` must corresponds to the lenghtes of buffers.
*/
/// Write samples as 32-bit floating-point numbers
#[allow(clippy::too_many_arguments)]
#[inline]
pub fn write_f32(
&mut self,
len: usize,
left_out: &mut [f32],
loff: u32,
lincr: u32,
loff: usize,
lincr: usize,
right_out: &mut [f32],
roff: u32,
rincr: u32,
roff: usize,
rincr: usize,
) {
self.core.write_f32(
len as _, left_out, loff as _, lincr as _, right_out, roff as _, rincr as _,
)
}
for i in 0..len {
let next = self.core.read_next();

/**
Write samples as 64-bit floating-point numbers
# Safety
left_out[loff + i * lincr] = next.0;
right_out[roff + i * rincr] = next.1;
}
}

The `len` must corresponds to the lenghtes of buffers.
*/
/// Write samples as 64-bit floating-point numbers
#[allow(clippy::too_many_arguments)]
#[inline]
#[inline(always)]
pub fn write_f64(
&mut self,
len: usize,
left_out: &mut [f64],
loff: u32,
lincr: u32,
loff: usize,
lincr: usize,
right_out: &mut [f64],
roff: u32,
rincr: u32,
roff: usize,
rincr: usize,
) {
self.core.write_f64(
len as _, left_out, loff as _, lincr as _, right_out, roff as _, rincr as _,
)
for i in 0..len {
let next = self.core.read_next();

left_out[loff + i * lincr] = f64::from(next.0);
right_out[roff + i * rincr] = f64::from(next.1);
}
}
}

0 comments on commit 2363911

Please sign in to comment.