Subversion Repositories svnkaklik

Rev

Details | Last modification | View Log

Rev Author Line No. Line
532 kaklik 1
///////////////////////////////////////////////////////////////////////////////////
2
//                        This small demo of sonar.
3
// Program allow distance measuring.
4
//
5
//
6
///////////////////////////////////////////////////////////////////////////////////
526 kaklik 7
 
8
#include <stdio.h>
9
#include <stdlib.h>
10
#include <string.h>
11
#include <sched.h>
12
#include <errno.h>
13
#include <getopt.h>
14
#include <alsa/asoundlib.h>
15
#include <sys/time.h>
16
#include <math.h>
17
 
18
static char *device = "plughw:0,0";			/* playback device */
19
static snd_pcm_format_t format = SND_PCM_FORMAT_S16;	/* sample format */
20
static unsigned int rate = 44100;			/* stream rate */
21
static unsigned int channels = 1;			/* count of channels */
22
static unsigned int buffer_time = 500000;		/* ring buffer length in us */
23
static unsigned int period_time = 100000;		/* period time in us */
24
static double freq = 440;				/* sinusoidal wave frequency in Hz */
25
static int verbose = 0;					/* verbose flag */
26
static int resample = 1;				/* enable alsa-lib resampling */
27
static int period_event = 0;				/* produce poll event after each period */
28
 
531 kaklik 29
unsigned int chirp_size;
527 kaklik 30
 
526 kaklik 31
int period=0;
527 kaklik 32
int cperiod=0;
532 kaklik 33
int chirp[100000];
34
short signal[1000000];		// record 6s of input samples
526 kaklik 35
 
36
static snd_pcm_sframes_t buffer_size;	// size of buffer at sound card
37
static snd_pcm_sframes_t period_size;	//samples per frame
38
static snd_output_t *output = NULL;
39
 
40
static int set_hwparams(snd_pcm_t *handle,
41
			snd_pcm_hw_params_t *params,
42
			snd_pcm_access_t access)
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) {
51
		printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err));
52
		return err;
53
	}
54
	/* set hardware resampling */
55
	err = snd_pcm_hw_params_set_rate_resample(handle, params, resample);
56
	if (err < 0) {
57
		printf("Resampling setup failed for playback: %s\n", snd_strerror(err));
58
		return err;
59
	}
60
	/* set the interleaved read/write format */
61
	err = snd_pcm_hw_params_set_access(handle, params, access);
62
	if (err < 0) {
63
		printf("Access type not available for playback: %s\n", snd_strerror(err));
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
	/* set the buffer time */
90
	err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, &dir);
91
	if (err < 0) {
92
		printf("Unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror(err));
93
		return err;
94
	}
95
	err = snd_pcm_hw_params_get_buffer_size(params, &size);
96
	if (err < 0) {
97
		printf("Unable to get buffer size for playback: %s\n", snd_strerror(err));
98
		return err;
99
	}
100
	buffer_size = size;
101
	/* set the period time */
102
	err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, &dir);
103
	if (err < 0) {
104
		printf("Unable to set period time %i for playback: %s\n", period_time, snd_strerror(err));
105
		return err;
106
	}
107
	err = snd_pcm_hw_params_get_period_size(params, &size, &dir);
108
	if (err < 0) {
109
		printf("Unable to get period size for playback: %s\n", snd_strerror(err));
110
		return err;
111
	}
112
	period_size = size;
113
	/* write the parameters to device */
114
	err = snd_pcm_hw_params(handle, params);
115
	if (err < 0) {
116
		printf("Unable to set hw params for playback: %s\n", snd_strerror(err));
117
		return err;
118
	}
119
	return 0;
120
}
121
 
122
static int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams)
123
{
124
	int err;
125
 
126
	/* get the current swparams */
127
	err = snd_pcm_sw_params_current(handle, swparams);
128
	if (err < 0) {
129
		printf("Unable to determine current swparams for playback: %s\n", snd_strerror(err));
130
		return err;
131
	}
132
	/* start the transfer when the buffer is almost full: */
133
	/* (buffer_size / avail_min) * avail_min */
134
	err = snd_pcm_sw_params_set_start_threshold(handle, swparams, (buffer_size / period_size) * period_size);
135
	if (err < 0) {
136
		printf("Unable to set start threshold mode for playback: %s\n", snd_strerror(err));
137
		return err;
138
	}
139
	/* allow the transfer when at least period_size samples can be processed */
140
	/* or disable this mechanism when period event is enabled (aka interrupt like style processing) */
141
	err = snd_pcm_sw_params_set_avail_min(handle, swparams, period_event ? buffer_size : period_size);
142
	if (err < 0) {
143
		printf("Unable to set avail min for playback: %s\n", snd_strerror(err));
144
		return err;
145
	}
146
	/* enable period events when requested */
147
	if (period_event) {
148
		err = snd_pcm_sw_params_set_period_event(handle, swparams, 1);
149
		if (err < 0) {
150
			printf("Unable to set period event: %s\n", snd_strerror(err));
151
			return err;
152
		}
153
	}
154
	/* write the parameters to the playback device */
155
	err = snd_pcm_sw_params(handle, swparams);
156
	if (err < 0) {
157
		printf("Unable to set sw params for playback: %s\n", snd_strerror(err));
158
		return err;
159
	}
160
	return 0;
161
}
162
 
163
struct async_private_data {
164
	signed short *samples;
165
	snd_pcm_channel_area_t *areas;
166
	unsigned int period;
167
};
168
 
169
/*int linear_chirp(int *pole, int delka_pole){  // vygeneruje linearni chirp a vzorky ulozi do pole
170
 
171
static const float f0 = 0.0001;
172
static const float k = 0.00001;
173
 
174
int t;
175
 
176
//  if((spozdeni+delka) < delka_pole)
177
    for(t=0;t < delka_pole;t++) pole[t] = round ( 10000*sin(2*M_PI*(t+faze)*(f0+(k/2)*(t+faze))) );
178
    faze +=t;
179
//  else return 0;
180
 
527 kaklik 181
}*/
526 kaklik 182
 
532 kaklik 183
// vygeneruje linearni chirp a vzorky ulozi do pole
184
unsigned int linear_windowed_chirp(unsigned int *pole, unsigned int delka_pole)
185
{  
527 kaklik 186
unsigned int maxval = (1 << (snd_pcm_format_width(format) - 1)) - 1;
526 kaklik 187
 
531 kaklik 188
static const float f0 = 1000;
189
static const float fmax = 5000;
190
static const float Tw = 0.2;
527 kaklik 191
static float k;
526 kaklik 192
 
531 kaklik 193
unsigned int n=0;
194
double t;
195
unsigned int perioda;
526 kaklik 196
 
532 kaklik 197
  k=2*(fmax-f0)/Tw;
198
  perioda = rate*Tw; 
526 kaklik 199
 
532 kaklik 200
  for(n=0;n<=perioda;n++){
201
     t = (double) n/ (double)rate;
202
     pole[n] = (short) round ( (0.35875 - 0.48829*cos(2*M_PI*t*1/Tw) + 0.14128*cos(2*M_PI*2*t*1/Tw) - 0.01168*cos(2*M_PI*3*t*1/Tw))*maxval*sin(2*M_PI*(t)*(f0+(k/2)*(t))) );
203
  }
204
  return perioda;
527 kaklik 205
}
206
 
532 kaklik 207
// generate sine samples and store
531 kaklik 208
int sine(unsigned int *pole, unsigned int delka_pole)
526 kaklik 209
{
527 kaklik 210
unsigned int maxval = (1 << (snd_pcm_format_width(format) - 1)) - 1;
531 kaklik 211
unsigned int n;
212
double t;
213
 
214
  for(n=0;n < delka_pole;n++){
215
    t = 440.0 * (double) n/ (double)rate;
216
    pole[n] = (short) round(maxval*sin(2*M_PI*t));
217
  }
526 kaklik 218
}
219
 
220
 
221
 
222
static void async_playback_callback(snd_async_handler_t *ahandler)
223
{
224
	snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler);
527 kaklik 225
/*	struct async_private_data *data = snd_async_handler_get_callback_private(ahandler);
526 kaklik 226
	signed short *samples = data->samples;
527 kaklik 227
	snd_pcm_channel_area_t *areas = data->areas;*/
526 kaklik 228
	snd_pcm_sframes_t avail;
229
	int err;
230
 
231
	avail = snd_pcm_avail_update(handle);
531 kaklik 232
	while ((avail >= period_size) && ((period*period_size) < chirp_size) ) {
526 kaklik 233
 
527 kaklik 234
		err = snd_pcm_writei(handle, (chirp+period*period_size), period_size);
526 kaklik 235
		if (err < 0) {
236
			printf("Write error: %s\n", snd_strerror(err));
237
			exit(EXIT_FAILURE);
238
		}
239
		if (err != period_size) {
240
			printf("Write error: written %i expected %li\n", err, period_size);
241
			exit(EXIT_FAILURE);
242
		}
243
		avail = snd_pcm_avail_update(handle);
527 kaklik 244
		period++;
526 kaklik 245
	}
246
}
247
 
527 kaklik 248
static void async_capture_callback(snd_async_handler_t *ahandler)
249
{
250
	snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler);
251
/*	struct async_private_data *data = snd_async_handler_get_callback_private(ahandler);
252
	signed short *samples = data->samples;
253
	snd_pcm_channel_area_t *areas = data->areas;*/
254
	snd_pcm_sframes_t avail;
255
	int err;
256
 
257
	avail = snd_pcm_avail_update(handle);
532 kaklik 258
	while ((avail >= period_size) /*&& ((period*period_size) < (CHIRP_SIZE-100))*/ ) {  // segmentation fault checking disabled
527 kaklik 259
 
260
		err = snd_pcm_readi(handle, (signal+cperiod*period_size), period_size);
261
		if (err < 0) {
262
			printf("Read error: %s\n", snd_strerror(err));
263
			exit(EXIT_FAILURE);
264
		}
265
		if (err != period_size) {
266
			printf("Read error: red %i expected %li\n", err, period_size);
267
			exit(EXIT_FAILURE);
268
		}
269
		avail = snd_pcm_avail_update(handle);
270
		cperiod++;
531 kaklik 271
	}
527 kaklik 272
}
273
 
274
 
526 kaklik 275
int main(int argc, char *argv[])
276
{
277
	snd_pcm_t *playback_handle, *capture_handle;
278
	int err;
279
	snd_pcm_hw_params_t *hwparams;
280
	snd_pcm_sw_params_t *swparams;
281
	signed short *frame;  // pointer to array of samples
282
	unsigned int chn;
283
	snd_pcm_channel_area_t *areas;
284
 
285
	struct async_private_data data;
527 kaklik 286
	snd_async_handler_t *chandler, *phandler;
526 kaklik 287
	int count;
532 kaklik 288
	unsigned int i,j,m,n;
289
	unsigned int delay;	//store delay of maximal correlation
290
  	double r;
291
	double correlation[1000000]; //array to store correlation curve
526 kaklik 292
 
527 kaklik 293
	FILE *out;
526 kaklik 294
 
295
	snd_pcm_hw_params_alloca(&hwparams);
296
	snd_pcm_sw_params_alloca(&swparams);
297
 
532 kaklik 298
//open and set playback device
526 kaklik 299
	if ((err = snd_pcm_open(&playback_handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
300
		printf("Playback open error: %s\n", snd_strerror(err));
301
		return 0;
302
	}
303
 
304
	if ((err = set_hwparams(playback_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
305
		printf("Setting of hwparams failed: %s\n", snd_strerror(err));
306
		exit(EXIT_FAILURE);
307
	}
308
	if ((err = set_swparams(playback_handle, swparams)) < 0) {
309
		printf("Setting of swparams failed: %s\n", snd_strerror(err));
310
		exit(EXIT_FAILURE);
311
	}
312
 
313
//open and set capture device
314
	if ((err = snd_pcm_open(&capture_handle, device, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
315
		printf("Playback open error: %s\n", snd_strerror(err));
316
		return 0;
317
	}
318
 
319
	if ((err = set_hwparams(capture_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
320
		printf("Setting of hwparams failed: %s\n", snd_strerror(err));
321
		exit(EXIT_FAILURE);
322
	}
530 kaklik 323
	if ((err = set_swparams(capture_handle, swparams)) < 0) {
526 kaklik 324
		printf("Setting of swparams failed: %s\n", snd_strerror(err));
325
		exit(EXIT_FAILURE);
530 kaklik 326
	}
526 kaklik 327
 
531 kaklik 328
        chirp_size=linear_windowed_chirp(chirp,1000000);
526 kaklik 329
 
527 kaklik 330
/// register playback callback 
331
	err = snd_async_add_pcm_handler(&phandler, playback_handle, async_playback_callback, &data); // fill by dummy &data
526 kaklik 332
	if (err < 0) {
333
		printf("Unable to register async handler\n");
334
		exit(EXIT_FAILURE);
335
	}
531 kaklik 336
	for (period = 0; period < 2; period++) {
526 kaklik 337
 
527 kaklik 338
		err = snd_pcm_writei(playback_handle, (chirp+period*period_size), period_size);
526 kaklik 339
		if (err < 0) {
340
			printf("Initial write error: %s\n", snd_strerror(err));
341
			exit(EXIT_FAILURE);
342
		}
343
		if (err != period_size) {
344
			printf("Initial write error: written %i expected %li\n", err, period_size);
345
			exit(EXIT_FAILURE);
346
		}
347
	}
348
 
527 kaklik 349
// register capture callback 
350
	err = snd_async_add_pcm_handler(&chandler, capture_handle, async_capture_callback, &data); // fill by dummy &data
351
	if (err < 0) {
352
		printf("Unable to register async handler\n");
353
		exit(EXIT_FAILURE);
354
	}
355
 
526 kaklik 356
//start playback
357
	if (snd_pcm_state(playback_handle) == SND_PCM_STATE_PREPARED) {
358
		err = snd_pcm_start(playback_handle);
359
		if (err < 0) {
360
			printf("Start error: %s\n", snd_strerror(err));
361
			exit(EXIT_FAILURE);
362
		}
363
	}
364
 
527 kaklik 365
//start capture
366
	if ((err = snd_pcm_prepare (capture_handle)) < 0) {
367
		fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
368
			 snd_strerror (err));
369
		exit (1);
370
	}
371
 
372
	err = snd_pcm_start(capture_handle);
373
	if (err < 0) {
374
			printf("Start error: %s\n", snd_strerror(err));
375
			exit(EXIT_FAILURE);
376
	}
377
 
532 kaklik 378
//wait until all samples aren't transmitted
379
	printf("Waiting for transmitt all samples\n");
531 kaklik 380
	while(cperiod<10) {
526 kaklik 381
		sleep(1);
532 kaklik 382
		printf(".");
527 kaklik 383
	}	
532 kaklik 384
	printf("\nData transmitted... \nprocessing...\n");
526 kaklik 385
 
527 kaklik 386
	out=fopen("./output.txt","w");
532 kaklik 387
	for(i=0;i<=100000;i++) fprintf(out,"%6d	%6d %6d \n",i,chirp[i],signal[i]); 
531 kaklik 388
	fclose(out);
526 kaklik 389
 
532 kaklik 390
#define SIGNAL_SAMPLES 100000
391
#define SAMPLES  1000
392
 
393
   for(n=0; n < (SIGNAL_SAMPLES - SAMPLES);n++){			//spocita korelaci pro mozna spozdeni
394
     r=0;
395
     for(m=0;m < SAMPLES;m++) r += chirp[m]*signal[m+n];
396
     correlation[n]=r;
397
   }
398
 
399
   r=0;
400
   for(n=0; n < (SIGNAL_SAMPLES - SAMPLES);n++){			//najde nejvetsi shodu (pro nazornost v samostatnem cyklu)
401
     if (r < correlation[n]){
402
       delay = n;
403
       r = correlation[n];
404
     }
405
   }
406
 
407
	printf("\nEcho zacina na: %d vzorku.\n", delay);
408
	printf("\nCasove na: %ds", delay);
409
 
526 kaklik 410
	snd_pcm_close(playback_handle);
411
	snd_pcm_close(capture_handle);
412
	return 0;
413
}
414