All of lore.kernel.org
 help / color / mirror / Atom feed
* Need a little help with underruns / fullduplex
@ 2003-06-20 19:14 alsa
  2003-06-21  7:25 ` Jaroslav Kysela
  0 siblings, 1 reply; 2+ messages in thread
From: alsa @ 2003-06-20 19:14 UTC (permalink / raw)
  To: alsa-devel


Hi all,

I'm trying to build a full-duplex app using alsa, but I'm having some
problems with getting buffsersizes and timing right. I can't get a simple 
record-and-playback app working right without underruns occuring.

I hope some experienced alsa programmers can take a quick look at my
attached piece of code and tell me what I need to do to get this working
right. (or am I just doing things *really* wrong here ?)

Hope to get some helpfull tips,

Ico




os : linx 2.4.20
alsa version: 0.9.4
soundcard: intel810

-----------------------------------------------------------------------------

#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <sys/select.h>

#define ALSA_PCM_NEW_HW_PARAMS_API
#define ALSA_PCM_NEW_SW_PARAMS_API
#include <alsa/asoundlib.h>
#include <math.h>

#define PERIODSIZE 512
#define BUFSIZE	(PERIODSIZE*4)

char *device	= "hw:0,0";
int samplerate 	= 16000;
int channels 	= 2;
int accessmode	= SND_PCM_ACCESS_RW_INTERLEAVED;
int format	= SND_PCM_FORMAT_S16_LE;
int periods	= 4;
snd_pcm_uframes_t buffer_size = PERIODSIZE * 4;
snd_pcm_uframes_t period_size = PERIODSIZE;

snd_output_t *output = NULL;


#define checkr(r) if(r<0) { \
			fprintf(stderr, "line %d: %s\n", __LINE__, snd_strerror(r)); \
			exit(-1); \
		  }


int set_hw_params(snd_pcm_t *handle, int play)
{
	int r;
	snd_pcm_hw_params_t *hwparams;
	snd_pcm_sw_params_t *swparams;
	
	r = snd_pcm_hw_params_malloc(&hwparams); checkr(r);
	r = snd_pcm_hw_params_any(handle, hwparams); checkr(r);
	r = snd_pcm_hw_params_set_access(handle, hwparams, accessmode);	checkr(r);
	r = snd_pcm_hw_params_set_format(handle, hwparams, format); checkr(r);
	r = snd_pcm_hw_params_set_channels(handle, hwparams, channels); checkr(r);
	r = snd_pcm_hw_params_set_rate_near(handle, hwparams, &samplerate, 0); checkr(r);
	r = snd_pcm_hw_params_set_periods(handle, hwparams, periods, 0); checkr(r);
	r = snd_pcm_hw_params_set_buffer_size_near(handle, hwparams, &buffer_size); checkr(r);
	r = snd_pcm_hw_params_set_period_size_near(handle, hwparams, &period_size, 0); checkr(r);
	r = snd_pcm_hw_params(handle, hwparams); checkr(r);
	snd_pcm_hw_params_free (hwparams);

	r = snd_pcm_sw_params_malloc(&swparams); checkr(r);
	r = snd_pcm_sw_params_current(handle, swparams); checkr(r);
	r = snd_pcm_sw_params_set_avail_min(handle, swparams, period_size); checkr(r);
	r = snd_pcm_sw_params(handle, swparams); checkr(r);
	snd_pcm_sw_params_free(swparams);

	snd_pcm_prepare(handle);
	
	return(0);
}

int main(int argc, char **argv)
{
	short buf[BUFSIZE*10];
	int r;
	
	snd_pcm_t *pcmr;
	snd_pcm_t *pcmp;
	
	r = snd_pcm_open(&pcmr, device, SND_PCM_STREAM_CAPTURE, 0); checkr(r);
	set_hw_params(pcmr, 1);	

	r = snd_pcm_open(&pcmp, device, SND_PCM_STREAM_PLAYBACK, 0); checkr(r);
	set_hw_params(pcmp, 1);

	while(1) {
		
		r = snd_pcm_readi(pcmr, buf, BUFSIZE);

		if(r != BUFSIZE) printf("rec  r=%d\n", r);
		checkr(r);

		r = snd_pcm_writei(pcmp, buf, BUFSIZE);

		if(r != BUFSIZE) printf("play r=%d\n", r);
		if(r == -EPIPE) {
			snd_pcm_prepare(pcmp);
		} else {
			checkr(r);
		}

	}
		
	return(0);
}


-- 


-------------------------------------------------------
This SF.Net email is sponsored by: INetU
Attention Web Developers & Consultants: Become An INetU Hosting Partner.
Refer Dedicated Servers. We Manage Them. You Get 10% Monthly Commission!
INetU Dedicated Managed Hosting http://www.inetu.net/partner/index.php

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Need a little help with underruns / fullduplex
  2003-06-20 19:14 Need a little help with underruns / fullduplex alsa
@ 2003-06-21  7:25 ` Jaroslav Kysela
  0 siblings, 0 replies; 2+ messages in thread
From: Jaroslav Kysela @ 2003-06-21  7:25 UTC (permalink / raw)
  To: alsa@zevv.nl; +Cc: alsa-devel@lists.sourceforge.net

On Fri, 20 Jun 2003, alsa@zevv.nl wrote:

> 	while(1) {
> 		
> 		r = snd_pcm_readi(pcmr, buf, BUFSIZE);
> 
> 		if(r != BUFSIZE) printf("rec  r=%d\n", r);
> 		checkr(r);
> 
> 		r = snd_pcm_writei(pcmp, buf, BUFSIZE);
> 
> 		if(r != BUFSIZE) printf("play r=%d\n", r);
> 		if(r == -EPIPE) {
> 			snd_pcm_prepare(pcmp);
> 		} else {
> 			checkr(r);
> 		}
> 
> 	}


This loop is definitely wrong. I explained several times why. You cannot 
do while (1) { read(); write(); } but:

/* prefill the playback buffer with the desired latency */
while (!minimal_latency_reached)
	write();
start_capture();
start_playback();
/* normal loop */
while (1) {
	read();
	write();
}

						Jaroslav

-----
Jaroslav Kysela <perex@suse.cz>
Linux Kernel Sound Maintainer
ALSA Project, SuSE Labs



-------------------------------------------------------
This SF.Net email is sponsored by: INetU
Attention Web Developers & Consultants: Become An INetU Hosting Partner.
Refer Dedicated Servers. We Manage Them. You Get 10% Monthly Commission!
INetU Dedicated Managed Hosting http://www.inetu.net/partner/index.php

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2003-06-21  7:25 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-06-20 19:14 Need a little help with underruns / fullduplex alsa
2003-06-21  7:25 ` Jaroslav Kysela

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.