#![doc = include_str!("../README.md")]
#![cfg_attr(feature = "simd-nightly", feature(portable_simd))]
#![cfg_attr(feature = "simd-nightly", feature(test))]
#![warn(clippy::all, clippy::nursery, clippy::pedantic, clippy::cargo)]
#![allow(unknown_lints)]
#![allow(
clippy::cast_possible_truncation,
clippy::cast_possible_wrap,
clippy::cast_precision_loss,
clippy::cast_sign_loss,
clippy::missing_const_for_fn,
clippy::multiple_crate_versions,
clippy::must_use_candidate,
clippy::wildcard_dependencies,
clippy::manual_is_multiple_of // `is_multiple_of` is introduced at 1.87.
)]
#![warn(
clippy::clone_on_ref_ptr,
clippy::create_dir,
clippy::dbg_macro,
clippy::empty_structs_with_brackets,
clippy::exit,
clippy::if_then_some_else_none,
clippy::impl_trait_in_params,
clippy::implicit_clone,
clippy::let_underscore_must_use,
clippy::lossy_float_literal,
clippy::multiple_inherent_impl,
clippy::print_stdout,
clippy::rc_buffer,
clippy::rc_mutex,
clippy::rest_pat_in_fully_bound_structs,
clippy::separated_literal_suffix,
clippy::str_to_string,
clippy::string_add,
clippy::try_err,
clippy::unnecessary_self_imports,
clippy::wildcard_enum_match_arm
)]
#![allow(clippy::needless_raw_string_hashes, clippy::doc_markdown)]
#![allow(clippy::non_std_lazy_statics)]
macro_rules! import_simd {
(as $modalias:ident) => {
#[cfg(feature = "simd-nightly")]
use std::simd as $modalias;
#[cfg(not(feature = "simd-nightly"))]
use $crate::fakesimd as $modalias;
#[allow(unused_imports)]
use simd::prelude::*;
#[allow(unused_imports)]
use simd::StdFloat;
};
}
macro_rules! reusable {
($key:ident: $t:ty) => {
thread_local! {
static $key: std::cell::RefCell<$t> = std::cell::RefCell::new(Default::default());
}
};
($key:ident: $t:ty = $init:expr) => {
thread_local! {
static $key: std::cell::RefCell<$t> = std::cell::RefCell::new($init);
}
};
}
macro_rules! reuse {
($key:ident, $fn:expr) => {{
#[allow(clippy::redundant_closure_call)]
$key.with(|cell| $fn(&mut cell.borrow_mut()))
}};
}
#[allow(unused)]
macro_rules! info { (target: $t:literal, $($x:tt)*) => (
#[cfg(feature = "log")] {
log::info!(target: $t, $($x)*)
}
) }
pub(crate) mod arrayutils;
pub mod bitsink;
pub(crate) mod coding;
pub mod component;
pub mod config;
pub mod constant;
pub mod error;
#[cfg(not(feature = "simd-nightly"))]
#[doc(hidden)]
pub(crate) mod fakesimd;
pub(crate) mod lpc;
#[cfg(feature = "par")]
pub(crate) mod par;
pub(crate) mod repeat;
pub(crate) mod rice;
#[cfg(any(test, feature = "__export_sigen"))]
#[doc(hidden)]
pub mod sigen;
pub mod source;
#[cfg(test)]
pub mod test_helper;
#[cfg(clippy)]
mod doctest_helper;
#[cfg(feature = "mimalloc")]
use mimalloc::MiMalloc;
#[cfg(feature = "mimalloc")]
#[global_allocator]
static GLOBAL: MiMalloc = MiMalloc;
pub use coding::encode_fixed_size_frame;
pub use coding::encode_with_fixed_block_size;
#[cfg(test)]
mod tests {
#[cfg(feature = "serde")]
use super::error::Verify;
#[cfg(feature = "serde")]
use super::*;
#[cfg(feature = "serde")]
use crate::sigen::Signal;
#[cfg(feature = "serde")]
use rstest::rstest;
#[allow(dead_code)] const FIXED_BLOCK_CONFIGS: [&str; 5] = [
"",
r"
block_sizes = [512]
",
r"
block_sizes = [123]
",
r"
block_sizes = [1024]
[subframe_coding.qlpc]
use_direct_mse = true
mae_optimization_steps = 2
",
r"
multithread = false
",
];
#[cfg(feature = "serde")]
#[rstest]
fn e2e_with_generated_sinusoids(
#[values(1, 2, 3, 5, 8)] channels: usize,
#[values(16000, 16001, 95800)] sample_rate: usize,
#[values(FIXED_BLOCK_CONFIGS[0],
FIXED_BLOCK_CONFIGS[1],
FIXED_BLOCK_CONFIGS[2],
FIXED_BLOCK_CONFIGS[3],
FIXED_BLOCK_CONFIGS[4])]
config: &str,
) {
let signal_len = 16123;
let bits_per_sample = 16;
let mut channel_signals = vec![];
for _ch in 0..channels {
channel_signals.push(
sigen::Sine::new(36, 0.4)
.noise(0.04)
.to_vec_quantized(bits_per_sample, signal_len),
);
}
let mut signal = vec![];
for t in 0..signal_len {
for s in &channel_signals {
signal.push(s[t]);
}
}
let mut config: config::Encoder = toml::from_str(config).expect("config parsing error");
if !cfg!(feature = "experimental") {
config.subframe_coding.qlpc.use_direct_mse = false;
config.subframe_coding.qlpc.mae_optimization_steps = 0;
}
let config = config.into_verified().expect("config value error");
let source =
source::MemSource::from_samples(&signal, channels, bits_per_sample, sample_rate);
test_helper::integrity_test(
|s| {
coding::encode_with_fixed_block_size(&config, s, config.block_size)
.expect("source error")
},
&source,
);
}
reusable!(REUSABLE_BUF: Vec<i32>);
#[test]
fn call_twice() {
fn fn1() {
reuse!(REUSABLE_BUF, |buf: &mut Vec<i32>| {
assert_eq!(buf.len(), 0);
buf.resize(5, 0i32);
});
}
fn fn2() {
reuse!(REUSABLE_BUF, |buf: &mut Vec<i32>| {
assert_eq!(buf.len(), 5);
});
}
fn1();
fn2();
}
}