shithub: opus

Download patch

ref: 0b00b3196713305443080aaf35f1ddc05ce94306
parent: b56c278b0edc7dff90b1a930e8b79edfb4fc4829
author: Koen Vos <[email protected]>
date: Thu Jul 12 10:55:49 EDT 2012

Attenuates the HF in hybrid mode to match what SILK does below the cutoff

Conflicts:

	src/opus_multistream.c
	src/opus_private.h

--- a/src/opus_decoder.c
+++ b/src/opus_decoder.c
@@ -693,7 +693,7 @@
       *out_toc = toc;
 
    if (payload_offset)
-      *payload_offset = data-data0;
+      *payload_offset = (int)(data-data0);
 
    return count;
 }
--- a/src/opus_encoder.c
+++ b/src/opus_encoder.c
@@ -97,8 +97,8 @@
 static const opus_int32 mono_voice_bandwidth_thresholds[8] = {
         11000, 1000, /* NB<->MB */
         14000, 1000, /* MB<->WB */
-        21000, 2000, /* WB<->SWB */
-        29000, 2000, /* SWB<->FB */
+        17000, 1000, /* WB<->SWB */
+        20000, 1000, /* SWB<->FB */
 };
 static const opus_int32 mono_music_bandwidth_thresholds[8] = {
         14000, 1000, /* MB not allowed */
@@ -946,6 +946,7 @@
     /* SILK processing */
     if (st->mode != MODE_CELT_ONLY)
     {
+        opus_int32 total_bitRate, celt_rate, HB_gain_Q16;
 #ifdef FIXED_POINT
        const opus_int16 *pcm_silk;
 #else
@@ -952,31 +953,33 @@
        VARDECL(opus_int16, pcm_silk);
        ALLOC(pcm_silk, st->channels*frame_size, opus_int16);
 #endif
-        st->silk_mode.bitRate = 8*bytes_target*frame_rate;
+
+        /* Distribute bits between SILK and CELT */
+        total_bitRate = 8 * bytes_target * frame_rate;
         if( st->mode == MODE_HYBRID ) {
-            st->silk_mode.bitRate /= st->stream_channels;
+            /* Base rate for SILK */
+            st->silk_mode.bitRate = st->stream_channels * ( 5000 + 1000 * ( st->Fs == 100 * frame_size ) );
             if( curr_bandwidth == OPUS_BANDWIDTH_SUPERWIDEBAND ) {
-                if( st->Fs == 100 * frame_size ) {
-                    /* 24 kHz, 10 ms */
-                    st->silk_mode.bitRate = ( ( st->silk_mode.bitRate + 2000 + st->use_vbr * 1000 ) * 2 ) / 3;
-                } else {
-                    /* 24 kHz, 20 ms */
-                    st->silk_mode.bitRate = ( ( st->silk_mode.bitRate + 1000 + st->use_vbr * 1000 ) * 2 ) / 3;
-                }
-            } else {
-                if( st->Fs == 100 * frame_size ) {
-                    /* 48 kHz, 10 ms */
-                    st->silk_mode.bitRate = ( st->silk_mode.bitRate + 8000 + st->use_vbr * 3000 ) / 2;
-                } else {
-                    /* 48 kHz, 20 ms */
-                    st->silk_mode.bitRate = ( st->silk_mode.bitRate + 9000 + st->use_vbr * 1000 ) / 2;
-                }
+                /* SILK gets 2/3 of the remaining bits */
+                st->silk_mode.bitRate += ( total_bitRate - st->silk_mode.bitRate ) * 2 / 3;
+            } else { /* FULLBAND */
+                /* SILK gets 3/5 of the remaining bits */
+                st->silk_mode.bitRate += ( total_bitRate - st->silk_mode.bitRate ) * 3 / 5;
             }
-            st->silk_mode.bitRate *= st->stream_channels;
-            /* don't let SILK use more than 80% */
-            if( st->silk_mode.bitRate > ( st->bitrate_bps - 8*st->Fs/frame_size ) * 4/5 ) {
-                st->silk_mode.bitRate = ( st->bitrate_bps - 8*st->Fs/frame_size ) * 4/5;
+            /* Don't let SILK use more than 80% */
+            if( st->silk_mode.bitRate > total_bitRate * 4/5 ) {
+                st->silk_mode.bitRate = total_bitRate * 4/5;
             }
+            /* Increasingly attenuate high band when it gets allocated fewer bits */
+            celt_rate = total_bitRate - st->silk_mode.bitRate;
+            if( curr_bandwidth == OPUS_BANDWIDTH_SUPERWIDEBAND ) {
+                HB_gain_Q16 = ( celt_rate << 10 ) / ( ( celt_rate + st->stream_channels * 2000 ) >> 6 );
+            } else { /* FULLBAND */
+                HB_gain_Q16 = ( celt_rate << 10 ) / ( ( celt_rate + st->stream_channels * 2400 ) >> 6 );
+            }
+        } else {
+            /* SILK gets all bits */
+            st->silk_mode.bitRate = total_bitRate;
         }
 
         st->silk_mode.payloadSize_ms = 1000 * frame_size / st->Fs;
@@ -1085,6 +1088,19 @@
            redundancy = 1;
            celt_to_silk = 0;
            st->silk_bw_switch = 1;
+        }
+
+        if( st->mode == MODE_HYBRID ) {
+#ifdef FIXED_POINT
+            for (i=0;i<frame_size*st->channels;i++) {
+                pcm_buf[delay_compensation*st->channels + i] = (opus_val16)( ( HB_gain_Q16 * pcm_buf[delay_compensation*st->channels + i] ) >> 16 );
+            }
+#else
+            float HB_gain = HB_gain_Q16 / 65536.0f;
+            for (i=0;i<frame_size*st->channels;i++) {
+                pcm_buf[delay_compensation*st->channels + i] *= HB_gain;
+            }
+#endif
         }
     }
 
--- a/src/opus_private.h
+++ b/src/opus_private.h
@@ -77,7 +77,7 @@
 /* Make sure everything's aligned to sizeof(void *) bytes */
 static inline int align(int i)
 {
-    return (i+sizeof(void *)-1)&-((int)sizeof(void *));
+    return (i+(int)sizeof(void *)-1)&-(int)sizeof(void *);
 }
 
 opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen, int self_delimited);