]> git.nihav.org Git - nihav-encoder.git/blobdiff - src/acvt.rs
force PCM audio processing in (almost) all cases
[nihav-encoder.git] / src / acvt.rs
index 5343039d1fb62e8fc8249ebf77d88660fe8cdd81..ef4191820b71fb10de261b89fde715a93e381d8c 100644 (file)
@@ -21,7 +21,14 @@ impl<T:Clone+Copy+From<u8>> AudioQueue<T> {
             data:       vec![0.into(); rec_size * channels],
         }
     }
-    fn get_cur_size(&self) -> usize { self.end - self.start }
+    fn get_cur_size(&self) -> usize {
+        let size = self.end - self.start;
+        if !self.ileaved {
+            size
+        } else {
+            size / self.channels
+        }
+    }
     fn get_cur_avail(&self) -> usize { self.stride - self.end }
     fn get_potentially_avail(&self) -> usize { self.stride - self.get_cur_size() }
     fn read(&mut self, src: &NAAudioBuffer<T>) {
@@ -39,11 +46,18 @@ impl<T:Clone+Copy+From<u8>> AudioQueue<T> {
 
                 let old_len = self.get_cur_size();
                 let new_len = src.get_length();
-                for (dst, (old, new)) in new_buf.chunks_exact_mut(new_stride).zip(
-                        self.data.chunks_exact(self.stride).zip(
-                            src.get_data().chunks(src.get_stride()))) {
-                    dst[..old_len].copy_from_slice(&old[self.start..self.end]);
-                    dst[old_len..][..new_len].copy_from_slice(&new[..new_len]);
+                if old_len > 0 {
+                    for (dst, (old, new)) in new_buf.chunks_exact_mut(new_stride).zip(
+                            self.data.chunks_exact(self.stride).zip(
+                                src.get_data().chunks(src.get_stride()))) {
+                        dst[..old_len].copy_from_slice(&old[self.start..self.end]);
+                        dst[old_len..][..new_len].copy_from_slice(&new[..new_len]);
+                    }
+                } else {
+                    for (dst, new) in new_buf.chunks_exact_mut(new_stride).zip(
+                                src.get_data().chunks(src.get_stride())) {
+                        dst[..new_len].copy_from_slice(&new[..new_len]);
+                    }
                 }
                 self.data = new_buf;
                 self.stride = new_stride;
@@ -52,19 +66,45 @@ impl<T:Clone+Copy+From<u8>> AudioQueue<T> {
                 return;
             }
         }
-        for (dst, src) in self.data.chunks_exact_mut(self.stride).zip(src.get_data().chunks_exact(src.get_stride())) {
-            dst[self.end..][..to_copy].copy_from_slice(&src[..to_copy]);
-        }
+        match (src.get_step() != 1, self.ileaved) {
+            (false, false) => {
+                for (dst, src) in self.data.chunks_exact_mut(self.stride).zip(src.get_data().chunks_exact(src.get_stride())) {
+                    dst[self.end..][..to_copy].copy_from_slice(&src[..to_copy]);
+                }
+            },
+            (true, false) => {
+                for (i, chunk) in src.get_data().chunks_exact(src.get_step()).enumerate() {
+                    for (ch, &samp) in chunk.iter().enumerate() {
+                        self.data[self.stride * ch + self.end + i] = samp;
+                    }
+                }
+            }
+            (true, true) => {
+                let sdata = src.get_data();
+                self.data[self.end..][..to_copy].copy_from_slice(&sdata[..to_copy]);
+            },
+            _ => unimplemented!(),
+        };
         self.end += to_copy;
     }
     fn write(&mut self, dbuf: &mut NAAudioBuffer<T>) {
-        let dst_len = dbuf.get_length();
+        let mut dst_len = dbuf.get_length();
         let dst_stride = dbuf.get_stride();
+        let dst_step = dbuf.get_step();
         let dst = dbuf.get_data_mut().unwrap();
 
-        for (dst, src) in dst.chunks_mut(dst_stride).zip(self.data.chunks_exact(self.stride)) {
-            dst[..dst_len].copy_from_slice(&src[self.start..][..dst_len]);
-        }
+        match (self.ileaved, dst_step != 1) {
+            (false, false) => {
+                for (dst, src) in dst.chunks_mut(dst_stride).zip(self.data.chunks_exact(self.stride)) {
+                    dst[..dst_len].copy_from_slice(&src[self.start..][..dst_len]);
+                }
+            },
+            (true, true) => {
+                dst_len *= self.channels;
+                dst[..dst_len].copy_from_slice(&self.data[self.start..][..dst_len]);
+            },
+            _ => unimplemented!(),
+        };
         self.start += dst_len;
     }
     fn renorm(&mut self) {
@@ -110,10 +150,11 @@ pub struct AudioConverter {
     dst_fmt:    NAAudioInfo,
     dst_chmap:  NAChannelMap,
     apts:       Option<u64>,
+    resampler:  NAResample,
 }
 
 impl AudioConverter {
-    pub fn new(_sinfo: &NAAudioInfo, dinfo: &NAAudioInfo, dst_chmap: NAChannelMap) -> Self {
+    pub fn new(sinfo: &NAAudioInfo, dinfo: &NAAudioInfo, dst_chmap: NAChannelMap) -> Self {
         let ch = usize::from(dinfo.channels);
         let size = dinfo.block_len * 2;
         let il = !dinfo.format.planar;
@@ -124,15 +165,18 @@ impl AudioConverter {
                 (32, true, _)      => AudioDataType::F32(AudioQueue::new(ch, size, il)),
                 _ => AudioDataType::Packed(AudioQueue::new(ch, size, il)),
             };
+        const RESAMPLE_FILTER_ORDER: usize = 16;
+        let resampler = NAResample::new(sinfo.sample_rate, dinfo, &dst_chmap, RESAMPLE_FILTER_ORDER);
         Self {
             queue,
             dst_fmt:    *dinfo,
             dst_chmap,
             apts:       None,
+            resampler,
         }
     }
     pub fn queue_frame(&mut self, buf: NABufferType, tinfo: NATimeInfo) -> bool {
-        let ret = convert_audio_frame(&buf, &self.dst_fmt, &self.dst_chmap);
+        let ret = self.resampler.convert_audio_frame(&buf);
         if let Ok(dbuf) = ret {
             if self.apts.is_none() && tinfo.get_pts().is_some() {
                 self.apts = tinfo.get_pts();