Subversion Repositories svnkaklik

Rev

Rev 526 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log

Rev Author Line No. Line
526 kaklik 1
/*
2
 *  This small demo sends a simple sinusoidal wave to your speakers.
3
 */
4
 
5
#include <stdio.h>
6
#include <stdlib.h>
7
#include <string.h>
8
#include <sched.h>
9
#include <errno.h>
10
#include <getopt.h>
11
#include <alsa/asoundlib.h>
12
#include <sys/time.h>
13
#include <math.h>
14
 
15
static char *device = "plughw:0,0";			/* playback device */
16
static snd_pcm_format_t format = SND_PCM_FORMAT_S16;	/* sample format */
17
static unsigned int rate = 44100;			/* stream rate */
18
static unsigned int channels = 1;			/* count of channels */
19
static unsigned int buffer_time = 500000;		/* ring buffer length in us */
20
static unsigned int period_time = 100000;		/* period time in us */
21
static double freq = 440;				/* sinusoidal wave frequency in Hz */
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
 
527 kaklik 26
#define  CHIRP_SIZE	1000000
27
 
526 kaklik 28
int period=0;
527 kaklik 29
int cperiod=0;
30
short chirp[CHIRP_SIZE];
31
short signal[44100*6];		// record 6s of input samples
526 kaklik 32
 
33
static snd_pcm_sframes_t buffer_size;	// size of buffer at sound card
34
static snd_pcm_sframes_t period_size;	//samples per frame
35
static snd_output_t *output = NULL;
36
 
37
/*static void generate_sine(const snd_pcm_channel_area_t *areas, 
38
			  snd_pcm_uframes_t offset,
39
			  int count, double *_phase)
40
{
41
	static double max_phase = 2. * M_PI;
42
	double phase = *_phase;
43
	double step = max_phase*freq/(double)rate;
44
	double res;
45
	unsigned char *samples[channels], *tmp;
46
	int steps[channels];
47
	unsigned int chn, byte;
48
	union {
49
		int i;
50
		unsigned char c[4];
51
	} ires;
52
	unsigned int maxval = (1 << (snd_pcm_format_width(format) - 1)) - 1;
53
	int bps = snd_pcm_format_width(format) / 8;  /* bytes per sample */
54
 
55
	/* verify and prepare the contents of areas 
56
	for (chn = 0; chn < channels; chn++) {
57
		if ((areas[chn].first % 8) != 0) {
58
			printf("areas[%i].first == %i, aborting...\n", chn, areas[chn].first);
59
			exit(EXIT_FAILURE);
60
		}
61
		samples[chn] = /*(signed short *)(((unsigned char *)areas[chn].addr) + (areas[chn].first / 8));
62
		if ((areas[chn].step % 16) != 0) {
63
			printf("areas[%i].step == %i, aborting...\n", chn, areas[chn].step);
64
			exit(EXIT_FAILURE);
65
		}
66
		steps[chn] = areas[chn].step / 8;
67
		samples[chn] += offset * steps[chn];
68
	}
69
	/* fill the channel areas 
70
	while (count-- > 0) {
71
		res = sin(phase) * maxval;
72
		ires.i = res;
73
		tmp = ires.c;
74
		for (chn = 0; chn < channels; chn++) {
75
			for (byte = 0; byte < (unsigned int)bps; byte++)
76
				*(samples[chn] + byte) = tmp[byte];
77
			samples[chn] += steps[chn];
78
		}
79
		phase += step;
80
		if (phase >= max_phase)
81
			phase -= max_phase;
82
	}
83
	*_phase = phase;
84
}*/
85
 
86
static int set_hwparams(snd_pcm_t *handle,
87
			snd_pcm_hw_params_t *params,
88
			snd_pcm_access_t access)
89
{
90
	unsigned int rrate;
91
	snd_pcm_uframes_t size;
92
	int err, dir;
93
 
94
	/* choose all parameters */
95
	err = snd_pcm_hw_params_any(handle, params);
96
	if (err < 0) {
97
		printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err));
98
		return err;
99
	}
100
	/* set hardware resampling */
101
	err = snd_pcm_hw_params_set_rate_resample(handle, params, resample);
102
	if (err < 0) {
103
		printf("Resampling setup failed for playback: %s\n", snd_strerror(err));
104
		return err;
105
	}
106
	/* set the interleaved read/write format */
107
	err = snd_pcm_hw_params_set_access(handle, params, access);
108
	if (err < 0) {
109
		printf("Access type not available for playback: %s\n", snd_strerror(err));
110
		return err;
111
	}
112
	/* set the sample format */
113
	err = snd_pcm_hw_params_set_format(handle, params, format);
114
	if (err < 0) {
115
		printf("Sample format not available for playback: %s\n", snd_strerror(err));
116
		return err;
117
	}
118
	/* set the count of channels */
119
	err = snd_pcm_hw_params_set_channels(handle, params, channels);
120
	if (err < 0) {
121
		printf("Channels count (%i) not available for playbacks: %s\n", channels, snd_strerror(err));
122
		return err;
123
	}
124
	/* set the stream rate */
125
	rrate = rate;
126
	err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0);
127
	if (err < 0) {
128
		printf("Rate %iHz not available for playback: %s\n", rate, snd_strerror(err));
129
		return err;
130
	}
131
	if (rrate != rate) {
132
		printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, err);
133
		return -EINVAL;
134
	}
135
	/* set the buffer time */
136
	err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, &dir);
137
	if (err < 0) {
138
		printf("Unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror(err));
139
		return err;
140
	}
141
	err = snd_pcm_hw_params_get_buffer_size(params, &size);
142
	if (err < 0) {
143
		printf("Unable to get buffer size for playback: %s\n", snd_strerror(err));
144
		return err;
145
	}
146
	buffer_size = size;
147
	/* set the period time */
148
	err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, &dir);
149
	if (err < 0) {
150
		printf("Unable to set period time %i for playback: %s\n", period_time, snd_strerror(err));
151
		return err;
152
	}
153
	err = snd_pcm_hw_params_get_period_size(params, &size, &dir);
154
	if (err < 0) {
155
		printf("Unable to get period size for playback: %s\n", snd_strerror(err));
156
		return err;
157
	}
158
	period_size = size;
159
	/* write the parameters to device */
160
	err = snd_pcm_hw_params(handle, params);
161
	if (err < 0) {
162
		printf("Unable to set hw params for playback: %s\n", snd_strerror(err));
163
		return err;
164
	}
165
	return 0;
166
}
167
 
168
static int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams)
169
{
170
	int err;
171
 
172
	/* get the current swparams */
173
	err = snd_pcm_sw_params_current(handle, swparams);
174
	if (err < 0) {
175
		printf("Unable to determine current swparams for playback: %s\n", snd_strerror(err));
176
		return err;
177
	}
178
	/* start the transfer when the buffer is almost full: */
179
	/* (buffer_size / avail_min) * avail_min */
180
	err = snd_pcm_sw_params_set_start_threshold(handle, swparams, (buffer_size / period_size) * period_size);
181
	if (err < 0) {
182
		printf("Unable to set start threshold mode for playback: %s\n", snd_strerror(err));
183
		return err;
184
	}
185
	/* allow the transfer when at least period_size samples can be processed */
186
	/* or disable this mechanism when period event is enabled (aka interrupt like style processing) */
187
	err = snd_pcm_sw_params_set_avail_min(handle, swparams, period_event ? buffer_size : period_size);
188
	if (err < 0) {
189
		printf("Unable to set avail min for playback: %s\n", snd_strerror(err));
190
		return err;
191
	}
192
	/* enable period events when requested */
193
	if (period_event) {
194
		err = snd_pcm_sw_params_set_period_event(handle, swparams, 1);
195
		if (err < 0) {
196
			printf("Unable to set period event: %s\n", snd_strerror(err));
197
			return err;
198
		}
199
	}
200
	/* write the parameters to the playback device */
201
	err = snd_pcm_sw_params(handle, swparams);
202
	if (err < 0) {
203
		printf("Unable to set sw params for playback: %s\n", snd_strerror(err));
204
		return err;
205
	}
206
	return 0;
207
}
208
 
209
struct async_private_data {
210
	signed short *samples;
211
	snd_pcm_channel_area_t *areas;
212
	unsigned int period;
213
};
214
 
215
/*int linear_chirp(int *pole, int delka_pole){  // vygeneruje linearni chirp a vzorky ulozi do pole
216
 
217
static const float f0 = 0.0001;
218
static const float k = 0.00001;
219
 
220
int t;
221
 
222
//  if((spozdeni+delka) < delka_pole)
223
    for(t=0;t < delka_pole;t++) pole[t] = round ( 10000*sin(2*M_PI*(t+faze)*(f0+(k/2)*(t+faze))) );
224
    faze +=t;
225
//  else return 0;
226
 
527 kaklik 227
}*/
526 kaklik 228
 
527 kaklik 229
 
230
 
526 kaklik 231
int linear_windowed_chirp(int *pole, int delka_pole){  // vygeneruje linearni chirp a vzorky ulozi do pole
232
 
527 kaklik 233
unsigned int maxval = (1 << (snd_pcm_format_width(format) - 1)) - 1;
526 kaklik 234
 
527 kaklik 235
static const float f0 = 1/1000;
236
static const float fmax = 1/10000;
237
static const float Tw = 10;
526 kaklik 238
 
527 kaklik 239
static float k;
526 kaklik 240
 
241
 
527 kaklik 242
//k=2*(fmax-Tw*f0)/Tw*Tw;
243
k=1/10000;
526 kaklik 244
 
527 kaklik 245
int n;
246
double t;
247
 
248
   for(n=0;n < delka_pole;n++){
249
      t=n*1/rate;
250
      pole[n] = (short) round ( /*(0.35875 - 0.48829*cos((t)*0.0001) + 0.14128*cos(.0002*(t)) - 0.01168*cos(.0003*(t)))*/  maxval*sin(2*M_PI*(t)*(f0+(k/2)*(t))) );
251
   }
252
}
253
 
526 kaklik 254
int sine(int *pole, int delka_pole)
255
{
527 kaklik 256
unsigned int maxval = (1 << (snd_pcm_format_width(format) - 1)) - 1;
526 kaklik 257
int t;
527 kaklik 258
  for(t=0;t < delka_pole;t++) pole[t] = (short) round(maxval*sin( (double)(t)/10.0));
526 kaklik 259
}
260
 
261
 
262
 
263
static void async_playback_callback(snd_async_handler_t *ahandler)
264
{
265
	snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler);
527 kaklik 266
/*	struct async_private_data *data = snd_async_handler_get_callback_private(ahandler);
526 kaklik 267
	signed short *samples = data->samples;
527 kaklik 268
	snd_pcm_channel_area_t *areas = data->areas;*/
526 kaklik 269
	snd_pcm_sframes_t avail;
270
	int err;
271
 
272
	avail = snd_pcm_avail_update(handle);
527 kaklik 273
	while ((avail >= period_size) /*&& ((period*period_size) < (CHIRP_SIZE-100))*/ ) {
526 kaklik 274
 
527 kaklik 275
		err = snd_pcm_writei(handle, (chirp+period*period_size), period_size);
526 kaklik 276
		if (err < 0) {
277
			printf("Write error: %s\n", snd_strerror(err));
278
			exit(EXIT_FAILURE);
279
		}
280
		if (err != period_size) {
281
			printf("Write error: written %i expected %li\n", err, period_size);
282
			exit(EXIT_FAILURE);
283
		}
284
		avail = snd_pcm_avail_update(handle);
527 kaklik 285
		period++;
526 kaklik 286
	}
287
}
288
 
527 kaklik 289
static void async_capture_callback(snd_async_handler_t *ahandler)
290
{
291
	snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler);
292
/*	struct async_private_data *data = snd_async_handler_get_callback_private(ahandler);
293
	signed short *samples = data->samples;
294
	snd_pcm_channel_area_t *areas = data->areas;*/
295
	snd_pcm_sframes_t avail;
296
	int err;
297
 
298
	avail = snd_pcm_avail_update(handle);
299
//	while ((avail >= period_size) /*&& ((period*period_size) < (CHIRP_SIZE-100))*/ ) {
300
 
301
		err = snd_pcm_readi(handle, (signal+cperiod*period_size), period_size);
302
		if (err < 0) {
303
			printf("Read error: %s\n", snd_strerror(err));
304
			exit(EXIT_FAILURE);
305
		}
306
		if (err != period_size) {
307
			printf("Read error: red %i expected %li\n", err, period_size);
308
			exit(EXIT_FAILURE);
309
		}
310
		avail = snd_pcm_avail_update(handle);
311
		cperiod++;
312
//	}
313
}
314
 
315
 
526 kaklik 316
int main(int argc, char *argv[])
317
{
318
	snd_pcm_t *playback_handle, *capture_handle;
319
	int err;
320
	snd_pcm_hw_params_t *hwparams;
321
	snd_pcm_sw_params_t *swparams;
322
	signed short *frame;  // pointer to array of samples
323
	unsigned int chn;
324
	snd_pcm_channel_area_t *areas;
325
 
326
	struct async_private_data data;
527 kaklik 327
	snd_async_handler_t *chandler, *phandler;
526 kaklik 328
	int count;
527 kaklik 329
	unsigned int i,j;
526 kaklik 330
 
527 kaklik 331
	FILE *out;
526 kaklik 332
 
527 kaklik 333
 
526 kaklik 334
	snd_pcm_hw_params_alloca(&hwparams);
335
	snd_pcm_sw_params_alloca(&swparams);
336
 
337
//open adn set playback device
338
	if ((err = snd_pcm_open(&playback_handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
339
		printf("Playback open error: %s\n", snd_strerror(err));
340
		return 0;
341
	}
342
 
343
	if ((err = set_hwparams(playback_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
344
		printf("Setting of hwparams failed: %s\n", snd_strerror(err));
345
		exit(EXIT_FAILURE);
346
	}
347
	if ((err = set_swparams(playback_handle, swparams)) < 0) {
348
		printf("Setting of swparams failed: %s\n", snd_strerror(err));
349
		exit(EXIT_FAILURE);
350
	}
351
 
352
//open and set capture device
353
	if ((err = snd_pcm_open(&capture_handle, device, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
354
		printf("Playback open error: %s\n", snd_strerror(err));
355
		return 0;
356
	}
357
 
358
	if ((err = set_hwparams(capture_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
359
		printf("Setting of hwparams failed: %s\n", snd_strerror(err));
360
		exit(EXIT_FAILURE);
361
	}
527 kaklik 362
/*	if ((err = set_swparams(capture_handle, swparams)) < 0) {
526 kaklik 363
		printf("Setting of swparams failed: %s\n", snd_strerror(err));
364
		exit(EXIT_FAILURE);
527 kaklik 365
	}*/
526 kaklik 366
 
367
// allocate memory for frame (package of samples)
368
	frame = malloc((period_size * channels * snd_pcm_format_physical_width(format)) / 8);
369
	if (frame == NULL) {
370
		printf("No enough memory\n");
371
		exit(EXIT_FAILURE);
372
	}
373
 
527 kaklik 374
 
375
// dummy structure
526 kaklik 376
//allocate memory for frame structure definition	
377
	areas = calloc(channels, sizeof(snd_pcm_channel_area_t));
378
	if (areas == NULL) {
379
		printf("No enough memory\n");
380
		exit(EXIT_FAILURE);
381
	}
382
//fill areas by definition of frame structure
383
	for (chn = 0; chn < channels; chn++) {
384
		areas[chn].addr = frame; 	// frame start adress
385
		areas[chn].first = chn * snd_pcm_format_physical_width(format); // ofset to first sample (in bits)
386
		areas[chn].step = channels * snd_pcm_format_physical_width(format); // step between samples
387
	}
388
 
527 kaklik 389
       	data.samples = frame;
526 kaklik 390
	data.areas = areas;
391
	data.period = 1;
527 kaklik 392
// end of dummy structure 
526 kaklik 393
 
394
 
527 kaklik 395
 sine(chirp,100000);
396
 
397
/// register playback callback 
398
	err = snd_async_add_pcm_handler(&phandler, playback_handle, async_playback_callback, &data); // fill by dummy &data
526 kaklik 399
	if (err < 0) {
400
		printf("Unable to register async handler\n");
401
		exit(EXIT_FAILURE);
402
	}
527 kaklik 403
	for (period = 0; period < 3; period++) {
526 kaklik 404
 
527 kaklik 405
		err = snd_pcm_writei(playback_handle, (chirp+period*period_size), period_size);
526 kaklik 406
		if (err < 0) {
407
			printf("Initial write error: %s\n", snd_strerror(err));
408
			exit(EXIT_FAILURE);
409
		}
410
		if (err != period_size) {
411
			printf("Initial write error: written %i expected %li\n", err, period_size);
412
			exit(EXIT_FAILURE);
413
		}
414
	}
415
 
527 kaklik 416
// register capture callback 
417
	err = snd_async_add_pcm_handler(&chandler, capture_handle, async_capture_callback, &data); // fill by dummy &data
418
	if (err < 0) {
419
		printf("Unable to register async handler\n");
420
		exit(EXIT_FAILURE);
421
	}
422
 
526 kaklik 423
//start playback
424
	if (snd_pcm_state(playback_handle) == SND_PCM_STATE_PREPARED) {
425
		err = snd_pcm_start(playback_handle);
426
		if (err < 0) {
427
			printf("Start error: %s\n", snd_strerror(err));
428
			exit(EXIT_FAILURE);
429
		}
430
	}
431
 
527 kaklik 432
//start capture
433
	if ((err = snd_pcm_prepare (capture_handle)) < 0) {
434
		fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
435
			 snd_strerror (err));
436
		exit (1);
437
	}
438
 
439
	err = snd_pcm_start(capture_handle);
440
	if (err < 0) {
441
			printf("Start error: %s\n", snd_strerror(err));
442
			exit(EXIT_FAILURE);
443
	}
444
 
445
 
446
 
526 kaklik 447
	/* because all other work is done in the signal handler,
448
	   suspend the process */
527 kaklik 449
	while(cperiod<10) {
526 kaklik 450
		sleep(1);
527 kaklik 451
	}	
526 kaklik 452
 
527 kaklik 453
	out=fopen("./output.txt","w");
454
	for(i=0;i<=100000;i++) fprintf(out,"%d ",signal[i]); 
455
	fclose(out);	
526 kaklik 456
 
457
	free(areas);
458
	free(frame);
527 kaklik 459
 
526 kaklik 460
	snd_pcm_close(playback_handle);
461
	snd_pcm_close(capture_handle);
462
	return 0;
463
}
464