Improved (I think) quality in presence of packet loss...
authorjmvalin <jmvalin@0101bb08-14d6-0310-b084-bc0e0c8e3800>
Fri, 21 Jun 2002 19:38:12 +0000 (19:38 +0000)
committerjmvalin <jmvalin@0101bb08-14d6-0310-b084-bc0e0c8e3800>
Fri, 21 Jun 2002 19:38:12 +0000 (19:38 +0000)
git-svn-id: http://svn.xiph.org/trunk/speex@3402 0101bb08-14d6-0310-b084-bc0e0c8e3800

libspeex/ltp.c
libspeex/nb_celp.c
libspeex/nb_celp.h
libspeex/speex_header.h
src/speexdec.c

index 48dd829..c2ca0a9 100644 (file)
@@ -442,13 +442,18 @@ int lost)
    gain[2] = gain_cdbk[gain_index*12+2];
    if (lost)
    {
-      float gain_sum = gain[0]+gain[1]+gain[2];
-      if (gain_sum>.8)
+      float gain_sum;
+      /*Put everything in one tap*/
+      gain[1]+=gain[0]+gain[2];
+      gain[0]=gain[2]=0;
+      gain_sum = fabs(gain[0])+fabs(gain[1])+fabs(gain[2]);
+      if (gain_sum>.85)
       {
-         float fact = .8/gain_sum;
+         float fact = .85/gain_sum;
          for (i=0;i<3;i++)
             gain[i]*=fact;
       }
+      /*gain[1]=.8;*/
    }
 
    *pitch_val = pitch;
index 6e47719..2ff8f71 100644 (file)
@@ -679,7 +679,8 @@ void *nb_decoder_init(SpeexMode *m)
    st->mem_pf2 = calloc(st->lpcSize, sizeof(float));
 
    st->pi_gain = calloc(st->nbSubframes, sizeof(float));
-   
+   st->last_pitch = 40;
+   st->count_lost=0;
    return st;
 }
 
@@ -711,6 +712,8 @@ void nb_decode(void *state, SpeexBits *bits, float *out, int lost)
    float pitch_gain[3];
    float ol_gain;
    int ol_pitch=0;
+   int best_pitch=40;
+   float best_pitch_gain=-1;
    st=state;
 
    memmove(st->inBuf, st->inBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float));
@@ -719,7 +722,7 @@ void nb_decode(void *state, SpeexBits *bits, float *out, int lost)
 
 
    st->lsp_unquant(st->qlsp, st->lpcSize, bits);
-   if (st->first)
+   if (st->first || st->count_lost)
    {
       for (i=0;i<st->lpcSize;i++)
          st->old_qlsp[i] = st->qlsp[i];
@@ -757,6 +760,7 @@ void nb_decode(void *state, SpeexBits *bits, float *out, int lost)
 
       lsp_enforce_margin(st->interp_qlsp, st->lpcSize, .002);
 
+
       /* Compute interpolated LPCs (unquantized) */
       for (i=0;i<st->lpcSize;i++)
          st->interp_qlsp[i] = cos(st->interp_qlsp[i]);
@@ -783,11 +787,34 @@ void nb_decode(void *state, SpeexBits *bits, float *out, int lost)
             ol_pitch=st->min_pitch+7;
          pit_min = ol_pitch-7;
          pit_max = ol_pitch+8;
-         st->ltp_unquant(exc, pit_min, pit_max, st->ltp_params, st->subframeSize, &pitch, &pitch_gain[0], bits, st->stack, lost);
-      } else
-         st->ltp_unquant(exc, st->min_pitch, st->max_pitch, st->ltp_params, st->subframeSize, &pitch, &pitch_gain[0], bits, st->stack, lost);
-      
+         st->ltp_unquant(exc, pit_min, pit_max, st->ltp_params, st->subframeSize, &pitch, &pitch_gain[0], bits, st->stack, 0);
+      } else {
+         st->ltp_unquant(exc, st->min_pitch, st->max_pitch, st->ltp_params, st->subframeSize, &pitch, &pitch_gain[0], bits, st->stack, 0);
+      }
 
+      if (!lost)
+      {
+         tmp = fabs(pitch_gain[0])+fabs(pitch_gain[1])+fabs(pitch_gain[2]);
+         tmp = fabs(pitch_gain[0]+pitch_gain[1]+pitch_gain[2]);
+         if (tmp>best_pitch_gain)
+         {
+            best_pitch = pitch;
+            while (best_pitch+pitch<st->max_pitch)
+            {
+               best_pitch+=pitch;
+            }
+            best_pitch_gain = tmp*.9;
+            if (best_pitch_gain>.85)
+               best_pitch_gain=.85;
+         }
+      } else {
+         for (i=0;i<st->subframeSize;i++)
+            exc[i]=0;
+         /*printf ("best_pitch: %d %f\n", st->last_pitch, st->last_pitch_gain);*/
+         for (i=0;i<st->subframeSize;i++)
+            exc[i]=st->last_pitch_gain*exc[i-st->last_pitch];
+      }
+         
       {
          int q_energy;
          float ener;
@@ -808,6 +835,9 @@ void nb_decode(void *state, SpeexBits *bits, float *out, int lost)
          /*Fixed codebook contribution*/
          st->innovation_unquant(innov, st->innovation_params, st->subframeSize, bits, st->stack);
 
+         if (st->count_lost)
+            ener*=pow(.8,st->count_lost);
+
          for (i=0;i<st->subframeSize;i++)
             exc[i]+=ener*innov[i];
 
@@ -852,7 +882,15 @@ void nb_decode(void *state, SpeexBits *bits, float *out, int lost)
 
    /* The next frame will not be the first (Duh!) */
    st->first = 0;
-
+   if (!lost)
+      st->count_lost=0;
+   else
+      st->count_lost++;
+   if (!lost)
+   {
+      st->last_pitch = best_pitch;
+      st->last_pitch_gain = best_pitch_gain;
+   }
 }
 
 void nb_encoder_ctl(void *state, int request, void *ptr)
index fa63f0a..13ec2ea 100644 (file)
@@ -86,6 +86,7 @@ typedef struct EncState {
 typedef struct DecState {
    SpeexMode *mode;
    int    first;          /* Is this the first frame? */
+   int    count_lost;     /* Was the last frame lost? */
    int    frameSize;      /* Size of frames */
    int    subframeSize;   /* Size of sub-frames */
    int    nbSubframes;    /* Number of sub-frames */
@@ -114,6 +115,8 @@ typedef struct DecState {
    float *mem_pf;
    float *mem_pf2;
    float *pi_gain;
+   int    last_pitch;
+   float  last_pitch_gain;
 
    lsp_unquant_func  lsp_unquant;
    ltp_unquant_func  ltp_unquant;
index 4afcbff..a71fc5e 100644 (file)
 #ifndef SPEEX_HEADER_H
 #define SPEEX_HEADER_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 struct SpeexMode;
 #define SPEEX_HEADER_VERSION_LENGTH 20
 
@@ -51,4 +55,9 @@ char *speex_header_to_packet(SpeexHeader *header, int *size);
 
 SpeexHeader *speex_packet_to_header(char *packet, int size);
 
+#ifdef __cplusplus
+}
+#endif
+
+
 #endif
index bacc1b1..223b1eb 100644 (file)
@@ -289,11 +289,28 @@ int main(int argc, char **argv)
                /*End of stream condition*/
                if (strncmp((char *)op.packet, "END OF STREAM", 13)==0)
                   break;
-               /*Copy Ogg packet to Speex bitstream*/
-               speex_bits_read_from(&bits, (char*)op.packet, op.bytes);
-               /*Decode a frame*/
-               speex_decode(st, &bits, output, 0);
-               
+
+               /* Put 0 here only to simulate packet loss */
+               if (1)
+               {
+                  /*Copy Ogg packet to Speex bitstream*/
+                  speex_bits_read_from(&bits, (char*)op.packet, op.bytes);
+                  /*Decode a frame*/
+                  speex_decode(st, &bits, output, 0);
+               } else {
+                  static int first=1;
+                  if ((((float)rand())/RAND_MAX < .1) && !first)
+                  {
+                     printf ("PACKET LOSS\n");
+                     speex_bits_rewind(&bits);
+                     speex_decode(st, &bits, output, 1);
+                  } else {
+                     printf ("PACKET OK\n");
+                     speex_bits_read_from(&bits, (char*)op.packet, op.bytes);
+                     speex_decode(st, &bits, output, 0);
+                  }
+                  first=0;
+               }
                /*PCM saturation (just in case)*/
                for (i=0;i<frame_size;i++)
                {