[libav-devel] [PATCH 3/4] opus: Add Special Hybrid Folding (per RFC8251)

Andrew D'Addesio modchipv12 at gmail.com
Sun Dec 3 22:33:31 CET 2017


This decoder-side change, introduced in RFC 8251 (section 9), slightly
improves the decoded quality of 16kbps speech in Hybrid Mode.

Differences can be seen/heard in testvector05.bit, testvector06.bit,
and testvector12.bit in the RFC 6716/8251 testvectors found here:
https://people.xiph.org/~greg/opus_testvectors/

Signed-off-by: Andrew D'Addesio <modchipv12 at gmail.com>
---
 libavcodec/opus_celt.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/libavcodec/opus_celt.c b/libavcodec/opus_celt.c
index 17298ac..4ba4fde 100644
--- a/libavcodec/opus_celt.c
+++ b/libavcodec/opus_celt.c
@@ -1914,10 +1914,22 @@ static void celt_decode_bands(CeltContext *s, OpusRangeCoder *rc)
         } else
             b = 0;
 
-        if (celt_freq_bands[i] - celt_freq_range[i] >= celt_freq_bands[s->startband] &&
-            (update_lowband || lowband_offset == 0))
+        if ((celt_freq_bands[i] - celt_freq_range[i] >= celt_freq_bands[s->startband] ||
+            i == s->startband + 1) && (update_lowband || lowband_offset == 0))
             lowband_offset = i;
 
+        if (i == s->startband + 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 * celt_freq_bands[i];
+            int count = 8 * (celt_freq_range[i] - celt_freq_range[i-1]);
+
+            memcpy(&norm[offset], &norm[offset - count], count * sizeof(float));
+
+            if (s->coded_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 && (s->spread != CELT_SPREAD_AGGRESSIVE ||
@@ -1930,7 +1942,7 @@ static void celt_decode_bands(CeltContext *s, OpusRangeCoder *rc)
             foldstart = lowband_offset;
             while (celt_freq_bands[--foldstart] > effective_lowband);
             foldend = lowband_offset - 1;
-            while (celt_freq_bands[++foldend] < effective_lowband + celt_freq_range[i]);
+            while (++foldend < i && celt_freq_bands[foldend] < effective_lowband + celt_freq_range[i]);
 
             cm[0] = cm[1] = 0;
             for (j = foldstart; j < foldend; j++) {
-- 
2.15.1.windows.2



More information about the libav-devel mailing list