diff --git a/include/opus_defines.h b/include/opus_defines.h
index cd8f4dde8..4f35fd7b2 100644
--- a/include/opus_defines.h
+++ b/include/opus_defines.h
@@ -133,6 +133,8 @@ extern "C" {
#define OPUS_GET_BITRATE_REQUEST 4003
#define OPUS_SET_MAX_BANDWIDTH_REQUEST 4004
#define OPUS_GET_MAX_BANDWIDTH_REQUEST 4005
+#define OPUS_SET_MIN_BANDWIDTH_REQUEST 40050
+#define OPUS_GET_MIN_BANDWIDTH_REQUEST 40051
#define OPUS_SET_VBR_REQUEST 4006
#define OPUS_GET_VBR_REQUEST 4007
#define OPUS_SET_BANDWIDTH_REQUEST 4008
@@ -406,6 +408,29 @@ extern "C" {
* @hideinitializer */
#define OPUS_GET_MAX_BANDWIDTH(x) OPUS_GET_MAX_BANDWIDTH_REQUEST, __opus_check_int_ptr(x)
+ /** Configures the minimum bandpass that the encoder will select automatically.
+ * LACE and NoLACE are currently only applied when the frame size is 20 ms (the default)
+ * and the bandwidth is at least wideband, to use LACE and NOLACE for low bandwidth
+ * and keep OPUS_AUTO for other bandwidth, we may need OPUS_SET_MIN_BANDWIDTH
+ * @see OPUS_GET_MIN_BANDWIDTH
+ * @param[in] x opus_int32: Allowed values:
+ *
+ * - OPUS_BANDWIDTH_NARROWBAND
- 4 kHz passband
+ * - OPUS_BANDWIDTH_WIDEBAND
- 8 kHz passband
+ *
+ * @hideinitializer */
+#define OPUS_SET_MIN_BANDWIDTH(x) OPUS_SET_MIN_BANDWIDTH_REQUEST, __opus_check_int(x)
+
+/** Gets the encoder's configured minimum allowed bandpass.
+ * @see OPUS_SET_MIN_BANDWIDTH
+ * @param[out] x opus_int32 *: Allowed values:
+ *
+ * - #OPUS_BANDWIDTH_NARROWBAND
- 4 kHz passband
+ * - #OPUS_BANDWIDTH_WIDEBAND
- 8 kHz passband
+ *
+ * @hideinitializer */
+#define OPUS_GET_MIN_BANDWIDTH(x) OPUS_GET_MIN_BANDWIDTH_REQUEST, __opus_check_int_ptr(x)
+
/** Sets the encoder's bandpass to a specific value.
* This prevents the encoder from automatically selecting the bandpass based
* on the available bitrate. If an application knows the bandpass of the input
diff --git a/src/opus_encoder.c b/src/opus_encoder.c
index d18d582f0..745766a21 100644
--- a/src/opus_encoder.c
+++ b/src/opus_encoder.c
@@ -85,6 +85,7 @@ struct OpusEncoder {
int signal_type;
int user_bandwidth;
int max_bandwidth;
+ int min_bandwidth;
int user_forced_mode;
int voice_ratio;
opus_int32 Fs;
@@ -270,6 +271,7 @@ int opus_encoder_init(OpusEncoder* st, opus_int32 Fs, int channels, int applicat
st->signal_type = OPUS_AUTO;
st->user_bandwidth = OPUS_AUTO;
st->max_bandwidth = OPUS_BANDWIDTH_FULLBAND;
+ st->min_bandwidth = OPUS_BANDWIDTH_NARROWBAND;
st->force_channels = OPUS_AUTO;
st->user_forced_mode = OPUS_AUTO;
st->voice_ratio = -1;
@@ -1476,6 +1478,9 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
mode transitions. */
if (bandwidth == OPUS_BANDWIDTH_MEDIUMBAND)
bandwidth = OPUS_BANDWIDTH_WIDEBAND;
+ /* If have minbandwidth (currently just use wideband to apply LACE & NOLACE)*/
+ if(st->min_bandwidth == OPUS_BANDWIDTH_WIDEBAND && bandwidth < st->min_bandwidth)
+ bandwidth = st->min_bandwidth;
st->bandwidth = st->auto_bandwidth = bandwidth;
/* Prevents any transition to SWB/FB until the SILK layer has fully
switched to WB mode and turned the variable LP filter off */
@@ -1948,7 +1953,13 @@ static opus_int32 opus_encode_frame_native(OpusEncoder *st, const opus_val16 *pc
/* Don't allow bandwidth reduction at lowest bitrates in hybrid mode */
st->silk_mode.minInternalSampleRate = 16000;
} else {
- st->silk_mode.minInternalSampleRate = 8000;
+ if (st->min_bandwidth == OPUS_BANDWIDTH_WIDEBAND) {
+ st->silk_mode.minInternalSampleRate = 16000;
+ }
+ else {
+ st->silk_mode.minInternalSampleRate = 8000;
+ }
+
}
st->silk_mode.maxInternalSampleRate = 16000;
@@ -2641,6 +2652,33 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
*value = st->max_bandwidth;
}
break;
+ case OPUS_SET_MIN_BANDWIDTH_REQUEST:
+ {
+ opus_int32 value = va_arg(ap, opus_int32);
+ if (value < OPUS_BANDWIDTH_NARROWBAND || value > OPUS_BANDWIDTH_FULLBAND)
+ {
+ goto bad_arg;
+ }
+ if (value == OPUS_BANDWIDTH_WIDEBAND) {
+ st->min_bandwidth = OPUS_BANDWIDTH_WIDEBAND;
+ st->silk_mode.minInternalSampleRate = 16000;
+ }
+ else {
+ st->min_bandwidth = OPUS_BANDWIDTH_NARROWBAND;
+ st->silk_mode.minInternalSampleRate = 8000;
+ }
+ }
+ break;
+ case OPUS_GET_MIN_BANDWIDTH_REQUEST:
+ {
+ opus_int32* value = va_arg(ap, opus_int32*);
+ if (!value)
+ {
+ goto bad_arg;
+ }
+ *value = st->min_bandwidth;
+ }
+ break;
case OPUS_SET_BANDWIDTH_REQUEST:
{
opus_int32 value = va_arg(ap, opus_int32);