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

📄 capidtmf.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
#define CAPIDTMF_RECV_INDICATION_DIGIT        0x0001static long capidtmf_recv_goertzel_coef_table[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] ={  0xda97L * 2,  /* 697 Hz (Low group 697 Hz) */  0xd299L * 2,  /* 770 Hz (Low group 770 Hz) */  0xc8cbL * 2,  /* 852 Hz (Low group 852 Hz) */  0xbd36L * 2,  /* 941 Hz (Low group 941 Hz) */  0x9501L * 2,  /* 1209 Hz (High group 1209 Hz) */  0x7f89L * 2,  /* 1336 Hz (High group 1336 Hz) */  0x6639L * 2,  /* 1477 Hz (High group 1477 Hz) */  0x48c6L * 2,  /* 1633 Hz (High group 1633 Hz) */  0xe14cL * 2,  /* 630 Hz (Lower guard of low group 631 Hz) */  0xb2e0L * 2,  /* 1015 Hz (Upper guard of low group 1039 Hz) */  0xa1a0L * 2,  /* 1130 Hz (Lower guard of high group 1140 Hz) */  0x8a87L * 2,  /* 1272 Hz (Guard between 1209 Hz and 1336 Hz: 1271 Hz) */  0x7353L * 2,  /* 1405 Hz (2nd harmonics of 697 Hz and guard between 1336 Hz and 1477 Hz: 1405 Hz) */  0x583bL * 2,  /* 1552 Hz (2nd harmonics of 770 Hz and guard between 1477 Hz and 1633 Hz: 1553 Hz) */  0x37d8L * 2,  /* 1720 Hz (2nd harmonics of 852 Hz and upper guard of high group: 1715 Hz) */  0x0000L * 2   /* 100-630 Hz (fundamentals) */};static word capidtmf_recv_guard_snr_low_table[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] ={  14,                                    /* Low group peak versus 697 Hz */  14,                                    /* Low group peak versus 770 Hz */  16,                                    /* Low group peak versus 852 Hz */  16,                                    /* Low group peak versus 941 Hz */  CAPIDTMF_RECV_GUARD_SNR_DONTCARE,      /* Low group peak versus 1209 Hz */  CAPIDTMF_RECV_GUARD_SNR_DONTCARE,      /* Low group peak versus 1336 Hz */  CAPIDTMF_RECV_GUARD_SNR_DONTCARE,      /* Low group peak versus 1477 Hz */  CAPIDTMF_RECV_GUARD_SNR_DONTCARE,      /* Low group peak versus 1633 Hz */  14,                                    /* Low group peak versus 635 Hz */  16,                                    /* Low group peak versus 1010 Hz */  CAPIDTMF_RECV_GUARD_SNR_DONTCARE,      /* Low group peak versus 1140 Hz */  CAPIDTMF_RECV_GUARD_SNR_DONTCARE,      /* Low group peak versus 1272 Hz */  DSPDTMF_RX_HARMONICS_SEL_DEFAULT - 8,  /* Low group peak versus 1405 Hz */  DSPDTMF_RX_HARMONICS_SEL_DEFAULT - 4,  /* Low group peak versus 1555 Hz */  DSPDTMF_RX_HARMONICS_SEL_DEFAULT - 4,  /* Low group peak versus 1715 Hz */  12                                     /* Low group peak versus 100-630 Hz */};static word capidtmf_recv_guard_snr_high_table[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] ={  CAPIDTMF_RECV_GUARD_SNR_DONTCARE,      /* High group peak versus 697 Hz */  CAPIDTMF_RECV_GUARD_SNR_DONTCARE,      /* High group peak versus 770 Hz */  CAPIDTMF_RECV_GUARD_SNR_DONTCARE,      /* High group peak versus 852 Hz */  CAPIDTMF_RECV_GUARD_SNR_DONTCARE,      /* High group peak versus 941 Hz */  20,                                    /* High group peak versus 1209 Hz */  20,                                    /* High group peak versus 1336 Hz */  20,                                    /* High group peak versus 1477 Hz */  20,                                    /* High group peak versus 1633 Hz */  CAPIDTMF_RECV_GUARD_SNR_DONTCARE,      /* High group peak versus 635 Hz */  CAPIDTMF_RECV_GUARD_SNR_DONTCARE,      /* High group peak versus 1010 Hz */  16,                                    /* High group peak versus 1140 Hz */  4,                                     /* High group peak versus 1272 Hz */  6,                                     /* High group peak versus 1405 Hz */  8,                                     /* High group peak versus 1555 Hz */  16,                                    /* High group peak versus 1715 Hz */  12                                     /* High group peak versus 100-630 Hz */};/*---------------------------------------------------------------------------*/static void capidtmf_recv_init (t_capidtmf_state   *p_state){  p_state->recv.min_gap_duration = 1;  p_state->recv.min_digit_duration = 1;  p_state->recv.cycle_counter = 0;  p_state->recv.current_digit_on_time = 0;  p_state->recv.current_digit_off_time = 0;  p_state->recv.current_digit_value = CAPIDTMF_RECV_NO_DIGIT;  p_state->recv.digit_write_pos = 0;  p_state->recv.digit_read_pos = 0;  p_state->recv.indication_state = 0;  p_state->recv.indication_state_ack = 0;  p_state->recv.state = CAPIDTMF_RECV_STATE_IDLE;}void capidtmf_recv_enable (t_capidtmf_state   *p_state, word min_digit_duration, word min_gap_duration){  p_state->recv.indication_state_ack &= CAPIDTMF_RECV_INDICATION_DIGIT;  p_state->recv.min_digit_duration = (word)(((((dword) min_digit_duration) * 8) +    ((dword)(CAPIDTMF_RECV_TIME_GRANULARITY / 2))) / ((dword) CAPIDTMF_RECV_TIME_GRANULARITY));  if (p_state->recv.min_digit_duration <= 1)    p_state->recv.min_digit_duration = 1;  else    (p_state->recv.min_digit_duration)--;  p_state->recv.min_gap_duration =    (word)((((dword) min_gap_duration) * 8) / ((dword) CAPIDTMF_RECV_TIME_GRANULARITY));  if (p_state->recv.min_gap_duration <= 1)    p_state->recv.min_gap_duration = 1;  else    (p_state->recv.min_gap_duration)--;  p_state->recv.state |= CAPIDTMF_RECV_STATE_DTMF_ACTIVE;}void capidtmf_recv_disable (t_capidtmf_state   *p_state){  p_state->recv.state &= ~CAPIDTMF_RECV_STATE_DTMF_ACTIVE;  if (p_state->recv.state == CAPIDTMF_RECV_STATE_IDLE)    capidtmf_recv_init (p_state);  else  {    p_state->recv.cycle_counter = 0;    p_state->recv.current_digit_on_time = 0;    p_state->recv.current_digit_off_time = 0;    p_state->recv.current_digit_value = CAPIDTMF_RECV_NO_DIGIT;  }}word capidtmf_recv_indication (t_capidtmf_state   *p_state, byte *buffer){  word i, j, k, flags;  flags = p_state->recv.indication_state ^ p_state->recv.indication_state_ack;  p_state->recv.indication_state_ack ^= flags & CAPIDTMF_RECV_INDICATION_DIGIT;  if (p_state->recv.digit_write_pos != p_state->recv.digit_read_pos)  {    i = 0;    k = p_state->recv.digit_write_pos;    j = p_state->recv.digit_read_pos;    do    {      buffer[i++] = p_state->recv.digit_buffer[j];      j = (j == CAPIDTMF_RECV_DIGIT_BUFFER_SIZE - 1) ? 0 : j + 1;    } while (j != k);    p_state->recv.digit_read_pos = k;    return (i);  }  p_state->recv.indication_state_ack ^= flags;  return (0);}#define CAPIDTMF_RECV_WINDOWED_SAMPLES  32void capidtmf_recv_block (t_capidtmf_state   *p_state, byte   *buffer, word length){  byte result_digit;  word sample_number, cycle_counter, n, i;  word low_peak, high_peak;  dword lo, hi;  byte   *p;  short *q;  byte goertzel_result_buffer[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT];    short windowed_sample_buffer[CAPIDTMF_RECV_WINDOWED_SAMPLES];  if (p_state->recv.state & CAPIDTMF_RECV_STATE_DTMF_ACTIVE)  {    cycle_counter = p_state->recv.cycle_counter;    sample_number = 0;    while (sample_number < length)    {      if (cycle_counter < CAPIDTMF_RECV_ACCUMULATE_CYCLES)      {        if (cycle_counter == 0)        {          for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT; i++)          {            p_state->recv.goertzel_buffer[0][i] = 0;            p_state->recv.goertzel_buffer[1][i] = 0;          }        }        n = CAPIDTMF_RECV_ACCUMULATE_CYCLES - cycle_counter;        if (n > length - sample_number)          n = length - sample_number;        if (n > CAPIDTMF_RECV_WINDOWED_SAMPLES)          n = CAPIDTMF_RECV_WINDOWED_SAMPLES;        p = buffer + sample_number;        q = capidtmf_recv_window_function + cycle_counter;        if (p_state->ulaw)        {          for (i = 0; i < n; i++)          {            windowed_sample_buffer[i] =              (short)((capidtmf_expand_table_ulaw[p[i]] * ((long)(q[i]))) >> 15);	  }        }        else        {          for (i = 0; i < n; i++)          {            windowed_sample_buffer[i] =              (short)((capidtmf_expand_table_alaw[p[i]] * ((long)(q[i]))) >> 15);	  }        }        capidtmf_recv_goertzel_coef_table[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT - 1] = CAPIDTMF_RECV_FUNDAMENTAL_OFFSET;        capidtmf_goertzel_loop (p_state->recv.goertzel_buffer[0],          capidtmf_recv_goertzel_coef_table, windowed_sample_buffer, n);        cycle_counter += n;        sample_number += n;      }      else      {        capidtmf_goertzel_result (p_state->recv.goertzel_buffer[0],          capidtmf_recv_goertzel_coef_table);        for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT; i++)        {          lo = (dword)(p_state->recv.goertzel_buffer[0][i]);          hi = (dword)(p_state->recv.goertzel_buffer[1][i]);          if (hi != 0)          {            n = capidtmf_dword_leading_zeroes (hi);            hi = (hi << n) | (lo >> (32 - n));          }          else          {            n = capidtmf_dword_leading_zeroes (lo);            hi = lo << n;	    n += 32;          }          n = 195 - 3 * n;          if (hi >= 0xcb300000L)            n += 2;          else if (hi >= 0xa1450000L)            n++;	  goertzel_result_buffer[i] = (byte) n;        }        low_peak = DSPDTMF_RX_SENSITIVITY_LOW_DEFAULT;        result_digit = CAPIDTMF_RECV_NO_DIGIT;        for (i = 0; i < CAPIDTMF_LOW_GROUP_FREQUENCIES; i++)        {          if (goertzel_result_buffer[i] > low_peak)	  {	    low_peak = goertzel_result_buffer[i];	    result_digit = (byte) i;	  }        }        high_peak = DSPDTMF_RX_SENSITIVITY_HIGH_DEFAULT;        n = CAPIDTMF_RECV_NO_DIGIT;        for (i = CAPIDTMF_LOW_GROUP_FREQUENCIES; i < CAPIDTMF_RECV_BASE_FREQUENCY_COUNT; i++)        {          if (goertzel_result_buffer[i] > high_peak)	  {	    high_peak = goertzel_result_buffer[i];	    n = (i - CAPIDTMF_LOW_GROUP_FREQUENCIES) << 2;	  }        }        result_digit |= (byte) n;        if (low_peak + DSPDTMF_RX_HIGH_EXCEEDING_LOW_DEFAULT < high_peak)          result_digit = CAPIDTMF_RECV_NO_DIGIT;        if (high_peak + DSPDTMF_RX_LOW_EXCEEDING_HIGH_DEFAULT < low_peak)          result_digit = CAPIDTMF_RECV_NO_DIGIT;        n = 0;        for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT; i++)        {          if ((((short)(low_peak - goertzel_result_buffer[i] - capidtmf_recv_guard_snr_low_table[i])) < 0)           || (((short)(high_peak - goertzel_result_buffer[i] - capidtmf_recv_guard_snr_high_table[i])) < 0))	  {	    n++;	  }        }        if (n != 2)          result_digit = CAPIDTMF_RECV_NO_DIGIT;        if (result_digit == CAPIDTMF_RECV_NO_DIGIT)        {          if (p_state->recv.current_digit_on_time != 0)          {            if (++(p_state->recv.current_digit_off_time) >= p_state->recv.min_gap_duration)            {              p_state->recv.current_digit_on_time = 0;              p_state->recv.current_digit_off_time = 0;            }          }          else          {            if (p_state->recv.current_digit_off_time != 0)              (p_state->recv.current_digit_off_time)--;          }        }        else        {          if ((p_state->recv.current_digit_on_time == 0)           && (p_state->recv.current_digit_off_time != 0))          {            (p_state->recv.current_digit_off_time)--;          }          else          {            n = p_state->recv.current_digit_off_time;            if ((p_state->recv.current_digit_on_time != 0)             && (result_digit != p_state->recv.current_digit_value))            {              p_state->recv.current_digit_on_time = 0;              n = 0;            }            p_state->recv.current_digit_value = result_digit;            p_state->recv.current_digit_off_time = 0;            if (p_state->recv.current_digit_on_time != 0xffff)            {              p_state->recv.current_digit_on_time += n + 1;              if (p_state->recv.current_digit_on_time >= p_state->recv.min_digit_duration)              {                p_state->recv.current_digit_on_time = 0xffff;                i = (p_state->recv.digit_write_pos == CAPIDTMF_RECV_DIGIT_BUFFER_SIZE - 1) ?                  0 : p_state->recv.digit_write_pos + 1;                if (i == p_state->recv.digit_read_pos)                {                  trace (dprintf ("%s,%d: Receive digit overrun",                    (char   *)(FILE_), __LINE__));                }                else                {                  p_state->recv.digit_buffer[p_state->recv.digit_write_pos] = result_digit;                  p_state->recv.digit_write_pos = i;                  p_state->recv.indication_state =                    (p_state->recv.indication_state & ~CAPIDTMF_RECV_INDICATION_DIGIT) |                    (~p_state->recv.indication_state_ack & CAPIDTMF_RECV_INDICATION_DIGIT);                }              }            }          }        }        cycle_counter = 0;        sample_number++;      }    }    p_state->recv.cycle_counter = cycle_counter;  }}void capidtmf_init (t_capidtmf_state   *p_state, byte ulaw){  p_state->ulaw = ulaw;  capidtmf_recv_init (p_state);}/*---------------------------------------------------------------------------*/

⌨️ 快捷键说明

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