Subversion Repositories svnkaklik

Rev

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