From 278389defeeb9ea26100ca8f4783f44c9b446fa5 Mon Sep 17 00:00:00 2001
From: Jean-Marc Valin <jmvalin@jmvalin.ca>
Date: Fri, 17 May 2013 02:03:33 -0400
Subject: [PATCH] Automatic bandwidth decisions get more conservative as rate
 increases.

This should prevent errors in the bandwidth detection from affecting quality
when we have enough bits to be close to transparent.
---
 celt/celt.h        |  1 -
 src/analysis.c     | 12 ------------
 src/analysis.h     |  1 -
 src/opus_encoder.c | 36 ++++++++++++++++++++++++++++++------
 4 files changed, 30 insertions(+), 20 deletions(-)

diff --git a/celt/celt.h b/celt/celt.h
index 0404d9181..c4b3ddbab 100644
--- a/celt/celt.h
+++ b/celt/celt.h
@@ -58,7 +58,6 @@ typedef struct {
    opus_val16 activity;
    opus_val16 music_prob;
    int        bandwidth;
-   int        opus_bandwidth;
 }AnalysisInfo;
 
 #define __celt_check_mode_ptr_ptr(ptr) ((ptr) + ((ptr) - (const CELTMode**)(ptr)))
diff --git a/src/analysis.c b/src/analysis.c
index b978b6e05..ee71bda65 100644
--- a/src/analysis.c
+++ b/src/analysis.c
@@ -575,19 +575,7 @@ void tonality_analysis(TonalityAnalysisState *tonal, AnalysisInfo *info_out, con
        printf("%f ", features[i]);
     printf("\n");*/
 
-    if (bandwidth<=12)
-       tonal->opus_bandwidth = OPUS_BANDWIDTH_NARROWBAND;
-    else if (bandwidth<=14)
-       tonal->opus_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
-    else if (bandwidth<=16)
-       tonal->opus_bandwidth = OPUS_BANDWIDTH_WIDEBAND;
-    else if (bandwidth<=18)
-       tonal->opus_bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND;
-    else
-       tonal->opus_bandwidth = OPUS_BANDWIDTH_FULLBAND;
-
     info->bandwidth = bandwidth;
-    info->opus_bandwidth = tonal->opus_bandwidth;
     /*printf("%d %d\n", info->bandwidth, info->opus_bandwidth);*/
     info->noisiness = frame_noisiness;
     info->valid = 1;
diff --git a/src/analysis.h b/src/analysis.h
index 7b17118cf..bce94a510 100644
--- a/src/analysis.h
+++ b/src/analysis.h
@@ -60,7 +60,6 @@ typedef struct {
    int last_music;
    int last_transition;
    int count;
-   int opus_bandwidth;
    opus_val32   subframe_mem[3];
    int analysis_offset;
    float pspeech[DETECT_SIZE];
diff --git a/src/opus_encoder.c b/src/opus_encoder.c
index 29ac96796..1f2491aec 100644
--- a/src/opus_encoder.c
+++ b/src/opus_encoder.c
@@ -941,9 +941,21 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
     st->detected_bandwidth = 0;
     if (analysis_info->valid)
     {
+       int analysis_bandwidth;
        if (st->signal_type == OPUS_AUTO)
           st->voice_ratio = (int)floor(.5+100*(1-analysis_info->music_prob));
-       st->detected_bandwidth = analysis_info->opus_bandwidth;
+
+       analysis_bandwidth = analysis_info->bandwidth;
+       if (analysis_bandwidth<=12)
+          st->detected_bandwidth = OPUS_BANDWIDTH_NARROWBAND;
+       else if (analysis_bandwidth<=14)
+          st->detected_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
+       else if (analysis_bandwidth<=16)
+          st->detected_bandwidth = OPUS_BANDWIDTH_WIDEBAND;
+       else if (analysis_bandwidth<=18)
+          st->detected_bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND;
+       else
+          st->detected_bandwidth = OPUS_BANDWIDTH_FULLBAND;
     }
 #endif
 
@@ -1217,12 +1229,24 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
     /* Use detected bandwidth to reduce the encoded bandwidth. */
     if (st->detected_bandwidth && st->user_bandwidth == OPUS_AUTO)
     {
-       /* When operating in SILK/hybrid mode, we don't go below wideband to avoid
-          more complicated switches that require redundancy */
-       if (st->mode == MODE_CELT_ONLY)
-          st->bandwidth = IMIN(st->bandwidth, st->detected_bandwidth);
+       int min_detected_bandwidth;
+       /* Makes bandwidth detection more conservative just in case the detector
+          gets it wrong when we could have coded a high bandwidth transparently.
+          When operating in SILK/hybrid mode, we don't go below wideband to avoid
+          more complicated switches that require redundancy. */
+       if (st->bitrate_bps <= 18000*st->stream_channels && st->mode == MODE_CELT_ONLY)
+          min_detected_bandwidth = OPUS_BANDWIDTH_NARROWBAND;
+       else if (st->bitrate_bps <= 24000*st->stream_channels && st->mode == MODE_CELT_ONLY)
+          min_detected_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
+       else if (st->bitrate_bps <= 30000*st->stream_channels)
+          min_detected_bandwidth = OPUS_BANDWIDTH_WIDEBAND;
+       else if (st->bitrate_bps <= 44000*st->stream_channels)
+          min_detected_bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND;
        else
-          st->bandwidth = IMIN(st->bandwidth, IMAX(OPUS_BANDWIDTH_WIDEBAND, st->detected_bandwidth));
+          min_detected_bandwidth = OPUS_BANDWIDTH_FULLBAND;
+
+       st->detected_bandwidth = IMAX(st->detected_bandwidth, min_detected_bandwidth);
+       st->bandwidth = IMIN(st->bandwidth, st->detected_bandwidth);
     }
 #endif
     celt_encoder_ctl(celt_enc, OPUS_SET_LSB_DEPTH(lsb_depth));
-- 
GitLab