Improved output format possibilities
[mirrors/Programs.git] / c / goertzel / goertzel.c
CommitLineData
4b43521a
H
1#include <stdio.h>
2#include <math.h>
59934436
H
3#include <getopt.h>
4
4b43521a
H
5float goertzel_mag(int numSamples,int TARGET_FREQUENCY,int SAMPLING_RATE, float* data)
6{
4b43521a
H
7 int k,i;
8 float floatnumSamples;
9 float omega,sine,cosine,coeff,q0,q1,q2,magnitude,real,imag;
10
11 float scalingFactor = numSamples / 2.0;
12
13 floatnumSamples = (float) numSamples;
14 k = (int) (0.5 + ((floatnumSamples * TARGET_FREQUENCY) / SAMPLING_RATE));
15 omega = (2.0 * M_PI * k) / floatnumSamples;
16 sine = sin(omega);
17 cosine = cos(omega);
18 coeff = 2.0 * cosine;
19 q0=0;
20 q1=0;
21 q2=0;
22
23 for(i=0; i<numSamples; i++)
24 {
25 q0 = coeff * q1 - q2 + data[i];
26 q2 = q1;
27 q1 = q0;
28 }
29
30 // calculate the real and imaginary results
31 // scaling appropriately
32 real = (q1 - q2 * cosine) / scalingFactor;
33 imag = (q2 * sine) / scalingFactor;
34
35 magnitude = sqrtf(real*real + imag*imag);
36 return magnitude;
37}
38
59934436 39void print_help(char ** argv) {
8f751717
H
40 printf(
41 "%s takes raw (wav) audio stream and computes power (or magnitude)\n"
42 "of desired frequencies using Goertzel algorithm for time frames\n"
43 "of fixed length (specified in samples or relative to sample rate).\n"
44 "This can be used in various frequency detection applications\n"
45 "like guitar tuning, DTMF decoding and many others...\n"
46 "\n"
47 "http://en.wikipedia.org/wiki/Goertzel_algorithm\n"
48 "\n"
49 "Curently only raw unsigned 8bit (u8) mono audio is supported, but\n"
50 "samplerate may vary. You can convert other formats before processing.\n"
51 "\n"
52 "On lower samplerates and frame sizes this may perform sub-optimally. Eg.:\n"
53 "When set to detect 440Hz (at 8000Hz samplerate and ~4000 samples)\n"
54 "it actually detects something around 438,3Hz rather than 400Hz...\n"
55 "If you can't increase samplerate way around this is just to increase sensitivity.\n"
56 "\n"
57 ,argv[0]
58 );
84329d34
H
59
60 printf(
61 "Arguments:\n"
84329d34
H
62 "\t-i <file>\tInput from file (default STDIN)\n"
63 "\t-o <file>\tOutput to file (default STDOUT)\n"
64 "\t-a <file>\tOutput to file (append) (default STDOUT)\n"
65 "\n"
66 "\t-r <samplerate>\tInput samplerate (deault 8000 Hz)\n"
67 "\t-c <count>\tFrame size in samples (default 4000 Samples)\n"
68 "\t-d <ratio>\tFrame size (default 2) (samplerate will be divided by this number to get frame size same as -c)\n"
69 "\n"
8f751717 70 "\t-f <freq>\tAdd frequency in Hz to detect (use multiple times, if no added 440 Hz will be...)\n"
84329d34
H
71 "\n"
72 "\t-t <treshold>\tSet treshold (used to hide magnitudes lower than treshold) (defaults -1)\n"
c9be90d5
TM
73 "\t-n <format>\tSet output format\n"
74 "\t\tf: float (default)\n"
75 "\t\ti: integer\n"
76 "\t\tb: binary (0|1)\n"
77 "\t\tB: Boolean (false|true)\n"
84329d34
H
78 "\t-l\t\tDo not repeat values while still over treshold\n"
79 "\t-b\t\tDo not print first value that will fall under treshold\n"
80 "\t-q\t\tQuiet mode: print only values\n"
81 "\n"
82 "\t-?\t\tPrint help\n"
83 "\n"
84 );
85
86 printf(
87 "Usage examples:\n"
88 "\tarecord | %s\n"
89 "\tsox input.mp3 -b 8 -c 1 -r 8000 -t wav - | %s\n"
90 "\t%s -n -q -l -r 8000 -d 20 -t $tresh -f 697 [-f 770 ...]\n"
91 "\n"
92 ,argv[0],argv[0],argv[0]
93 );
94
95 printf(
96 "Frequencies for DTMF decoding:\n"
97 "\t-f 697 -f 770 -f 852 -f 941 -f 1209 -f 1336 -f 1477 -f 1633 -t 10\n"
98 );
59934436
H
99}
100
101void addfreq(int *freqs, int freq) {
102 int i = 0;
103 while(freqs[i]!=-1) i++;
104 freqs[i]=freq;
105 freqs[i+1]=-1;
106}
107
108int main(int argc, char ** argv) {
4b43521a
H
109 int samplerate = 8000;
110 int samplecount = 4000;
59934436
H
111 int treshold = -1;
112 char noreturn = 0;
4b50f692 113 char repeat = 1;
c9be90d5 114 char format=0;
59934436
H
115 char verbose=1;
116 int freqs[argc+1]; freqs[0]=-1;
117
118 int opt;
c9be90d5 119 while ((opt = getopt(argc, argv, "?i:o:a:r:c:d:f:t:n:lbq")) != -1) {
59934436 120 switch (opt) {
c7611c89
H
121 case 'i':
122 freopen(optarg, "r", stdin);
123 break;
124 case 'o':
125 freopen(optarg, "w", stdout);
126 break;
127 case 'a':
128 freopen(optarg, "a", stdout);
129 break;
59934436
H
130 case 'r':
131 samplerate = atoi(optarg);
132 break;
c7611c89 133 case 'c':
59934436
H
134 samplecount = atoi(optarg);
135 break;
f5c8b03d
H
136 case 'd':
137 samplecount = samplerate/atoi(optarg);
138 break;
59934436
H
139 case 'f':
140 addfreq(freqs, atoi(optarg));
141 break;
142 case 't':
143 treshold = atoi(optarg);
144 break;
c7611c89 145 case 'n':
c9be90d5 146 format = optarg[0];
59934436 147 break;
c7611c89 148 case 'l':
4b50f692
H
149 repeat = 0;
150 break;
c7611c89 151 case 'b':
59934436
H
152 noreturn = 1;
153 break;
154 case 'q':
155 verbose = 0;
156 break;
157 case '?':
158 print_help(argv);
159 return 0;
160 break;
161 }
162 }
163
164 if(freqs[0]==-1) addfreq(freqs, 440);
4b43521a
H
165 float samples[samplecount];
166 float position = 0;
59934436
H
167
168 if(verbose) {
169 fprintf(stderr,
170 "#Detected tone: %d Hz\n"
171 "#Samplerate: %d Hz\n"
172 "#Frame lenght: %d samples\n"
173 "#Treshold: %d\n"
174 "#\n"
175 ,freqs[0],samplerate,samplecount,treshold);
176 fflush(stderr);
177
178 printf("#Position");
179 int i; for(i=0;freqs[i]!=-1;i++) {
180 printf("\t%2dHz",freqs[i]);
181 }
182 puts("");
183 }
184
185 char print=0, printnow=0, printlast = 0;
4b43521a
H
186 while(!feof(stdin)) {
187 int i;
59934436
H
188
189 //Sample data
4b43521a
H
190 for(i=0;i<samplecount && !feof(stdin);i++) {
191 unsigned char sample;
192 fread(&sample,1,1,stdin);
193 samples[i]=sample;
194 //printf("%d\n", sample);
195 }
59934436
H
196
197 //Apply goertzel
198 float power[argc];
199 print=0;
200 for(i=0;freqs[i]!=-1;i++) {
201 power[i] = goertzel_mag(samplecount, freqs[i], samplerate, samples);
202
203 //Set print true if over treshold or if changed to false (print for the last time after going under treshold)
204 printnow = power[i] > treshold;
4b50f692 205 print = !(!repeat && printlast && !(!printnow)) && (print || printnow || (printlast && !noreturn));
59934436
H
206 }
207 printlast = printnow;
208 fflush(stdout);
209
210 //Print data
211 if(print) {
212 printf("%8.2f", position);
213 for(i=0;freqs[i]!=-1;i++) {
214 printf("\t");
c9be90d5
TM
215 switch(format) {
216 case 'i':
217 printf("%d",(int)power[i]);
218 break;
219 case 'b':
220 printf("%d",power[i]>treshold);
221 break;
222 case 'B':
223 if(power[i]>treshold) printf("true");
224 else printf("false");
225 break;
226 case 'f':
227 default:
228 printf("%.4f",power[i]);
229 }
59934436
H
230 }
231 puts("");
232 fflush(stdout);
233 }
234
235 //Increase time
4b43521a 236 position += ((float)samplecount/(float)samplerate);
4b43521a
H
237 }
238}
This page took 0.272855 seconds and 4 git commands to generate.