support interleaved audio properly
[nihav.git] / nihav-core / src / soundcvt / mod.rs
index 8d1ebb8a1487fca180afffeecc585902225f311a..1b7b0309f000506372fd29281cb2faf6065f504a 100644 (file)
@@ -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<NABufferType, SoundConvertError> {
     let mut nsamples = src.get_audio_length();
@@ -359,6 +368,8 @@ Result<NABufferType, SoundConvertError> {
     }
     let mut dst_buf = ret.unwrap();
 
+    let sstep = src.get_audio_step();
+    let dstep = dst_buf.get_audio_step();
     let sr: Box<dyn SampleReader> = match src {
             NABufferType::AudioU8(ref ab) => {
                 let stride = ab.get_stride();
@@ -418,26 +429,34 @@ Result<NABufferType, SoundConvertError> {
     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<NABufferType, SoundConvertError> {
     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<usize> {
     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<f32> {
     if is_stereo(src) && dst.num_channels() == 1 &&
         (dst.get_channel(0) == NAChannelType::L || dst.get_channel(0) == NAChannelType::C) {