Fragment size

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello List-users!

I have been dealing with this for quite some time now and I cannot get
to the point.

I have a rather simple code of maybe 100 lines which just writes some
buffer to the soundcard using snd_pcm_writei(). Although the buffer is
just there within the program itself (no external source, just internal
in order to understand the code), I am running into underruns.

I don't see the point - how ca I run into underruns, if data is always
there?

In addition I would like to set the "fragment count" of the driver - I
think this term is derived from OSS. I would like to have at least three
fragments of each 256 frames, but I do not know how to set this. The
doxygen documentation is not a real good source I must admit...

Could anyone please help me?

Thanks in advance
Dennis

I attached my testcode.
#include "includes.h"
#include "defines.h"

struct globals global;

int main( int argc, char ** argv) {
	int transmitter_decision = 0;	/* simple flag for bool choice of server */
	snd_pcm_t *sound_handler;
	struct sched_param scheduler_parameter;
	char read_data[2048];
	char *pointer;
	int written_frames;
	int len=256;
	struct timeval time2,time3;
	scheduler_parameter.sched_priority = SCHEDULER_PRIORITY;
	sched_setscheduler(0, SCHEDULER_POLICY, &scheduler_parameter);
	snd_pcm_stream_t stream;
	snd_pcm_hw_params_t *hwparams;
	snd_pcm_sw_params_t *swparams;
	char *pcm_name;
	unsigned int exact_rate;
	snd_pcm_access_t accesstype = ACCESS;
	snd_pcm_format_t format = FORMAT;
	snd_pcm_uframes_t buffersize = BUFFERSIZE_FRAMES;
	unsigned int periods = PERIODS_PER_INTERRUPT;
	int dir, err;
	snd_pcm_uframes_t val;
	snd_pcm_t *pcm_handle;

	memset( &read_data, 0xff, sizeof( read_data ) );

	if (argc < 2) {
		printf("usage: '%s <SERVER-IP>' for client or '%s 1' for server \n",argv[0],argv[0]);
		exit( -1 );
	}
	if( memset( &global, 0, sizeof(struct globals) ) == NULL ) perror("memset");
	if( strncmp(argv[1],"1",1) == 0 ) transmitter_decision = 1;

	pcm_name = strdup("hw:0,0");
	snd_pcm_hw_params_alloca( &hwparams );

	stream = SND_PCM_STREAM_PLAYBACK;
	if( snd_pcm_open( &pcm_handle, pcm_name, stream, 0 ) != 0 ) {
		fprintf(stderr, "Error opening PCM device %s\n", pcm_name);
		return(-1);
	}
	if( snd_pcm_hw_params_any( pcm_handle, hwparams ) != 0 ) {
		fprintf(stderr, "Cannot configure PCM device\n");
		return(-1);
	}
	/** Setting the previously tested capabilities */
	if( snd_pcm_hw_params_set_access( pcm_handle, hwparams, accesstype ) != 0 ) {
		fprintf(stderr, "SET: Error setting access\n");
		return(-1);
	}
	if( snd_pcm_hw_params_set_format( pcm_handle, hwparams, format ) != 0 ) {
		fprintf(stderr, "SET: Error setting format\n");
		return(-1);
	}
	exact_rate = RATE;
	dir = -1;
	if( snd_pcm_hw_params_set_rate_near( pcm_handle, hwparams, &exact_rate, &dir ) != 0 ) {
		fprintf(stderr, "SET: Error setting rate %d\n", dir);
		return(-1);
	}
	if( RATE != exact_rate ) {
		fprintf(stderr, "The rate is not supported by your hardware.\n" \
		"ATTENTION! Alsa-resampler being used!!! ==> Using %d_Hz instead of %d_Hz.\n", exact_rate, RATE);
	}
	if( snd_pcm_hw_params_set_channels( pcm_handle, hwparams, CHANNELS ) != 0 ) {
		fprintf(stderr, "SET: Error setting channels\n");
		return(-1);
	}
	if( snd_pcm_hw_params_set_periods_near( pcm_handle, hwparams, &periods, 0 ) != 0 ) {
		fprintf(stderr, "SET: Error setting periods\n");
		return(-1);
	}
	// Set buffer size (in frames). The resulting latency is given by
	// latency = periodsize * periods / (rate * bytes_per_frame)
	// Buffersize in FRAMES!!!! Not in bytes!!!!!!
	if( snd_pcm_hw_params_set_buffer_size_near( pcm_handle, hwparams, &buffersize ) != 0 ) {
		fprintf(stderr, "SET: Error buffer size\n");
		return(-1);
	}
	if( buffersize != BUFFERSIZE_FRAMES ) {
		fprintf(stderr, "BUFFERSIZE_FRAMES not set, check capture.cpp!\n");
		return(-1);
	}
	if( snd_pcm_hw_params( pcm_handle, hwparams ) != 0 ) {
		fprintf(stderr, "SET: Error applying parameters\n");
		return(-1);
	}
	snd_pcm_sw_params_alloca(&swparams);

	err = snd_pcm_sw_params_current(pcm_handle, swparams);
	if (err < 0) {
		printf("Unable to determine current swparams %s\n",snd_strerror(err));
		return err;
	}

	snd_pcm_hw_params_get_period_size(hwparams, &val, NULL);
	err = snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, val);
	if (err < 0) {
		printf("Unable to set avail min  %s\n", snd_strerror(err));
		return err;
	}
	err = snd_pcm_sw_params(pcm_handle, swparams);
	if (err < 0) {
		printf("Unable to set sw params %s\n", snd_strerror(err));
		return err;
	}

	while(1){
		len=256;
		pointer=read_data;
		while (len > 0) {
			while( ( written_frames = snd_pcm_writei( pcm_handle, pointer, len ) ) < 0 ) {
				snd_pcm_prepare( pcm_handle );
				printf("<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>>\n");
			}
			if(written_frames!=256)printf("%d\n",written_frames);
			pointer+=written_frames*4;
			len-=written_frames;
		}
	}
}
------------------------------------------------------------------------------
OpenSolaris 2009.06 is a cutting edge operating system for enterprises 
looking to deploy the next generation of Solaris that includes the latest 
innovations from Sun and the OpenSource community. Download a copy and 
enjoy capabilities such as Networking, Storage and Virtualization. 
Go to: http://p.sf.net/sfu/opensolaris-get
_______________________________________________
Alsa-user mailing list
Alsa-user@xxxxxxxxxxxxxxxxxxxxx
https://lists.sourceforge.net/lists/listinfo/alsa-user

[Index of Archives]     [ALSA Devel]     [Linux Audio Users]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [Yosemite Photos]     [KDE Users]     [Fedora Tools]

  Powered by Linux