41 const char* pdevice,
const char* cdevice)
43 format = SND_PCM_FORMAT_S16;
60 if ((err = snd_pcm_open(&
phandle, pdevice, SND_PCM_STREAM_PLAYBACK,
block ? 0 : SND_PCM_NONBLOCK)) < 0) {
61 cat_error(
"SndPcm::SndPcm(...): Playback open error: %s\n", snd_strerror(err));
68 if ((err = snd_pcm_open(&
chandle, cdevice, SND_PCM_STREAM_CAPTURE,
block ? 0 : SND_PCM_NONBLOCK)) < 0) {
69 cat_error(
"SndPcm::SndPcm(...): Record open error: %s\n", snd_strerror(err));
99 int nSilentBlockSamples = 0;
100 int nSilentBlockFrames = 0;
103 nSilentBlockSamples = snd_pcm_bytes_to_samples(
phandle,1024);
104 nSilentBlockFrames = snd_pcm_bytes_to_frames(
phandle,1024);
106 nSilentBlockSamples = snd_pcm_bytes_to_samples(
chandle,1024);
107 nSilentBlockFrames = snd_pcm_bytes_to_frames(
chandle,1024);
113 cat_error(
"Streams link error: %s\n", snd_strerror(err));
117 if (snd_pcm_format_set_silence(
format, buffer, nSilentBlockSamples) < 0) {
128 if (m>nSilentBlockFrames) m = nSilentBlockFrames;
129 if (writebuf(
phandle, buffer, m) < 0) {
139 if ((err = snd_pcm_start(
chandle)) < 0) {
140 cat_error(
"Go error: %s\n", snd_strerror(err));
146 if ((err = snd_pcm_start(
phandle)) < 0) {
147 cat_error(
"Go error: %s\n", snd_strerror(err));
197 if ((err = snd_pcm_start(
chandle)) < 0) {
198 cat_error(
"Go error: %s\n", snd_strerror(err));
206 if ((err = snd_pcm_start(
phandle)) < 0) {
207 cat_error(
"Go error: %s\n", snd_strerror(err));
251 int SndPcm::setparams_stream(snd_pcm_t *handle,
252 snd_pcm_hw_params_t *params,
258 err = snd_pcm_hw_params_any(handle, params);
260 cat_error(
"Broken configuration for %s PCM: no configurations available: %s\n", snd_strerror(err),
id);
263 err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
265 cat_error(
"Access type not available for %s: %s\n",
id, snd_strerror(err));
268 err = snd_pcm_hw_params_set_format(handle, params,
format);
270 cat_error(
"Sample format not available for %s: %s\n",
id, snd_strerror(err));
273 err = snd_pcm_hw_params_set_channels(handle, params, channels);
275 cat_error(
"Channels count (%i) not available for %s: %s\n", channels,
id, snd_strerror(err));
279 err = snd_pcm_hw_params_set_rate_near(handle, params,
rate, 0);
281 cat_error(
"Rate %iHz not available for %s: %s\n",
rate,
id, snd_strerror(err));
285 if (abs(err-
rate)<3) {
rate = err;
goto setrate; }
286 cat_error(
"Rate doesn't match (requested %iHz, get %iHz)\n",
rate, err);
292 int SndPcm::setparams_bufsize(snd_pcm_t *handle,
293 snd_pcm_hw_params_t *params,
294 snd_pcm_hw_params_t *tparams,
295 snd_pcm_uframes_t bufsize,
299 snd_pcm_uframes_t periodsize;
301 snd_pcm_hw_params_copy(params, tparams);
302 err = snd_pcm_hw_params_set_buffer_size_near(handle, params, bufsize * 2);
304 cat_error(
"Unable to set buffer size %li for %s: %s\n", bufsize * 2,
id, snd_strerror(err));
307 periodsize = snd_pcm_hw_params_get_buffer_size(params) / 2;
308 err = snd_pcm_hw_params_set_period_size_near(handle, params, periodsize, 0);
310 cat_error(
"Unable to set period size %li for %s: %s\n", periodsize,
id, snd_strerror(err));
316 int SndPcm::setparams_set(snd_pcm_t *handle,
317 snd_pcm_hw_params_t *params,
318 snd_pcm_sw_params_t *swparams,
321 int err, val, sleep_min = 0;
323 err = snd_pcm_hw_params(handle, params);
325 cat_error(
"Unable to set hw params for %s: %s\n",
id, snd_strerror(err));
328 err = snd_pcm_sw_params_current(handle, swparams);
330 cat_error(
"Unable to determine current swparams for %s: %s\n",
id, snd_strerror(err));
333 err = snd_pcm_sw_params_set_start_threshold(handle, swparams, 0x7fffffff);
335 cat_error(
"Unable to set start threshold mode for %s: %s\n",
id, snd_strerror(err));
341 time = snd_pcm_hw_params_get_period_time(params,
NULL);
342 ttime = snd_pcm_hw_params_get_tick_time(params,
NULL);
344 cat_error(
"Skipping to set minimal sleep: period time < tick time\n");
345 }
else if (ttime <= 0) {
346 cat_error(
"Skipping to set minimal sleep: tick time <= 0 (%i)\n", ttime);
351 err = snd_pcm_sw_params_set_sleep_min(handle, swparams, sleep_min);
353 cat_error(
"Unable to set minimal sleep %i for %s: %s\n", sleep_min,
id, snd_strerror(err));
359 val = !
block ? 4 : snd_pcm_hw_params_get_period_size(params,
NULL);
362 val = snd_pcm_hw_params_get_period_size(params,
NULL);
363 err = snd_pcm_sw_params_set_avail_min(handle, swparams, val);
365 cat_error(
"Unable to set avail min for %s: %s\n",
id, snd_strerror(err));
368 val = !
block ? 4 : 1;
369 err = snd_pcm_sw_params_set_xfer_align(handle, swparams, val);
371 cat_error(
"Unable to set transfer align for %s: %s\n",
id, snd_strerror(err));
374 err = snd_pcm_sw_params(handle, swparams);
376 cat_error(
"Unable to set sw params for %s: %s\n",
id, snd_strerror(err));
382 int SndPcm::setparams(snd_pcm_t *phandle, snd_pcm_t *chandle,
int *bufsize)
384 int err, last_bufsize = *bufsize;
385 snd_pcm_hw_params_t *pt_params = 0, *ct_params = 0;
386 snd_pcm_hw_params_t *p_params = 0, *c_params = 0;
387 snd_pcm_sw_params_t *p_swparams = 0, *c_swparams = 0;
388 snd_pcm_sframes_t size;
392 snd_pcm_hw_params_alloca(&p_params);
393 snd_pcm_hw_params_alloca(&pt_params);
394 snd_pcm_sw_params_alloca(&p_swparams);
399 snd_pcm_hw_params_alloca(&c_params);
400 snd_pcm_hw_params_alloca(&ct_params);
401 snd_pcm_sw_params_alloca(&c_swparams);
404 if (phandle && (err = setparams_stream(phandle, pt_params,
channels_out,
"playback")) < 0) {
405 cat_error(
"Unable to set parameters for playback stream: %s\n", snd_strerror(err));
408 if (chandle && (err = setparams_stream(chandle, ct_params,
channels_in,
"capture")) < 0) {
409 cat_error(
"Unable to set parameters for playback stream: %s\n", snd_strerror(err));
413 if (last_bufsize == *bufsize)
415 last_bufsize = *bufsize;
419 if (phandle && (err = setparams_bufsize(phandle, p_params, pt_params, *bufsize,
"playback")) < 0) {
420 cat_error(
"Unable to set sw parameters for playback stream: %s\n", snd_strerror(err));
424 if (chandle && (err = setparams_bufsize(chandle, c_params, ct_params, *bufsize,
"capture")) < 0) {
425 cat_error(
"Unable to set sw parameters for playback stream: %s\n", snd_strerror(err));
431 size = snd_pcm_hw_params_get_period_size(p_params,
NULL);
438 size = snd_pcm_hw_params_get_period_size(c_params,
NULL);
443 if (c_params && p_params)
444 if (snd_pcm_hw_params_get_period_time(p_params,
NULL) !=
445 snd_pcm_hw_params_get_period_time(c_params,
NULL))
447 if (p_params && snd_pcm_hw_params_get_period_size(p_params,
NULL) * 2 < snd_pcm_hw_params_get_buffer_size(p_params))
449 if (c_params && snd_pcm_hw_params_get_period_size(c_params,
NULL) * 2 < snd_pcm_hw_params_get_buffer_size(c_params))
452 if (phandle && (err = setparams_set(phandle, p_params, p_swparams,
"playback")) < 0) {
453 cat_error(
"Unable to set sw parameters for playback stream: %s\n", snd_strerror(err));
456 if (chandle && (err = setparams_set(chandle, c_params, c_swparams,
"capture")) < 0) {
457 cat_error(
"Unable to set sw parameters for playback stream: %s\n", snd_strerror(err));
463 if ((err = snd_pcm_prepare(phandle)) < 0) {
464 cat_error(
"Prepare error: %s\n", snd_strerror(err));
468 if ((err = snd_pcm_prepare(chandle)) < 0) {
469 cat_error(
"Prepare error: %s\n", snd_strerror(err));
478 long SndPcm::readbuf(snd_pcm_t *handle,
char *buf,
long len)
484 r = snd_pcm_readi(handle, buf, len);
485 }
while (r == -EAGAIN);
495 r = snd_pcm_readi(handle, buf, len);
497 buf += r * frame_bytes;
504 }
while (r >= 1 && len > 0);
510 long SndPcm::writebuf(snd_pcm_t *handle,
char *buf,
long len)
515 r = snd_pcm_writei(handle, buf, len);
556 void setscheduler(
void)
558 struct sched_param sched_param;
560 if (sched_getparam(0, &sched_param) < 0) {
561 printf(
"Scheduler getparam failed...\n");
564 sched_param.sched_priority = sched_get_priority_max(SCHED_RR);
565 if (!sched_setscheduler(0, SCHED_RR, &sched_param)) {
566 printf(
"Scheduler set to Round Robin with priority %i...\n", sched_param.sched_priority);
570 printf(
"!!!Scheduler set to Round Robin with priority %i FAILED!!!\n", sched_param.sched_priority);
578 SndPcm sndpcm(44099,2,
"plughw:0,0",
"plughw:0,0");
584 for (
int i=0;i<1000;i++)
588 sndpcm.WriteBuf(buf);