aacsbr: fix off-by-one situation with envelope borders
authorKostya Shishkov <kostya.shishkov@gmail.com>
Mon, 13 Mar 2023 11:00:09 +0000 (12:00 +0100)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Mon, 13 Mar 2023 11:00:09 +0000 (12:00 +0100)
nihav-mpeg/src/codecs/aac/sbr/bs.rs
nihav-mpeg/src/codecs/aac/sbr/synth.rs

index 02c11080015b9203cdf7a9755f26e21af12bab25..74e820da626bc669289021eb8c4d8181e2ddfdaf 100644 (file)
@@ -107,14 +107,14 @@ fn read_grid(br: &mut BitReader, chan: &mut SBRChannel) -> DecoderResult<()> {
             for el in chan.freq_res[..chan.num_env].iter_mut() {
                 *el = freq_res;
             }
+            chan.env_border[0] = 0;
             if chan.num_env > 1 {
                 let delta = (MAX_SLOTS + chan.num_env / 2) / chan.num_env;
-                chan.env_border[0] = delta;
-                for i in 0..chan.num_env - 1 {
-                    chan.env_border[i + 1] = chan.env_border[i] + delta;
+                for i in 1..chan.num_env {
+                    chan.env_border[i] = chan.env_border[i - 1] + delta;
                 }
             }
-            chan.env_border[chan.num_env - 1] = MAX_SLOTS;
+            chan.env_border[chan.num_env] = MAX_SLOTS;
         },
         FrameClass::FixVar => {
             let var_bord_1              = br.read(2)? as u8;
@@ -129,9 +129,10 @@ fn read_grid(br: &mut BitReader, chan: &mut SBRChannel) -> DecoderResult<()> {
                 *el                 = br.read_bool()?;
             }
 
-            chan.env_border[chan.num_env - 1] = MAX_SLOTS + usize::from(var_bord_1);
+            chan.env_border[0] = 0;
+            chan.env_border[chan.num_env] = MAX_SLOTS + usize::from(var_bord_1);
             for (i, &delta) in (1..chan.num_env).rev().zip(rel_bord_1.iter()) {
-                chan.env_border[i - 1] = chan.env_border[i] - usize::from(delta);
+                chan.env_border[i] = chan.env_border[i + 1] - usize::from(delta);
             }
         },
         FrameClass::VarFix => {
@@ -147,11 +148,11 @@ fn read_grid(br: &mut BitReader, chan: &mut SBRChannel) -> DecoderResult<()> {
                 *el                 = br.read_bool()?;
             }
 
-            chan.env_border[0] = usize::from(var_bord_0 + rel_bord_0[0]);
-            for i in 1..chan.num_env {
-                chan.env_border[i] = chan.env_border[i - 1] + usize::from(rel_bord_0[i]);
+            chan.env_border[0] = usize::from(var_bord_0);
+            for i in 0..chan.num_env - 1 {
+                chan.env_border[i + 1] = chan.env_border[i] + usize::from(rel_bord_0[i]);
             }
-            chan.env_border[chan.num_env - 1] = MAX_SLOTS;
+            chan.env_border[chan.num_env] = MAX_SLOTS;
         },
         FrameClass::VarVar => {
             let var_bord_0          = br.read(2)? as u8;
@@ -173,35 +174,37 @@ fn read_grid(br: &mut BitReader, chan: &mut SBRChannel) -> DecoderResult<()> {
                 *el                 = br.read_bool()?;
             }
 
-            chan.env_border[0] = usize::from(var_bord_0 + rel_bord_0[0]);
-            for i in 1..=num_rel_0 {
-                chan.env_border[i] = chan.env_border[i - 1] + usize::from(rel_bord_0[i]);
+            chan.env_border[0] = usize::from(var_bord_0);
+            for i in 0..num_rel_0 {
+                chan.env_border[i + 1] = chan.env_border[i] + usize::from(rel_bord_0[i]);
             }
-            chan.env_border[chan.num_env - 1] = MAX_SLOTS + usize::from(var_bord_1);
+            chan.env_border[chan.num_env] = MAX_SLOTS + usize::from(var_bord_1);
             for i in 0..num_rel_1 {
-                chan.env_border[chan.num_env - 2 - i] = chan.env_border[chan.num_env - 1 - i] - usize::from(rel_bord_1[i]);
+                chan.env_border[chan.num_env - 1 - i] = chan.env_border[chan.num_env - i] - usize::from(rel_bord_1[i]);
             }
         },
     };
-    for i in 0..chan.num_env - 1 {
+    for i in 0..chan.num_env {
         validate!(chan.env_border[i] < chan.env_border[i + 1]);
     }
 
     if chan.num_env > 1 {
         chan.num_noise = 2;
         let mid = match (chan.fclass, chan.pointer) {
-                (FrameClass::FixFix, _) => chan.num_env / 2 - 1,
-                (FrameClass::VarFix, 0) => 0,
-                (FrameClass::VarFix, 1) => chan.num_env - 2,
-                (FrameClass::VarFix, _) => chan.pointer as usize - 2,
-                (_, 0) | (_, 1)         => chan.num_env - 2,
-                (_, _)                  => chan.num_env - (chan.pointer as usize),
+                (FrameClass::FixFix, _) => chan.num_env / 2,
+                (FrameClass::VarFix, 0) => 1,
+                (FrameClass::VarFix, 1) => chan.num_env - 1,
+                (FrameClass::VarFix, _) => chan.pointer as usize - 1,
+                (_, 0) | (_, 1)         => chan.num_env - 1,
+                (_, _)                  => chan.num_env + 1 - (chan.pointer as usize),
             };
-        chan.noise_env_border[0] = chan.env_border[mid];
-        chan.noise_env_border[1] = chan.env_border[chan.num_env - 1];
+        chan.noise_env_border[0] = chan.env_border[0];
+        chan.noise_env_border[1] = chan.env_border[mid];
+        chan.noise_env_border[2] = chan.env_border[chan.num_env];
     } else {
         chan.num_noise = 1;
         chan.noise_env_border[0] = chan.env_border[0];
+        chan.noise_env_border[1] = chan.env_border[1];
     }
 
 
index e06a8c113c8c9e04641d9d1c04a19cc978b71e9b..75c808eed2bfc0d7d23b1e14c7988ca7f2f81a80 100644 (file)
@@ -41,7 +41,7 @@ pub struct SBRChannel {
     pub num_env:            usize,
         prev_num_env:       usize,
     pub freq_res:           [bool; NUM_ENVELOPES],
-    pub env_border:         [usize; NUM_ENVELOPES],
+    pub env_border:         [usize; NUM_ENVELOPES + 1],
     pub noise_env_border:   [usize; 3],
     pub pointer:            u8,
     pub num_noise:          usize,
@@ -93,7 +93,7 @@ impl SBRChannel {
             num_env:            0,
             prev_num_env:       0,
             freq_res:           [false; NUM_ENVELOPES],
-            env_border:         [0; NUM_ENVELOPES],
+            env_border:         [0; NUM_ENVELOPES + 1],
             noise_env_border:   [0; 3],
             pointer:            0,
             num_noise:          0,
@@ -214,7 +214,7 @@ impl SBRChannel {
                 };
         }
 
-        for (l, x_high) in self.x_high.iter_mut().enumerate().skip(HF_ADJ).take(self.env_border[self.num_env - 1] * 2) {
+        for (l, x_high) in self.x_high.iter_mut().enumerate().skip(HF_ADJ).take(self.env_border[self.num_env] * 2).skip(self.env_border[0]) {
             *x_high = [FFTC_ZERO; SBR_BANDS];
             let mut dst_k = state.k_x;
             for (&patch_start, &patch_len) in state.patch_start_subband[..state.num_patches].iter().zip(state.patch_num_subbands.iter()) {
@@ -247,7 +247,8 @@ impl SBRChannel {
 
         let kx = state.k_x;
         let km = state.f[state.num_master];
-        let envelope_end = self.env_border[self.num_env - 1];
+        let envelope_start = self.env_border[0];
+        let envelope_end = self.env_border[self.num_env];
 
         let high_start = state.f[..=state.num_master].binary_search(&state.k_x).unwrap();
         let f_high = &state.f[..=state.num_master][high_start..];
@@ -342,11 +343,11 @@ impl SBRChannel {
             }
         };
         let mut q_mapped = [[0.0; SBR_BANDS]; NUM_ENVELOPES];
-        let mut start = 0;
-        let noise_env = [0, self.noise_env_border[0], self.noise_env_border[1]];
+        let mut start = self.env_border[0];
+        let noise_env = self.noise_env_border;
         match self.qmode {
             QuantMode::Single => {
-                for (env_no, &env_end) in self.env_border[..self.num_env].iter().enumerate() {
+                for (env_no, &env_end) in self.env_border[1..=self.num_env].iter().enumerate() {
                     let env_end = env_end;
                     let mut noise_env_no = 0;
                     for nenv in 0..self.num_noise {
@@ -367,7 +368,7 @@ impl SBRChannel {
                 }
             },
             QuantMode::Left => {
-                for (env_no, &env_end) in self.env_border[..self.num_env].iter().enumerate() {
+                for (env_no, &env_end) in self.env_border[1..=self.num_env].iter().enumerate() {
                     let env_end = env_end;
                     let mut noise_env_no = 0;
                     for nenv in 0..self.num_noise {
@@ -388,7 +389,7 @@ impl SBRChannel {
                 }
             },
             QuantMode::Right => {
-                for (env_no, &env_end) in self.env_border[..self.num_env].iter().enumerate() {
+                for (env_no, &env_end) in self.env_border[1..=self.num_env].iter().enumerate() {
                     let env_end = env_end;
                     let mut noise_env_no = 0;
                     for nenv in 0..self.num_noise {
@@ -410,9 +411,9 @@ impl SBRChannel {
             },
         };
 
-        let mut start = 0;
+        let mut start = self.env_border[0];
         let mut e_curr = [[0.0f32; SBR_BANDS]; NUM_ENVELOPES];
-        for (e_curr, &env_end) in e_curr.iter_mut().zip(self.env_border[..self.num_env].iter()) {
+        for (e_curr, &env_end) in e_curr.iter_mut().zip(self.env_border[1..=self.num_env].iter()) {
             for slot in self.x_high[HF_ADJ..][(start * 2)..(env_end * 2)].iter() {
                 for (dst, x) in e_curr[kx..km].iter_mut().zip(slot[kx..km].iter()) {
                     *dst += x.sq_modulus();
@@ -504,8 +505,8 @@ impl SBRChannel {
         }
 
         let mut env_map = [0; MAX_SLOTS * 2 + QMF_DELAY];
-        let mut start = 0;
-        for (env, &env_end) in self.env_border[..self.num_env].iter().enumerate() {
+        let mut start = self.env_border[0];
+        for (env, &env_end) in self.env_border[1..=self.num_env].iter().enumerate() {
             for l in (start * 2)..(env_end * 2) {
                 env_map[l] = env;
             }
@@ -517,8 +518,8 @@ impl SBRChannel {
         if self.last_env_end > 0 {
             ghead.copy_from_slice(&gcur[self.last_env_end - SMOOTH_DELAY..][..SMOOTH_DELAY]);
             qhead.copy_from_slice(&qcur[self.last_env_end - SMOOTH_DELAY..][..SMOOTH_DELAY]);
-            let mut start = 0;
-            for (&env_end, (g_lim, q_lim)) in self.env_border[..self.num_env].iter().zip(g_lim_boost.iter().zip(q_m_lim_boost.iter())) {
+            let mut start = self.env_border[0];
+            for (&env_end, (g_lim, q_lim)) in self.env_border[1..=self.num_env].iter().zip(g_lim_boost.iter().zip(q_m_lim_boost.iter())) {
                 for slot in (start * 2)..(env_end * 2) {
                     gcur[slot] = *g_lim;
                     qcur[slot] = *q_lim;
@@ -533,7 +534,7 @@ impl SBRChannel {
                 *dst = q_m_lim_boost[0];
             }
             let mut start = 0;
-            for (&env_end, (g_lim, q_lim)) in self.env_border[..self.num_env].iter().zip(g_lim_boost.iter().zip(q_m_lim_boost.iter())) {
+            for (&env_end, (g_lim, q_lim)) in self.env_border[1..=self.num_env].iter().zip(g_lim_boost.iter().zip(q_m_lim_boost.iter())) {
                 for slot in (start * 2)..(env_end * 2) {
                     gcur[slot] = *g_lim;
                     qcur[slot] = *q_lim;
@@ -545,7 +546,7 @@ impl SBRChannel {
         let mut g_filt = [[0.0; SBR_BANDS]; MAX_SLOTS * 2 + QMF_DELAY];
         let mut q_filt = [[0.0; SBR_BANDS]; MAX_SLOTS * 2 + QMF_DELAY];
         if !hdr.smoothing_mode {
-            for slot in 0..(envelope_end * 2) {
+            for slot in (envelope_start * 2)..(envelope_end * 2) {
                 if (slot as i8) == (la_prev * 2) {
                     g_filt[slot].copy_from_slice(&self.g_temp[slot + SMOOTH_DELAY]);
                     q_filt[slot].copy_from_slice(&self.q_temp[slot + SMOOTH_DELAY]);
@@ -568,7 +569,7 @@ impl SBRChannel {
         }
 
         let index_noise = self.index_noise.wrapping_sub(self.env_border[0] * 2) & 511;
-        for (slot, y) in self.y.iter_mut().skip(HF_ADJ).take(envelope_end * 2).enumerate() {
+        for (slot, y) in self.y.iter_mut().skip(HF_ADJ).take(envelope_end * 2).skip(envelope_start * 2).enumerate() {
             for (k, y) in y.iter_mut().enumerate().skip(kx).take(km - kx) {
                 *y = self.x_high[HF_ADJ + slot][k].scale(g_filt[slot][k]);