alsabat: add buffer size and period size settings

Add buffer size and period size settings in alsabat.
With -E and -B options, alsabat performs the test with
specified buffer size and period size

Signed-off-by: Zhang Vivian <vivian.zhang@intel.com>
Acked-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
vivian,zhang 2016-05-31 15:31:32 +08:00 committed by Takashi Iwai
parent 569f2c116e
commit 9e196efda4
4 changed files with 94 additions and 32 deletions

View file

@ -74,6 +74,8 @@ static int set_snd_pcm_params(struct bat *bat, struct pcm_container *sndpcm)
snd_pcm_format_t format; snd_pcm_format_t format;
unsigned int buffer_time = 0; unsigned int buffer_time = 0;
unsigned int period_time = 0; unsigned int period_time = 0;
snd_pcm_uframes_t buffer_size = 0;
snd_pcm_uframes_t period_size = 0;
unsigned int rate; unsigned int rate;
int err; int err;
const char *device_name = snd_pcm_name(sndpcm->handle); const char *device_name = snd_pcm_name(sndpcm->handle);
@ -145,9 +147,40 @@ static int set_snd_pcm_params(struct bat *bat, struct pcm_container *sndpcm)
return -EINVAL; return -EINVAL;
} }
if (bat->buffer_size > 0 && bat->period_size == 0)
bat->period_size = bat->buffer_size / DIV_BUFFERTIME;
if (bat->buffer_size > 0) {
buffer_size = bat->buffer_size;
period_size = bat->period_size;
fprintf(bat->log, _("Set period size: %d buffer size: %d\n"),
(int) period_size, (int) buffer_size);
err = snd_pcm_hw_params_set_buffer_size_near(sndpcm->handle,
params, &buffer_size);
if (err < 0) {
fprintf(bat->err, _("Set parameter to device error: "));
fprintf(bat->err, _("buffer size: %d %s: %s(%d)\n"),
(int) buffer_size,
device_name, snd_strerror(err), err);
return err;
}
err = snd_pcm_hw_params_set_period_size_near(sndpcm->handle,
params, &period_size, 0);
if (err < 0) {
fprintf(bat->err, _("Set parameter to device error: "));
fprintf(bat->err, _("period size: %d %s: %s(%d)\n"),
(int) period_size,
device_name, snd_strerror(err), err);
return err;
}
} else {
if (snd_pcm_hw_params_get_buffer_time_max(params, if (snd_pcm_hw_params_get_buffer_time_max(params,
&buffer_time, 0) < 0) { &buffer_time, 0) < 0) {
fprintf(bat->err, _("Get parameter from device error: ")); fprintf(bat->err,
_("Get parameter from device error: "));
fprintf(bat->err, _("buffer time: %d %s: %s(%d)\n"), fprintf(bat->err, _("buffer time: %d %s: %s(%d)\n"),
buffer_time, buffer_time,
device_name, snd_strerror(err), err); device_name, snd_strerror(err), err);
@ -160,8 +193,8 @@ static int set_snd_pcm_params(struct bat *bat, struct pcm_container *sndpcm)
period_time = buffer_time / DIV_BUFFERTIME; period_time = buffer_time / DIV_BUFFERTIME;
/* Set buffer time and period time */ /* Set buffer time and period time */
err = snd_pcm_hw_params_set_buffer_time_near(sndpcm->handle, params, err = snd_pcm_hw_params_set_buffer_time_near(sndpcm->handle,
&buffer_time, 0); params, &buffer_time, 0);
if (err < 0) { if (err < 0) {
fprintf(bat->err, _("Set parameter to device error: ")); fprintf(bat->err, _("Set parameter to device error: "));
fprintf(bat->err, _("buffer time: %d %s: %s(%d)\n"), fprintf(bat->err, _("buffer time: %d %s: %s(%d)\n"),
@ -170,8 +203,8 @@ static int set_snd_pcm_params(struct bat *bat, struct pcm_container *sndpcm)
return err; return err;
} }
err = snd_pcm_hw_params_set_period_time_near(sndpcm->handle, params, err = snd_pcm_hw_params_set_period_time_near(sndpcm->handle,
&period_time, 0); params, &period_time, 0);
if (err < 0) { if (err < 0) {
fprintf(bat->err, _("Set parameter to device error: ")); fprintf(bat->err, _("Set parameter to device error: "));
fprintf(bat->err, _("period time: %d %s: %s(%d)\n"), fprintf(bat->err, _("period time: %d %s: %s(%d)\n"),
@ -179,6 +212,7 @@ static int set_snd_pcm_params(struct bat *bat, struct pcm_container *sndpcm)
device_name, snd_strerror(err), err); device_name, snd_strerror(err), err);
return err; return err;
} }
}
/* Write the parameters to the driver */ /* Write the parameters to the driver */
if (snd_pcm_hw_params(sndpcm->handle, params) < 0) { if (snd_pcm_hw_params(sndpcm->handle, params) < 0) {
@ -214,6 +248,9 @@ static int set_snd_pcm_params(struct bat *bat, struct pcm_container *sndpcm)
return -EINVAL; return -EINVAL;
} }
fprintf(bat->log, _("Get period size: %d buffer size: %d\n"),
(int) sndpcm->period_size, (int) sndpcm->buffer_size);
err = snd_pcm_format_physical_width(format); err = snd_pcm_format_physical_width(format);
if (err < 0) { if (err < 0) {
fprintf(bat->err, _("Invalid parameters: ")); fprintf(bat->err, _("Invalid parameters: "));

View file

@ -292,6 +292,8 @@ _("Usage: alsabat [-options]...\n"
" -k parameter for frequency detecting threshold\n" " -k parameter for frequency detecting threshold\n"
" -F target frequency\n" " -F target frequency\n"
" -p total number of periods to play/capture\n" " -p total number of periods to play/capture\n"
" -B buffer size in frames\n"
" -E period size in frames\n"
" --log=# file that both stdout and strerr redirecting to\n" " --log=# file that both stdout and strerr redirecting to\n"
" --file=# file for playback\n" " --file=# file for playback\n"
" --saveplay=# file that storing playback content, for debug\n" " --saveplay=# file that storing playback content, for debug\n"
@ -324,6 +326,8 @@ static void set_defaults(struct bat *bat)
bat->capture.device = NULL; bat->capture.device = NULL;
bat->buf = NULL; bat->buf = NULL;
bat->local = false; bat->local = false;
bat->buffer_size = 0;
bat->period_size = 0;
#ifdef HAVE_LIBTINYALSA #ifdef HAVE_LIBTINYALSA
bat->channels = 2; bat->channels = 2;
bat->playback.fct = &playback_tinyalsa; bat->playback.fct = &playback_tinyalsa;
@ -342,8 +346,8 @@ static void set_defaults(struct bat *bat)
static void parse_arguments(struct bat *bat, int argc, char *argv[]) static void parse_arguments(struct bat *bat, int argc, char *argv[])
{ {
int c, option_index; int c, option_index, err;
static const char short_options[] = "D:P:C:f:n:F:c:r:s:k:p:lth"; static const char short_options[] = "D:P:C:f:n:F:c:r:s:k:p:B:E:lth";
static const struct option long_options[] = { static const struct option long_options[] = {
{"help", 0, 0, 'h'}, {"help", 0, 0, 'h'},
{"log", 1, 0, OPT_LOG}, {"log", 1, 0, OPT_LOG},
@ -414,6 +418,16 @@ static void parse_arguments(struct bat *bat, int argc, char *argv[])
bat->periods_total = atoi(optarg); bat->periods_total = atoi(optarg);
bat->period_is_limited = true; bat->period_is_limited = true;
break; break;
case 'B':
err = atoi(optarg);
bat->buffer_size = err >= MIN_BUFFERSIZE
&& err < MAX_BUFFERSIZE ? err : 0;
break;
case 'E':
err = atoi(optarg);
bat->period_size = err >= MIN_PERIODSIZE
&& err < MAX_PERIODSIZE ? err : 0;
break;
case 'h': case 'h':
default: default:
usage(bat); usage(bat);

View file

@ -46,6 +46,12 @@
#define DIV_BUFFERTIME 8 #define DIV_BUFFERTIME 8
/* margin to avoid sign inversion when generate sine wav */ /* margin to avoid sign inversion when generate sine wav */
#define RANGE_FACTOR 0.95 #define RANGE_FACTOR 0.95
#define MAX_BUFFERSIZE 200000
#define MIN_BUFFERSIZE 32
#define MAX_PERIODSIZE 200000
#define MIN_PERIODSIZE 32
/* default period size for tinyalsa */
#define TINYALSA_PERIODSIZE 1024
#define EBATBASE 1000 #define EBATBASE 1000
#define ENOPEAK (EBATBASE + 1) #define ENOPEAK (EBATBASE + 1)
@ -152,6 +158,8 @@ struct bat {
int frame_size; /* size of frame */ int frame_size; /* size of frame */
int sample_size; /* size of sample */ int sample_size; /* size of sample */
enum _bat_pcm_format format; /* PCM format */ enum _bat_pcm_format format; /* PCM format */
int buffer_size; /* buffer size in frames */
int period_size; /* period size in frames */
float sigma_k; /* threshold for peak detection */ float sigma_k; /* threshold for peak detection */
float target_freq[MAX_CHANNELS]; float target_freq[MAX_CHANNELS];

View file

@ -57,7 +57,10 @@ static int init_config(struct bat *bat, struct pcm_config *config)
{ {
config->channels = bat->channels; config->channels = bat->channels;
config->rate = bat->rate; config->rate = bat->rate;
config->period_size = 1024; if (bat->period_size > 0)
config->period_size = bat->period_size;
else
config->period_size = TINYALSA_PERIODSIZE;
config->period_count = 4; config->period_count = 4;
config->start_threshold = 0; config->start_threshold = 0;
config->stop_threshold = 0; config->stop_threshold = 0;