Subversion Repositories svnkaklik

Rev

Rev 530 | 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
 
531 kaklik 26
unsigned int chirp_size;
527 kaklik 27
 
526 kaklik 28
int period=0;
527 kaklik 29
int cperiod=0;
531 kaklik 30
int chirp[1000000];
527 kaklik 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
 
531 kaklik 231
unsigned int linear_windowed_chirp(unsigned int *pole, unsigned int delka_pole){  // vygeneruje linearni chirp a vzorky ulozi do pole
526 kaklik 232
 
527 kaklik 233
unsigned int maxval = (1 << (snd_pcm_format_width(format) - 1)) - 1;
526 kaklik 234
 
531 kaklik 235
static const float f0 = 1000;
236
static const float fmax = 5000;
237
static const float Tw = 0.2;
527 kaklik 238
static float k;
526 kaklik 239
 
531 kaklik 240
unsigned int n=0;
241
double t;
242
unsigned int perioda;
526 kaklik 243
 
531 kaklik 244
k=2*(fmax-f0)/Tw;
245
perioda = rate*Tw; 
526 kaklik 246
 
531 kaklik 247
   for(n=0;n<=perioda;n++){
248
      t = (double) n/ (double)rate;
249
      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))) );
527 kaklik 250
   }
531 kaklik 251
   return perioda;
527 kaklik 252
}
253
 
531 kaklik 254
int sine(unsigned int *pole, unsigned int delka_pole)
526 kaklik 255
{
527 kaklik 256
unsigned int maxval = (1 << (snd_pcm_format_width(format) - 1)) - 1;
531 kaklik 257
unsigned int n;
258
double t;
259
 
260
  for(n=0;n < delka_pole;n++){
261
    t = 440.0 * (double) n/ (double)rate;
262
    pole[n] = (short) round(maxval*sin(2*M_PI*t));
263
  }
526 kaklik 264
}
265
 
266
 
267
 
268
static void async_playback_callback(snd_async_handler_t *ahandler)
269
{
270
	snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler);
527 kaklik 271
/*	struct async_private_data *data = snd_async_handler_get_callback_private(ahandler);
526 kaklik 272
	signed short *samples = data->samples;
527 kaklik 273
	snd_pcm_channel_area_t *areas = data->areas;*/
526 kaklik 274
	snd_pcm_sframes_t avail;
275
	int err;
276
 
277
	avail = snd_pcm_avail_update(handle);
531 kaklik 278
	while ((avail >= period_size) && ((period*period_size) < chirp_size) ) {
526 kaklik 279
 
527 kaklik 280
		err = snd_pcm_writei(handle, (chirp+period*period_size), period_size);
526 kaklik 281
		if (err < 0) {
282
			printf("Write error: %s\n", snd_strerror(err));
283
			exit(EXIT_FAILURE);
284
		}
285
		if (err != period_size) {
286
			printf("Write error: written %i expected %li\n", err, period_size);
287
			exit(EXIT_FAILURE);
288
		}
289
		avail = snd_pcm_avail_update(handle);
527 kaklik 290
		period++;
526 kaklik 291
	}
292
}
293
 
527 kaklik 294
static void async_capture_callback(snd_async_handler_t *ahandler)
295
{
296
	snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler);
297
/*	struct async_private_data *data = snd_async_handler_get_callback_private(ahandler);
298
	signed short *samples = data->samples;
299
	snd_pcm_channel_area_t *areas = data->areas;*/
300
	snd_pcm_sframes_t avail;
301
	int err;
302
 
303
	avail = snd_pcm_avail_update(handle);
531 kaklik 304
	while ((avail >= period_size) /*&& ((period*period_size) < (CHIRP_SIZE-100))*/ ) {
527 kaklik 305
 
306
		err = snd_pcm_readi(handle, (signal+cperiod*period_size), period_size);
307
		if (err < 0) {
308
			printf("Read error: %s\n", snd_strerror(err));
309
			exit(EXIT_FAILURE);
310
		}
311
		if (err != period_size) {
312
			printf("Read error: red %i expected %li\n", err, period_size);
313
			exit(EXIT_FAILURE);
314
		}
315
		avail = snd_pcm_avail_update(handle);
316
		cperiod++;
531 kaklik 317
	}
527 kaklik 318
}
319
 
320
 
526 kaklik 321
int main(int argc, char *argv[])
322
{
323
	snd_pcm_t *playback_handle, *capture_handle;
324
	int err;
325
	snd_pcm_hw_params_t *hwparams;
326
	snd_pcm_sw_params_t *swparams;
327
	signed short *frame;  // pointer to array of samples
328
	unsigned int chn;
329
	snd_pcm_channel_area_t *areas;
330
 
331
	struct async_private_data data;
527 kaklik 332
	snd_async_handler_t *chandler, *phandler;
526 kaklik 333
	int count;
527 kaklik 334
	unsigned int i,j;
526 kaklik 335
 
527 kaklik 336
	FILE *out;
526 kaklik 337
 
527 kaklik 338
 
526 kaklik 339
	snd_pcm_hw_params_alloca(&hwparams);
340
	snd_pcm_sw_params_alloca(&swparams);
341
 
342
//open adn set playback device
343
	if ((err = snd_pcm_open(&playback_handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
344
		printf("Playback open error: %s\n", snd_strerror(err));
345
		return 0;
346
	}
347
 
348
	if ((err = set_hwparams(playback_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
349
		printf("Setting of hwparams failed: %s\n", snd_strerror(err));
350
		exit(EXIT_FAILURE);
351
	}
352
	if ((err = set_swparams(playback_handle, swparams)) < 0) {
353
		printf("Setting of swparams failed: %s\n", snd_strerror(err));
354
		exit(EXIT_FAILURE);
355
	}
356
 
357
//open and set capture device
358
	if ((err = snd_pcm_open(&capture_handle, device, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
359
		printf("Playback open error: %s\n", snd_strerror(err));
360
		return 0;
361
	}
362
 
363
	if ((err = set_hwparams(capture_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
364
		printf("Setting of hwparams failed: %s\n", snd_strerror(err));
365
		exit(EXIT_FAILURE);
366
	}
530 kaklik 367
	if ((err = set_swparams(capture_handle, swparams)) < 0) {
526 kaklik 368
		printf("Setting of swparams failed: %s\n", snd_strerror(err));
369
		exit(EXIT_FAILURE);
530 kaklik 370
	}
526 kaklik 371
 
531 kaklik 372
        chirp_size=linear_windowed_chirp(chirp,1000000);
526 kaklik 373
 
527 kaklik 374
/// register playback callback 
375
	err = snd_async_add_pcm_handler(&phandler, playback_handle, async_playback_callback, &data); // fill by dummy &data
526 kaklik 376
	if (err < 0) {
377
		printf("Unable to register async handler\n");
378
		exit(EXIT_FAILURE);
379
	}
531 kaklik 380
	for (period = 0; period < 2; period++) {
526 kaklik 381
 
527 kaklik 382
		err = snd_pcm_writei(playback_handle, (chirp+period*period_size), period_size);
526 kaklik 383
		if (err < 0) {
384
			printf("Initial write error: %s\n", snd_strerror(err));
385
			exit(EXIT_FAILURE);
386
		}
387
		if (err != period_size) {
388
			printf("Initial write error: written %i expected %li\n", err, period_size);
389
			exit(EXIT_FAILURE);
390
		}
391
	}
392
 
527 kaklik 393
// register capture callback 
394
	err = snd_async_add_pcm_handler(&chandler, capture_handle, async_capture_callback, &data); // fill by dummy &data
395
	if (err < 0) {
396
		printf("Unable to register async handler\n");
397
		exit(EXIT_FAILURE);
398
	}
399
 
526 kaklik 400
//start playback
401
	if (snd_pcm_state(playback_handle) == SND_PCM_STATE_PREPARED) {
402
		err = snd_pcm_start(playback_handle);
403
		if (err < 0) {
404
			printf("Start error: %s\n", snd_strerror(err));
405
			exit(EXIT_FAILURE);
406
		}
407
	}
408
 
527 kaklik 409
//start capture
410
	if ((err = snd_pcm_prepare (capture_handle)) < 0) {
411
		fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
412
			 snd_strerror (err));
413
		exit (1);
414
	}
415
 
416
	err = snd_pcm_start(capture_handle);
417
	if (err < 0) {
418
			printf("Start error: %s\n", snd_strerror(err));
419
			exit(EXIT_FAILURE);
420
	}
421
 
422
 
423
 
526 kaklik 424
	/* because all other work is done in the signal handler,
425
	   suspend the process */
531 kaklik 426
	while(cperiod<10) {
526 kaklik 427
		sleep(1);
527 kaklik 428
	}	
526 kaklik 429
 
527 kaklik 430
	out=fopen("./output.txt","w");
531 kaklik 431
	for(i=0;i<=100000;i++) fprintf(out,"%6d	%6d \n",chirp[i],signal[i]); 
432
	fclose(out);
526 kaklik 433
 
434
	snd_pcm_close(playback_handle);
435
	snd_pcm_close(capture_handle);
436
	return 0;
437
}
438