I had initially posted this to the alsa-devel list but haven't
received a response and thought that maybe that was the wrong list. If
this is the incorrect place for this please let me know.

I am attempting to upgrade from Ubuntu version 10.04 to version 12.04. Version
10.04 has ALSA version 1.0.22 and version 12.04 has ALSA 1.0.25. I have a
simple test application that captures microphone input and then plays the
audio through the speaker. When run with ALSA 1.0.22 the program works as
expected. When I run the program with ALSA 1.0.25, I get a bad pipe error
indicating buffer underrun when calling writes. Both systems have the same
hardware (Dell Latitude E6400 laptop).

I tried looking through the change logs to determine if there were any obvious
changes that stood out to me, but couldn't find anything. I have attached
my code. Any suggestions?

Program is compiled using "g++ audio_test.cpp -o audio_test -lasound"

Audio sample rate: 8000
Buffer size: 1800
Format: Signed 16bit LE, interleaved
#include <alsa/asoundlib.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>

#define BUFFER_SIZE			1800

int main( int argc, char* argv[] )
{
	//Speaker

	snd_pcm_t* pcm_handle;
	snd_pcm_t* cap_handle;
	snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
	snd_pcm_stream_t receive = SND_PCM_STREAM_CAPTURE;
	snd_pcm_hw_params_t *hwparams;
	char *pcm_name;
	pcm_name = strdup( "default" );

	snd_pcm_hw_params_alloca( &hwparams );

	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_open( &cap_handle, pcm_name, receive, 0 ) < 0 )
	{
		fprintf( stderr, "Error opening PCM device %s\n", pcm_name );
		return -1;
	}

	if( snd_pcm_hw_params_malloc( &hwparams ) < 0 )
	{
		fprintf( stderr, "cannot allocate hardware parameter structure\n" );
		return -1;
	}

	if( snd_pcm_hw_params_any( pcm_handle, hwparams ) < 0 )
	{
		fprintf( stderr, "cannot initialize hardware parameter structure\n" );
		return -1;
	}
	if( snd_pcm_hw_params_any( cap_handle, hwparams ) < 0 )
	{
		fprintf( stderr, "cannot initialize hardware parameter structure\n" );
		return -1;
	}

	int rate = 8000;
	unsigned int exact_rate;
	unsigned int periods = 2;
	int chan = 1;
	int err;

	if( err = ( snd_pcm_hw_params_set_access( pcm_handle, hwparams,
		SND_PCM_ACCESS_RW_INTERLEAVED ) < 0 ) )
	{
		fprintf( stderr, "Error setting access (%s).\n", snd_strerror( err ) );
		return -1;
	}
	if( err = ( snd_pcm_hw_params_set_access( cap_handle, hwparams,
		SND_PCM_ACCESS_RW_INTERLEAVED ) < 0 ) )
	{
		fprintf( stderr, "Error setting access (%s).\n", snd_strerror( err ) );
		return -1;
	}

	if( snd_pcm_hw_params_set_format( pcm_handle, hwparams, 
		SND_PCM_FORMAT_S16_LE ) < 0 )
	{
		fprintf( stderr, "Error setting rate.\n" );
		return -1;
	}
	if( snd_pcm_hw_params_set_format( cap_handle, hwparams, 
		SND_PCM_FORMAT_S16_LE ) < 0 )
	{
		fprintf( stderr, "Error setting rate.\n" );
		return -1;
	}

	exact_rate = rate;
	if( snd_pcm_hw_params_set_rate_near( pcm_handle, hwparams, &exact_rate, 
		0 )	< 0 )
	{
		fprintf( stderr, "Error setting rate.\n" );
		return -1;
	}
	if( rate != exact_rate )
	{
		fprintf( stderr, "The rate %d Hz is not supported by your hardware.\n " 
				" ==> Using %d Hz instead.\n", rate, exact_rate );
	}
	exact_rate = rate;
	if( snd_pcm_hw_params_set_rate_near( cap_handle, hwparams, &exact_rate, 
		0 )	< 0 )
	{
		fprintf( stderr, "Error setting rate.\n" );
		return -1;
	}

	if( rate != exact_rate )
	{
		fprintf( stderr, "The rate %d Hz is not supported by your hardware.\n " 
				" ==> Using %d Hz instead.\n", rate, exact_rate );
	}

	if( snd_pcm_hw_params_set_channels( pcm_handle, hwparams, chan ) < 0 )
	{
		fprintf( stderr, "Error setting channels.\n" );
		return -1;
	}
	if( snd_pcm_hw_params_set_channels( cap_handle, hwparams, chan ) < 0 )
	{
		fprintf( stderr, "Error setting channels.\n" );
		return -1;
	}

	if( snd_pcm_hw_params_set_periods_near( pcm_handle, hwparams, &periods, 0 )
		< 0 )
	{
		fprintf( stderr, "Error setting periods.\n" );
		return -1;
	}
	if( snd_pcm_hw_params_set_periods_near( cap_handle, hwparams, &periods, 0 )
		< 0 )
	{
		fprintf( stderr, "Error setting periods.\n" );
		return -1;
	}

	int frameSize = chan * 2;
	snd_pcm_uframes_t frme = BUFFER_SIZE / frameSize * periods;
	if( snd_pcm_hw_params_set_buffer_size_near( pcm_handle, hwparams, &frme ) 
		< 0 )
	{
		fprintf( stderr, "Error setting buffersize.\n" );
		return -1;
	}

	if( BUFFER_SIZE != ( int )( frme * frameSize / periods ) )
	{
		printf( "asked for %d, got %d\n", BUFFER_SIZE, 
			( int )( frme * frameSize / periods ) );
	}

	frme = BUFFER_SIZE / frameSize * periods;

	if( snd_pcm_hw_params_set_buffer_size_near( cap_handle, hwparams, &frme ) 
		< 0 )
	{
		fprintf( stderr, "Error setting buffersize.\n" );
		return -1;
	}
	if( BUFFER_SIZE != ( int )( frme * frameSize / periods ) )
	{
		printf( "asked for %d, got %d\n", BUFFER_SIZE, 
			( int )( frme * frameSize / periods ) );
	}

	if( snd_pcm_hw_params( pcm_handle, hwparams ) < 0 )
	{
		fprintf( stderr, "Error setting HW params.\n" );
		return -1;
	}
	if( snd_pcm_hw_params( cap_handle, hwparams ) < 0 )
	{
		fprintf( stderr, "Error setting HW params.\n" );
		return -1;
	}

	unsigned char *data;
	int frames;

	data = ( unsigned char* )malloc( BUFFER_SIZE );
	frames = BUFFER_SIZE/frameSize;

	while( true )
	{
		if( ( pcmreturn = snd_pcm_readi( cap_handle, data, frames ) ) < 0 )
		{
			snd_pcm_prepare( cap_handle );
			printf( "read error: %d\n", pcmreturn );
		}
		else
		{
			if( ( pcmreturn = snd_pcm_writei( pcm_handle, data, frames ) ) 
				< 0 )
			{
				printf( "write error: %d\n", pcmreturn );
			}
		}
	}

	snd_pcm_drop( pcm_handle );
	snd_pcm_drain( pcm_handle );

	return 0;
}
------------------------------------------------------------------------------
LogMeIn Central: Instant, anywhere, Remote PC access and management.
Stay in control, update software, and manage PCs from one command center
Diagnose problems and improve visibility into emerging IT issues
Automate, monitor and manage. Do more in less time with Central
http://p.sf.net/sfu/logmein12331_d2d
_______________________________________________
Alsa-user mailing list
Alsa-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/alsa-user

Reply via email to