X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihav-core%2Fsrc%2Fsoundcvt%2Fmod.rs;h=30f0cd66d24aca76dcb76c89f9bf9c3934dab910;hb=210f21b33136c0d4ed0c8e2dd02ffc7c9c518fc1;hp=a9f16c623b5e8dd0f3fc888b0f2f65ecb1f33d5d;hpb=6f2630992fe340ad1a122ec10c649f756e478185;p=nihav.git diff --git a/nihav-core/src/soundcvt/mod.rs b/nihav-core/src/soundcvt/mod.rs index a9f16c6..30f0cd6 100644 --- a/nihav-core/src/soundcvt/mod.rs +++ b/nihav-core/src/soundcvt/mod.rs @@ -7,8 +7,12 @@ pub use crate::frame::{NAAudioBuffer,NAAudioInfo,NABufferType}; use crate::formats::NAChannelType; use crate::frame::alloc_audio_buffer; use crate::io::byteio::*; +use crate::io::bitreader::*; use std::f32::consts::SQRT_2; +mod resample; +pub use resample::NAResample; + /// A list specifying general sound conversion errors. #[derive(Clone,Copy,Debug,PartialEq)] pub enum SoundConvertError { @@ -216,11 +220,32 @@ struct PackedSampleReader<'a> { impl<'a> PackedSampleReader<'a> { fn new(data: &'a [u8], fmt: NASoniton) -> Self { - if (fmt.bits & 7) != 0 { unimplemented!(); } let bpp = (fmt.bits >> 3) as usize; Self { data, fmt, bpp } } fn get_samples(&self, pos: usize, dst: &mut [T]) where u8: IntoFmt, i16: IntoFmt, i32: IntoFmt, f32: IntoFmt { + if (self.fmt.bits & 7) != 0 { + let mode = if self.fmt.be { BitReaderMode::BE } else { BitReaderMode::LE }; + let mut br = BitReader::new(self.data, mode); + let offset = pos * (self.fmt.bits as usize) * dst.len(); + + if br.skip(offset as u32).is_ok() { + for el in dst.iter_mut() { + if self.fmt.bits < 16 { + *el = ((br.read(self.fmt.bits).unwrap_or(0) as i16) << (16 - self.fmt.bits)).cvt_into(); + } else { + *el = ((br.read(self.fmt.bits).unwrap_or(0) as i32) << (32 - self.fmt.bits)).cvt_into(); + } + } + } else { + for el in dst.iter_mut() { + *el = 0i16.cvt_into(); + } + } + + return; + } + let mut offset = pos * self.bpp * dst.len(); for el in dst.iter_mut() { @@ -345,20 +370,19 @@ 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(); + let nsamples = src.get_audio_length(); if nsamples == 0 { return Err(SoundConvertError::InvalidInput); } let src_chmap = src.get_chmap().unwrap(); let src_info = src.get_audio_info().unwrap(); + if src_info.sample_rate != dst_info.sample_rate { + return Err(SoundConvertError::Unsupported); + } if (src_chmap.num_channels() == 0) || (dst_chmap.num_channels() == 0) { return Err(SoundConvertError::InvalidInput); } - if let NABufferType::AudioPacked(_) = src { - nsamples = nsamples * 8 / (src_info.get_format().get_bits() as usize) / src_chmap.num_channels(); - } - let needs_remix = src_chmap.num_channels() != dst_chmap.num_channels(); let no_channel_needs = !needs_remix && channel_maps_equal(src_chmap, dst_chmap); let needs_reorder = !needs_remix && !no_channel_needs && channel_maps_reordered(src_chmap, dst_chmap); @@ -649,5 +673,40 @@ mod test { } else { panic!("wrong buffer type"); } + + const PCM12: &[u8] = &[ 0x02, 0x50, 0x00, 0x07, 0x70, 0x00, 0x0D, 0x00 ]; + const PCM12_SAMPLES: usize = 5; + let src_ainfo = NAAudioInfo { + sample_rate: 44100, + channels: 1, + format: NASoniton::new(12, SONITON_FLAG_PACKED | SONITON_FLAG_SIGNED), + block_len: 3, + }; + let dst_ainfo = NAAudioInfo { + sample_rate: 44100, + channels: 1, + format: SND_S16P_FORMAT, + block_len: 512, + }; + let mono = NAChannelMap::from_str("C").unwrap(); + let mut src_frm = alloc_audio_buffer(src_ainfo, PCM12_SAMPLES, mono.clone()).unwrap(); + if let NABufferType::AudioPacked(ref mut abuf) = src_frm { + let data = abuf.get_data_mut().unwrap(); + data.copy_from_slice(PCM12); + } else { + panic!("wrong buffer type"); + } + let out_frm = convert_audio_frame(&src_frm, &dst_ainfo, &mono).unwrap(); + if let NABufferType::AudioI16(ref abuf) = out_frm { + let data = abuf.get_data(); + assert_eq!(data.len(), PCM12_SAMPLES); + assert_eq!(data[0], 0x0020); + assert_eq!(data[1], 0x0050); + assert_eq!(data[2], 0x0070); + assert_eq!(data[3], 0x0070); + assert_eq!(data[4], 0x00D0); + } else { + panic!("wrong buffer type"); + } } }