make audio pipe work with interleaved audio properly master
authorKostya Shishkov <kostya.shishkov@gmail.com>
Fri, 5 Jan 2024 17:10:51 +0000 (18:10 +0100)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Fri, 5 Jan 2024 17:10:51 +0000 (18:10 +0100)
src/acvt.rs

index ef4191820b71fb10de261b89fde715a93e381d8c..254bed692c0056371bc116b7c31da08b307832eb 100644 (file)
@@ -10,6 +10,37 @@ struct AudioQueue<T> {
     ileaved:    bool,
 }
 
+fn copy_audio<T:Clone+Copy>(dst: &mut [T], dstride: usize,
+                            src: &[T], sstride: usize,
+                            len: usize, channels: usize)
+{
+    match (sstride == 1, dstride == 1) {
+        (false, false) => {
+            for (dchan, schan) in dst.chunks_mut(dstride).zip(
+                        src.chunks(sstride)).take(channels) {
+                dchan[..len].copy_from_slice(&schan[..len]);
+            }
+        },
+        (false, true) => {
+            for (ch, schan) in src.chunks(sstride).take(channels).enumerate() {
+                for (dchunk, &samp) in dst[ch..].chunks_mut(channels).zip(schan.iter()).take(len / channels) {
+                    dchunk[0] = samp;
+                }
+            }
+        },
+        (true, false) => {
+            for (i, frame) in src.chunks_exact(channels).take(len).enumerate() {
+                for (&samp, dchan) in frame.iter().zip(dst[i..].chunks_mut(dstride)) {
+                    dchan[0] = samp;
+                }
+            }
+        },
+        (true, true) => {
+            dst[..len].copy_from_slice(&src[..len]);
+        },
+    }
+}
+
 impl<T:Clone+Copy+From<u8>> AudioQueue<T> {
     fn new(channels: usize, rec_size: usize, ileaved: bool) -> Self {
         Self {
@@ -21,8 +52,9 @@ impl<T:Clone+Copy+From<u8>> AudioQueue<T> {
             data:       vec![0.into(); rec_size * channels],
         }
     }
-    fn get_cur_size(&self) -> usize {
-        let size = self.end - self.start;
+    fn get_cur_size(&self) -> usize { self.end - self.start }
+    fn get_length(&self) -> usize {
+        let size = self.get_cur_size();
         if !self.ileaved {
             size
         } else {
@@ -47,17 +79,19 @@ impl<T:Clone+Copy+From<u8>> AudioQueue<T> {
                 let old_len = self.get_cur_size();
                 let new_len = src.get_length();
                 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]);
+                    if !self.ileaved {
+                        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 {
+                        new_buf[..old_len].copy_from_slice(&self.data[self.start..self.end]);
+                        copy_audio(&mut new_buf[old_len..], 1, src.get_data(), src.get_stride(), new_len, self.channels);
                     }
                 } 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]);
-                    }
+                    copy_audio(&mut new_buf, if !self.ileaved { new_stride } else { 1 }, src.get_data(), src.get_stride(), new_len, self.channels);
                 }
                 self.data = new_buf;
                 self.stride = new_stride;
@@ -66,45 +100,20 @@ impl<T:Clone+Copy+From<u8>> AudioQueue<T> {
                 return;
             }
         }
-        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!(),
-        };
+        copy_audio(&mut self.data[self.end..], if !self.ileaved { self.stride } else { 1 }, src.get_data(), src.get_stride(),
+                   to_copy, self.channels);
         self.end += to_copy;
     }
     fn write(&mut self, dbuf: &mut NAAudioBuffer<T>) {
         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();
 
-        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!(),
-        };
+        if dst_stride == 1 {
+            dst_len *= self.channels;
+        }
+        copy_audio(dst, dst_stride, &self.data[self.start..], if !self.ileaved { self.stride } else { 1 },
+                   dst_len, self.channels);
         self.start += dst_len;
     }
     fn renorm(&mut self) {
@@ -136,11 +145,11 @@ enum AudioDataType {
 impl AudioDataType {
     fn get_length(&self) -> usize {
         match self {
-            AudioDataType::U8(ref queue) => queue.get_cur_size(),
-            AudioDataType::I16(ref queue) => queue.get_cur_size(),
-            AudioDataType::I32(ref queue) => queue.get_cur_size(),
-            AudioDataType::F32(ref queue) => queue.get_cur_size(),
-            AudioDataType::Packed(ref queue) => queue.get_cur_size(),
+            AudioDataType::U8(ref queue) => queue.get_length(),
+            AudioDataType::I16(ref queue) => queue.get_length(),
+            AudioDataType::I32(ref queue) => queue.get_length(),
+            AudioDataType::F32(ref queue) => queue.get_length(),
+            AudioDataType::Packed(ref queue) => queue.get_length(),
         }
     }
 }