Intermittent problem with feedback - could someone point out my error?

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

 



Hi there,

I've been trying to get basic audio working on an embedded board -
TX25 with an SGTL5000 codec.

I did have a problem with xruns silencing my audio, and thanks to
Jaroslav Kysela I've found a way round that. Now I have a similar
problem - sometimes, the audio is simply not there for more than one
buffer's worth (I think it's one buffer...).

Anyway, the attached file is an example of something that produces the
behaviour. It opens a capture and playback PCM, sets the hw/sw params
to the right audio format (as well as setting stop_threshold to the
boundary, so I don't get the problem with xruns). Then it feeds back
audio for two seconds, simply copying the input buffer straight to the
output buffer.

So, I have a couple of questions about this:

1) Does this code look like it should work in the first place? It
works some of the time, but it occurs to me that it might be working
"by accident" but is broken when it works as it should.

2) As I said before, audio either drops after what I *think* is one
buffer being transferred, or not at all. Could it be that my xrun
problem is occurring, but that my setting stop_threshold doesn't take
effect until after the first buffer is transferred (i.e. the first
buffer causes the xrun, stopping the rest of my audio like before)? Is
there any way I can "flush" the sw_params to make sure they take
effect right from when I start moving audio around?

Thanks very much to anyone who can give me any pointers on this.

John G
#include <alsa/asoundlib.h>

#include <cstdlib>
#include <iostream>
#include <stdint.h>

using namespace std;



class AlsaStream
{

	public:

		AlsaStream ( const char *device );

	private:

		AlsaStream ( const AlsaStream& );
		AlsaStream& operator= ( const AlsaStream& );

	private:

		const std::string deviceName;

		const int rate;

		const unsigned int buffer_size;

		const int period_size;

		volatile bool running;

		void run ( void );

		void setHwParams ( snd_pcm_t        **pcm,
						   const char        *name,
		                   snd_pcm_stream_t  type );

		void setSwParams ( snd_pcm_t **pcm );
};



#define atest(X)                                             \
		{                                                    \
			int err = 0;                                     \
			if ((err = (X)) < 0)                             \
			{                                                \
				std::cout << "Error in " << #X               \
					<< ", line " << __LINE__ <<              \
					": " << snd_strerror(err) << std::endl;  \
					::exit(1);                               \
			}                                                \
		}



AlsaStream::AlsaStream ( const char *device )
	: deviceName ( device ),
	rate ( 8000 ),
	buffer_size ( 512 ),
	period_size ( buffer_size / 4 ),
	running ( true )
{
	this->run();
}



void
AlsaStream::run ( void )
{
	snd_pcm_t *pcm_in  = NULL;
	snd_pcm_t *pcm_out = NULL;

	setHwParams(&pcm_in,  deviceName.c_str(), SND_PCM_STREAM_CAPTURE);
	setSwParams(&pcm_in);

	setHwParams(&pcm_out, deviceName.c_str(), SND_PCM_STREAM_PLAYBACK);
	setSwParams(&pcm_out);

	atest(snd_pcm_start(pcm_in));
	atest(snd_pcm_start(pcm_out));

	cout << "running" << endl;

	snd_pcm_uframes_t total_frames = 0;

	while (total_frames < 16000)
	{
		const snd_pcm_channel_area_t *area_in, *area_out;

		snd_pcm_uframes_t offset_in, offset_out;

		snd_pcm_uframes_t frames_in, frames_out;

		atest(snd_pcm_wait(pcm_in,  10000));
		atest(snd_pcm_wait(pcm_out, 10000));

		atest(frames_in  = snd_pcm_avail_update(pcm_in));
		atest(frames_out = snd_pcm_avail_update(pcm_out));

		// only handle simplest case (for now)
		assert(frames_in == frames_out);

		atest(snd_pcm_mmap_begin(pcm_in,  &area_in,  &offset_in,  &frames_in));
		atest(snd_pcm_mmap_begin(pcm_out, &area_out, &offset_out, &frames_out));

		assert(frames_in == frames_out);
		assert(offset_in == 0 && offset_out == 0);

		memcpy(area_out->addr, area_in->addr, frames_in * sizeof(int16_t));

		atest(snd_pcm_mmap_commit(pcm_in,  offset_in,  frames_in));
		atest(snd_pcm_mmap_commit(pcm_out, offset_out, frames_out));

		total_frames += frames_in;
	}

	atest(snd_pcm_close(pcm_in));
	atest(snd_pcm_close(pcm_out));

	std::cout << "all done" << std::endl;
}



void
AlsaStream::setHwParams ( snd_pcm_t        **pcm,
							const char        *name,
							snd_pcm_stream_t  type )
{
	snd_pcm_hw_params_t *hw_params = NULL;

	snd_pcm_access_mask_t *access_mask;


	atest(snd_pcm_open(pcm, name, type, 0));

	snd_pcm_hw_params_alloca(&hw_params);

	atest(snd_pcm_hw_params_any(*pcm, hw_params));

	atest(snd_pcm_access_mask_malloc(&access_mask));

	snd_pcm_access_mask_none(access_mask);

	snd_pcm_access_mask_set(access_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);

	atest(snd_pcm_hw_params_set_access_mask(*pcm, hw_params, access_mask));

	atest(snd_pcm_hw_params_set_format(*pcm, hw_params, SND_PCM_FORMAT_S16_LE));

	atest(snd_pcm_hw_params_set_channels(*pcm, hw_params, 2));

	atest(snd_pcm_hw_params_set_rate(*pcm, hw_params, rate, 0));

	atest(snd_pcm_hw_params_set_buffer_size(*pcm, hw_params, buffer_size));

	atest(snd_pcm_hw_params_set_period_size(*pcm, hw_params, period_size, 0));

	atest(snd_pcm_hw_params(*pcm, hw_params));
}




void
AlsaStream::setSwParams ( snd_pcm_t **pcm )
{
	snd_pcm_sw_params_t *sw_params = NULL;

	atest(snd_pcm_sw_params_malloc(&sw_params));

	atest(snd_pcm_sw_params_current(*pcm, sw_params));

	atest(snd_pcm_sw_params_set_avail_min(*pcm, sw_params, buffer_size));

	atest(snd_pcm_sw_params_set_start_threshold(*pcm, sw_params, 0));

	// set stop_threshold to boundary so we never get alerted to xruns
	snd_pcm_uframes_t stop_threshold    = 0;
	atest(snd_pcm_sw_params_get_boundary(sw_params, &stop_threshold));

	atest(snd_pcm_sw_params_set_stop_threshold(*pcm, sw_params, stop_threshold));


	atest(snd_pcm_sw_params(*pcm, sw_params));
}



int main(void)
{
	AlsaStream stream("plug:default");

	cout << "ending" << endl;

	exit(EXIT_SUCCESS);
}
------------------------------------------------------------------------------
Download Intel&#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
_______________________________________________
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