+//! 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;
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,
}
}
}
-pub fn convert_audio_frame(src: &NABufferType, dst_info: &NAAudioInfo, dst_chmap: &NAChannelMap) ->
+/// 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();
if nsamples == 0 {
}
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();
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);
-
+
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() {
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];
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();
fn is_stereo(chmap: &NAChannelMap) -> bool {
(chmap.num_channels() == 2) &&
- (chmap.get_channel(0) == NAChannelType::L) &&
+ (chmap.get_channel(0) == NAChannelType::L) &&
(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) {