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

📄 pitch.dsp

📁 作者:Analog Devices,Inc 平台:ADSP21xx 编程语言:ASM 说明:ADSP21xx用AD的16位定点DSP作音频压缩器性价比不错
💻 DSP
字号:
.module/boot=3/boot=4        pitch_detection; 

{ PITCH.DSP - extracts the pitch period, and makes a 
              voiced/unvoiced decision.

  INPUT:
    i0 -> k[N]
    l0 =  0
    i6 -> autocor_speech[FRAME_LENGTH]
    l6 =  0
  
  OUTPUT:
    si = pitch (= 0 if unvoiced)
   
  CONST:
    PITCH_DETECT_LENGTH = part of frame used for pitch detection
                           starting at 3 msec.

    mSEC_3 = sample to start pitch detection at

  FUNCIOTNS CALLED:
    None

  DESCRIPTION:
    The k's are autoscaled, and then autocorrelated. The new values are
    correlated with the autocorrelated speech R[]. The resulting sequence
    is searched for the largest peak in the interval
      mSEC_3 .....  mSEC_3+PITCH_DETECT_LENGTH

    Depending on the relative size of the peak (to re[0]), a decision of 
    voiced/unvoiced is made. In case of voiced the location is equal to
    the pitch period.
}

{Include constant definition}
#include "lpc.h"

.entry    detect_pitch;

.external overflow;

.var/dm   rk[N];             {autocorrelation of k[]}
{.var/pm   re[FRAME_LENGTH];}  {cross correlation of R[] and rk[]}
.var/dm   k_dm[N];           {scratch copy's of k}
.var/dm   p2_k;
.var/dm   p2_autocor_speech;
.var/dm   zero_crossings;    {in re[]}


detect_pitch:

 {store pointers for later use}
  dm(p2_k) = i0;
  dm(p2_autocor_speech) = i6;
  
 {autoscale befored autocorrelation}
 {detect largest value in k's}  
 {i0 = ^k;     l0 = 0;} 
  cntr = N;
  sb = -16;
  do max_k until ce;
    si = dm(i0,m1);
  max_k: sb = expadj si;

 {adjust k input: normalize to largest and then right shift
  to |P_K_SHIFT|.(16-|P_K_SHIFT|) format (done in one shift).
  At the same time copy to pm for correlation}
  i0 = dm(p2_k);    l0 = 0; 
  i1 = ^k_dm;       l1 = 0; 
  cntr = N;
  ax0 = sb;
  ay0 = P_K_SHIFT;  {scale down to avoid overflow (worst case)}
  ar = ay0 - ax0;
  se = ar;
  do adj_k until ce;
    si = dm(i0,m1);
    sr = ashift si (hi);
  adj_k: dm(i1,m1) = sr1;

  {calculate autocorrelation of k[], rk[i] = sum_of k[j]*k[i+j]}
  i5 = ^k_dm;    l5 = 0;  {k[i+j]}
  i2 = N;        l2 = 0;  {innerloop counter 'refill'}
  i1 = ^rk;      l1 = 0;  
  m2 = -1;
  cntr = N;
  do corr_loop until ce;
    i0 = ^k_dm;   l0 = 0; {k[j]}
    i4 = i5;      l4 = 0;
    cntr = i2;
    mr=0, my0 = dm(i4,m5);
     mx0=dm(i0,m1);
    do cor_data_loop until ce;
      mr=mr+mx0*my0(ss),my0=dm(i4,m5);
    cor_data_loop:      mx0=dm(i0,m1);
    if mv call overflow;
    mx0 = dm(i2,m2); 
     my0 = dm(i5,m5); {(innerloop cnt'er)--, i++}
  corr_loop: dm(i1,m1) = mr1;

 {shift down R[] (autocor_speech) to |P_R_SHIFT|.(16-|P_R_SHIFT|) format}
  cntr = FRAME_LENGTH;
 {i6 = ^autocor_speech;   l6 = 0;}
  do shft_ac until ce;
    si = pm(i6,m4);
    sr = ashift si by P_R_SHIFT (hi);
  shft_ac:  pm(i6,m5) = sr1;


  {Setup rk[] and R[] (autocor_speech) for correlation.
   Only calculate the necessary correlation coefficients, equivalent 
   to the 0-15 ms portion of the frame (samples 0-120 (out of 160),
   re(0) is necesary for later voiced/unvoiced calc}
  { re[i] = sum_of(rk[j]*R[i+j]) }
  
  i5 = dm(p2_autocor_speech);   l5 = 0;  {R[i+j]}
  i2 = N;                       l2 = 0;
  i6 = dm(p2_autocor_speech);   l6 = 0;  
  ay0 = 0;              {last 'sign' for zerocrossing count}
  af  = pass ay0;       {zerocrossing counter}
  cntr = PITCH_DETECT_LENGTH + mSEC_3;  {0-15 msec}
  {correlate rk's and R's}
   do cor_loop until ce;
     i0 = ^rk; l0 = 0;     {rk[j]}
     i4 = i5;  l4 = 0;
     cntr=i2;
     mr=0, my0=pm(i4,m5), mx0=dm(i0,m1);
     do cor_inner_loop until ce;
     cor_inner_loop: mr=mr+mx0*my0(ss),my0=pm(i4,m5),mx0=dm(i0,m1);
     
     ar = mr1 xor ay0;  {test for sign switch = zerocrossing}
     if ge jump no_crossing;
       af  = af + 1;    {inc zerocrossing counter}  
       ay0 = mr1;       {store new sign}
     no_crossing:
     
     modify(i5,m5);        {i++}
   cor_loop: pm(i6,m5) = mr1;
   ar = pass af;
   i5 = ar; {zerocrossing count}

  {find the largest peak in range 3-15 msec. The index of the largest 
   peak is equal to the pitch period. At the same time count the 
   nr of zerocrossings in re[]}

  si  = 0;       {store for pitch of max peak}
  ay1 = 0;       {store for value of max peak}
  i6  = dm(p2_autocor_speech);  l6 = 0;
  ax0 = pm(i6,m4);     {save re(0) for voiced/unvoiced check}
  m7  = mSEC_3;
  modify(i6,m7);       {-> re(mSEC_3)}
  i2  = mSEC_3;  l2 = 0; {pitch counter}
  cntr = PITCH_DETECT_LENGTH;
  do find_max_peak until ce;
    ax1 = pm(i6,m5);   {re[j]}
    ar  = ax1 - ay1;   {re[j] > max?} 
    if le jump not_bigger;
      ay1 = ax1;       {new max value}
      si = i2;         {corresponding pitch value}
    not_bigger: 
    nop;
  find_max_peak: modify(i2,m1);  {(pitch period cnt'er)++}

  {Check for voiced/unvoiced excitation. If unvoiced set pitch = 0}
   {ax0 = re(0)}
   {ay1 = MSW of peakvalue}
  ay0 = 0000;      {LSB of peakvalue}
  divide(ax0,ay1); {ay0 = re[peak]/re[0]}
  ax0 = i5;        {nr of zerocrossings in re[]}
  ay1 = 70;  
  ar = ax0 - ay1;  {i5>treshold => unvoiced}
  if ge jump not_voiced; 
  ax1 = 0x1999;    {= 0.20}
  ar  = ay0 - ax1; {re(j)/re(0) - 0.20}
  if lt jump not_voiced; 
  ax1 = 0x2666;    {= 0.30}
  ar  = ay0 - ax1; {re(j)/re(0) - 0.30}
  if gt jump frame_voiced; 
  ay1 = 60;        
  ar = ax0 - ay1;  {i5>treshold => unvoiced}
  if lt jump frame_voiced;
  not_voiced:
    si = 0;        {unvoiced => pitch period = 0}
    i0 = dm(p2_k);  l0 = 0; {zero out k5 - k10 for unvoiced speech}
    m3 = 4;
    modify(i0,m3);
    ax0 = 0;
    cntr = 6;
    do zero_ks until ce;
    zero_ks:  dm(i0,m1) = ax0;
  frame_voiced:

rts;

.endmod;

⌨️ 快捷键说明

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