Improved Goertzel + DTMF decoder example
authorHarvie <tomas@mudrunka.cz>
Tue, 31 Jul 2012 22:47:42 +0000 (00:47 +0200)
committerHarvie <tomas@mudrunka.cz>
Tue, 31 Jul 2012 22:47:42 +0000 (00:47 +0200)
c/goertzel/dtmf.sh [new file with mode: 0755]
c/goertzel/goertzel.c

diff --git a/c/goertzel/dtmf.sh b/c/goertzel/dtmf.sh
new file mode 100755 (executable)
index 0000000..6c7798e
--- /dev/null
@@ -0,0 +1,71 @@
+#!/bin/bash
+#This is sample implementation of DTMF decoder using my C implementation of Goertzel Algorithm
+#This is not very efficient or precise, it's just proof of concept
+#Usage example: arecord 2>/dev/null | ./dtmf.sh
+
+tresh=3
+last='';
+./goertzel -i -q -r 8000 -s 400 -t $tresh -f 697 -f 770 -f 852 -f 941 -f 1209 -f 1336 -f 1477 -f 1633 | while read line; do
+       #echo "$line";
+
+       #Get time
+       pos="$(echo "$line" | cut -f 1)";
+
+       #Get values for each tone
+       a="$(echo "$line" | cut -f 2)";
+       b="$(echo "$line" | cut -f 3)";
+       c="$(echo "$line" | cut -f 4)";
+       d="$(echo "$line" | cut -f 5)";
+       e="$(echo "$line" | cut -f 6)";
+       f="$(echo "$line" | cut -f 7)";
+       g="$(echo "$line" | cut -f 8)";
+       h="$(echo "$line" | cut -f 9)";
+
+       #Compare values to treshold
+       test $a -gt $tresh && a=true || a=false
+       test $b -gt $tresh && b=true || b=false
+       test $c -gt $tresh && c=true || c=false
+       test $d -gt $tresh && d=true || d=false
+       test $e -gt $tresh && e=true || e=false
+       test $f -gt $tresh && f=true || f=false
+       test $g -gt $tresh && g=true || g=false
+       test $h -gt $tresh && h=true || h=false
+
+       #echo "$pos: $a $b $c $d $e $f $g $h";
+       state="$a$b$c$d$e$f$g$h";
+
+       #Test if tones changed since last time
+       #echo test "$state" != "$last"
+       test "$state" != "$last" && {
+
+               #DTMF Table
+               $a && {
+                       $e && echo -n '1'
+                       $f && echo -n '2'
+                       $g && echo -n '3'
+                       $h && echo -n 'A'
+               }
+               $b && {
+                       $e && echo -n '4'
+                       $f && echo -n '5'
+                       $g && echo -n '6'
+                       $h && echo -n 'B'
+               }
+               $c && {
+                       $e && echo -n '7'
+                       $f && echo -n '8'
+                       $g && echo -n '9'
+                       $h && echo -n 'C'
+               }
+               $d && {
+                       $e && echo -n '*'
+                       $f && echo -n '0'
+                       $g && echo    '#'
+                       $h && echo -n 'D'
+               }
+
+       }
+
+       last="$state"
+
+done
index bcf7a919418e15815c2829dfcd53672970b909f2..f5250a0d11e2740e2a4e9987c0bae928c78796a1 100644 (file)
@@ -1,10 +1,15 @@
 #include <stdio.h>
 #include <math.h>
+#include <getopt.h>
+
 
 /*
        Usage examples
        arecord | ./goertzel
        sox input.mp3 -b 8 -c 1 -r 8000 -t wav - | ./goertzel
+
+       Arguments for DTMF decoding:
+       -f 697 -f 770 -f 852 -f 941 -f 1209 -f 1336 -f 1477 -f 1633 -t 10
 */
 
 float goertzel_mag(int numSamples,int TARGET_FREQUENCY,int SAMPLING_RATE, float* data)
@@ -48,7 +53,18 @@ float goertzel_mag(int numSamples,int TARGET_FREQUENCY,int SAMPLING_RATE, float*
     return magnitude;
 }
 
-int main() {
+void print_help(char ** argv) {
+       printf("help me %s\n", argv[0]);
+}
+
+void addfreq(int *freqs, int freq) {
+       int i = 0;
+       while(freqs[i]!=-1) i++;
+       freqs[i]=freq;
+       freqs[i+1]=-1;
+}
+
+int main(int argc, char ** argv) {
        /*
        int samples[] = {0,1,2,3,4,5,6,7,8,9,8,7,6,5,4,3,2,1};
        int samplecount = 18;
@@ -58,19 +74,104 @@ int main() {
 
        int samplerate = 8000;
        int samplecount = 4000;
+       int treshold = -1;
+       char noreturn = 0;
+       char integers=0;
+       char verbose=1;
+       int freqs[argc+1]; freqs[0]=-1;
+
+       int opt;
+       while ((opt = getopt(argc, argv, "?r:s:f:t:iqn")) != -1) {
+               switch (opt) {
+                       case 'r':
+                               samplerate = atoi(optarg);
+                               break;
+                       case 's':
+                               samplecount = atoi(optarg);
+                               break;
+                       case 'f':
+                               addfreq(freqs, atoi(optarg));
+                               break;
+                       case 't':
+                               treshold = atoi(optarg);
+                               break;
+                       case 'i':
+                               integers = 1;
+                               break;
+                       case 'n':
+                               noreturn = 1;
+                               break;
+                       case 'q':
+                               verbose = 0;
+                               break;
+                       case '?':
+                               print_help(argv);
+                               return 0;
+                               break;
+               }
+       }
+
+       if(freqs[0]==-1) addfreq(freqs, 440);
        float samples[samplecount];
        float position = 0;
-       fprintf(stderr,"Position (Secs)\tMagnitude\n");
+
+       if(verbose) {
+               fprintf(stderr,
+                       "#Detected tone: %d Hz\n"
+                       "#Samplerate: %d Hz\n"
+                       "#Frame lenght: %d samples\n"
+                       "#Treshold: %d\n"
+                       "#\n"
+                       ,freqs[0],samplerate,samplecount,treshold);
+               fflush(stderr);
+
+               printf("#Position");
+               int i; for(i=0;freqs[i]!=-1;i++) {
+                       printf("\t%2dHz",freqs[i]);
+               }
+               puts("");
+       }
+
+       char print=0, printnow=0, printlast = 0;
        while(!feof(stdin)) {
                int i;
+
+               //Sample data
                for(i=0;i<samplecount && !feof(stdin);i++) {
                        unsigned char sample;
                        fread(&sample,1,1,stdin);
                        samples[i]=sample;
                        //printf("%d\n", sample);
                }
+
+               //Apply goertzel
+               float power[argc];
+               print=0;
+               for(i=0;freqs[i]!=-1;i++) {
+                       power[i] = goertzel_mag(samplecount, freqs[i], samplerate, samples);
+
+                       //Set print true if over treshold or if changed to false (print for the last time after going under treshold)
+                       printnow = power[i] > treshold;
+                       print = print || printnow || (printlast && !noreturn);
+               }
+               printlast = printnow;
+               fflush(stdout);
+
+               //Print data
+               if(print) {
+                       printf("%8.2f", position);
+                       for(i=0;freqs[i]!=-1;i++) {
+                               printf("\t");
+                               if(integers)
+                                       printf("%d",(int)power[i]);
+                               else
+                                       printf("%.4f",power[i]);
+                       }
+                       puts("");
+                       fflush(stdout);
+               }
+
+               //Increase time
                position += ((float)samplecount/(float)samplerate);
-               float power = goertzel_mag(samplecount, 440, samplerate, samples);
-               printf("%f\t%f\n", position, power);
        }
 }
This page took 0.271234 seconds and 4 git commands to generate.