#include #include #include #include #include #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; }