#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use core::{num::NonZeroUsize, ops::Range};
pub fn interleave<T: Copy, Vin: AsRef<[T]>, const CHANNELS: usize>(
input: &[Vin],
input_range: Range<usize>,
output: &mut [T],
) {
assert!(CHANNELS > 0);
assert!(input.len() >= CHANNELS);
if input_range.is_empty() {
return;
}
assert!(output.len() >= (input_range.end - input_range.start) * CHANNELS);
for ch in input.iter() {
let ch = ch.as_ref();
assert!(input_range.start <= ch.len());
assert!(input_range.end <= ch.len());
}
unsafe {
interleave_unchecked::<T, _, CHANNELS>(input, input_range, output);
}
}
pub unsafe fn interleave_unchecked<T: Copy, Vin: AsRef<[T]>, const CHANNELS: usize>(
input: &[Vin],
input_range: Range<usize>,
output: &mut [T],
) {
if input_range.is_empty() {
return;
}
unsafe {
for i in 0..(input_range.end - input_range.start) {
for ch_i in 0..CHANNELS {
*output.get_unchecked_mut((i * CHANNELS) + ch_i) = *input
.get_unchecked(ch_i)
.as_ref()
.get_unchecked(input_range.start + i);
}
}
}
}
pub fn deinterleave<T: Copy, Vout: AsMut<[T]>, const CHANNELS: usize>(
input: &[T],
output: &mut [Vout],
output_range: Range<usize>,
) {
assert!(CHANNELS > 0);
assert!(output.len() >= CHANNELS);
if output_range.is_empty() {
return;
}
assert!(input.len() >= (output_range.end - output_range.start) * CHANNELS);
for ch in output.iter_mut() {
let ch = ch.as_mut();
assert!(output_range.start <= ch.len());
assert!(output_range.end <= ch.len());
}
unsafe {
deinterleave_unchecked::<T, _, CHANNELS>(input, output, output_range);
}
}
pub unsafe fn deinterleave_unchecked<T: Copy, Vout: AsMut<[T]>, const CHANNELS: usize>(
input: &[T],
output: &mut [Vout],
output_range: Range<usize>,
) {
if output_range.is_empty() {
return;
}
unsafe {
for i in 0..(output_range.end - output_range.start) {
for ch_i in 0..CHANNELS {
*output
.get_unchecked_mut(ch_i)
.as_mut()
.get_unchecked_mut(output_range.start + i) =
*input.get_unchecked((i * CHANNELS) + ch_i)
}
}
}
}
pub fn interleave_variable<T: Copy, Vin: AsRef<[T]>>(
input: &[Vin],
input_range: Range<usize>,
output: &mut [T],
num_out_channels: NonZeroUsize,
) {
if input_range.is_empty() || input.is_empty() {
return;
}
let in_frames = input_range.end - input_range.start;
assert!(output.len() >= in_frames * num_out_channels.get());
if num_out_channels.get() == 1 {
output[..in_frames].copy_from_slice(&input[0].as_ref()[input_range.clone()]);
return;
}
if num_out_channels.get() == 2 && input.len() >= 2 {
interleave::<T, _, 2>(input, input_range, output);
return;
}
for (ch_i, in_ch) in (0..num_out_channels.get()).zip(input.iter()) {
let in_ch = in_ch.as_ref();
assert!(input_range.start < in_ch.len() && input_range.end <= in_ch.len());
unsafe {
for i in 0..in_frames {
*output.get_unchecked_mut((i * num_out_channels.get()) + ch_i) =
*in_ch.get_unchecked(input_range.start + i);
}
}
}
}
#[cfg(feature = "alloc")]
pub fn interleave_to_vec_variable<T: Copy + Default, Vin: AsRef<[T]>>(
input: &[Vin],
input_range: Range<usize>,
num_out_channels: NonZeroUsize,
) -> Vec<T> {
let out_len = (input_range.end - input_range.start) * num_out_channels.get();
let mut out: Vec<T> = Vec::new();
out.reserve_exact(out_len);
if num_out_channels.get() > input.len() {
out.resize(out_len, T::default());
} else {
unsafe {
out.set_len(out_len);
}
}
interleave_variable(input, input_range, out.as_mut_slice(), num_out_channels);
out
}
pub fn deinterleave_variable<T: Copy, Vout: AsMut<[T]>>(
input: &[T],
num_in_channels: NonZeroUsize,
output: &mut [Vout],
output_range: Range<usize>,
) {
if output_range.is_empty() || output.is_empty() {
return;
}
let out_frames = output_range.end - output_range.start;
if num_in_channels.get() == 1 {
output[0].as_mut()[output_range.clone()].copy_from_slice(&input[..out_frames]);
return;
}
if num_in_channels.get() == 2 && output.len() >= 2 {
deinterleave::<T, _, 2>(input, output, output_range);
return;
}
assert!(input.len() >= (output_range.end - output_range.start) * num_in_channels.get());
for (ch_i, out_ch) in (0..num_in_channels.get()).zip(output.iter_mut()) {
let out_ch = out_ch.as_mut();
assert!(output_range.start < out_ch.len() && output_range.end <= out_ch.len());
unsafe {
for i in 0..(output_range.end - output_range.start) {
*out_ch.get_unchecked_mut(output_range.start + i) =
*input.get_unchecked((i * num_in_channels.get()) + ch_i);
}
}
}
}
#[cfg(test)]
mod tests {
#[cfg(feature = "alloc")]
use alloc::{vec, vec::Vec};
use super::*;
#[test]
fn test_interleave() {
let input: Vec<Vec<i32>> = vec![vec![1, 2, 3, 4]];
let mut output: Vec<i32> = vec![0; 4];
interleave::<_, _, 1>(&input, 1..4, &mut output);
assert_eq!(&output, &[2, 3, 4, 0]);
let input: Vec<Vec<i32>> = vec![vec![1, 2, 3, 4], vec![5, 6, 7, 8]];
let mut output: Vec<i32> = vec![0; 8];
interleave::<_, _, 2>(&input, 1..4, &mut output);
assert_eq!(&output, &[2, 6, 3, 7, 4, 8, 0, 0]);
let input: Vec<Vec<i32>> = vec![vec![1, 2, 3, 4], vec![5, 6, 7, 8], vec![9, 10, 11, 12]];
let mut output: Vec<i32> = vec![0; 12];
interleave::<_, _, 3>(&input, 1..4, &mut output);
assert_eq!(&output, &[2, 6, 10, 3, 7, 11, 4, 8, 12, 0, 0, 0]);
}
#[test]
fn test_deinterleave() {
let input: Vec<i32> = vec![1, 2, 3, 4];
let mut output: Vec<Vec<i32>> = vec![vec![0; 4]];
deinterleave::<_, _, 1>(&input, &mut output, 1..4);
assert_eq!(&output[0], &[0, 1, 2, 3]);
let input: Vec<i32> = vec![1, 2, 3, 4, 5, 6, 7, 8];
let mut output: Vec<Vec<i32>> = vec![vec![0; 4], vec![0; 4]];
deinterleave::<_, _, 2>(&input, &mut output, 1..4);
assert_eq!(&output[0], &[0, 1, 3, 5]);
assert_eq!(&output[1], &[0, 2, 4, 6]);
let input: Vec<i32> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
let mut output: Vec<Vec<i32>> = vec![vec![0; 4], vec![0; 4], vec![0; 4]];
deinterleave::<_, _, 3>(&input, &mut output, 1..4);
assert_eq!(&output[0], &[0, 1, 4, 7]);
assert_eq!(&output[1], &[0, 2, 5, 8]);
assert_eq!(&output[2], &[0, 3, 6, 9]);
}
#[test]
fn test_interleave_variable() {
let input: Vec<Vec<i32>> = vec![vec![1, 2, 3, 4]];
let mut output: Vec<i32> = vec![0; 4];
interleave_variable(&input, 1..4, &mut output, NonZeroUsize::new(1).unwrap());
assert_eq!(&output, &[2, 3, 4, 0]);
let input: Vec<Vec<i32>> = vec![vec![1, 2, 3, 4], vec![5, 6, 7, 8]];
let mut output: Vec<i32> = vec![0; 8];
interleave_variable(&input, 0..4, &mut output, NonZeroUsize::new(1).unwrap());
assert_eq!(&output, &[1, 2, 3, 4, 0, 0, 0, 0]);
let input: Vec<Vec<i32>> = vec![vec![1, 2, 3, 4]];
let mut output: Vec<i32> = vec![0; 8];
interleave_variable(&input, 0..4, &mut output, NonZeroUsize::new(2).unwrap());
assert_eq!(&output, &[1, 0, 2, 0, 3, 0, 4, 0]);
let input: Vec<Vec<i32>> = vec![vec![1, 2, 3, 4], vec![5, 6, 7, 8]];
let mut output: Vec<i32> = vec![0; 8];
interleave_variable(&input, 0..4, &mut output, NonZeroUsize::new(2).unwrap());
assert_eq!(&output, &[1, 5, 2, 6, 3, 7, 4, 8]);
let input: Vec<Vec<i32>> = vec![vec![1, 2, 3, 4], vec![5, 6, 7, 8], vec![9, 10, 11, 12]];
let mut output: Vec<i32> = vec![0; 8];
interleave_variable(&input, 0..4, &mut output, NonZeroUsize::new(2).unwrap());
assert_eq!(&output, &[1, 5, 2, 6, 3, 7, 4, 8]);
let input: Vec<Vec<i32>> = vec![vec![1, 2, 3, 4], vec![5, 6, 7, 8], vec![9, 10, 11, 12]];
let mut output: Vec<i32> = vec![0; 12];
interleave_variable(&input, 0..4, &mut output, NonZeroUsize::new(3).unwrap());
assert_eq!(&output, &[1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12]);
}
#[test]
fn test_interleave_to_vec_variable() {
let input: Vec<Vec<i32>> = vec![vec![1, 2, 3, 4]];
let output = interleave_to_vec_variable(&input, 1..4, NonZeroUsize::new(1).unwrap());
assert_eq!(&output, &[2, 3, 4]);
let input: Vec<Vec<i32>> = vec![vec![1, 2, 3, 4], vec![5, 6, 7, 8]];
let output = interleave_to_vec_variable(&input, 0..4, NonZeroUsize::new(1).unwrap());
assert_eq!(&output, &[1, 2, 3, 4]);
let input: Vec<Vec<i32>> = vec![vec![1, 2, 3, 4]];
let output = interleave_to_vec_variable(&input, 0..4, NonZeroUsize::new(2).unwrap());
assert_eq!(&output, &[1, 0, 2, 0, 3, 0, 4, 0]);
let input: Vec<Vec<i32>> = vec![vec![1, 2, 3, 4], vec![5, 6, 7, 8]];
let output = interleave_to_vec_variable(&input, 0..4, NonZeroUsize::new(2).unwrap());
assert_eq!(&output, &[1, 5, 2, 6, 3, 7, 4, 8]);
let input: Vec<Vec<i32>> = vec![vec![1, 2, 3, 4], vec![5, 6, 7, 8], vec![9, 10, 11, 12]];
let output = interleave_to_vec_variable(&input, 0..4, NonZeroUsize::new(2).unwrap());
assert_eq!(&output, &[1, 5, 2, 6, 3, 7, 4, 8]);
let input: Vec<Vec<i32>> = vec![vec![1, 2, 3, 4], vec![5, 6, 7, 8], vec![9, 10, 11, 12]];
let output = interleave_to_vec_variable(&input, 0..4, NonZeroUsize::new(3).unwrap());
assert_eq!(&output, &[1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12]);
}
#[test]
fn test_deinterleave_variable() {
let input: Vec<i32> = vec![1, 2, 3, 4];
let mut output: Vec<Vec<i32>> = vec![vec![0; 4]];
deinterleave_variable(&input, NonZeroUsize::new(1).unwrap(), &mut output, 1..4);
assert_eq!(&output[0], &[0, 1, 2, 3]);
let input: Vec<i32> = vec![1, 2, 3, 4];
let mut output: Vec<Vec<i32>> = vec![vec![0; 4], vec![0; 4]];
deinterleave_variable(&input, NonZeroUsize::new(1).unwrap(), &mut output, 0..4);
assert_eq!(&output[0], &[1, 2, 3, 4]);
assert_eq!(&output[1], &[0, 0, 0, 0]);
let input: Vec<i32> = vec![1, 2, 3, 4, 5, 6, 7, 8];
let mut output: Vec<Vec<i32>> = vec![vec![0; 4]];
deinterleave_variable(&input, NonZeroUsize::new(2).unwrap(), &mut output, 0..4);
assert_eq!(&output[0], &[1, 3, 5, 7]);
let input: Vec<i32> = vec![1, 2, 3, 4, 5, 6, 7, 8];
let mut output: Vec<Vec<i32>> = vec![vec![0; 4], vec![0; 4]];
deinterleave_variable(&input, NonZeroUsize::new(2).unwrap(), &mut output, 0..4);
assert_eq!(&output[0], &[1, 3, 5, 7]);
assert_eq!(&output[1], &[2, 4, 6, 8]);
let input: Vec<i32> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
let mut output: Vec<Vec<i32>> = vec![vec![0; 4], vec![0; 4], vec![0; 4]];
deinterleave_variable(&input, NonZeroUsize::new(3).unwrap(), &mut output, 0..4);
assert_eq!(&output[0], &[1, 4, 7, 10]);
assert_eq!(&output[1], &[2, 5, 8, 11]);
assert_eq!(&output[2], &[3, 6, 9, 12]);
}
}