[alsa-devel] Audio Driver -- too much data, coming in two quickly
Brett Bolen
bbolen at extron.com
Wed Sep 1 17:11:31 CEST 2010
Here's the source code for the example program I ran in the last message.
/*
* This example reads from the default PCM device
*/
/* Use the newer ALSA API */
#define ALSA_PCM_NEW_HW_PARAMS_API
#include <alsa/asoundlib.h>
#include <sys/time.h>
static snd_output_t *log;
double arg_duration_ms = 2000.0; // milliseconds
int arg_sampling_rate = 48000;
char arg_device_name[128] = "plughw:0,0";
char arg_output_fname[128] = "/dev/null";
int arg_frames = 16*1024; // 16k
int verbose = 1;
/* @brief get number of seconds since timer reset
*
*/
unsigned long base_tm;
unsigned long get_time()
{
// faster method?
struct timeval tv;
unsigned long tm;
gettimeofday( &tv, NULL);
tm = 1000l*1000l*tv.tv_sec;
tm += tv.tv_usec;
return tm - base_tm;
}
void args( int argc, char *argv[])
{
//int flags;
int opt;
// getopt
while (( opt = getopt( argc, argv,"f:r:d:o:t:")) != -1) {
switch (opt) {
case 'f':
arg_frames = atoi(optarg);
printf(" -- frames ( time samples) requested set to %d\n",
arg_frames);
break;
case 'r':
arg_sampling_rate = atoi(optarg);
printf(" -- samping rate set to %d\n", arg_sampling_rate);
break;
case 'd':
strcpy( arg_device_name, optarg);
printf(" -- device_name set to '%s'\n", arg_device_name);
break;
case 't':
printf("t optarg is %s\n", optarg);
arg_duration_ms = (double) atoi(optarg);
printf(" -- duration set to %fms\n", arg_duration_ms);
break;
case 'o':
strcpy( arg_output_fname, optarg);
printf(" -- output file name set to '%s'\n", arg_output_fname);
break;
default:
fprintf(stderr, "Usage: %s \n"
" -r <rate>\n"
" -d <input_device_name>\n"
" -o <output_file_name>\n"
"",
argv[0]);
exit( -1);
}
}
}
/***
*
*
***/
void dump_params( snd_pcm_t *handle,
snd_pcm_hw_params_t *params )
{
unsigned int val, val2;
int dir;
printf("PCM handle name = '%s'\n",
snd_pcm_name(handle));
printf("PCM state = %s\n",
snd_pcm_state_name(snd_pcm_state(handle)));
snd_pcm_hw_params_get_access(params,
(snd_pcm_access_t *) &val);
printf("access type = %s\n",
snd_pcm_access_name((snd_pcm_access_t)val));
// changed val to fmt
snd_pcm_format_t fmt;
snd_pcm_hw_params_get_format(params, &fmt);
printf("format = '%s' (%s)\n",
snd_pcm_format_name(fmt),
snd_pcm_format_description(fmt));
snd_pcm_hw_params_get_subformat(params,
(snd_pcm_subformat_t *)&val);
printf("subformat = '%s' (%s)\n",
snd_pcm_subformat_name((snd_pcm_subformat_t)val),
snd_pcm_subformat_description(
(snd_pcm_subformat_t)val));
snd_pcm_hw_params_get_channels(params, &val);
printf("channels = %d\n", val);
snd_pcm_hw_params_get_rate(params, &val, &dir);
printf("rate = %d bps\n", val);
snd_pcm_hw_params_get_period_time(params, &val, &dir);
printf("period time = %d us\n", val);
snd_pcm_uframes_t uframes;
snd_pcm_hw_params_get_period_size(params, &uframes, &dir);
printf("period size = %d frames !!\n", (int)uframes);
snd_pcm_hw_params_get_buffer_time(params, &val, &dir);
printf("buffer time = %d us\n", val);
snd_pcm_hw_params_get_buffer_size(params, (snd_pcm_uframes_t *) &val);
printf("buffer size = %d frames\n", val);
snd_pcm_hw_params_get_periods(params, &val, &dir);
printf("periods per buffer = %d frames\n", val);
snd_pcm_hw_params_get_rate_numden(params,
&val, &val2);
printf("exact rate = %d/%d bps\n", val, val2);
val = snd_pcm_hw_params_get_sbits(params);
printf("significant bits = %d\n", val);
#if 0
snd_pcm_hw_params_get_tick_time(params, &val, &dir);
printf("tick time = %d us\n", val);
#endif
val = snd_pcm_hw_params_is_batch(params);
printf("is batch = %d\n", val);
val = snd_pcm_hw_params_is_block_transfer(params);
printf("is block transfer = %d\n", val);
val = snd_pcm_hw_params_is_double(params);
printf("is double = %d\n", val);
val = snd_pcm_hw_params_is_half_duplex(params);
printf("is half duplex = %d\n", val);
val = snd_pcm_hw_params_is_joint_duplex(params);
printf("is joint duplex = %d\n", val);
val = snd_pcm_hw_params_can_overrange(params);
printf("can overrange = %d\n", val);
val = snd_pcm_hw_params_can_mmap_sample_resolution(params);
printf("can mmap = %d\n", val);
val = snd_pcm_hw_params_can_pause(params);
printf("can pause = %d\n", val);
val = snd_pcm_hw_params_can_resume(params);
printf("can resume = %d\n", val);
val = snd_pcm_hw_params_can_sync_start(params);
printf("can sync start = %d\n", val);
}
int main( int argc, char *argv[])
{
long loops;
int rc;
int size;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
unsigned int val, val2;
int dir;
snd_pcm_uframes_t frames;
char *buffer;
fprintf(stderr, "alsa_capture: v0.1b\n");
args(argc, argv);
base_tm = get_time();
unsigned long ttim[10];
ttim[0] = get_time(); usleep (0);
ttim[1] = get_time(); usleep (10);
ttim[2] = get_time(); usleep (100);
ttim[3] = get_time(); usleep (1000);
ttim[4] = get_time(); usleep (10000);
ttim[5] = get_time(); usleep (100000);
ttim[6] = get_time();
printf("delay calibration:"
"0=%ld 10=%ld 100=%ld 1000=%ld 10000=%ld 100000=%ld ticks "
"( %ld %ld %ld %ld %ld %ld %ld) ticks\n",
ttim[1] - ttim[0],
ttim[2] - ttim[1],
ttim[3] - ttim[2],
ttim[4] - ttim[3],
ttim[5] - ttim[4],
ttim[6] - ttim[5],
ttim[6], ttim[5],
ttim[4], ttim[3],
ttim[2], ttim[1],
ttim[0]);
/* Open PCM device for recording (capture). */
rc = snd_pcm_open(&handle, arg_device_name,
SND_PCM_STREAM_CAPTURE, 0);
if (rc < 0) {
fprintf(stderr,
"unable to open pcm device: %s\n",
snd_strerror(rc));
exit(1);
}
snd_output_stdio_attach(&log, stderr, 0);
/* Allocate a hardware parameters object. */
snd_pcm_hw_params_alloca(¶ms);
/* Fill it in with default values. */
snd_pcm_hw_params_any(handle, params);
/* Set the desired hardware parameters. */
/* Interleaved mode */
snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
/* Signed 16-bit little-endian format */
snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
/* Two channels (stereo) */
snd_pcm_hw_params_set_channels(handle, params, 2);
/* sampling rate in time_samples/second : cd=44100, dat=48000 */
val = arg_sampling_rate;
snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);
/* Set period size to 32 frames. */
frames = arg_frames;
printf("Requesting %d frames per period\n", frames);
snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
printf("Returned %d frames per period\n", frames);
/* Write the parameters to the driver */
rc = snd_pcm_hw_params(handle, params);
if (rc < 0) {
fprintf(stderr,
"unable to set hw parameters: %s\n",
snd_strerror(rc));
exit(1);
}
printf("---------------------------after set hw params 1\n");
dump_params( handle, params);
printf(".........................................\n");
int fout;
fout = open(arg_output_fname, O_CREAT | O_WRONLY | O_TRUNC);
if ( fout < 0) {
printf("could not open output file\n");
exit(-1);
}
/* Use a buffer large enough to hold one period */
snd_pcm_hw_params_get_period_size(params,
&frames, &dir);
size = frames * 4; /* 2 bytes/sample, 2 channels */
buffer = (char *) malloc(size);
/* We want to loop for duration_ms */
snd_pcm_hw_params_get_period_time(params, &val, &dir);
loops = (int) (arg_duration_ms*1000 / val);
printf("loops is %d/0x%x, period_time is %d/%x, frames=%d/%x\n",
loops, loops,
val, val,
frames,frames);
while (loops > 0) {
snd_htimestamp_t ts1;
snd_pcm_uframes_t frames1;
snd_pcm_htimestamp( handle, &frames1, &ts1);
loops--;
ttim[0] = get_time();
rc = snd_pcm_readi(handle, buffer, frames);
ttim[1] = get_time();
if (rc == -EPIPE) {
/* EPIPE means overrun */
fprintf(stderr, "overrun occurred\n");
printf("PIPE\n");
//snd_pcm_prepare(handle);
//snd_pcm_drop(handle);
snd_pcm_recover(handle, rc, 0);
snd_pcm_drain(handle);
} else if (rc < 0) {
printf("ERR\n");
fprintf(stderr,
"error from read: %s\n",
snd_strerror(rc));
} else if (rc != (int)frames) {
printf("SR\n");
fprintf(stderr, "short read, read %d frames\n", rc);
}
// write out a file
rc = write(fout, buffer, size);
if (rc != size)
fprintf(stderr,
"short write: wrote %d bytes\n", rc);
ttim[2]= get_time();
printf("%8d-l%04d:%d frames %12ld ticks read, %8ld ticks process\n",
ttim[0],
loops,
frames,
ttim[1] - ttim[0],
ttim[2] - ttim[1]);
}
printf(".end\n");
close(fout);
printf(".drain\n");
snd_pcm_drain(handle);
printf(".pcm_close\n");
snd_pcm_close(handle);
printf(".free\n");
free(buffer);
snd_output_close(log);
return 0;
}
More information about the Alsa-devel
mailing list