fix some clippy warnings
[nihav.git] / nihav-core / src / soundcvt / mod.rs
index b218e4ae588d61b2f9c60ffed77fe4ba230adac9..a9f16c623b5e8dd0f3fc888b0f2f65ecb1f33d5d 100644 (file)
@@ -29,15 +29,11 @@ enum ChannelOp {
 
 impl ChannelOp {
     fn is_remix(&self) -> bool {
-        match *self {
-            ChannelOp::Remix(_) => true,
-            ChannelOp::DupMono(_) => true,
-            _ => false,
-        }
+        matches! (*self, ChannelOp::Remix(_) | ChannelOp::DupMono(_))
     }
 }
 
-fn apply_channel_op<T:Copy>(ch_op: &ChannelOp, src: &[T], dst: &mut Vec<T>) {
+fn apply_channel_op<T:Copy>(ch_op: &ChannelOp, src: &[T], dst: &mut [T]) {
     match *ch_op {
         ChannelOp::Passthrough => {
             dst.copy_from_slice(src);
@@ -51,7 +47,7 @@ fn apply_channel_op<T:Copy>(ch_op: &ChannelOp, src: &[T], dst: &mut Vec<T>) {
     };
 }
 
-fn remix_i32(ch_op: &ChannelOp, src: &[i32], dst: &mut Vec<i32>) {
+fn remix_i32(ch_op: &ChannelOp, src: &[i32], dst: &mut [i32]) {
     if let ChannelOp::Remix(ref remix_mat) = ch_op {
         let sch = src.len();
         for (out, coeffs) in dst.iter_mut().zip(remix_mat.chunks(sch)) {
@@ -70,7 +66,7 @@ fn remix_i32(ch_op: &ChannelOp, src: &[i32], dst: &mut Vec<i32>) {
     }
 }
 
-fn remix_f32(ch_op: &ChannelOp, src: &[f32], dst: &mut Vec<f32>) {
+fn remix_f32(ch_op: &ChannelOp, src: &[f32], dst: &mut [f32]) {
     if let ChannelOp::Remix(ref remix_mat) = ch_op {
         let sch = src.len();
         for (out, coeffs) in dst.iter_mut().zip(remix_mat.chunks(sch)) {
@@ -97,10 +93,10 @@ impl FromFmt<u8> for u8 {
     fn cvt_from(val: u8) -> u8 { val }
 }
 impl FromFmt<u8> for i16 {
-    fn cvt_from(val: u8) -> i16 { (i16::from(val) - 128).wrapping_mul(0x101) }
+    fn cvt_from(val: u8) -> i16 { u16::from(val ^ 0x80).wrapping_mul(0x101) as i16}
 }
 impl FromFmt<u8> for i32 {
-    fn cvt_from(val: u8) -> i32 { (i32::from(val) - 128).wrapping_mul(0x01010101) }
+    fn cvt_from(val: u8) -> i32 { u32::from(val ^ 0x80).wrapping_mul(0x01010101) as i32 }
 }
 impl FromFmt<u8> for f32 {
     fn cvt_from(val: u8) -> f32 { (f32::from(val) - 128.0) / 128.0 }
@@ -113,7 +109,7 @@ impl FromFmt<i16> for i16 {
     fn cvt_from(val: i16) -> i16 { val }
 }
 impl FromFmt<i16> for i32 {
-    fn cvt_from(val: i16) -> i32 { i32::from(val).wrapping_mul(0x10001) }
+    fn cvt_from(val: i16) -> i32 { (i32::from(val) & 0xFFFF) | (i32::from(val) << 16) }
 }
 impl FromFmt<i16> for f32 {
     fn cvt_from(val: i16) -> f32 { f32::from(val) / 32768.0 }
@@ -136,10 +132,19 @@ impl FromFmt<f32> for u8 {
     fn cvt_from(val: f32) -> u8 { ((val * 128.0) + 128.0).min(255.0).max(0.0) as u8 }
 }
 impl FromFmt<f32> for i16 {
-    fn cvt_from(val: f32) -> i16 { (val * 32768.0).min(16383.0).max(-16384.0) as i16 }
+    fn cvt_from(val: f32) -> i16 { (val * 32768.0).min(32767.0).max(-32768.0) as i16 }
 }
 impl FromFmt<f32> for i32 {
-    fn cvt_from(val: f32) -> i32 { (val * 31.0f32.exp2()) as i32 }
+    fn cvt_from(val: f32) -> i32 {
+        if val >= 1.0 {
+            std::i32::MAX
+        } else if val <= -1.0 {
+            std::i32::MIN
+        } else {
+            let scale = (1u32 << 31) as f32;
+            (val * scale) as i32
+        }
+    }
 }
 impl FromFmt<f32> for f32 {
     fn cvt_from(val: f32) -> f32 { val }
@@ -155,8 +160,8 @@ impl<T:Copy, U:Copy> IntoFmt<U> for T where U: FromFmt<T> {
 
 
 trait SampleReader {
-    fn get_samples_i32(&self, pos: usize, dst: &mut Vec<i32>);
-    fn get_samples_f32(&self, pos: usize, dst: &mut Vec<f32>);
+    fn get_samples_i32(&self, pos: usize, dst: &mut [i32]);
+    fn get_samples_f32(&self, pos: usize, dst: &mut [f32]);
 }
 
 struct GenericSampleReader<'a, T:Copy> {
@@ -165,14 +170,14 @@ struct GenericSampleReader<'a, T:Copy> {
 }
 
 impl<'a, T:Copy+IntoFmt<i32>+IntoFmt<f32>> SampleReader for GenericSampleReader<'a, T> {
-    fn get_samples_i32(&self, pos: usize, dst: &mut Vec<i32>) {
+    fn get_samples_i32(&self, pos: usize, dst: &mut [i32]) {
         let mut off = pos;
         for el in dst.iter_mut() {
             *el = self.data[off].cvt_into();
             off += self.stride;
         }
     }
-    fn get_samples_f32(&self, pos: usize, dst: &mut Vec<f32>) {
+    fn get_samples_f32(&self, pos: usize, dst: &mut [f32]) {
         let mut off = pos;
         for el in dst.iter_mut() {
             *el = self.data[off].cvt_into();
@@ -181,6 +186,28 @@ impl<'a, T:Copy+IntoFmt<i32>+IntoFmt<f32>> SampleReader for GenericSampleReader<
     }
 }
 
+struct S8SampleReader<'a> {
+    data:   &'a [u8],
+    stride: usize,
+}
+
+impl<'a> SampleReader for S8SampleReader<'a> {
+    fn get_samples_i32(&self, pos: usize, dst: &mut [i32]) {
+        let mut off = pos;
+        for el in dst.iter_mut() {
+            *el = (self.data[off] ^ 0x80).cvt_into();
+            off += self.stride;
+        }
+    }
+    fn get_samples_f32(&self, pos: usize, dst: &mut [f32]) {
+        let mut off = pos;
+        for el in dst.iter_mut() {
+            *el = (self.data[off] ^ 0x80).cvt_into();
+            off += self.stride;
+        }
+    }
+}
+
 struct PackedSampleReader<'a> {
     data:   &'a [u8],
     fmt:    NASoniton,
@@ -193,14 +220,14 @@ impl<'a> PackedSampleReader<'a> {
         let bpp = (fmt.bits >> 3) as usize;
         Self { data, fmt, bpp }
     }
-    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> {
+    fn get_samples<T:Copy>(&self, pos: usize, dst: &mut [T]) where u8: IntoFmt<T>, i16: IntoFmt<T>, i32: IntoFmt<T>, f32: IntoFmt<T> {
         let mut offset = pos * self.bpp * dst.len();
 
         for el in dst.iter_mut() {
             let src = &self.data[offset..];
             *el = if !self.fmt.float {
                     match (self.bpp, self.fmt.be) {
-                        (1, _)     => src[0].cvt_into(),
+                        (1, _)     => if !self.fmt.signed { src[0].cvt_into() } else { (src[0] ^ 0x80).cvt_into() },
                         (2, true)  => (read_u16be(src).unwrap() as i16).cvt_into(),
                         (2, false) => (read_u16le(src).unwrap() as i16).cvt_into(),
                         (3, true)  => ((read_u24be(src).unwrap() << 8) as i32).cvt_into(),
@@ -224,10 +251,10 @@ impl<'a> PackedSampleReader<'a> {
 }
 
 impl SampleReader for PackedSampleReader<'_> {
-    fn get_samples_i32(&self, pos: usize, dst: &mut Vec<i32>) {
+    fn get_samples_i32(&self, pos: usize, dst: &mut [i32]) {
         self.get_samples(pos, dst);
     }
-    fn get_samples_f32(&self, pos: usize, dst: &mut Vec<f32>) {
+    fn get_samples_f32(&self, pos: usize, dst: &mut [f32]) {
         self.get_samples(pos, dst);
     }
 }
@@ -280,6 +307,9 @@ impl<'a> PackedSampleWriter<'a> {
                 match (self.bpp, self.fmt.be) {
                     (1, _) => {
                         dst[0] = u8::cvt_from(*el);
+                        if self.fmt.signed {
+                            dst[0] ^= 0x80;
+                        }
                     },
                     (2, true)  => write_u16be(dst, i16::cvt_from(*el) as u16).unwrap(),
                     (2, false) => write_u16le(dst, i16::cvt_from(*el) as u16).unwrap(),
@@ -374,7 +404,11 @@ Result<NABufferType, SoundConvertError> {
             NABufferType::AudioU8(ref ab) => {
                 let stride = ab.get_stride();
                 let data = ab.get_data();
-                Box::new(GenericSampleReader { data, stride })
+                if !src_fmt.signed {
+                    Box::new(GenericSampleReader { data, stride })
+                } else {
+                    Box::new(S8SampleReader { data, stride })
+                }
             },
             NABufferType::AudioI16(ref ab) => {
                 let data = ab.get_data();
@@ -597,7 +631,7 @@ mod test {
             let l = data[off0];
             let r = data[off1];
             assert_eq!(l, 7445);
-            assert_eq!(r, -19943);
+            assert_eq!(r, -19505);
         } else {
             panic!("wrong buffer type");
         }