Implemented VAD-only mode with comfort noise generation, did some tuning to
authorjm <jm@0101bb08-14d6-0310-b084-bc0e0c8e3800>
Thu, 12 Dec 2002 07:51:35 +0000 (07:51 +0000)
committerjm <jm@0101bb08-14d6-0310-b084-bc0e0c8e3800>
Thu, 12 Dec 2002 07:51:35 +0000 (07:51 +0000)
the VAD too. Next thing: adapt VAD-only to work with wideband too.

git-svn-id: http://svn.xiph.org/trunk/speex@4146 0101bb08-14d6-0310-b084-bc0e0c8e3800

TODO
libspeex/nb_celp.c
libspeex/nb_celp.h
libspeex/speex.h
libspeex/vbr.c
src/speexenc.c

diff --git a/TODO b/TODO
index 71a1184..db405c1 100644 (file)
--- a/TODO
+++ b/TODO
@@ -2,14 +2,13 @@ Features
 *Average bit-rate VBR
 -Add maximum/minimum bit-rate control for VBR
 *Add "VAD-only" VBR (constant bit-rate or comfort noise)
-*Add encoder/decoder reset function
 -Get the encoder to use the rate of packet loss (more conservative pitch gains)
-*No transmission when constant noise/silence
+-No transmission when constant noise/silence
 
-Codec
-*Improve perceptual enhancement (including wideband)
--Improve VAD
--Improve narrowband vocoder
+Long-term quality improvements
+-Improve perceptual enhancement (including wideband)
+-Improve VAD and VBR
+-Packet-loss concealment
 
 Standards
 *Complete Speex RTP profile
@@ -17,3 +16,9 @@ Standards
 -MS ACM wrapper
 
 *required for 1.0
+
+ideas:
+peelable stream (double codebook, higher bands, stereo)
+DTX in Ogg? (painful)
+LPC from spectral domain
+Masking curve from Vorbis
index be0d921..e991386 100644 (file)
@@ -93,7 +93,7 @@ void *nb_encoder_init(SpeexMode *m)
    st->preemph = mode->preemph;
   
    st->submodes=mode->submodes;
-   st->submodeID=mode->defaultSubmode;
+   st->submodeID=st->submodeSelect=mode->defaultSubmode;
    st->pre_mem=0;
    st->pre_mem2=0;
    st->bounded_pitch = 1;
@@ -162,14 +162,12 @@ void *nb_encoder_init(SpeexMode *m)
 
    st->pitch = (int*)speex_alloc(st->nbSubframes*sizeof(int));
 
-   if (1) {
-      st->vbr = (VBRState*)speex_alloc(sizeof(VBRState));
-      vbr_init(st->vbr);
-      st->vbr_quality = 8;
-      st->vbr_enabled = 0;
-   } else {
-      st->vbr = 0;
-   }
+   st->vbr = (VBRState*)speex_alloc(sizeof(VBRState));
+   vbr_init(st->vbr);
+   st->vbr_quality = 8;
+   st->vbr_enabled = 0;
+   st->vad_enabled = 0;
+
    st->complexity=2;
    st->sampling_rate=8000;
 
@@ -320,7 +318,7 @@ void nb_encode(void *state, float *in, SpeexBits *bits)
 
 
       /*Open-loop pitch*/
-      if (!st->submodes[st->submodeID] || st->vbr_enabled || SUBMODE(forced_pitch_gain) ||
+      if (!st->submodes[st->submodeID] || st->vbr_enabled || st->vad_enabled || SUBMODE(forced_pitch_gain) ||
           SUBMODE(lbr_pitch) != -1)
       {
          int nol_pitch[6];
@@ -369,8 +367,8 @@ void nb_encode(void *state, float *in, SpeexBits *bits)
       ol_gain=sqrt(1+ol_gain/st->frameSize);
    }
 
-   /*Experimental VBR stuff*/
-   if (st->vbr)
+   /*VBR stuff*/
+   if (st->vbr && (st->vbr_enabled||st->vad_enabled))
    {
       st->relative_quality = vbr_analysis(st->vbr, in, st->frameSize, ol_pitch, ol_pitch_coef);
       /*if (delta_qual<0)*/
@@ -399,8 +397,17 @@ void nb_encode(void *state, float *in, SpeexBits *bits)
          speex_encoder_ctl(state, SPEEX_SET_MODE, &mode);
          /*fprintf(stderr, "encode: %d %d\n",st->submodeID, mode);*/
       } else {
-         st->relative_quality = -1;
-      }
+         /*VAD only case*/
+         int mode;
+         if (st->relative_quality<2.0)
+            mode=0;
+         else
+            mode=st->submodeSelect;
+         /*speex_encoder_ctl(state, SPEEX_SET_MODE, &mode);*/
+         st->submodeID=mode;
+      } 
+   } else {
+      st->relative_quality = -1;
    }
    /*printf ("VBR quality = %f\n", vbr_qual);*/
 
@@ -1405,7 +1412,7 @@ void nb_encoder_ctl(void *state, int request, void *ptr)
       break;
    case SPEEX_SET_LOW_MODE:
    case SPEEX_SET_MODE:
-      st->submodeID = (*(int*)ptr);
+      st->submodeSelect = st->submodeID = (*(int*)ptr);
       break;
    case SPEEX_GET_LOW_MODE:
    case SPEEX_GET_MODE:
@@ -1417,6 +1424,12 @@ void nb_encoder_ctl(void *state, int request, void *ptr)
    case SPEEX_GET_VBR:
       (*(int*)ptr) = st->vbr_enabled;
       break;
+   case SPEEX_SET_VAD:
+      st->vad_enabled = (*(int*)ptr);
+      break;
+   case SPEEX_GET_VAD:
+      (*(int*)ptr) = st->vad_enabled;
+      break;
    case SPEEX_SET_VBR_QUALITY:
       st->vbr_quality = (*(float*)ptr);
       break;
@@ -1430,7 +1443,7 @@ void nb_encoder_ctl(void *state, int request, void *ptr)
             quality = 0;
          if (quality > 10)
             quality = 10;
-         st->submodeID = ((SpeexNBMode*)(st->mode->mode))->quality_map[quality];
+         st->submodeSelect = st->submodeID = ((SpeexNBMode*)(st->mode->mode))->quality_map[quality];
       }
       break;
    case SPEEX_SET_COMPLEXITY:
index e9d74db..0605c95 100644 (file)
@@ -102,11 +102,13 @@ typedef struct EncState {
    float  vbr_quality;    /**< Quality setting for VBR encoding */
    float  relative_quality; /**< Relative quality that will be needed by VBR */
    int    vbr_enabled;    /**< 1 for enabling VBR, 0 otherwise */
+   int    vad_enabled;    /**< 1 for enabling VAD, 0 otherwise */
    int    complexity;     /**< Complexity setting (0-10 from least complex to most complex) */
    int    sampling_rate;
 
    SpeexSubmode **submodes; /**< Sub-mode data */
    int    submodeID;      /**< Activated sub-mode */
+   int    submodeSelect;  /**< Mode chosen by the user (may differ from submodeID if VAD is on) */
 } EncState;
 
 /**Structure representing the full state of the narrowband decoder*/
index cd97448..032ab39 100644 (file)
@@ -104,7 +104,11 @@ extern "C" {
 
 #define SPEEX_RESET_STATE 26
 
-#define SPEEX_GET_RELATIVE_QUALITY 27
+#define SPEEX_GET_RELATIVE_QUALITY 29
+
+#define SPEEX_SET_VAD 30
+#define SPEEX_GET_VAD 31
+
 
    /* Used internally, not to be used in applications */
 #define SPEEX_GET_PI_GAIN 100
index 6c1da1a..a304f10 100644 (file)
@@ -41,7 +41,7 @@
 
 #define sqr(x) ((x)*(x))
 
-#define MIN_ENERGY 1000
+#define MIN_ENERGY 6000
 #define NOISE_POW .3
 
 
@@ -147,8 +147,13 @@ float vbr_analysis(VBRState *vbr, float *sig, int len, int pitch, float pitch_co
    vbr->average_energy = (1-vbr->energy_alpha)*vbr->average_energy + vbr->energy_alpha*ener;
    vbr->noise_level=vbr->noise_accum/vbr->noise_accum_count;
    pow_ener = pow(ener,NOISE_POW);
+   if (vbr->noise_accum_count<.06 && ener>MIN_ENERGY)
+      vbr->noise_accum = .05*pow_ener;
+
    if ((voicing<.3 && non_st < .2 && pow_ener < 1.2*vbr->noise_level)
-       || (voicing<.2 && non_st < .1))
+       || (voicing<.3 && non_st < .05 && pow_ener < 1.5*vbr->noise_level)
+       || (voicing<.4 && non_st < .05 && pow_ener < 1.2*vbr->noise_level)
+       || (voicing<0 && non_st < .05))
    {
       float tmp;
       va = 0;
@@ -167,6 +172,12 @@ float vbr_analysis(VBRState *vbr, float *sig, int len, int pitch, float pitch_co
       vbr->consec_noise=0;
    }
 
+   if (pow_ener < vbr->noise_level && ener>MIN_ENERGY)
+   {
+      vbr->noise_accum = .95*vbr->noise_accum + .05*pow_ener;
+      vbr->noise_accum_count = .95*vbr->noise_accum_count + .05;      
+   }
+
    /* Checking for very low absolute energy */
    if (ener < 30000)
    {
@@ -219,17 +230,20 @@ float vbr_analysis(VBRState *vbr, float *sig, int len, int pitch, float pitch_co
    if (vbr->consec_noise>=12)
       qual-=1.3;
    */
+   if (vbr->consec_noise>=3)
+      qual=4;
+
    if (vbr->consec_noise)
-      qual-=.8*log(2.0 + vbr->consec_noise);
+      qual -= 1.0 * (log(3.0 + vbr->consec_noise)-log(3));
    if (qual<0)
       qual=0;
    
    if (ener<60000)
    {
-      if (vbr->consec_noise)
-         qual-=0.8*log(2.0 + vbr->consec_noise);
-      if (ener<10000&&vbr->consec_noise)
-         qual-=0.8*log(2.0 + vbr->consec_noise);
+      if (vbr->consec_noise>2)
+         qual-=0.5*(log(3.0 + vbr->consec_noise)-log(3));
+      if (ener<10000&&vbr->consec_noise>2)
+         qual-=0.5*(log(3.0 + vbr->consec_noise)-log(3));
       if (qual<0)
          qual=0;
       qual += .3*log(ener/60000.0);
@@ -237,6 +251,8 @@ float vbr_analysis(VBRState *vbr, float *sig, int len, int pitch, float pitch_co
    if (qual<-1)
       qual=-1;
 
+   /*printf ("%f %f %f %f %d\n", qual, voicing, non_st, pow_ener/(.01+vbr->noise_level), va);*/
+
    vbr->last_pitch_coef = pitch_coef;
    vbr->last_quality = qual;
 
index 3d0a7fa..042743c 100644 (file)
@@ -144,6 +144,7 @@ void usage()
    printf (" --quality n        Encoding quality (0-10), default 3\n"); 
    printf (" --bitrate n        Encoding bit-rate (use bit-rate n or lower)\n"); 
    printf (" --vbr              Enable variable bit-rate (VBR)\n"); 
+   printf (" --vad              Enable voice activity detection (VAD)\n"); 
    printf (" --comp n           Set encoding complexity (0-10), default 3\n"); 
    printf (" --nframes n        Number of frames per Ogg packet (1-10), default 1\n"); 
    printf (" --comment          Add the given string as an extra comment. This may be\n");
@@ -177,6 +178,7 @@ int main(int argc, char **argv)
    float input[MAX_FRAME_SIZE];
    int frame_size;
    int vbr_enabled=0;
+   int vad_enabled=0;
    int nbBytes;
    SpeexMode *mode=NULL;
    void *st;
@@ -188,6 +190,7 @@ int main(int argc, char **argv)
       {"ultra-wideband", no_argument, NULL, 0},
       {"narrowband", no_argument, NULL, 0},
       {"vbr", no_argument, NULL, 0},
+      {"vad", no_argument, NULL, 0},
       {"quality", required_argument, NULL, 0},
       {"bitrate", required_argument, NULL, 0},
       {"nframes", required_argument, NULL, 0},
@@ -253,6 +256,9 @@ int main(int argc, char **argv)
          } else if (strcmp(long_options[option_index].name,"vbr")==0)
          {
             vbr_enabled=1;
+         } else if (strcmp(long_options[option_index].name,"vad")==0)
+         {
+            vad_enabled=1;
          } else if (strcmp(long_options[option_index].name,"quality")==0)
          {
             quality = atoi (optarg);
@@ -534,6 +540,12 @@ int main(int argc, char **argv)
       tmp=1;
       speex_encoder_ctl(st, SPEEX_SET_VBR, &tmp);
    }
+   if (vad_enabled)
+   {
+      int tmp;
+      tmp=1;
+      speex_encoder_ctl(st, SPEEX_SET_VAD, &tmp);
+   }
    if (quality >= 0)
    {
       if (vbr_enabled)