diff libtwamr/dtx_enc.c @ 407:5a1d18542f8a

libtwamr: integrate dtx_dec.c and dtx_enc.c
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 07 May 2024 00:05:12 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libtwamr/dtx_enc.c	Tue May 07 00:05:12 2024 +0000
@@ -0,0 +1,308 @@
+/*
+********************************************************************************
+*
+*      GSM AMR-NB speech codec   R98   Version 7.6.0   December 12, 2001
+*                                R99   Version 3.3.0                
+*                                REL-4 Version 4.1.0                
+*
+********************************************************************************
+*
+*      File             : dtx_enc.c
+*      Purpose          : DTX mode computation of SID parameters
+*
+********************************************************************************
+*/
+
+/*
+********************************************************************************
+*                         MODULE INCLUDE FILE AND VERSION ID
+********************************************************************************
+*/
+#include "namespace.h"
+#include "dtx_enc.h"
+ 
+/*
+********************************************************************************
+*                         INCLUDE FILES
+********************************************************************************
+*/
+#include "tw_amr.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "q_plsf.h"
+#include "memops.h"
+#include "log2.h"
+#include "lsp_lsf.h"
+#include "reorder.h"
+#include "no_count.h"
+#include "lsp_tab.h"
+
+/*
+********************************************************************************
+*                         PUBLIC PROGRAM CODE
+********************************************************************************
+*/
+ 
+/*
+**************************************************************************
+*
+*  Function    : dtx_enc_reset
+*
+**************************************************************************
+*/
+void dtx_enc_reset (dtx_encState *st)
+{
+  Word16 i;
+
+  st->hist_ptr = 0;
+  st->log_en_index = 0;
+  st->init_lsf_vq_index = 0;
+  st->lsp_index[0] = 0;
+  st->lsp_index[1] = 0;
+  st->lsp_index[2] = 0;
+ 
+  /* Init lsp_hist[] */
+  for(i = 0; i < DTX_HIST_SIZE; i++)
+  {
+    Copy(lsp_init_data, &st->lsp_hist[i * M], M);
+  }
+
+  /* Reset energy history */
+  Set_zero(st->log_en_hist, M);
+
+  st->dtxHangoverCount = DTX_HANG_CONST;
+  st->decAnaElapsedCount = 32767; 
+}
+ 
+/*
+**************************************************************************
+*
+*  Function    : dtx_enc
+*                
+**************************************************************************
+*/
+int dtx_enc(dtx_encState *st,        /* i/o : State struct                    */
+            Word16 computeSidFlag,   /* i   : compute SID                     */
+            Q_plsfState *qSt,        /* i/o : Qunatizer state struct          */
+            gc_predState* predState, /* i/o : State struct                    */
+	    Word16 **anap            /* o   : analysis parameters             */
+	    )
+{
+   Word16 i,j;
+   Word16 log_en;
+   Word16 lsf[M];
+   Word16 lsp[M];
+   Word16 lsp_q[M];
+   Word32 L_lsp[M];
+
+   /* VOX mode computation of SID parameters */
+   test (); test ();
+   if ((computeSidFlag != 0))
+   {
+      /* compute new SID frame if safe i.e don't
+       * compute immediately after a talk spurt  */
+      log_en = 0;                                           move16 ();
+      for (i = 0; i < M; i++)
+      {
+         L_lsp[i] = 0;                                      move16 ();
+      }
+      
+      /* average energy and lsp */
+      for (i = 0; i < DTX_HIST_SIZE; i++)
+      {
+         log_en = add(log_en,
+                      shr(st->log_en_hist[i],2));
+
+         for (j = 0; j < M; j++)
+         {
+            L_lsp[j] = L_add(L_lsp[j],
+                             L_deposit_l(st->lsp_hist[i * M + j]));
+         }
+      }
+
+      log_en = shr(log_en, 1);
+      for (j = 0; j < M; j++)
+      {
+         lsp[j] = extract_l(L_shr(L_lsp[j], 3));   /* divide by 8 */
+      }
+
+      /*  quantize logarithmic energy to 6 bits */
+      st->log_en_index = add(log_en, 2560);          /* +2.5 in Q10      */
+      st->log_en_index = add(st->log_en_index, 128); /* add 0.5/4 in Q10 */
+      st->log_en_index = shr(st->log_en_index, 8);
+
+      test ();
+      if (sub(st->log_en_index, 63) > 0)
+      {
+         st->log_en_index = 63;                             move16 ();
+      }
+      test ();
+      if (st->log_en_index < 0)
+      {
+         st->log_en_index = 0;                              move16 ();
+      }
+         
+      /* update gain predictor memory */
+      log_en = shl(st->log_en_index, -2+10); /* Q11 and divide by 4 */
+      log_en = sub(log_en, 2560);            /* add 2.5 in Q11      */
+      
+      log_en = sub(log_en, 9000);
+      test ();
+      if (log_en > 0)
+      {
+         log_en = 0;                                        move16 ();
+      }
+      test ();
+      if (sub(log_en, -14436) < 0)
+      {
+         log_en = -14436;                                   move16 ();
+      }
+      
+      /* past_qua_en for other modes than MR122 */      
+      predState->past_qua_en[0] = log_en;                   move16 ();
+      predState->past_qua_en[1] = log_en;                   move16 ();
+      predState->past_qua_en[2] = log_en;                   move16 ();
+      predState->past_qua_en[3] = log_en;                   move16 ();
+
+      /* scale down by factor 20*log10(2) in Q15 */
+      log_en = mult(5443, log_en);
+      
+      /* past_qua_en for mode MR122 */      
+      predState->past_qua_en_MR122[0] = log_en;             move16 ();
+      predState->past_qua_en_MR122[1] = log_en;             move16 ();
+      predState->past_qua_en_MR122[2] = log_en;             move16 ();
+      predState->past_qua_en_MR122[3] = log_en;             move16 ();
+ 
+      /* make sure that LSP's are ordered */
+      Lsp_lsf(lsp, lsf, M);
+      Reorder_lsf(lsf, LSF_GAP, M);
+      Lsf_lsp(lsf, lsp, M);
+      
+      /* Quantize lsp and put on parameter list */
+      Q_plsf_3(qSt, MRDTX, lsp, lsp_q, st->lsp_index, 
+               &st->init_lsf_vq_index);
+   }
+   
+   *(*anap)++ = st->init_lsf_vq_index; /* 3 bits */         move16 ();
+   
+   *(*anap)++ = st->lsp_index[0];      /* 8 bits */         move16 ();
+   *(*anap)++ = st->lsp_index[1];      /* 9 bits */         move16 ();
+   *(*anap)++ = st->lsp_index[2];      /* 9 bits */         move16 ();
+   
+   
+   *(*anap)++ = st->log_en_index;      /* 6 bits    */      move16 ();
+                                       /* = 35 bits */
+   
+   return 0;
+}
+
+/*
+**************************************************************************
+*
+*  Function    : dtx_buffer
+*  Purpose     : handles the DTX buffer
+*                
+**************************************************************************
+*/
+int dtx_buffer(dtx_encState *st,   /* i/o : State struct                    */
+	       Word16 lsp_new[],   /* i   : LSP vector                      */
+	       Word16 speech[]     /* i   : speech samples                  */
+	       )
+{
+   Word16 i;
+   Word32 L_frame_en;
+   Word16 log_en_e;
+   Word16 log_en_m;
+   Word16 log_en;
+   
+   /* update pointer to circular buffer      */
+   st->hist_ptr = add(st->hist_ptr, 1);
+   test ();
+   if (sub(st->hist_ptr, DTX_HIST_SIZE) == 0)
+   {
+      st->hist_ptr = 0;                                     move16 ();
+   }
+   
+   /* copy lsp vector into buffer */
+   Copy(lsp_new, &st->lsp_hist[st->hist_ptr * M], M);
+   
+   /* compute log energy based on frame energy */
+   L_frame_en = 0;     /* Q0 */                             move32 ();
+   for (i=0; i < L_FRAME; i++)
+   {
+      L_frame_en = L_mac(L_frame_en, speech[i], speech[i]); 
+   }
+   Log2(L_frame_en, &log_en_e, &log_en_m);
+   
+   /* convert exponent and mantissa to Word16 Q10 */
+   log_en = shl(log_en_e, 10);  /* Q10 */
+   log_en = add(log_en, shr(log_en_m, 15-10));
+   
+   /* divide with L_FRAME i.e subtract with log2(L_FRAME) = 7.32193 */
+   log_en = sub(log_en, 8521);
+   
+   /* insert into log energy buffer with division by 2 */
+   log_en = shr(log_en, 1);
+   st->log_en_hist[st->hist_ptr] = log_en; /* Q10 */        move16 ();
+
+   return 0;
+}
+
+/*
+**************************************************************************
+*
+*  Function    : tx_dtx_handler
+*  Purpose     : adds extra speech hangover to analyze speech on the decoding side. 
+*                
+**************************************************************************
+*/
+Word16 tx_dtx_handler(dtx_encState *st,      /* i/o : State struct           */
+                      Word16 vad_flag,       /* i   : vad decision           */
+                      enum Mode *usedMode    /* i/o : mode changed or not    */
+                      )
+{
+   Word16 compute_new_sid_possible;
+   
+   /* this state machine is in synch with the GSMEFR txDtx machine      */ 
+   st->decAnaElapsedCount = add(st->decAnaElapsedCount, 1);  
+   
+   compute_new_sid_possible = 0;                       move16(); 
+
+   test();
+   if (vad_flag != 0)
+   {
+      st->dtxHangoverCount = DTX_HANG_CONST;           move16();
+   }
+   else 
+   {  /* non-speech */
+      test();
+      if (st->dtxHangoverCount == 0)
+      {  /* out of decoder analysis hangover  */
+         st->decAnaElapsedCount = 0;                   move16();        
+         *usedMode = MRDTX;                            move16(); 
+         compute_new_sid_possible = 1;                 move16(); 
+      }
+      else
+      { /* in possible analysis hangover */
+         st->dtxHangoverCount = sub(st->dtxHangoverCount, 1);
+         
+         /* decAnaElapsedCount + dtxHangoverCount < DTX_ELAPSED_FRAMES_THRESH */
+         test ();
+         if (sub(add(st->decAnaElapsedCount, st->dtxHangoverCount),
+                 DTX_ELAPSED_FRAMES_THRESH) < 0)
+         {
+            *usedMode = MRDTX;                         move16(); 
+            /* if short time since decoder update, do not add extra HO */            
+         }
+         /*
+          else 
+            override VAD and stay in 
+            speech mode *usedMode 
+            and add extra hangover
+         */
+      }
+   }
+   
+   return compute_new_sid_possible;
+}