dtmf
no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
| — | dtmf [2016-01-24 17:32:38] (current) – created - external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== FFTW demo - DTMF decoder ====== | ||
| + | Hanging on IRC, we decided to try how fast can I write a DTMF decoder with library FFT. I estimated 30 minutes. Finally, it took me exactly one hour, and the code quality is terrible. | ||
| + | |||
| + | Yes, I know that computing these 8 bins from definition would be faster and would not require fftw. | ||
| + | |||
| + | Now the whole world sees how I code for competitions where only right output, not the code quality, is evaluated. | ||
| + | <code c> | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | #include < | ||
| + | |||
| + | #include < | ||
| + | |||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | #include < | ||
| + | |||
| + | |||
| + | double hamming(int i, int length) { | ||
| + | double a, b, w, N1; | ||
| + | a = 25.0/46.0; | ||
| + | b = 21.0/46.0; | ||
| + | N1 = (double)(length-1); | ||
| + | w = a - b*cos(2*i*M_PI/ | ||
| + | return w; | ||
| + | } | ||
| + | |||
| + | |||
| + | int main(int argc, char **argv) { | ||
| + | |||
| + | int i; | ||
| + | |||
| + | float* acc; | ||
| + | float* fftbuf; | ||
| + | int fftsize = 512; | ||
| + | |||
| + | acc = (float*) calloc(fftsize * 2, sizeof(float)); | ||
| + | fftbuf = (float*) calloc(fftsize * 2, sizeof(float)); | ||
| + | |||
| + | /* Setup FFTW */ | ||
| + | int N = fftsize; | ||
| + | |||
| + | fftwf_complex *fftw_in, *fftw_out; | ||
| + | fftwf_plan p; | ||
| + | | ||
| + | fftw_in = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * N); | ||
| + | fftw_out = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * N); | ||
| + | p = fftwf_plan_dft_1d(N, | ||
| + | |||
| + | float * win = malloc(fftsize * sizeof(float)); | ||
| + | for(i=0; i< | ||
| + | win[i] = hamming(i, fftsize); | ||
| + | } | ||
| + | |||
| + | int16_t * data; | ||
| + | |||
| + | int fd = open("/ | ||
| + | |||
| + | size_t dsize = 168204; | ||
| + | |||
| + | data = (int16_t*)mmap(NULL, | ||
| + | |||
| + | int samples = dsize/2; | ||
| + | |||
| + | /* compute smooth func */ | ||
| + | |||
| + | int16_t * mx = malloc(sizeof(int16_t) * dsize); | ||
| + | |||
| + | for(int i = 0; i< | ||
| + | int max = 0; | ||
| + | for(int j = i; j<i+30; j++) { | ||
| + | if(abs(data[j]) > max) { | ||
| + | max = abs(data[j]); | ||
| + | } | ||
| + | } | ||
| + | mx[i] = max; | ||
| + | /*if(i%20 == 1) { | ||
| + | printf(" | ||
| + | }*/ | ||
| + | } | ||
| + | |||
| + | #define sigth1 15000 | ||
| + | #define sigth2 10000 | ||
| + | #define sigstart 32000 | ||
| + | |||
| + | // | ||
| + | |||
| + | int pos = sigstart; | ||
| + | |||
| + | while(1) { | ||
| + | |||
| + | /* find start of burst */ | ||
| + | |||
| + | while(pos++) { | ||
| + | // printf(" | ||
| + | if(mx[pos] > sigth1) { | ||
| + | break; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | /* find end of burst */ | ||
| + | int endpos = pos+10; | ||
| + | while(endpos++) { | ||
| + | // printf(" | ||
| + | if(mx[endpos] < sigth2) { | ||
| + | break; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | /* align */ | ||
| + | |||
| + | int center = (pos+endpos)/ | ||
| + | int dur = endpos-pos; | ||
| + | int start = center-fftsize/ | ||
| + | |||
| + | // | ||
| + | |||
| + | /* Read data */ | ||
| + | |||
| + | for(i=0; i< | ||
| + | float sample = (float) ( data[i+start] ); | ||
| + | fftbuf[i*2] = sample * win[i]; | ||
| + | fftbuf[i*2+1] = 0.0; | ||
| + | } | ||
| + | |||
| + | // Transform | ||
| + | |||
| + | memcpy(fftw_in, | ||
| + | fftwf_execute(p); | ||
| + | |||
| + | float* fout = (float*)fftw_out; | ||
| + | |||
| + | // Read output | ||
| + | |||
| + | float* rout = (float*)malloc(sizeof(float)*fftsize); | ||
| + | |||
| + | for(int i = 0; i< | ||
| + | float orig = hypot(fftbuf[i*2], | ||
| + | float ret = hypot(fout[i*2], | ||
| + | rout[i] = ret; | ||
| + | // | ||
| + | } | ||
| + | |||
| + | /* find two maximums */ | ||
| + | |||
| + | int max1 = 8; | ||
| + | int max2 = 8; | ||
| + | rout[511] = 0.0; | ||
| + | float dtmf[] = { 1209, 1336, 1477, 1633, 697, 770, 852, 941 }; | ||
| + | int bins[9]; | ||
| + | for(int i = 0; i<8; i++) { | ||
| + | bins[i] = (float)fftsize * dtmf[i]/ | ||
| + | // | ||
| + | } | ||
| + | bins[8] = 511; | ||
| + | |||
| + | /* horiz */ | ||
| + | for(int i = 0; i<4; i++) { | ||
| + | if(rout[bins[i]] > rout[bins[max1]]) { | ||
| + | max1 = i; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | /* vert */ | ||
| + | for(int i = 4; i<8; i++) { | ||
| + | // | ||
| + | if(rout[bins[i]] > rout[bins[max2]]) { | ||
| + | max2 = i; | ||
| + | } | ||
| + | } | ||
| + | max2 -= 4; | ||
| + | |||
| + | // | ||
| + | |||
| + | int res[4][4] = {{1, 2, 3, ' | ||
| + | {4, 5, 6, ' | ||
| + | {7, 8, 9, ' | ||
| + | | ||
| + | |||
| + | int rt = res[max2][max1]; | ||
| + | if(rt> | ||
| + | printf(" | ||
| + | } else { | ||
| + | printf(" | ||
| + | } | ||
| + | |||
| + | pos = endpos+10; | ||
| + | |||
| + | } | ||
| + | |||
| + | |||
| + | } | ||
| + | |||
| + | </ | ||
dtmf.txt · Last modified: by 127.0.0.1
