8magsvn – Blame information for rev 28

Subversion Repositories:
Rev:
Rev Author Line No. Line
25 kaklik 1 ///////////////////////////////////////////////////////////////////////////////////
2 //
3 //
4 ///////////////////////////////////////////////////////////////////////////////////
5  
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <sched.h>
10 #include <errno.h>
11 #include <getopt.h>
12 #include <alsa/asoundlib.h>
13 #include <sys/time.h>
14 #include <math.h>
15 #include <fftw3.h>
16  
17 static char *device = "plughw:0,0"; /* playback device */
18 static snd_pcm_format_t format = SND_PCM_FORMAT_S16; /* sample format */
28 kaklik 19 static unsigned int rate = 24000; /* stream rate */
20 static unsigned int buffer_time = 200000; /* ring buffer length in us */
21 static unsigned int period_time = 10000; /* period time in us */
25 kaklik 22 static int verbose = 0; /* verbose flag */
23 static int resample = 1; /* enable alsa-lib resampling */
24 static int period_event = 0; /* produce poll event after each period */
25  
26 static snd_pcm_sframes_t buffer_size; // size of buffer at sound card
27 static snd_pcm_sframes_t period_size; //samples per frame
28 static snd_output_t *output = NULL;
29  
30 FILE *out;
31  
28 kaklik 32 double df; //frequency resolution
33 unsigned int frequency_bins; // number of output frequency bins
34  
25 kaklik 35 double *inl, *inr;
36 fftw_complex *outl, *outr;
37 fftw_plan fft_plan_left, fft_plan_right;
38  
26 kaklik 39 double *spect_avg_left, *spect_avg_right;
25 kaklik 40 unsigned int period;
41  
42 static int set_hwparams(snd_pcm_t *handle, snd_pcm_hw_params_t *params, unsigned int channels)
43 {
44 unsigned int rrate;
45 snd_pcm_uframes_t size;
46 int err, dir;
47  
48 /* choose all parameters */
49 err = snd_pcm_hw_params_any(handle, params);
50 if (err < 0) {
28 kaklik 51 printf("Broken configuration for capture: no configurations available: %s\n", snd_strerror(err));
25 kaklik 52 return err;
53 }
54 /* set hardware resampling */
55 err = snd_pcm_hw_params_set_rate_resample(handle, params, resample);
56 if (err < 0) {
28 kaklik 57 printf("Resampling setup failed for capture: %s\n", snd_strerror(err));
25 kaklik 58 return err;
59 }
60 /* set the interleaved read/write format */
61 err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
62 if (err < 0) {
28 kaklik 63 printf("Access type not available for capture: %s\n", snd_strerror(err));
25 kaklik 64 return err;
65 }
66 /* set the sample format */
67 err = snd_pcm_hw_params_set_format(handle, params, format);
68 if (err < 0) {
69 printf("Sample format not available for playback: %s\n", snd_strerror(err));
70 return err;
71 }
72 /* set the count of channels */
73 err = snd_pcm_hw_params_set_channels(handle, params, channels);
74 if (err < 0) {
75 printf("Channels count (%i) not available for playbacks: %s\n", channels, snd_strerror(err));
76 return err;
77 }
78 /* set the stream rate */
79 rrate = rate;
80 err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0);
81 if (err < 0) {
82 printf("Rate %iHz not available for playback: %s\n", rate, snd_strerror(err));
83 return err;
84 }
85 if (rrate != rate) {
86 printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, err);
87 return -EINVAL;
88 }
89 else printf("Rate set to %i Hz\n", rate, err);
90 /* set the buffer time */
91 err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, &dir);
92 if (err < 0) {
93 printf("Unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror(err));
94 return err;
95 }
96 err = snd_pcm_hw_params_get_buffer_size(params, &size);
97 if (err < 0) {
98 printf("Unable to get buffer size for playback: %s\n", snd_strerror(err));
99 return err;
100 }
101 buffer_size = size;
102 /* set the period time */
103 err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, &dir);
104 if (err < 0) {
105 printf("Unable to set period time %i for playback: %s\n", period_time, snd_strerror(err));
106 return err;
107 }
108 err = snd_pcm_hw_params_get_period_size(params, &size, &dir);
109 if (err < 0) {
110 printf("Unable to get period size for playback: %s\n", snd_strerror(err));
111 return err;
112 }
113 period_size = size;
114 /* write the parameters to device */
115 err = snd_pcm_hw_params(handle, params);
116 if (err < 0) {
117 printf("Unable to set hw params for playback: %s\n", snd_strerror(err));
118 return err;
119 }
120 return 0;
121 }
122  
123 static int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams)
124 {
125 int err;
126  
127 /* get the current swparams */
128 err = snd_pcm_sw_params_current(handle, swparams);
129 if (err < 0) {
130 printf("Unable to determine current swparams for playback: %s\n", snd_strerror(err));
131 return err;
132 }
133 /* start the transfer when the buffer is almost full: */
134 /* (buffer_size / avail_min) * avail_min */
135 err = snd_pcm_sw_params_set_start_threshold(handle, swparams, (buffer_size / period_size) * period_size);
136 if (err < 0) {
137 printf("Unable to set start threshold mode for playback: %s\n", snd_strerror(err));
138 return err;
139 }
140 /* allow the transfer when at least period_size samples can be processed */
141 /* or disable this mechanism when period event is enabled (aka interrupt like style processing) */
142 err = snd_pcm_sw_params_set_avail_min(handle, swparams, period_event ? buffer_size : period_size);
143 if (err < 0) {
144 printf("Unable to set avail min for playback: %s\n", snd_strerror(err));
145 return err;
146 }
147 /* enable period events when requested */
148 if (period_event) {
149 err = snd_pcm_sw_params_set_period_event(handle, swparams, 1);
150 if (err < 0) {
151 printf("Unable to set period event: %s\n", snd_strerror(err));
152 return err;
153 }
154 }
155 /* write the parameters to the playback device */
156 err = snd_pcm_sw_params(handle, swparams);
157 if (err < 0) {
158 printf("Unable to set sw params for playback: %s\n", snd_strerror(err));
159 return err;
160 }
161 return 0;
162 }
163  
164 struct async_private_data {
165 signed short *samples;
166 snd_pcm_channel_area_t *areas;
167 unsigned int period;
168 };
169  
170 /////////// CALL BACK STUFF ///////////////////
171  
172 static void async_capture_callback(snd_async_handler_t *ahandler)
173 {
174 snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler);
26 kaklik 175 int err;
176 unsigned int i, n;
28 kaklik 177 short signal[300000];
25 kaklik 178  
26 kaklik 179 /*signal = calloc( (unsigned int) period_size, sizeof(short) );
25 kaklik 180 if (signal = NULL) printf("memory allocation failed");*/
181  
182 while (snd_pcm_avail_update(handle) >= period_size) { // read until data is ready in buffer
183  
184 err = snd_pcm_readi(handle, signal, period_size);
185 if (err < 0) {
186 printf("Read error: %s\n", snd_strerror(err));
187 exit(EXIT_FAILURE);
188 }
189 if (err != period_size) {
190 printf("Read error: red %i expected %li\n", err, period_size);
191 exit(EXIT_FAILURE);
192 }
193  
194 n=0;
195 i=0;
26 kaklik 196 do {
25 kaklik 197 inl[n]= signal[i];
26 kaklik 198 inr[n]= signal[i+1];
25 kaklik 199 n++;
200 i+=2;
26 kaklik 201 } while (n < period_size);
25 kaklik 202  
26 kaklik 203 fftw_execute(fft_plan_left);
204 fftw_execute(fft_plan_right);
205  
28 kaklik 206 for(i=0; i < frequency_bins; i++) spect_avg_left[i] += sqrt( (outl[i][0] * outl[i][0]) + (outl[i][1] * outl[i][1]) ); //acumulate average spectrum
207 for(i=0; i < frequency_bins; i++) spect_avg_right[i] += sqrt( (outr[i][0] * outr[i][0]) + (outr[i][1] * outr[i][1]) ); //acumulate average spectrum
25 kaklik 208 period++;
209 }
26 kaklik 210  
28 kaklik 211 if (period > 100)
212 {
213 for(i=0; i < frequency_bins; i++) spect_avg_left[i] = spect_avg_left[i]/100;
214 for(i=0; i < frequency_bins; i++) spect_avg_right[i] = spect_avg_right[i]/100;
215  
26 kaklik 216 out=fopen("/tmp/sidspect","w");
28 kaklik 217  
218 for(i=0; i < frequency_bins; i++)
219 {
220 fprintf(out,"%6f %6f %6f\n",(i+0.5)*df, spect_avg_left[i], spect_avg_right[i]);
221 spect_avg_left[i]=0;
222 spect_avg_right[i]=0;
223 }
25 kaklik 224 fclose(out);
26 kaklik 225 period=0;
25 kaklik 226 }
26 kaklik 227 // free(signal);
25 kaklik 228 }
229  
230  
231 int main(int argc, char *argv[])
232 {
233 snd_pcm_t *playback_handle, *capture_handle;
234 int err;
235 snd_pcm_hw_params_t *hwparams;
236 snd_pcm_sw_params_t *swparams;
237 signed short *frame; // pointer to array of samples
238 unsigned int chn;
239 snd_pcm_channel_area_t *areas;
240  
241 struct async_private_data data;
242 snd_async_handler_t *chandler;
243  
244 snd_pcm_hw_params_alloca(&hwparams);
245 snd_pcm_sw_params_alloca(&swparams);
246  
247 printf("SID monitor 2.0 starting work.. \n");
248  
249 //open and set capture device
250 if ((err = snd_pcm_open(&capture_handle, device, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
251 printf("Playback open error: %s\n", snd_strerror(err));
252 return 0;
253 }
254  
255 if ((err = set_hwparams(capture_handle, hwparams, 2)) < 0) {
256 printf("Setting of hwparams failed: %s\n", snd_strerror(err));
257 exit(EXIT_FAILURE);
258 }
259 if ((err = set_swparams(capture_handle, swparams)) < 0) {
260 printf("Setting of swparams failed: %s\n", snd_strerror(err));
261 exit(EXIT_FAILURE);
262 }
263  
28 kaklik 264 frequency_bins = period_size/2 + 1;
25 kaklik 265  
28 kaklik 266 spect_avg_left = calloc(frequency_bins, sizeof (double)); //allocate space for frrequency spectrum
267 spect_avg_right = calloc(frequency_bins, sizeof (double));
25 kaklik 268  
28 kaklik 269  
25 kaklik 270 // register capture callback
271 err = snd_async_add_pcm_handler(&chandler, capture_handle, async_capture_callback, &data); // fill by dummy &data
272 if (err < 0) {
273 printf("Unable to register async handler\n");
274 exit(EXIT_FAILURE);
275 }
276  
28 kaklik 277 // setup fft
278  
279 df = (double) rate/ (double) frequency_bins * 2.0;
280  
26 kaklik 281 inl = fftw_malloc(sizeof(double) * period_size); // period_size);
28 kaklik 282 outl = fftw_malloc(sizeof(fftw_complex) * frequency_bins);
25 kaklik 283  
26 kaklik 284 inr = fftw_malloc(sizeof(double) * period_size); // period_size);
28 kaklik 285 outr = fftw_malloc(sizeof(fftw_complex) * frequency_bins);
26 kaklik 286  
287  
288 fft_plan_left = fftw_plan_dft_r2c_1d(period_size, inl, outl, FFTW_ESTIMATE);
289 fft_plan_right = fftw_plan_dft_r2c_1d(period_size, inr, outr, FFTW_ESTIMATE);
25 kaklik 290 period=0;
26 kaklik 291  
25 kaklik 292 //start capture
293 if ((err = snd_pcm_prepare (capture_handle)) < 0) {
294 fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
295 snd_strerror (err));
296 exit (1);
297 }
298  
299 err = snd_pcm_start(capture_handle);
300 if (err < 0) {
301 printf("Start error: %s\n", snd_strerror(err));
302 exit(EXIT_FAILURE);
303 }
304  
28 kaklik 305 // wait for interrupt
25 kaklik 306 printf("processing audio input.. \n");
307  
308 while(1) usleep(1000);
309  
310 snd_pcm_close(capture_handle);
311 return 0;
312 }
313