2012-04-25 3 views
2

그래서 대담하게 생성 된 DTMF 톤의 .raw 파일을 열려고합니다. 나는 위키 피 디아 (wikipedia) 기사에서와 비슷한 통조림 goertzel 알고리즘을 사용했다. 그것은 올바른 숫자를 해독하는 것 같지 않습니다.DTMF Goertzel 알고리즘이 작동하지 않습니다.

디코딩 된 숫자는 N의 어떤 값을 알고리즘에 전달 하느냐에 따라 달라집니다. 늘어나는만큼 N의 높은 가치를 이해 더 나은 정확성을하지만, 숫자가 올바른 디코딩 얻을 것이라고 변경해서는 안됩니다? 여기

#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 

double goertzel(short samples[], double freq, int N) 
{ 
double s_prev = 0.0; 
double s_prev2 = 0.0;  
double coeff, normalizedfreq, power, s; 
int i; 
normalizedfreq = freq/8000; 
coeff = 2*cos(2*M_PI*normalizedfreq); 
for (i=0; i<N; i++) 
{ 
    s = samples[i] + coeff * s_prev - s_prev2; 
    s_prev2 = s_prev; 
    s_prev = s; 
} 
power = s_prev2*s_prev2+s_prev*s_prev-coeff*s_prev*s_prev2; 
return power; 
} 

int main() 
{ 
FILE *fp = fopen("9.raw", "rb"); 
short *buffer; 
float *sample; 
int sample_size; 
int file_size; 
int i=0, x=0; 

float frequency_row[] = {697, 770, 852, 941}; 
float frequency_col[] = {1209, 1336, 1477}; 
float magnitude_row[4]; 
float magnitude_col[4]; 

double result; 

fseek(fp, 0, SEEK_END); 
file_size = ftell(fp); 
fseek(fp, 0, SEEK_SET); 

buffer = malloc(file_size); 

buffer[x] = getc(fp); 
buffer[x] = buffer[x]<<8; 
buffer[x] = buffer[x] | getc(fp); 

while(!feof(fp)) 
{ 
    x++; 
    buffer[x] = getc(fp); 
    buffer[x] = buffer[x]<<8; 
    buffer[x] = buffer[x] | getc(fp); 
} 

for(i=0; i<x; i++) 
{ 
    //printf("%#x\n", (unsigned short)buffer[i]); 
} 
for(i=0; i<4; i++) 
{ 
    magnitude_row[i] = goertzel(buffer, frequency_row[i], 8000); 
} 
for(i=0; i<3; i++) 
{ 
    magnitude_col[i] = goertzel(buffer, frequency_col[i], 8000); 
} 

x=0; 
for(i=0; i<4; i++) 
{ 
    if(magnitude_row[i] > magnitude_row[x]) 
    x = i; 
} 
printf("Freq: %f\t Mag: %f\n", frequency_row[x], magnitude_row[x]); 

x=0; 
for(i=0; i<3; i++) 
{ 
    if(magnitude_col[i] > magnitude_col[x]) 
    x = i; 
} 
printf("Freq: %f\t Mag: %f\n", frequency_col[x], magnitude_col[x]); 
return 0; 
} 
+0

각 음색의 길이를 확인하십시오. N은 측정하려는 톤의 길이보다 클 수 없습니다. – user877329

+0

나는 이것을 결정하는 방법을 모르겠다 ... – BlackCow

+0

디코딩 된 숫자는 N의 값에 따라 크게 다르지만 내가 원하는 모든 실제 값을 디코딩 할 수는 없다. 그것은 아마도 알고리즘이 단지 틀린가? 우리가 작동하게하기 위해해야 ​​할 일이 무엇인지 알아낼 수 있다면 위키 백과를 작동시키는 것으로 업데이트하는 것이 좋을 것입니다! – BlackCow

답변

2

알고리즘도 DTMF 톤을 검출하는 것처럼 간단을 위해 사용하기 까다 롭다 실제로 코드이다. 실제로 실제로는 band-pass filter입니다. 주어진 주파수를 중심으로 한 주파수 대역을 골라냅니다. 이것은 실제로 좋은 일입니다. 샘플링 한 음색이 인 것으로 정확히으로 탐지 할 수는 없습니다.

까다로운 부분은 필터의 대역폭을 설정하려고 시도하는 것입니다. 즉, 특정 톤을 감지하기 위해 필터링되는 주파수의 범위입니다. 주제에 Wikipedia page에 참조

하나 (this one은 정확하게는) DSP에서 Goertzel 알고리즘을 사용하여 DTMF 톤 감지를 구현하는 방법에 대한 이야기. C가 제공하는 원칙은 대역폭을 확보하기 위해 제공된 상수의 올바른 조합을 사용해야합니다. 분명히 간단한 공식은 없습니다 -이 논문은 brute force search을 사용해야한다고 언급하고 8kHz에서 샘플링 된 DTMF 주파수에 대한 최적의 상수 목록을 제공합니다.

2

생성 된 Audacity 오디오 데이터가 빅 엔디안 형식입니까? 빅 엔디안으로 해석하고있는 반면, x86에서 실행하면 보통 리틀 엔디안으로 해석됩니다.

0

여기에 몇 가지 흥미로운 해답이 있습니다. 먼저, 거즈 젤은 실제로 "동정적인"오실레이터입니다. 이것은 폴이 DSP 용어로 단위 원에 있음을 의미합니다. 내부 변수 s, s_prev, s_prev2는 해당 탐지기의 예상 톤 (주파수)을 포함하는 긴 데이터 블록에서 코드를 실행하면 제한없이 커집니다. 이것은 결과를 얻기 위해 일종의 덤프 프로세스를 실행해야 함을 의미합니다. 가트 젤은 한 번에 약 105에서 110 개의 샘플을 DTMF 숫자로 구별하면 가장 잘 작동합니다. 따라서 N = 110으로 설정하고 데이터를 실행하면서 반복적으로 가트 젤을 호출하십시오. 덧붙여 말하자면 실제 DTMF 숫자는 60msec 정도일 수 있습니다. 40msec 이상을 발견하면 그 존재를보고해야합니다. 내가 언급 한 110 개의 샘플을 생각해 보면, 하나의 콜이 110/8000 = 13.75 msec를 커버한다는 것을 의미합니다. 운이 좋으면 검출기 호출을 4 회 반복하여 긍정적 인 결과를 볼 수 있습니다. 과거에는 시작 시간이 길어지면서 한 쌍의 감지기를 병렬로 작동시키는 것이 매우 짧은 톤 버스트의 더 나은 적용 범위를 제공한다는 것을 발견했습니다.