Interface for bandwidth switching
authorKoen Vos <koen.vos@skype.net>
Thu, 28 Apr 2011 01:45:48 +0000 (21:45 -0400)
committerJean-Marc Valin <jean-marc.valin@usherbrooke.ca>
Thu, 28 Apr 2011 04:16:09 +0000 (00:16 -0400)
interface/SKP_Silk_control.h
src_FIX/SKP_Silk_main_FIX.h
src_FLP/SKP_Silk_main_FLP.h
src_common/SKP_Silk_control_audio_bandwidth.c
src_common/SKP_Silk_control_codec.c
src_common/SKP_Silk_enc_API.c
src_common/SKP_Silk_structs.h
src_common/SKP_Silk_tuning_parameters.h

index 7c8db28..d970fac 100644 (file)
@@ -82,6 +82,12 @@ typedef struct {
 \r
     /* O:   Internal sampling rate used, in Hertz; 8000/12000/16000                         */\r
     SKP_int32 internalSampleRate;\r
+\r
+    /* O: Flag that bandwidth switching is allowed (because low voice activity)             */\r
+    SKP_int allowBandwidthSwitch;\r
+\r
+    /* O:   Flag that SILK runs in WB mode without variable LP filter (use for switching between WB/SWB/FB) */\r
+    SKP_int inWBmodeWithoutVariableLP;\r
 } SKP_SILK_SDK_EncControlStruct;\r
 \r
 /**************************************************************************/\r
index 5dba8e6..b72516b 100644 (file)
@@ -70,7 +70,8 @@ SKP_int SKP_Silk_init_encoder(
 SKP_int SKP_Silk_control_encoder( \r
     SKP_Silk_encoder_state_FIX      *psEnc,             /* I/O  Pointer to Silk encoder state           */\r
     SKP_SILK_SDK_EncControlStruct   *encControl,        /* I:   Control structure                       */\r
-    const SKP_int32                 TargetRate_bps      /* I    Target max bitrate (bps)                */\r
+    const SKP_int32                 TargetRate_bps,     /* I    Target max bitrate (bps)                */\r
+    const SKP_int                   allow_bw_switch     /* I    Flag to allow switching audio bandwidth */\r
 );\r
 \r
 /****************/\r
index 4447a8a..c3f3072 100644 (file)
@@ -68,7 +68,8 @@ SKP_int SKP_Silk_init_encoder(
 SKP_int SKP_Silk_control_encoder( \r
     SKP_Silk_encoder_state_FLP      *psEnc,             /* I/O  Pointer to Silk encoder state FLP       */\r
     SKP_SILK_SDK_EncControlStruct   *encControl,        /* I:   Control structure                       */\r
-    const SKP_int32                 TargetRate_bps      /* I    Target max bitrate (bps)                */\r
+    const SKP_int32                 TargetRate_bps,     /* I    Target max bitrate (bps)                */\r
+    const SKP_int                   allow_bw_switch     /* I    Flag to allow switching audio bandwidth */\r
 );\r
 \r
 /****************/\r
index 0e454c3..b2d0e04 100644 (file)
@@ -50,7 +50,11 @@ SKP_int SKP_Silk_control_audio_bandwidth(
         fs_kHz = SKP_DIV32_16( fs_Hz, 1000 );\r
     } else {\r
         /* State machine for the internal sampling rate switching */\r
-        if( psEncC->API_fs_Hz > 8000 && psEncC->prevSignalType == TYPE_NO_VOICE_ACTIVITY ) {\r
+        if( psEncC->sLP.transition_frame_no >= TRANSITION_FRAMES ) {\r
+            /* Stop transition phase */\r
+            psEncC->sLP.mode = 0;\r
+        }\r
+        if( psEncC->allow_bandwidth_switch ) {\r
             /* Check if we should switch down */\r
             if( SKP_SMULBB( psEncC->fs_kHz, 1000 ) > psEncC->desiredInternal_fs_Hz ) \r
             {\r
@@ -84,14 +88,12 @@ SKP_int SKP_Silk_control_audio_bandwidth(
 \r
                     /* New transition */\r
                     psEncC->sLP.transition_frame_no = 0;\r
+\r
+                    /* Reset transition filter state */\r
+                    SKP_memset( psEncC->sLP.In_LP_State, 0, sizeof( psEncC->sLP.In_LP_State ) );\r
                 } \r
-                if( psEncC->sLP.transition_frame_no >= TRANSITION_FRAMES ) {\r
-                    /* Stop transition phase */\r
-                    psEncC->sLP.mode = 0;\r
-                } else {\r
-                    /* Direction: up */\r
-                    psEncC->sLP.mode = 1;\r
-                }\r
+                /* Direction: up */\r
+                psEncC->sLP.mode = 1;\r
             }\r
         }\r
     }\r
index 00b4cc5..79ee49d 100644 (file)
@@ -60,18 +60,20 @@ SKP_INLINE SKP_int SKP_Silk_setup_LBRR(
 SKP_int SKP_Silk_control_encoder( \r
     SKP_Silk_encoder_state_Fxx      *psEnc,             /* I/O  Pointer to Silk encoder state           */\r
     SKP_SILK_SDK_EncControlStruct   *encControl,        /* I:   Control structure                       */\r
-    const SKP_int32                 TargetRate_bps      /* I    Target max bitrate (bps)                */\r
+    const SKP_int32                 TargetRate_bps,      /* I    Target max bitrate (bps)                */\r
+    const SKP_int                   allow_bw_switch     /* I    Flag to allow switching audio bandwidth */\r
 )\r
 {\r
     SKP_int   fs_kHz, ret = 0;\r
 \r
-    psEnc->sCmn.useDTX                = encControl->useDTX;\r
-    psEnc->sCmn.useCBR                = encControl->useCBR;\r
-    psEnc->sCmn.API_fs_Hz             = encControl->API_sampleRate;\r
-    psEnc->sCmn.maxInternal_fs_Hz     = encControl->maxInternalSampleRate;\r
-    psEnc->sCmn.minInternal_fs_Hz     = encControl->minInternalSampleRate;\r
-    psEnc->sCmn.desiredInternal_fs_Hz = encControl->desiredInternalSampleRate;\r
-    psEnc->sCmn.useInBandFEC          = encControl->useInBandFEC;\r
+    psEnc->sCmn.useDTX                 = encControl->useDTX;\r
+    psEnc->sCmn.useCBR                 = encControl->useCBR;\r
+    psEnc->sCmn.API_fs_Hz              = encControl->API_sampleRate;\r
+    psEnc->sCmn.maxInternal_fs_Hz      = encControl->maxInternalSampleRate;\r
+    psEnc->sCmn.minInternal_fs_Hz      = encControl->minInternalSampleRate;\r
+    psEnc->sCmn.desiredInternal_fs_Hz  = encControl->desiredInternalSampleRate;\r
+    psEnc->sCmn.useInBandFEC           = encControl->useInBandFEC;\r
+    psEnc->sCmn.allow_bandwidth_switch = allow_bw_switch;\r
 \r
     if( psEnc->sCmn.controlled_since_last_payload != 0 && psEnc->sCmn.prefillFlag == 0 ) {\r
         if( psEnc->sCmn.API_fs_Hz != psEnc->sCmn.prev_API_fs_Hz && psEnc->sCmn.fs_kHz > 0 ) {\r
index b2619a8..417253b 100644 (file)
@@ -31,6 +31,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "SKP_Silk_control.h"\r
 #include "SKP_Silk_typedef.h"\r
 #include "SKP_Silk_structs.h"\r
+#include "SKP_Silk_tuning_parameters.h"\r
 #if FIXED_POINT\r
 #include "SKP_Silk_main_FIX.h"\r
 #define SKP_Silk_encoder_state_Fxx      SKP_Silk_encoder_state_FIX\r
@@ -47,6 +48,8 @@ typedef struct {
     stereo_state                        sStereo;\r
     SKP_int32                           nBitsExceeded;\r
     SKP_int                             nChannels;\r
+    SKP_int                             timeSinceSwitchAllowed_ms;\r
+    SKP_int                             allowBandwidthSwitch;\r
 } SKP_Silk_encoder;\r
 \r
 /****************************************/\r
@@ -138,6 +141,7 @@ SKP_int SKP_Silk_SDK_Encode(
 {\r
     SKP_int   n, i, nBits, flags, tmp_payloadSize_ms, tmp_complexity, MS_predictorIx = 0, ret = 0;\r
     SKP_int   nSamplesToBuffer, nBlocksOf10ms, nSamplesFromInput = 0;\r
+    SKP_int   speech_act_thr_for_switch_Q8;\r
     SKP_int32 TargetRate_bps, channelRate_bps, LBRR_symbol;\r
     SKP_Silk_encoder *psEnc = ( SKP_Silk_encoder * )encState;\r
     SKP_int16 buf[ MAX_FRAME_LENGTH_MS * MAX_API_FS_KHZ ];\r
@@ -194,7 +198,7 @@ SKP_int SKP_Silk_SDK_Encode(
 \r
     TargetRate_bps = SKP_RSHIFT32( encControl->bitRate, encControl->nChannels - 1 );\r
     for( n = 0; n < encControl->nChannels; n++ ) {\r
-        if( ( ret = SKP_Silk_control_encoder( &psEnc->state_Fxx[ n ], encControl, TargetRate_bps ) ) != 0 ) {\r
+        if( ( ret = SKP_Silk_control_encoder( &psEnc->state_Fxx[ n ], encControl, TargetRate_bps, psEnc->allowBandwidthSwitch ) ) != 0 ) {\r
             SKP_assert( 0 );\r
             return ret;\r
         }\r
@@ -232,6 +236,9 @@ SKP_int SKP_Silk_SDK_Encode(
         samplesIn  += nSamplesFromInput * encControl->nChannels;\r
         nSamplesIn -= nSamplesFromInput;\r
 \r
+        /* Default */\r
+        psEnc->allowBandwidthSwitch = 0;\r
+\r
         /* Silk encoder */\r
         if( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx >= psEnc->state_Fxx[ 0 ].sCmn.frame_length ) {\r
             /* Enough data in input buffer, so encode */\r
@@ -340,6 +347,17 @@ SKP_int SKP_Silk_SDK_Encode(
                 psEnc->nBitsExceeded += *nBytesOut * 8;\r
                 psEnc->nBitsExceeded -= SKP_DIV32_16( SKP_MUL( encControl->bitRate, encControl->payloadSize_ms ), 1000 );\r
                 psEnc->nBitsExceeded  = SKP_LIMIT( psEnc->nBitsExceeded, 0, 10000 );\r
+\r
+                /* Update flag indicating if bandwidth switching is allowed */\r
+                speech_act_thr_for_switch_Q8 = SKP_SMLAWB( SKP_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ), \r
+                    SKP_FIX_CONST( ( 1 - SPEECH_ACTIVITY_DTX_THRES ) / MAX_BANDWIDTH_SWITCH_DELAY_MS, 16 + 8 ), psEnc->timeSinceSwitchAllowed_ms );\r
+                if( psEnc->state_Fxx[ 0 ].sCmn.speech_activity_Q8 < speech_act_thr_for_switch_Q8 ) {\r
+                    psEnc->allowBandwidthSwitch = 1;\r
+                    psEnc->timeSinceSwitchAllowed_ms = 0;\r
+                } else {\r
+                    psEnc->allowBandwidthSwitch = 0;\r
+                    psEnc->timeSinceSwitchAllowed_ms += encControl->payloadSize_ms;\r
+                }\r
             }\r
 \r
             if( nSamplesIn == 0 ) {\r
@@ -350,6 +368,8 @@ SKP_int SKP_Silk_SDK_Encode(
         }\r
     }\r
 \r
+    encControl->allowBandwidthSwitch = psEnc->allowBandwidthSwitch;\r
+    encControl->inWBmodeWithoutVariableLP = ( psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == 16 ) && ( psEnc->state_Fxx[ 0 ].sCmn.sLP.mode == 0 );\r
     encControl->internalSampleRate = SKP_SMULBB( psEnc->state_Fxx[ 0 ].sCmn.fs_kHz, 1000 );\r
     if( prefillFlag ) {\r
         encControl->payloadSize_ms = tmp_payloadSize_ms;\r
index a3b1519..fbd618d 100644 (file)
@@ -128,6 +128,7 @@ typedef struct {
     SKP_Silk_nsq_state              sNSQ;                           /* Noise Shape Quantizer State                                          */\r
     SKP_int16                       prev_NLSFq_Q15[ MAX_LPC_ORDER ];/* Previously quantized NLSF vector                                     */\r
     SKP_int                         speech_activity_Q8;             /* Speech activity                                                      */\r
+    SKP_int                         allow_bandwidth_switch;         /* Flag indicating that switching of internal bandwidth is allowed      */\r
     SKP_int8                        LBRRprevLastGainIndex;\r
     SKP_int8                        prevSignalType;\r
     SKP_int                         prevLag;\r
index c5d8d41..e85336d 100644 (file)
@@ -159,6 +159,9 @@ extern "C"
 /* Compensation in bitrate calculations for 10 ms modes */\r
 #define REDUCE_BITRATE_10_MS_BPS                        2200\r
 \r
+/* Maximum time before allowing a bandwidth transition */\r
+#define MAX_BANDWIDTH_SWITCH_DELAY_MS                   5000\r
+\r
 #ifdef __cplusplus\r
 }\r
 #endif\r