X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihav-core%2Fsrc%2Fsoundcvt%2Fmod.rs;h=1b7b0309f000506372fd29281cb2faf6065f504a;hb=98c6f2f05967e79b7d946c908d1198c108704293;hp=8d1ebb8a1487fca180afffeecc585902225f311a;hpb=d24468d9dbd54f5cbe414649ff061699337fa7fe;p=nihav.git diff --git a/nihav-core/src/soundcvt/mod.rs b/nihav-core/src/soundcvt/mod.rs index 8d1ebb8..1b7b030 100644 --- a/nihav-core/src/soundcvt/mod.rs +++ b/nihav-core/src/soundcvt/mod.rs @@ -1,3 +1,7 @@ +//! Sound format conversion. +//! +//! This module implements the functionality for conversion between different sound formats: packed or planar audio, 8-/16-/24-/32-bit, integer or floating point, different number of channels. +//! Eventually this might support resampling as well. pub use crate::formats::{NASoniton,NAChannelMap}; pub use crate::frame::{NAAudioBuffer,NAAudioInfo,NABufferType}; use crate::formats::NAChannelType; @@ -5,10 +9,14 @@ use crate::frame::alloc_audio_buffer; use crate::io::byteio::*; use std::f32::consts::SQRT_2; +/// A list specifying general sound conversion errors. #[derive(Clone,Copy,Debug,PartialEq)] pub enum SoundConvertError { + /// Invalid input arguments. InvalidInput, + /// Allocation failed. AllocError, + /// Requested feature is not supported. Unsupported, } @@ -304,6 +312,7 @@ impl SampleWriter for PackedSampleWriter<'_> { } } +/// Converts input audio buffer into desired format and returns a newly allocated buffer. pub fn convert_audio_frame(src: &NABufferType, dst_info: &NAAudioInfo, dst_chmap: &NAChannelMap) -> Result { let mut nsamples = src.get_audio_length(); @@ -359,6 +368,8 @@ Result { } let mut dst_buf = ret.unwrap(); + let sstep = src.get_audio_step(); + let dstep = dst_buf.get_audio_step(); let sr: Box = match src { NABufferType::AudioU8(ref ab) => { let stride = ab.get_stride(); @@ -418,26 +429,34 @@ Result { if !into_float { let mut svec = vec![0; src_chmap.num_channels()]; let mut dvec = vec![0; dst_chmap.num_channels()]; - for i in 0..nsamples { - sr.get_samples_i32(i, &mut svec); + let mut spos = 0; + let mut dpos = 0; + for _ in 0..nsamples { + sr.get_samples_i32(spos, &mut svec); if !channel_op.is_remix() { apply_channel_op(&channel_op, &svec, &mut dvec); } else { remix_i32(&channel_op, &svec, &mut dvec); } - sw.store_samples_i32(i, &dvec); + sw.store_samples_i32(dpos, &dvec); + spos += sstep; + dpos += dstep; } } else { let mut svec = vec![0.0; src_chmap.num_channels()]; let mut dvec = vec![0.0; dst_chmap.num_channels()]; - for i in 0..nsamples { - sr.get_samples_f32(i, &mut svec); + let mut spos = 0; + let mut dpos = 0; + for _ in 0..nsamples { + sr.get_samples_f32(spos, &mut svec); if !channel_op.is_remix() { apply_channel_op(&channel_op, &svec, &mut dvec); } else { remix_f32(&channel_op, &svec, &mut dvec); } - sw.store_samples_f32(i, &dvec); + sw.store_samples_f32(dpos, &dvec); + spos += sstep; + dpos += dstep; } } drop(sw); @@ -445,6 +464,7 @@ Result { Ok(dst_buf) } +/// Checks whether two channel maps are identical. pub fn channel_maps_equal(a: &NAChannelMap, b: &NAChannelMap) -> bool { if a.num_channels() != b.num_channels() { return false; } for i in 0..a.num_channels() { @@ -455,6 +475,7 @@ pub fn channel_maps_equal(a: &NAChannelMap, b: &NAChannelMap) -> bool { true } +/// Checks whether two channel maps have identical channels (but maybe in different order). pub fn channel_maps_reordered(a: &NAChannelMap, b: &NAChannelMap) -> bool { if a.num_channels() != b.num_channels() { return false; } let mut count_a = [0u8; 32]; @@ -471,6 +492,7 @@ pub fn channel_maps_reordered(a: &NAChannelMap, b: &NAChannelMap) -> bool { true } +/// Calculates permutation matrix for reordering channels from source channel map into destination one. pub fn calculate_reorder_matrix(src: &NAChannelMap, dst: &NAChannelMap) -> Vec { if src.num_channels() != dst.num_channels() { return Vec::new(); } let num_channels = src.num_channels(); @@ -494,6 +516,7 @@ fn is_stereo(chmap: &NAChannelMap) -> bool { (chmap.get_channel(1) == NAChannelType::R) } +/// Calculates matrix of remixing coefficients for converting input channel layout into destination one. pub fn calculate_remix_matrix(src: &NAChannelMap, dst: &NAChannelMap) -> Vec { if is_stereo(src) && dst.num_channels() == 1 && (dst.get_channel(0) == NAChannelType::L || dst.get_channel(0) == NAChannelType::C) {