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