forked from pool/alsa-utils
Takashi Iwai
f57427e846
- backport from upstream tree: * add support for the new chmap API OBS-URL: https://build.opensuse.org/request/show/138458 OBS-URL: https://build.opensuse.org/package/show/multimedia:libs/alsa-utils?expand=0&rev=60
246 lines
6.3 KiB
Diff
246 lines
6.3 KiB
Diff
From 951cb2c2974293db6e12ef067ae7001074887932 Mon Sep 17 00:00:00 2001
|
|
From: Takashi Iwai <tiwai@suse.de>
|
|
Date: Tue, 11 Sep 2012 11:36:45 +0200
|
|
Subject: [PATCH 1/5] speaker-test: Add support for channel mapping API
|
|
|
|
The surround channel map follows the given channel map from the
|
|
driver if available.
|
|
|
|
Also, the channels can be specified manually via -m option.
|
|
Pass the channel map like "FL,FR,FC,LFE".
|
|
|
|
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
---
|
|
speaker-test/speaker-test.c | 139 +++++++++++++++++++++++++++++++++++++++-----
|
|
1 file changed, 124 insertions(+), 15 deletions(-)
|
|
|
|
--- a/speaker-test/speaker-test.c
|
|
+++ b/speaker-test/speaker-test.c
|
|
@@ -60,6 +60,10 @@
|
|
#include <locale.h>
|
|
#endif
|
|
|
|
+#ifdef SND_CHMAP_API_VERSION
|
|
+#define CONFIG_SUPPORT_CHMAP 1
|
|
+#endif
|
|
+
|
|
enum {
|
|
TEST_PINK_NOISE = 1,
|
|
TEST_SINE,
|
|
@@ -100,6 +104,11 @@ static const char *given_test_wav_file =
|
|
static char *wav_file_dir = SOUNDSDIR;
|
|
static int debug = 0;
|
|
|
|
+#ifdef CONFIG_SUPPORT_CHMAP
|
|
+static snd_pcm_chmap_t *channel_map;
|
|
+static int channel_map_set;
|
|
+#endif
|
|
+
|
|
static const char *const channel_name[MAX_CHANNELS] = {
|
|
/* 0 */ N_("Front Left"),
|
|
/* 1 */ N_("Front Right"),
|
|
@@ -143,6 +152,65 @@ static const int channels8[] = {
|
|
6, /* Side Left */
|
|
5, /* LFE */
|
|
};
|
|
+
|
|
+static int get_mapped_channel(int chn)
|
|
+{
|
|
+#ifdef CONFIG_SUPPORT_CHMAP
|
|
+ static const int maps[MAX_CHANNELS] = {
|
|
+ SND_CHMAP_FL,
|
|
+ SND_CHMAP_FR,
|
|
+ SND_CHMAP_RL,
|
|
+ SND_CHMAP_RR,
|
|
+ SND_CHMAP_FC,
|
|
+ SND_CHMAP_LFE,
|
|
+ SND_CHMAP_SL,
|
|
+ SND_CHMAP_SR,
|
|
+ };
|
|
+
|
|
+ if (channel_map && maps[chn]) {
|
|
+ int i;
|
|
+ for (i = 0; i < channel_map->channels; i++) {
|
|
+ if (channel_map->pos[i] == maps[chn])
|
|
+ return i;
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
+ return chn;
|
|
+}
|
|
+
|
|
+static int get_speaker_channel(int chn)
|
|
+{
|
|
+#ifdef CONFIG_SUPPORT_CHMAP
|
|
+ if (channel_map_set)
|
|
+ return chn;
|
|
+#endif
|
|
+
|
|
+ switch (channels) {
|
|
+ case 4:
|
|
+ chn = channels4[chn];
|
|
+ break;
|
|
+ case 6:
|
|
+ chn = channels6[chn];
|
|
+ break;
|
|
+ case 8:
|
|
+ chn = channels8[chn];
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return get_mapped_channel(chn);
|
|
+}
|
|
+
|
|
+static const char *get_channel_name(int chn)
|
|
+{
|
|
+#ifdef CONFIG_SUPPORT_CHMAP
|
|
+ if (channel_map_set && chn < channel_map->channels) {
|
|
+ const char *name = snd_pcm_chmap_long_name(channel_map->pos[chn]);
|
|
+ return name ? name : "Unknown";
|
|
+ }
|
|
+#endif
|
|
+ return gettext(channel_name[chn]);
|
|
+}
|
|
+
|
|
static const int supported_formats[] = {
|
|
SND_PCM_FORMAT_S8,
|
|
SND_PCM_FORMAT_S16_LE,
|
|
@@ -519,6 +587,31 @@ static int set_swparams(snd_pcm_t *handl
|
|
return 0;
|
|
}
|
|
|
|
+#ifdef CONFIG_SUPPORT_CHMAP
|
|
+static int config_chmap(snd_pcm_t *handle, const char *mapstr)
|
|
+{
|
|
+ int err;
|
|
+
|
|
+ if (mapstr) {
|
|
+ channel_map = snd_pcm_chmap_parse_string(mapstr);
|
|
+ if (!channel_map) {
|
|
+ fprintf(stderr, _("Unable to parse channel map string: %s\n"), mapstr);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ err = snd_pcm_set_chmap(handle, channel_map);
|
|
+ if (err < 0) {
|
|
+ fprintf(stderr, _("Unable to set channel map: %s\n"), mapstr);
|
|
+ return err;
|
|
+ }
|
|
+ channel_map_set = 1;
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ channel_map = snd_pcm_get_chmap(handle);
|
|
+ return 0;
|
|
+}
|
|
+#endif
|
|
+
|
|
/*
|
|
* Underrun and suspend recovery
|
|
*/
|
|
@@ -815,6 +908,7 @@ static void help(void)
|
|
"-s,--speaker single speaker test. Values 1=Left, 2=right, etc\n"
|
|
"-w,--wavfile Use the given WAV file as a test sound\n"
|
|
"-W,--wavdir Specify the directory containing WAV files\n"
|
|
+ "-m,--chmap Specify the channel map to override\n"
|
|
"\n"));
|
|
printf(_("Recognized sample formats are:"));
|
|
for (fmt = supported_formats; *fmt >= 0; fmt++) {
|
|
@@ -837,6 +931,9 @@ int main(int argc, char *argv[]) {
|
|
double time1,time2,time3;
|
|
unsigned int n, nloops;
|
|
struct timeval tv1,tv2;
|
|
+#ifdef CONFIG_SUPPORT_CHMAP
|
|
+ const char *chmap = NULL;
|
|
+#endif
|
|
|
|
static const struct option long_option[] = {
|
|
{"help", 0, NULL, 'h'},
|
|
@@ -854,6 +951,9 @@ int main(int argc, char *argv[]) {
|
|
{"wavfile", 1, NULL, 'w'},
|
|
{"wavdir", 1, NULL, 'W'},
|
|
{"debug", 0, NULL, 'd'},
|
|
+#ifdef CONFIG_SUPPORT_CHMAP
|
|
+ {"chmap", 1, NULL, 'm'},
|
|
+#endif
|
|
{NULL, 0, NULL, 0 },
|
|
};
|
|
|
|
@@ -872,7 +972,11 @@ int main(int argc, char *argv[]) {
|
|
while (1) {
|
|
int c;
|
|
|
|
- if ((c = getopt_long(argc, argv, "hD:r:c:f:F:b:p:P:t:l:s:w:W:d", long_option, NULL)) < 0)
|
|
+ if ((c = getopt_long(argc, argv, "hD:r:c:f:F:b:p:P:t:l:s:w:W:d"
|
|
+#ifdef CONFIG_SUPPORT_CHMAP
|
|
+ "m:"
|
|
+#endif
|
|
+ , long_option, NULL)) < 0)
|
|
break;
|
|
|
|
switch (c) {
|
|
@@ -963,6 +1067,11 @@ int main(int argc, char *argv[]) {
|
|
case 'd':
|
|
debug = 1;
|
|
break;
|
|
+#ifdef CONFIG_SUPPORT_CHMAP
|
|
+ case 'm':
|
|
+ chmap = optarg;
|
|
+ break;
|
|
+#endif
|
|
default:
|
|
fprintf(stderr, _("Unknown option '%c'\n"), c);
|
|
exit(EXIT_FAILURE);
|
|
@@ -1008,6 +1117,13 @@ int main(int argc, char *argv[]) {
|
|
snd_pcm_close(handle);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
+
|
|
+#ifdef CONFIG_SUPPORT_CHMAP
|
|
+ err = config_chmap(handle, chmap);
|
|
+ if (err < 0)
|
|
+ exit(EXIT_FAILURE);
|
|
+#endif
|
|
+
|
|
if (debug) {
|
|
snd_output_t *log;
|
|
err = snd_output_stdio_attach(&log, stderr, 0);
|
|
@@ -1038,17 +1154,8 @@ int main(int argc, char *argv[]) {
|
|
|
|
gettimeofday(&tv1, NULL);
|
|
for(chn = 0; chn < channels; chn++) {
|
|
- int channel=chn;
|
|
- if (channels == 4) {
|
|
- channel=channels4[chn];
|
|
- }
|
|
- if (channels == 6) {
|
|
- channel=channels6[chn];
|
|
- }
|
|
- if (channels == 8) {
|
|
- channel=channels8[chn];
|
|
- }
|
|
- printf(" %d - %s\n", channel, gettext(channel_name[channel]));
|
|
+ int channel = get_speaker_channel(chn);
|
|
+ printf(" %d - %s\n", channel, get_channel_name(channel));
|
|
|
|
err = write_loop(handle, channel, ((rate*3)/period_size), frames);
|
|
|
|
@@ -1066,13 +1173,15 @@ int main(int argc, char *argv[]) {
|
|
printf(_("Time per period = %lf\n"), time3 );
|
|
}
|
|
} else {
|
|
+ chn = get_speaker_channel(speaker - 1);
|
|
+
|
|
if (test_type == TEST_WAV) {
|
|
- if (setup_wav_file(speaker - 1) < 0)
|
|
+ if (setup_wav_file(chn) < 0)
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
- printf(" - %s\n", gettext(channel_name[speaker-1]));
|
|
- err = write_loop(handle, speaker-1, ((rate*5)/period_size), frames);
|
|
+ printf(" - %s\n", get_channel_name(chn));
|
|
+ err = write_loop(handle, chn, ((rate*5)/period_size), frames);
|
|
|
|
if (err < 0) {
|
|
fprintf(stderr, _("Transfer failed: %s\n"), snd_strerror(err));
|