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