1 pub use crate::formats::{NASoniton,NAChannelMap};
2 pub use crate::frame::{NAAudioBuffer,NAAudioInfo,NABufferType};
3 use crate::formats::NAChannelType;
4 use crate::frame::alloc_audio_buffer;
5 use crate::io::byteio::*;
6 use std::f32::consts::SQRT_2;
8 #[derive(Clone,Copy,Debug,PartialEq)]
9 pub enum SoundConvertError {
23 fn is_remix(&self) -> bool {
25 ChannelOp::Remix(_) => true,
26 ChannelOp::DupMono(_) => true,
32 fn apply_channel_op<T:Copy>(ch_op: &ChannelOp, src: &Vec<T>, dst: &mut Vec<T>) {
34 ChannelOp::Passthrough => {
35 dst.copy_from_slice(src.as_slice());
37 ChannelOp::Reorder(ref reorder) => {
38 for (out, idx) in dst.iter_mut().zip(reorder.iter()) {
46 fn remix_i32(ch_op: &ChannelOp, src: &Vec<i32>, dst: &mut Vec<i32>) {
47 if let ChannelOp::Remix(ref remix_mat) = ch_op {
49 for (out, coeffs) in dst.iter_mut().zip(remix_mat.chunks(sch)) {
51 for (inval, coef) in src.iter().zip(coeffs.iter()) {
52 sum += (*inval as f32) * *coef;
57 if let ChannelOp::DupMono(ref dup_mat) = ch_op {
59 for (out, copy) in dst.iter_mut().zip(dup_mat.iter()) {
60 *out = if *copy { src } else { 0 };
65 fn remix_f32(ch_op: &ChannelOp, src: &Vec<f32>, dst: &mut Vec<f32>) {
66 if let ChannelOp::Remix(ref remix_mat) = ch_op {
68 for (out, coeffs) in dst.iter_mut().zip(remix_mat.chunks(sch)) {
70 for (inval, coef) in src.iter().zip(coeffs.iter()) {
71 sum += *inval * *coef;
76 if let ChannelOp::DupMono(ref dup_mat) = ch_op {
78 for (out, copy) in dst.iter_mut().zip(dup_mat.iter()) {
79 *out = if *copy { src } else { 0.0 };
84 trait FromFmt<T:Copy> {
85 fn cvt_from(val: T) -> Self;
88 impl FromFmt<u8> for u8 {
89 fn cvt_from(val: u8) -> u8 { val }
91 impl FromFmt<u8> for i16 {
92 fn cvt_from(val: u8) -> i16 { ((val as i16) - 128).wrapping_mul(0x101) }
94 impl FromFmt<u8> for i32 {
95 fn cvt_from(val: u8) -> i32 { ((val as i32) - 128).wrapping_mul(0x01010101) }
97 impl FromFmt<u8> for f32 {
98 fn cvt_from(val: u8) -> f32 { ((val as f32) - 128.0) / 128.0 }
101 impl FromFmt<i16> for u8 {
102 fn cvt_from(val: i16) -> u8 { ((val >> 8) + 128).min(255).max(0) as u8 }
104 impl FromFmt<i16> for i16 {
105 fn cvt_from(val: i16) -> i16 { val }
107 impl FromFmt<i16> for i32 {
108 fn cvt_from(val: i16) -> i32 { (val as i32).wrapping_mul(0x10001) }
110 impl FromFmt<i16> for f32 {
111 fn cvt_from(val: i16) -> f32 { (val as f32) / 32768.0 }
114 impl FromFmt<i32> for u8 {
115 fn cvt_from(val: i32) -> u8 { ((val >> 24) + 128).min(255).max(0) as u8 }
117 impl FromFmt<i32> for i16 {
118 fn cvt_from(val: i32) -> i16 { (val >> 16) as i16 }
120 impl FromFmt<i32> for i32 {
121 fn cvt_from(val: i32) -> i32 { val }
123 impl FromFmt<i32> for f32 {
124 fn cvt_from(val: i32) -> f32 { (val as f32) / 31.0f32.exp2() }
127 impl FromFmt<f32> for u8 {
128 fn cvt_from(val: f32) -> u8 { ((val * 128.0) + 128.0).min(255.0).max(0.0) as u8 }
130 impl FromFmt<f32> for i16 {
131 fn cvt_from(val: f32) -> i16 { (val * 32768.0).min(16383.0).max(-16384.0) as i16 }
133 impl FromFmt<f32> for i32 {
134 fn cvt_from(val: f32) -> i32 { (val * 31.0f32.exp2()) as i32 }
136 impl FromFmt<f32> for f32 {
137 fn cvt_from(val: f32) -> f32 { val }
140 trait IntoFmt<T:Copy> {
141 fn cvt_into(self) -> T;
144 impl<T:Copy, U:Copy> IntoFmt<U> for T where U: FromFmt<T> {
145 fn cvt_into(self) -> U { U::cvt_from(self) }
150 fn get_samples_i32(&self, pos: usize, dst: &mut Vec<i32>);
151 fn get_samples_f32(&self, pos: usize, dst: &mut Vec<f32>);
154 struct GenericSampleReader<'a, T:Copy> {
159 impl<'a, T:Copy+IntoFmt<i32>+IntoFmt<f32>> SampleReader for GenericSampleReader<'a, T> {
160 fn get_samples_i32(&self, pos: usize, dst: &mut Vec<i32>) {
162 for el in dst.iter_mut() {
163 *el = self.data[off].cvt_into();
167 fn get_samples_f32(&self, pos: usize, dst: &mut Vec<f32>) {
169 for el in dst.iter_mut() {
170 *el = self.data[off].cvt_into();
176 struct PackedSampleReader<'a> {
182 impl<'a> PackedSampleReader<'a> {
183 fn new(data: &'a [u8], fmt: NASoniton) -> Self {
184 if (fmt.bits & 7) != 0 { unimplemented!(); }
185 let bpp = (fmt.bits >> 3) as usize;
186 Self { data, fmt, bpp }
188 fn get_samples<T:Copy>(&self, pos: usize, dst: &mut Vec<T>) where u8: IntoFmt<T>, i16: IntoFmt<T>, i32: IntoFmt<T>, f32: IntoFmt<T> {
189 let mut offset = pos * self.bpp * dst.len();
191 for el in dst.iter_mut() {
192 let src = &self.data[offset..];
193 *el = if !self.fmt.float {
194 match (self.bpp, self.fmt.be) {
195 (1, _) => src[0].cvt_into(),
196 (2, true) => (read_u16be(src).unwrap() as i16).cvt_into(),
197 (2, false) => (read_u16le(src).unwrap() as i16).cvt_into(),
198 (3, true) => ((read_u24be(src).unwrap() << 8) as i32).cvt_into(),
199 (3, false) => ((read_u24be(src).unwrap() << 8) as i32).cvt_into(),
200 (4, true) => (read_u32be(src).unwrap() as i32).cvt_into(),
201 (4, false) => (read_u32be(src).unwrap() as i32).cvt_into(),
205 match (self.bpp, self.fmt.be) {
206 (4, true) => read_f32be(src).unwrap().cvt_into(),
207 (4, false) => read_f32le(src).unwrap().cvt_into(),
208 (8, true) => (read_f64be(src).unwrap() as f32).cvt_into(),
209 (8, false) => (read_f64le(src).unwrap() as f32).cvt_into(),
210 (_, _) => unreachable!(),
218 impl SampleReader for PackedSampleReader<'_> {
219 fn get_samples_i32(&self, pos: usize, dst: &mut Vec<i32>) {
220 self.get_samples(pos, dst);
222 fn get_samples_f32(&self, pos: usize, dst: &mut Vec<f32>) {
223 self.get_samples(pos, dst);
228 fn store_samples_i32(&mut self, pos: usize, src: &Vec<i32>);
229 fn store_samples_f32(&mut self, pos: usize, src: &Vec<f32>);
232 struct GenericSampleWriter<'a, T:Copy> {
237 impl<'a, T:Copy+FromFmt<i32>+FromFmt<f32>> SampleWriter for GenericSampleWriter<'a, T> {
238 fn store_samples_i32(&mut self, pos: usize, src: &Vec<i32>) {
240 for el in src.iter() {
241 self.data[off] = (*el).cvt_into();
245 fn store_samples_f32(&mut self, pos: usize, src: &Vec<f32>) {
247 for el in src.iter() {
248 self.data[off] = (*el).cvt_into();
254 struct PackedSampleWriter<'a> {
260 impl<'a> PackedSampleWriter<'a> {
261 fn new(data: &'a mut [u8], fmt: NASoniton) -> Self {
262 if (fmt.bits & 7) != 0 { unimplemented!(); }
263 let bpp = (fmt.bits >> 3) as usize;
264 Self { data, fmt, bpp }
267 fn store_samples<T:Copy>(&mut self, pos: usize, src: &Vec<T>) where u8: FromFmt<T>, i16: FromFmt<T>, i32: FromFmt<T>, f32: FromFmt<T> {
268 let mut offset = pos * self.bpp * src.len();
269 for el in src.iter() {
270 let dst = &mut self.data[offset..];
272 match (self.bpp, self.fmt.be) {
274 dst[0] = u8::cvt_from(*el);
276 (2, true) => write_u16be(dst, i16::cvt_from(*el) as u16).unwrap(),
277 (2, false) => write_u16le(dst, i16::cvt_from(*el) as u16).unwrap(),
278 (3, true) => write_u24be(dst, (i32::cvt_from(*el) >> 8) as u32).unwrap(),
279 (3, false) => write_u24le(dst, (i32::cvt_from(*el) >> 8) as u32).unwrap(),
280 (4, true) => write_u32be(dst, i32::cvt_from(*el) as u32).unwrap(),
281 (4, false) => write_u32le(dst, i32::cvt_from(*el) as u32).unwrap(),
285 match (self.bpp, self.fmt.be) {
286 (4, true) => write_f32be(dst, f32::cvt_from(*el)).unwrap(),
287 (4, false) => write_f32le(dst, f32::cvt_from(*el)).unwrap(),
288 (8, true) => write_f64be(dst, f32::cvt_from(*el) as f64).unwrap(),
289 (8, false) => write_f64le(dst, f32::cvt_from(*el) as f64).unwrap(),
290 (_, _) => unreachable!(),
298 impl SampleWriter for PackedSampleWriter<'_> {
299 fn store_samples_i32(&mut self, pos: usize, src: &Vec<i32>) {
300 self.store_samples(pos, src);
302 fn store_samples_f32(&mut self, pos: usize, src: &Vec<f32>) {
303 self.store_samples(pos, src);
307 pub fn convert_audio_frame(src: &NABufferType, dst_info: &NAAudioInfo, dst_chmap: &NAChannelMap) ->
308 Result<NABufferType, SoundConvertError> {
309 let mut nsamples = src.get_audio_length();
311 return Err(SoundConvertError::InvalidInput);
313 let src_chmap = src.get_chmap().unwrap();
314 let src_info = src.get_audio_info().unwrap();
315 if (src_chmap.num_channels() == 0) || (dst_chmap.num_channels() == 0) {
316 return Err(SoundConvertError::InvalidInput);
319 if let NABufferType::AudioPacked(_) = src {
320 nsamples = nsamples * 8 / (src_info.get_format().get_bits() as usize) / src_chmap.num_channels();
323 let needs_remix = src_chmap.num_channels() != dst_chmap.num_channels();
324 let no_channel_needs = !needs_remix && channel_maps_equal(src_chmap, dst_chmap);
325 let needs_reorder = !needs_remix && !no_channel_needs && channel_maps_reordered(src_chmap, dst_chmap);
327 let channel_op = if no_channel_needs {
328 ChannelOp::Passthrough
329 } else if needs_reorder {
330 let reorder_mat = calculate_reorder_matrix(src_chmap, dst_chmap);
331 ChannelOp::Reorder(reorder_mat)
332 } else if src_chmap.num_channels() > 1 {
333 let remix_mat = calculate_remix_matrix(src_chmap, dst_chmap);
334 ChannelOp::Remix(remix_mat)
336 let mut dup_mat: Vec<bool> = Vec::with_capacity(dst_chmap.num_channels());
337 for i in 0..dst_chmap.num_channels() {
338 let ch = dst_chmap.get_channel(i);
339 if ch.is_left() || ch.is_right() || ch == NAChannelType::C {
345 ChannelOp::DupMono(dup_mat)
348 let src_fmt = src_info.get_format();
349 let dst_fmt = dst_info.get_format();
350 let no_conversion = src_fmt == dst_fmt;
352 if no_conversion && no_channel_needs {
353 return Ok(src.clone());
356 let ret = alloc_audio_buffer(dst_info.clone(), nsamples, dst_chmap.clone());
358 return Err(SoundConvertError::AllocError);
360 let mut dst_buf = ret.unwrap();
362 let sr: Box<dyn SampleReader> = match src {
363 NABufferType::AudioU8(ref ab) => {
364 let stride = ab.get_stride();
365 let data = ab.get_data();
366 Box::new(GenericSampleReader { data, stride })
368 NABufferType::AudioI16(ref ab) => {
369 let data = ab.get_data();
370 let stride = ab.get_stride();
371 Box::new(GenericSampleReader { data, stride })
373 NABufferType::AudioI32(ref ab) => {
374 let data = ab.get_data();
375 let stride = ab.get_stride();
376 Box::new(GenericSampleReader { data, stride })
378 NABufferType::AudioF32(ref ab) => {
379 let data = ab.get_data();
380 let stride = ab.get_stride();
381 Box::new(GenericSampleReader { data, stride })
383 NABufferType::AudioPacked(ref ab) => {
384 let data = ab.get_data();
385 Box::new(PackedSampleReader::new(data, src_fmt))
387 _ => unimplemented!(),
389 let mut sw: Box<dyn SampleWriter> = match dst_buf {
390 NABufferType::AudioU8(ref mut ab) => {
391 let stride = ab.get_stride();
392 let data = ab.get_data_mut().unwrap();
393 Box::new(GenericSampleWriter { data, stride })
395 NABufferType::AudioI16(ref mut ab) => {
396 let stride = ab.get_stride();
397 let data = ab.get_data_mut().unwrap();
398 Box::new(GenericSampleWriter { data, stride })
400 NABufferType::AudioI32(ref mut ab) => {
401 let stride = ab.get_stride();
402 let data = ab.get_data_mut().unwrap();
403 Box::new(GenericSampleWriter { data, stride })
405 NABufferType::AudioF32(ref mut ab) => {
406 let stride = ab.get_stride();
407 let data = ab.get_data_mut().unwrap();
408 Box::new(GenericSampleWriter { data, stride })
410 NABufferType::AudioPacked(ref mut ab) => {
411 let data = ab.get_data_mut().unwrap();
412 Box::new(PackedSampleWriter::new(data, dst_fmt))
414 _ => unimplemented!(),
417 let into_float = dst_fmt.float;
419 let mut svec = vec![0; src_chmap.num_channels()];
420 let mut dvec = vec![0; dst_chmap.num_channels()];
421 for i in 0..nsamples {
422 sr.get_samples_i32(i, &mut svec);
423 if !channel_op.is_remix() {
424 apply_channel_op(&channel_op, &svec, &mut dvec);
426 remix_i32(&channel_op, &svec, &mut dvec);
428 sw.store_samples_i32(i, &dvec);
431 let mut svec = vec![0.0; src_chmap.num_channels()];
432 let mut dvec = vec![0.0; dst_chmap.num_channels()];
433 for i in 0..nsamples {
434 sr.get_samples_f32(i, &mut svec);
435 if !channel_op.is_remix() {
436 apply_channel_op(&channel_op, &svec, &mut dvec);
438 remix_f32(&channel_op, &svec, &mut dvec);
440 sw.store_samples_f32(i, &dvec);
448 pub fn channel_maps_equal(a: &NAChannelMap, b: &NAChannelMap) -> bool {
449 if a.num_channels() != b.num_channels() { return false; }
450 for i in 0..a.num_channels() {
451 if a.get_channel(i) != b.get_channel(i) {
458 pub fn channel_maps_reordered(a: &NAChannelMap, b: &NAChannelMap) -> bool {
459 if a.num_channels() != b.num_channels() { return false; }
460 let mut count_a = [0u8; 32];
461 let mut count_b = [0u8; 32];
462 for i in 0..a.num_channels() {
463 count_a[a.get_channel(i) as usize] += 1;
464 count_b[b.get_channel(i) as usize] += 1;
466 for (c0, c1) in count_a.iter().zip(count_b.iter()) {
474 pub fn calculate_reorder_matrix(src: &NAChannelMap, dst: &NAChannelMap) -> Vec<usize> {
475 if src.num_channels() != dst.num_channels() { return Vec::new(); }
476 let num_channels = src.num_channels();
477 let mut reorder: Vec<usize> = Vec::with_capacity(num_channels);
478 for i in 0..num_channels {
479 let dst_ch = dst.get_channel(i);
480 for j in 0..num_channels {
481 if src.get_channel(j) == dst_ch {
487 if reorder.len() != num_channels { reorder.clear(); }
491 fn is_stereo(chmap: &NAChannelMap) -> bool {
492 (chmap.num_channels() == 2) &&
493 (chmap.get_channel(0) == NAChannelType::L) &&
494 (chmap.get_channel(1) == NAChannelType::R)
497 pub fn calculate_remix_matrix(src: &NAChannelMap, dst: &NAChannelMap) -> Vec<f32> {
498 if is_stereo(src) && dst.num_channels() == 1 &&
499 (dst.get_channel(0) == NAChannelType::L || dst.get_channel(0) == NAChannelType::C) {
500 return vec![0.5, 0.5];
502 if src.num_channels() >= 5 && is_stereo(dst) {
503 let src_nch = src.num_channels();
504 let mut mat = vec![0.0f32; src_nch * 2];
505 let (l_mat, r_mat) = mat.split_at_mut(src_nch);
506 for ch in 0..src_nch {
507 match src.get_channel(ch) {
508 NAChannelType::L => l_mat[ch] = 1.0,
509 NAChannelType::R => r_mat[ch] = 1.0,
510 NAChannelType::C => { l_mat[ch] = SQRT_2 / 2.0; r_mat[ch] = SQRT_2 / 2.0; },
511 NAChannelType::Ls => l_mat[ch] = SQRT_2 / 2.0,
512 NAChannelType::Rs => r_mat[ch] = SQRT_2 / 2.0,
524 use std::str::FromStr;
525 use crate::formats::*;
529 let chcfg51 = NAChannelMap::from_str("L,R,C,LFE,Ls,Rs").unwrap();
530 let chcfg52 = NAChannelMap::from_str("C,L,R,Ls,Rs,LFE").unwrap();
531 let stereo = NAChannelMap::from_str("L,R").unwrap();
532 let reorder = calculate_reorder_matrix(&chcfg51, &chcfg52);
533 assert_eq!(reorder.as_slice(), [ 2, 0, 1, 4, 5, 3]);
534 let remix = calculate_remix_matrix(&chcfg51, &stereo);
535 assert_eq!(remix.as_slice(), [ 1.0, 0.0, SQRT_2 / 2.0, 0.0, SQRT_2 / 2.0, 0.0,
536 0.0, 1.0, SQRT_2 / 2.0, 0.0, 0.0, SQRT_2 / 2.0 ]);
539 fn test_conversion() {
540 const CHANNEL_VALUES: [u8; 6] = [ 140, 90, 130, 128, 150, 70 ];
541 let chcfg51 = NAChannelMap::from_str("L,R,C,LFE,Ls,Rs").unwrap();
542 let stereo = NAChannelMap::from_str("L,R").unwrap();
543 let src_ainfo = NAAudioInfo {
545 channels: chcfg51.num_channels() as u8,
546 format: SND_U8_FORMAT,
549 let mut dst_ainfo = NAAudioInfo {
551 channels: stereo.num_channels() as u8,
552 format: SND_S16P_FORMAT,
555 let mut src_frm = alloc_audio_buffer(src_ainfo, 42, chcfg51.clone()).unwrap();
556 if let NABufferType::AudioPacked(ref mut abuf) = src_frm {
557 let data = abuf.get_data_mut().unwrap();
560 for ch in 0..chcfg51.num_channels() {
561 data[idx] = CHANNEL_VALUES[ch];
566 panic!("wrong buffer type");
569 let out_frm = convert_audio_frame(&src_frm, &dst_ainfo, &stereo).unwrap();
570 if let NABufferType::AudioI16(ref abuf) = out_frm {
571 let off0 = abuf.get_offset(0);
572 let off1 = abuf.get_offset(1);
573 let data = abuf.get_data();
577 assert_eq!(r, -19943);
579 panic!("wrong buffer type");
582 dst_ainfo.format = SND_F32P_FORMAT;
583 let out_frm = convert_audio_frame(&src_frm, &dst_ainfo, &stereo).unwrap();
584 if let NABufferType::AudioF32(ref abuf) = out_frm {
585 let off0 = abuf.get_offset(0);
586 let off1 = abuf.get_offset(1);
587 let data = abuf.get_data();
590 assert_eq!(l, 0.22633252);
591 assert_eq!(r, -0.6062342);
593 panic!("wrong buffer type");