⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sb_celp.c

📁 这是著名的TCPMP播放器在WINDWOWS,和WINCE下编译通过的源程序.笔者对其中的LIBMAD库做了针对ARM MPU的优化. 并增加了词幕功能.
💻 C
📖 第 1 页 / 共 4 页
字号:
   mode = (const SpeexSBMode*)(st->mode->mode);

   {
      VARDECL(spx_word16_t *low);
      ALLOC(low, st->frame_size, spx_word16_t);

      /* Compute the two sub-bands by filtering with h0 and h1*/
      qmf_decomp(in, h0, st->x0d, st->x1d, st->full_frame_size, QMF_ORDER, st->h0_mem, stack);
      
      for (i=0;i<st->frame_size;i++)
         low[i] = SATURATE(PSHR(st->x0d[i],SIG_SHIFT),32767);
      
      /* Encode the narrowband part*/
      speex_encode_native(st->st_low, low, bits);

      for (i=0;i<st->frame_size;i++)
         st->x0d[i] = SHL(low[i],SIG_SHIFT);
   }
   /* High-band buffering / sync with low band */
   for (i=0;i<st->windowSize-st->frame_size;i++)
      st->high[i] = st->high[st->frame_size+i];
   for (i=0;i<st->frame_size;i++)
      st->high[st->windowSize-st->frame_size+i]=SATURATE(st->x1d[i],536854528);

   speex_move(st->excBuf, st->excBuf+st->frame_size, (st->bufSize-st->frame_size)*sizeof(spx_sig_t));


   ALLOC(low_pi_gain, st->nbSubframes, spx_word32_t);
   ALLOC(low_exc, st->frame_size, spx_sig_t);
   ALLOC(low_innov, st->frame_size, spx_sig_t);
   speex_encoder_ctl(st->st_low, SPEEX_GET_PI_GAIN, low_pi_gain);
   speex_encoder_ctl(st->st_low, SPEEX_GET_EXC, low_exc);
   speex_encoder_ctl(st->st_low, SPEEX_GET_INNOV, low_innov);
   
   speex_encoder_ctl(st->st_low, SPEEX_GET_LOW_MODE, &dtx);

   if (dtx==0)
      dtx=1;
   else
      dtx=0;

   {
      VARDECL(spx_word16_t *w_sig);
      ALLOC(w_sig, st->windowSize, spx_word16_t);
      /* Window for analysis */
      for (i=0;i<st->windowSize;i++)
         w_sig[i] = SHR(MULT16_16(SHR((spx_word32_t)(st->high[i]),SIG_SHIFT),st->window[i]),SIG_SHIFT);

      /* Compute auto-correlation */
      _spx_autocorr(w_sig, st->autocorr, st->lpcSize+1, st->windowSize);
   }

   st->autocorr[0] = (spx_word16_t)(st->autocorr[0]*st->lpc_floor); /* Noise floor in auto-correlation domain */

   /* Lag windowing: equivalent to filtering in the power-spectrum domain */
   for (i=0;i<st->lpcSize+1;i++)
      st->autocorr[i] = MULT16_16_Q14(st->autocorr[i],st->lagWindow[i]);

   /* Levinson-Durbin */
   _spx_lpc(st->lpc, st->autocorr, st->lpcSize);

   /* LPC to LSPs (x-domain) transform */
   roots=lpc_to_lsp (st->lpc, st->lpcSize, st->lsp, 15, LSP_DELTA1, stack);
   if (roots!=st->lpcSize)
   {
      roots = lpc_to_lsp (st->lpc, st->lpcSize, st->lsp, 11, LSP_DELTA2, stack);
      if (roots!=st->lpcSize) {
         /*If we can't find all LSP's, do some damage control and use a flat filter*/
         for (i=0;i<st->lpcSize;i++)
         {
            st->lsp[i]=M_PI*((float)(i+1))/(st->lpcSize+1);
         }
      }
   }

   /* VBR code */
   if ((st->vbr_enabled || st->vad_enabled) && !dtx)
   {
      float e_low=0, e_high=0;
      float ratio;
      if (st->abr_enabled)
      {
         float qual_change=0;
         if (st->abr_drift2 * st->abr_drift > 0)
         {
            /* Only adapt if long-term and short-term drift are the same sign */
            qual_change = -.00001*st->abr_drift/(1+st->abr_count);
            if (qual_change>.1)
               qual_change=.1;
            if (qual_change<-.1)
               qual_change=-.1;
         }
         st->vbr_quality += qual_change;
         if (st->vbr_quality>10)
            st->vbr_quality=10;
         if (st->vbr_quality<0)
            st->vbr_quality=0;
      }


      /*FIXME: Are the two signals (low, high) in sync? */
      e_low = compute_rms(st->x0d, st->frame_size);
      e_high = compute_rms(st->high, st->frame_size);
      ratio = 2*log((1+e_high)/(1+e_low));
      
      speex_encoder_ctl(st->st_low, SPEEX_GET_RELATIVE_QUALITY, &st->relative_quality);
      if (ratio<-4)
         ratio=-4;
      if (ratio>2)
         ratio=2;
      /*if (ratio>-2)*/
      if (st->vbr_enabled) 
      {
         int modeid;
         modeid = mode->nb_modes-1;
         st->relative_quality+=1.0*(ratio+2);
	 if (st->relative_quality<-1)
            st->relative_quality=-1;
         while (modeid)
         {
            int v1;
            float thresh;
            v1=(int)floor(st->vbr_quality);
            if (v1==10)
               thresh = mode->vbr_thresh[modeid][v1];
            else
               thresh = (st->vbr_quality-v1)   * mode->vbr_thresh[modeid][v1+1] + 
                        (1+v1-st->vbr_quality) * mode->vbr_thresh[modeid][v1];
            if (st->relative_quality >= thresh)
               break;
            modeid--;
         }
         speex_encoder_ctl(state, SPEEX_SET_HIGH_MODE, &modeid);
         if (st->abr_enabled)
         {
            int bitrate;
            speex_encoder_ctl(state, SPEEX_GET_BITRATE, &bitrate);
            st->abr_drift+=(bitrate-st->abr_enabled);
            st->abr_drift2 = .95*st->abr_drift2 + .05*(bitrate-st->abr_enabled);
            st->abr_count += 1.0;
         }

      } else {
         /* VAD only */
         int modeid;
         if (st->relative_quality<2.0)
            modeid=1;
         else
            modeid=st->submodeSelect;
         /*speex_encoder_ctl(state, SPEEX_SET_MODE, &mode);*/
         st->submodeID=modeid;

      }
      /*fprintf (stderr, "%f %f\n", ratio, low_qual);*/
   }

   if (st->encode_submode)
   {
      speex_bits_pack(bits, 1, 1);
      if (dtx)
         speex_bits_pack(bits, 0, SB_SUBMODE_BITS);
      else
         speex_bits_pack(bits, st->submodeID, SB_SUBMODE_BITS);
   }

   /* If null mode (no transmission), just set a couple things to zero*/
   if (dtx || st->submodes[st->submodeID] == NULL)
   {
      for (i=0;i<st->frame_size;i++)
         st->exc[i]=st->sw[i]=VERY_SMALL;

      for (i=0;i<st->lpcSize;i++)
         st->mem_sw[i]=0;
      st->first=1;

      /* Final signal synthesis from excitation */
      iir_mem2(st->exc, st->interp_qlpc, st->high, st->frame_size, st->lpcSize, st->mem_sp);

#ifdef RESYNTH
      /* Reconstruct the original */
      fir_mem_up(st->x0d, h0, st->y0, st->full_frame_size, QMF_ORDER, st->g0_mem, stack);
      fir_mem_up(st->high, h1, st->y1, st->full_frame_size, QMF_ORDER, st->g1_mem, stack);

      for (i=0;i<st->full_frame_size;i++)
         in[i]=SHR(st->y0[i]-st->y1[i], SIG_SHIFT-1);
#endif

      if (dtx)
         return 0;
      else
         return 1;
   }


   /* LSP quantization */
   SUBMODE(lsp_quant)(st->lsp, st->qlsp, st->lpcSize, bits);   

   if (st->first)
   {
      for (i=0;i<st->lpcSize;i++)
         st->old_lsp[i] = st->lsp[i];
      for (i=0;i<st->lpcSize;i++)
         st->old_qlsp[i] = st->qlsp[i];
   }
   
   ALLOC(mem, st->lpcSize, spx_mem_t);
   ALLOC(syn_resp, st->subframeSize, spx_word16_t);
   ALLOC(innov, st->subframeSize, spx_sig_t);

   for (sub=0;sub<st->nbSubframes;sub++)
   {
      spx_sig_t *exc, *sp, *res, *target, *sw;
      spx_word16_t filter_ratio;
      int offset;
      spx_word32_t rl, rh;
      spx_word16_t eh=0;

      offset = st->subframeSize*sub;
      sp=st->high+offset;
      exc=st->exc+offset;
      res=st->res+offset;
      target=st->target+offset;
      sw=st->sw+offset;
      
      /* LSP interpolation (quantized and unquantized) */
      lsp_interpolate(st->old_lsp, st->lsp, st->interp_lsp, st->lpcSize, sub, st->nbSubframes);
      lsp_interpolate(st->old_qlsp, st->qlsp, st->interp_qlsp, st->lpcSize, sub, st->nbSubframes);

      lsp_enforce_margin(st->interp_lsp, st->lpcSize, LSP_MARGIN);
      lsp_enforce_margin(st->interp_qlsp, st->lpcSize, LSP_MARGIN);

      lsp_to_lpc(st->interp_lsp, st->interp_lpc, st->lpcSize,stack);
      lsp_to_lpc(st->interp_qlsp, st->interp_qlpc, st->lpcSize, stack);

      bw_lpc(st->gamma1, st->interp_lpc, st->bw_lpc1, st->lpcSize);
      bw_lpc(st->gamma2, st->interp_lpc, st->bw_lpc2, st->lpcSize);

      /* Compute mid-band (4000 Hz for wideband) response of low-band and high-band
         filters */
      st->pi_gain[sub]=LPC_SCALING;
      rh = LPC_SCALING;
      for (i=0;i<st->lpcSize;i+=2)
      {
         rh += st->interp_qlpc[i+1] - st->interp_qlpc[i];
         st->pi_gain[sub] += st->interp_qlpc[i] + st->interp_qlpc[i+1];
      }
      
      rl = low_pi_gain[sub];
#ifdef FIXED_POINT
      filter_ratio=DIV32_16(SHL(rl+82,2),SHR(82+rh,5));
#else
      filter_ratio=(rl+.01)/(rh+.01);
#endif
      
      /* Compute "real excitation" */
      fir_mem2(sp, st->interp_qlpc, exc, st->subframeSize, st->lpcSize, st->mem_sp2);
      /* Compute energy of low-band and high-band excitation */

      eh = compute_rms(exc, st->subframeSize);

      if (!SUBMODE(innovation_quant)) {/* 1 for spectral folding excitation, 0 for stochastic */
         float g;
         spx_word16_t el;
         el = compute_rms(low_innov+offset, st->subframeSize);

         /* Gain to use if we want to use the low-band excitation for high-band */
         g=eh/(.01+el);
         
#if 0
         {
            char *tmp_stack=stack;
            float *tmp_sig;
            float g2;
            ALLOC(tmp_sig, st->subframeSize, spx_sig_t);
            for (i=0;i<st->lpcSize;i++)
               mem[i]=st->mem_sp[i];
            iir_mem2(low_innov+offset, st->interp_qlpc, tmp_sig, st->subframeSize, st->lpcSize, mem);
            g2 = compute_rms(sp, st->subframeSize)/(.01+compute_rms(tmp_sig, st->subframeSize));
            /*fprintf (stderr, "gains: %f %f\n", g, g2);*/
            g = g2;
            stack = tmp_stack;
         }
#endif

#ifdef FIXED_POINT
         g *= filter_ratio/128.;
#else
         g *= filter_ratio;
#endif
         /*print_vec(&g, 1, "gain factor");*/
         /* Gain quantization */
         {
            int quant = (int) floor(.5 + 10 + 8.0 * log((g+.0001)));
            /*speex_warning_int("tata", quant);*/
            if (quant<0)
               quant=0;
            if (quant>31)
               quant=31;
            speex_bits_pack(bits, quant, 5);
         }

      } else {
         spx_word16_t gc;
         spx_word32_t scale;
         spx_word16_t el;
         el = compute_rms(low_exc+offset, st->subframeSize);

         gc = DIV32_16(MULT16_16(filter_ratio,1+eh),1+el);

         /* This is a kludge that cleans up a historical bug */
         if (st->subframeSize==80)
            gc *= 0.70711;
         /*printf ("%f %f %f %f\n", el, eh, filter_ratio, gc);*/
#ifdef FIXED_POINT
         {
            int qgc = scal_quant(gc, gc_quant_bound, 16);
            speex_bits_pack(bits, qgc, 4);
            gc = MULT16_32_Q15(28626,gc_quant_bound[qgc]);
         }
#else
         {
            int qgc = (int)floor(.5+3.7*(log(gc)+0.15556));
            if (qgc<0)
               qgc=0;
            if (qgc>15)
               qgc=15;
            speex_bits_pack(bits, qgc, 4);
            gc = exp((1/3.7)*qgc-0.15556);
         }         
#endif
         if (st->subframeSize==80)
            gc *= 1.4142;

         scale = SHL(MULT16_16(DIV32_16(SHL(gc,SIG_SHIFT-4),filter_ratio),(1+el)),4);

         compute_impulse_response(st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, syn_resp, st->subframeSize, st->lpcSize, stack);

         
         /* Reset excitation */
         for (i=0;i<st->subframeSize;i++)
            exc[i]=VERY_SMALL;
         
         /* Compute zero response (ringing) of A(z/g1) / ( A(z/g2) * Aq(z) ) */
         for (i=0;i<st->lpcSize;i++)
            mem[i]=st->mem_sp[i];
         iir_mem2(exc, st->interp_qlpc, exc, st->subframeSize, st->lpcSize, mem);

         for (i=0;i<st->lpcSize;i++)
            mem[i]=st->mem_sw[i];
         filter_mem2(exc, st->bw_lpc1, st->bw_lpc2, res, st->subframeSize, st->lpcSize, mem);

         /* Compute weighted signal */
         for (i=0;i<st->lpcSize;i++)
            mem[i]=st->mem_sw[i];
         filter_mem2(sp, st->bw_lpc1, st->bw_lpc2, sw, st->subframeSize, st->lpcSize, mem);

         /* Compute target signal */
         for (i=0;i<st->subframeSize;i++)
            target[i]=sw[i]-res[i];

         for (i=0;i<st->subframeSize;i++)
           exc[i]=0;

         signal_div(target, target, scale, st->subframeSize);

         /* Reset excitation */
         for (i=0;i<st->subframeSize;i++)
            innov[i]=0;

         /*print_vec(target, st->subframeSize, "\ntarget");*/
         SUBMODE(innovation_quant)(target, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, 
                                   SUBMODE(innovation_params), st->lpcSize, st->subframeSize, 
                                   innov, syn_resp, bits, stack, (st->complexity+1)>>1, SUBMODE(double_codebook));
         /*print_vec(target, st->subframeSize, "after");*/

         signal_mul(innov, innov, scale, st->subframeSize);

         for (i=0;i<st->subframeSize;i++)
            exc[i] = ADD32(exc[i], innov[i]);

         if (SUBMODE(double_codebook)) {
            char *tmp_stack=stack;
            VARDECL(spx_sig_t *innov2);
            ALLOC(innov2, st->subframeSize, spx_sig_t);
            for (i=0;i<st->subframeSize;i++)
               innov2[i]=0;
            for (i=0;i<st->subframeSize;i++)
               target[i]*=2.5;
            SUBMODE(innovation_quant)(target, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, 
                                      SUBMODE(innovation_params), st->lpcSize, st->subframeSize, 
                                      innov2, syn_resp, bits, stack, (st->complexity+1)>>1, 0);
            for (i=0;i<st->subframeSize;i++)
               innov2[i]*=scale*(1/2.5)/SIG_SCALING;
            for (i=0;i<st->subframeSize;i++)
               exc[i] = ADD32(exc[i],innov2[i]);
            stack = tmp_stack;
         }

      }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -