alsa-devel.alsa-project.org archive mirror
 help / color / mirror / Atom feed
From: Anssi Hannula <anssi.hannula@iki.fi>
To: Takashi Iwai <tiwai@suse.de>, alsa-devel@alsa-project.org
Cc: "Olivier Langlois" <olivier@trillion01.com>,
	"Peter Frühberger" <fritsch@xbmc.org>
Subject: [PATCH 1/3 v2] speaker-test: Fix chmapped channel selection without specified chmap
Date: Tue, 12 Nov 2013 00:04:02 +0200	[thread overview]
Message-ID: <1384207442-830-1-git-send-email-anssi.hannula@iki.fi> (raw)
In-Reply-To: <52813CD4.30600@iki.fi>

The channel selection currently does not work properly when there is a
driver-provided non-ALSA-traditional channel map but no manual channel
map was explicitely requested with "-m".

For example, the CEA/HDMI 8ch map is FL,FR,RLC,RRC,FC,LFE,RL,RR. Note
that it is otherwise the same as the traditional ALSA channel map,
except that the traditional rear speakers are considered
rear-center speakers and the traditional side speakers are considered
rear speakers.

Speaker-test tries to play back channels in this following order:
  0, /* Front Left  */
  4, /* Center      */
  1, /* Front Right */
  7, /* Side Right  */
  3, /* Rear Right  */
  2, /* Rear Left   */
  6, /* Side Left   */
  5, /* LFE         */

When it is the time to play back Side Left/Right, speaker-test tries to
look for SL/SR in the chmap, but doesn't find it, so it just plays back
channels 6/7 (which indeed are the side speakers, or RL/RR in this
channel map - so the correct channels are selected).

When it becomes the time to playback Rear Left/Right, speaker-test again
tries to find RL/RR in the chmap, and this time it does find them in the
chmap positions 6/7.

So the channels 6/7 are tested twice and 2/3 are never tested.

To fix this, define a generic playback order channel_order[] to be used
when the channel map is present (but not user-defined) and generate a
(speaker/playback number => channel number) mapping with the channels
ordered in the following order:
1. regular channels found in channel_order[] in the defined order,
2. channels not found in channel_order[] ordered by channel number.
3. UNKNOWN channels ordered by channel number.
4. NA channels ordered by channel number.
For channels outside the channel map just use their channel numbers (so
they will be last after all of the above).

For example, if the playback device has a fictional default channel map
of FR,FL,UNKNOWN1,FOO,BAR,RR,RL,UNKNOWN2, the playback order will be
FL,FR,RR,RL,FOO,BAR,UNKNOWN1,UNKNOWN2(,any_extra_channels).

When the channel mapping is specified manually, the specified order is
used for playback as before.

Signed-off-by: Anssi Hannula <anssi.hannula@iki.fi>
---
 speaker-test/speaker-test.c | 113 +++++++++++++++++++++++++++++++++++---------
 1 file changed, 91 insertions(+), 22 deletions(-)

diff --git a/speaker-test/speaker-test.c b/speaker-test/speaker-test.c
index 45e92e5..261f399 100644
--- a/speaker-test/speaker-test.c
+++ b/speaker-test/speaker-test.c
@@ -88,6 +88,8 @@ enum {
 #define BE_INT(v)		(v)
 #endif
 
+#define ARRAY_SIZE(x) (int)(sizeof(x)/sizeof(x[0]))
+
 static char              *device      = "default";       /* playback device */
 static snd_pcm_format_t   format      = SND_PCM_FORMAT_S16; /* sample format */
 static unsigned int       rate        = 48000;	            /* stream rate */
@@ -110,6 +112,7 @@ static snd_pcm_t *pcm_handle = NULL;
 #ifdef CONFIG_SUPPORT_CHMAP
 static snd_pcm_chmap_t *channel_map;
 static int channel_map_set;
+static unsigned int *ordered_channels;
 #endif
 
 static const char *const channel_name[MAX_CHANNELS] = {
@@ -156,36 +159,94 @@ static const int	channels8[] = {
   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,
-  };
+/* circular clockwise and bottom-to-top order */
+static const int channel_order[] = {
+  [SND_CHMAP_FLW]  =  10,
+  [SND_CHMAP_FL]   =  20,
+  [SND_CHMAP_TFL]  =  30,
+  [SND_CHMAP_FLC]  =  40,
+  [SND_CHMAP_TFLC] =  50,
+  [SND_CHMAP_FC]   =  60,
+  [SND_CHMAP_TFC]  =  70,
+  [SND_CHMAP_FRC]  =  80,
+  [SND_CHMAP_TFRC] =  90,
+  [SND_CHMAP_FR]   = 100,
+  [SND_CHMAP_TFR]  = 110,
+  [SND_CHMAP_FRW]  = 120,
+  [SND_CHMAP_SR]   = 130,
+  [SND_CHMAP_TSR]  = 140,
+  [SND_CHMAP_RR]   = 150,
+  [SND_CHMAP_TRR]  = 160,
+  [SND_CHMAP_RRC]  = 170,
+  [SND_CHMAP_RC]   = 180,
+  [SND_CHMAP_TRC]  = 190,
+  [SND_CHMAP_RLC]  = 200,
+  [SND_CHMAP_RL]   = 210,
+  [SND_CHMAP_TRL]  = 220,
+  [SND_CHMAP_SL]   = 230,
+  [SND_CHMAP_TSL]  = 240,
+  [SND_CHMAP_BC]   = 250,
+  [SND_CHMAP_TC]   = 260,
+  [SND_CHMAP_LLFE] = 270,
+  [SND_CHMAP_LFE]  = 280,
+  [SND_CHMAP_RLFE] = 290,
+  /* not in table  = 10000 */
+  [SND_CHMAP_UNKNOWN] = 20000,
+  [SND_CHMAP_NA]      = 30000,
+};
 
-  if (channel_map && maps[chn]) {
-    int i;
-    for (i = 0; i < channel_map->channels; i++) {
-      if (channel_map->pos[i] == maps[chn])
-	return i;
-    }
+static int chpos_cmp(const void *chnum1p, const void *chnum2p)
+{
+  int chnum1 = *(int *)chnum1p;
+  int chnum2 = *(int *)chnum2p;
+  int chpos1 = channel_map->pos[chnum1];
+  int chpos2 = channel_map->pos[chnum2];
+  int weight1 = 10000;
+  int weight2 = 10000;
+
+  if (chpos1 < ARRAY_SIZE(channel_order) && channel_order[chpos1])
+    weight1 = channel_order[chpos1];
+  if (chpos2 < ARRAY_SIZE(channel_order) && channel_order[chpos2])
+    weight2 = channel_order[chpos2];
+
+  if (weight1 == weight2) {
+    /* order by channel number if both have the same position (e.g. UNKNOWN)
+     * or if neither is in channel_order[] */
+    return chnum1 - chnum2;
   }
-#endif
-  return chn;
+
+  /* order according to channel_order[] */
+  return weight1 - weight2;
+}
+
+static int *order_channels(void)
+{
+  /* create a (playback order => channel number) table with channels ordered
+   * according to channel_order[] values */
+  int i;
+  int *ordered_chs;
+
+  ordered_chs = calloc(channel_map->channels, sizeof(*ordered_chs));
+  if (!ordered_chs)
+    return NULL;
+
+  for (i = 0; i < channel_map->channels; i++)
+    ordered_chs[i] = i;
+
+  qsort(ordered_chs, channel_map->channels, sizeof(*ordered_chs), chpos_cmp);
+
+  return ordered_chs;
 }
+#endif
 
 static int get_speaker_channel(int chn)
 {
 #ifdef CONFIG_SUPPORT_CHMAP
-  if (channel_map_set)
+  if (channel_map_set || (ordered_channels && chn >= channel_map->channels))
     return chn;
+  if (ordered_channels)
+    return ordered_channels[chn];
 #endif
 
   switch (channels) {
@@ -200,7 +261,7 @@ static int get_speaker_channel(int chn)
     break;
   }
 
-  return get_mapped_channel(chn);
+  return chn;
 }
 
 static const char *get_channel_name(int chn)
@@ -613,6 +674,11 @@ static int config_chmap(snd_pcm_t *handle, const char *mapstr)
   }
 
   channel_map = snd_pcm_get_chmap(handle);
+
+  /* create a channel order table for default layouts */
+  if (channel_map)
+    ordered_channels = order_channels();
+
   return 0;
 }
 #endif
@@ -1232,6 +1298,9 @@ int main(int argc, char *argv[]) {
 
 
   free(frames);
+#ifdef CONFIG_SUPPORT_CHMAP
+  free(ordered_channels);
+#endif
 
   return prg_exit(EXIT_SUCCESS);
 }
-- 
1.8.1.5

  reply	other threads:[~2013-11-11 22:13 UTC|newest]

Thread overview: 71+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-10-24 18:10 [PATCH v3 0/5] ALSA: hda - hdmi: ATI/AMD multi-channel and HBR support Anssi Hannula
2013-10-24 18:10 ` [PATCH 1/5] ALSA: hda - hdmi: Allow HDA patches to customize more operations Anssi Hannula
2013-10-24 18:10 ` [PATCH 2/5] ALSA: hda - hdmi: Add ATI/AMD multi-channel audio support Anssi Hannula
2013-10-24 18:10 ` [PATCH 3/5] ALSA: hda - hdmi: Add ELD emulation for ATI/AMD codecs Anssi Hannula
2013-10-24 18:10 ` [PATCH 4/5] ALSA: hda - hdmi: Add HBR bitstreaming support for ATI/AMD HDMI codecs Anssi Hannula
2013-10-24 18:10 ` [PATCH 5/5] ALSA: hda - hdmi: Disable ramp-up/down for non-PCM on AMD codecs Anssi Hannula
2013-10-24 19:00   ` Anssi Hannula
2013-10-24 18:26 ` [PATCH v3 0/5] ALSA: hda - hdmi: ATI/AMD multi-channel and HBR support Anssi Hannula
2013-11-08  5:08   ` Olivier Langlois
2013-11-08 10:27     ` Anssi Hannula
2013-11-08 18:17       ` Olivier Langlois
2013-11-08 21:28         ` Olivier Langlois
2013-11-08 22:03           ` Anssi Hannula
2013-11-10  5:42             ` Olivier Langlois
2013-11-10  6:01               ` Anssi Hannula
2013-11-10  7:25                 ` speaker-test chmap bugs (was: [PATCH v3 0/5] ALSA: hda - hdmi: ATI/AMD multi-channel and HBR support) Anssi Hannula
2013-11-10 18:29                   ` [PATCH 1/3] speaker-test: Fix chmapped channel selection without specified chmap Anssi Hannula
2013-11-10 18:29                     ` [PATCH 2/3] speaker-test: Always show chmap channel names if available Anssi Hannula
2013-11-10 18:29                     ` [PATCH 3/3] speaker-test: Show out-of-chmap channels as Unknown Anssi Hannula
2013-11-11 15:56                     ` [PATCH 1/3] speaker-test: Fix chmapped channel selection without specified chmap Takashi Iwai
2013-11-11 20:23                       ` Anssi Hannula
2013-11-11 22:04                         ` Anssi Hannula [this message]
2013-11-12  8:11                           ` [PATCH 1/3 v2] " Takashi Iwai
2013-11-12 12:34                             ` Anssi Hannula
2013-11-12 13:08                               ` Takashi Iwai
2013-11-12  6:35                 ` [PATCH v3 0/5] ALSA: hda - hdmi: ATI/AMD multi-channel and HBR support Olivier Langlois
2013-11-14  0:04                   ` Anssi Hannula
2013-11-09  8:35         ` Takashi Iwai
2013-10-24 23:04 ` Takashi Iwai
2013-10-25 16:54   ` Andre Heider
2013-10-25 17:13     ` Takashi Iwai
2013-10-25 17:23     ` Anssi Hannula
2013-10-25 18:25       ` Andre Heider
2013-10-28 17:52       ` Andre Heider
2013-10-28 18:12         ` Anssi Hannula
2013-10-28 18:17           ` Andre Heider
2013-10-28 18:25             ` Anssi Hannula
2013-10-28 18:35               ` Andre Heider
2013-10-28 20:35                 ` Anssi Hannula
2013-10-28 22:00                   ` Andre Heider
2013-10-28 22:42                     ` Anssi Hannula
2013-10-28 23:15                       ` Andre Heider
2013-10-29 19:52                         ` LANGLOIS Olivier PIS -EXT
2013-10-29 20:30                           ` Anssi Hannula
2013-10-28 23:19                       ` [PATCH] drm/radeon/audio: fix missing multichannel PCM SAD in some cases Anssi Hannula
2013-10-31 23:38                         ` Rafał Miłecki
2013-10-31 23:46                           ` Rafał Miłecki
2013-10-31 23:52                           ` Anssi Hannula
2013-11-02  1:01                         ` Rafał Miłecki
2013-11-02  1:08                           ` Anssi Hannula
2013-11-02  1:15                             ` Rafał Miłecki
2013-11-02  1:03                         ` Rafał Miłecki
2013-11-02 15:32 ` [PATCH v3 0/5] ALSA: hda - hdmi: ATI/AMD multi-channel and HBR support Anssi Hannula
2013-11-23  1:05 ` James Le Cuirot
2013-11-23  1:29   ` Anssi Hannula
2013-11-23 15:40     ` James Le Cuirot
2013-11-23 15:45       ` Anssi Hannula
2013-11-24 14:57         ` James Le Cuirot
2013-11-25 13:20           ` Anssi Hannula
2013-11-25 14:32             ` James Le Cuirot
2013-11-25 14:56               ` Anssi Hannula
2014-05-13 12:01                 ` James Le Cuirot
2014-05-13 12:27                   ` Anssi Hannula
2014-05-13 16:16                     ` James Le Cuirot
2014-05-13 21:10                       ` James Le Cuirot
2014-05-13 21:50                         ` Anssi Hannula
2014-05-14 13:04                           ` Deucher, Alexander
2014-05-14 13:19                             ` James Le Cuirot
2013-11-25 15:07   ` Raymond Yau
2013-11-25 15:32     ` James Le Cuirot
2013-11-25 19:35     ` Anssi Hannula

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=1384207442-830-1-git-send-email-anssi.hannula@iki.fi \
    --to=anssi.hannula@iki.fi \
    --cc=alsa-devel@alsa-project.org \
    --cc=fritsch@xbmc.org \
    --cc=olivier@trillion01.com \
    --cc=tiwai@suse.de \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).