All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Stuart <dave@sipquest.com>
To: alsa-devel@lists.sourceforge.net
Subject: Could use some tips with example program
Date: Mon, 19 May 2003 13:26:02 -0400	[thread overview]
Message-ID: <3EC913AA.707@sipquest.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 845 bytes --]

Greetings all,

I've been trying to learn about ALSA this weekend. After reading a few 
HOWTOs and FAQs, I decided  to implement a simple program. Rather than 
cut n' paste some of the examples, I tried to write a small one myself. 
Unfortunately I'm running into some problems, and I'm not sure if my 
approach is even correct. Basically I would like to just read stuff from 
the capture device, and send it straight into the playback device.

Should be simple, but I find that each example I look at is different, 
and uses a some different hardware /software parameters to achieve the 
same thing..

Anyway, was hoping if some of you are so inclined, could you eyeball my 
program and give me some tips? I have a feeling I'm making lots of 
mistakes (due to misunderstanding some key concepts, probably). It's 
really quite a short program..

[-- Attachment #2: alsatest.c --]
[-- Type: text/plain, Size: 4862 bytes --]

#include <assert.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <alsa/asoundlib.h>

#define BUF_SIZE 1024

static snd_pcm_t *phandle = NULL; /* Handle for the playback pcm device */
static snd_pcm_t *chandle = NULL; /* Handle for the capture pcm device */
static short buf[BUF_SIZE];

/* print out errno and exit */
void die( char *message, int err )
{
	fprintf( stderr, "%s: %s\n", message, snd_strerror( err ));
	exit( err );
}

/* sets the hardware parameters on the pcm handle */
void set_hw_params( snd_pcm_t *handle, snd_pcm_hw_params_t *hw_params, snd_pcm_access_t access )
{
	int err = 0;

	/* initialize hw param structure */
	err = snd_pcm_hw_params_any( handle, hw_params );
	if( err < 0 )
		die( "snd_pcm_hw_params_any", err );

	/* set the read/write format */
	err = snd_pcm_hw_params_set_access( handle, hw_params, access );
	if( err < 0 )
		die( "snd_pcm_hw_params_set_access", err );

	/* set the sample format */
	err = snd_pcm_hw_params_set_format( handle, hw_params, SND_PCM_FORMAT_S16 );
	if( err < 0 )
		die( "snd_pcm_hw_params_set_format", err );
	
	/* set the stream reate */
	err = snd_pcm_hw_params_set_rate_near( handle, hw_params, 44100, 0 );
	if( err < 0 )
		die( "snd_pcm_hw_params_set_rate_near", err );

	/* set the number of channels (mono vs. stereo) */
	err = snd_pcm_hw_params_set_channels( handle, hw_params, 1 );
	if( err < 0 )
		die( "snd_pcm_hw_params_set_channels", err );

	err = snd_pcm_hw_params( handle, hw_params );
	if( err < 0 )
		die( "snd_pcm_hw_params", err );
}

/* Asynchronous handler for the capture
void capture_callback( snd_async_handler_t *handler )
{
	if( snd_pcm_readi( chandle, buf, BUF_SIZE ) != BUF_SIZE )
		die( "snd_pcm_readi" );

	printf( "captured %d shorts of data\n", BUF_SIZE );

	if( snd_pcm_writei( phandle, buf, BUF_SIZE ) != BUF_SIZE )
		die( "snd_pcm_writei" );

	printf( "wrote %d shorts of data\n", BUF_SIZE );
}
*/

/* Handler for exiting the application */
void handle_sigint(int signal)
{
	if( phandle != NULL ) snd_pcm_close(phandle);
	if( chandle != NULL ) snd_pcm_close(chandle);
}

/* The basic idea here is to take the capture output and put it straight
 * into the playback device. This should give us a "real-world" approximation
 * of the latency
 */
int main( int argc, char **argv )
{
	int err;
	char *pdevice;
	char *cdevice;
	struct sigaction actionStruct;
	snd_async_handler_t *handler;

	snd_pcm_stream_t pstream = SND_PCM_STREAM_PLAYBACK;
	snd_pcm_stream_t cstream = SND_PCM_STREAM_CAPTURE;

	snd_pcm_hw_params_t *hw_params;

	/* Check for the device */
	if( argc != 3 )
	{
		fprintf( stderr, "Please supply the playback and capture device to use\n" );
		exit( 1 );
	}

	pdevice = argv[1];
	cdevice = argv[2];


	/* Make sure the buffer is clean */
	memset( buf, 0, BUF_SIZE * sizeof( short ));

	/* open pcm handle for playback */
	err = snd_pcm_open( &phandle, pdevice, pstream, 0 );
	if( err < 0 )
		die( "snd_pcm_open", err );

	/* open pcm handle for capture */
	err = snd_pcm_open( &chandle, cdevice, cstream, 0 );
	if( err < 0 )
		die( "snd_pcm_open", err );

	/* set all hw params on the playback device */
	err = snd_pcm_hw_params_malloc( &hw_params );
	if( err < 0 )
		die( "snd_pcm_hw_params_malloc", err );

	set_hw_params( phandle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED );
	snd_pcm_hw_params_free( hw_params );

	/* set all the hw params on the capture device */
	err = snd_pcm_hw_params_malloc( &hw_params );
	if( err < 0 )
		die( "snd_pcm_hw_params_malloc", err );

	set_hw_params( chandle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED );
	snd_pcm_hw_params_free( hw_params );

	/* If we get past this point, install a signal handler to handle the
	 * cleanup */
	actionStruct.sa_handler = handle_sigint;
	err = sigaction( SIGINT, &actionStruct, NULL );
	if( err < 0 )
		die( "sigaction", err );

	/* Prepare both handles for capture and playback */
	err = snd_pcm_prepare( phandle );
	if( err < 0 )
		die( "snd_pcm_capture", err );

	err = snd_pcm_prepare( chandle );
	if( err < 0 )
		die( "snd_pcm_capture", err );

	/* set the callback for the capture */
	/*
	if( snd_async_add_pcm_handler( &handler, chandle, capture_callback, NULL ) < 0 )
		die( "snd_async_add_pcm_handler" );
		*/

	while(1) {

		/* read BUF_SIZE shorts from the capture device and write them
		 * to the playback device 
		 */
		err = snd_pcm_readi( chandle, buf, BUF_SIZE );
		if( err < 0 )
			die( "snd_pcm_readi", err );

		/*
		 * Try to play back the buffer that we just read. This doesn't seem
		 * to work, I'm not sure why?
		 */
		err = snd_pcm_writei( phandle, buf, BUF_SIZE );
		if( err < 0 )
		{
			if( err == -EPIPE )
			{
				fprintf( stderr, "buffer underrun\n" );
				err = snd_pcm_prepare( phandle );
				if( err < 0 )
					die( "snd_pcm_prepare", err );
			}
			else
				die( "snd_pcm_writei", err );
		}
	}
	/*pause();*/
	return 0;
}

                 reply	other threads:[~2003-05-19 17:26 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3EC913AA.707@sipquest.com \
    --to=dave@sipquest.com \
    --cc=alsa-devel@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.