From e6ff21ebe6e734a079c13409ea057a0ce4054823 Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Fri, 5 Jan 2024 18:10:51 +0100 Subject: [PATCH] make audio pipe work with interleaved audio properly --- src/acvt.rs | 105 ++++++++++++++++++++++++++++------------------------ 1 file changed, 57 insertions(+), 48 deletions(-) diff --git a/src/acvt.rs b/src/acvt.rs index ef41918..254bed6 100644 --- a/src/acvt.rs +++ b/src/acvt.rs @@ -10,6 +10,37 @@ struct AudioQueue { ileaved: bool, } +fn copy_audio(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> AudioQueue { fn new(channels: usize, rec_size: usize, ileaved: bool) -> Self { Self { @@ -21,8 +52,9 @@ impl> AudioQueue { 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> AudioQueue { 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> AudioQueue { 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) { 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(), } } } -- 2.30.2