]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/opus_celt.c
opus: Add Special Hybrid Folding (per RFC8251)
[ffmpeg] / libavcodec / opus_celt.c
index 84d484753b361fe9292d3941a2510a0f771ace51..2bbb96bded5c4e1b23f276df87941373e99f0656 100644 (file)
@@ -481,7 +481,8 @@ static void celt_denormalize(CeltFrame *f, CeltBlock *block, float *data)
 
     for (i = f->start_band; i < f->end_band; i++) {
         float *dst = data + (ff_celt_freq_bands[i] << f->size);
-        float norm = exp2f(block->energy[i] + ff_celt_mean_energy[i]);
+        float log_norm = block->energy[i] + ff_celt_mean_energy[i];
+        float norm = exp2f(FFMIN(log_norm, 32.0f));
 
         for (j = 0; j < ff_celt_freq_range[i] << f->size; j++)
             dst[j] *= norm;
@@ -711,10 +712,22 @@ static void celt_decode_bands(CeltFrame *f, OpusRangeCoder *rc)
             b = av_clip_uintp2(FFMIN(f->remaining2 + 1, f->pulses[i] + curr_balance), 14);
         }
 
-        if (ff_celt_freq_bands[i] - ff_celt_freq_range[i] >= ff_celt_freq_bands[f->start_band] &&
-            (update_lowband || lowband_offset == 0))
+        if ((ff_celt_freq_bands[i] - ff_celt_freq_range[i] >= ff_celt_freq_bands[f->start_band] ||
+            i == f->start_band + 1) && (update_lowband || lowband_offset == 0))
             lowband_offset = i;
 
+        if (i == f->start_band + 1) {
+            /* Special Hybrid Folding (RFC 8251 section 9). Copy the first band into
+            the second to ensure the second band never has to use the LCG. */
+            int offset = 8 * ff_celt_freq_bands[i];
+            int count = 8 * (ff_celt_freq_range[i] - ff_celt_freq_range[i-1]);
+
+            memcpy(&norm[offset], &norm[offset - count], count * sizeof(float));
+
+            if (f->channels == 2)
+                memcpy(&norm2[offset], &norm2[offset - count], count * sizeof(float));
+        }
+
         /* Get a conservative estimate of the collapse_mask's for the bands we're
            going to be folding from. */
         if (lowband_offset != 0 && (f->spread != CELT_SPREAD_AGGRESSIVE ||
@@ -727,7 +740,7 @@ static void celt_decode_bands(CeltFrame *f, OpusRangeCoder *rc)
             foldstart = lowband_offset;
             while (ff_celt_freq_bands[--foldstart] > effective_lowband);
             foldend = lowband_offset - 1;
-            while (ff_celt_freq_bands[++foldend] < effective_lowband + ff_celt_freq_range[i]);
+            while (++foldend < i && ff_celt_freq_bands[foldend] < effective_lowband + ff_celt_freq_range[i]);
 
             cm[0] = cm[1] = 0;
             for (j = foldstart; j < foldend; j++) {