ALSA:チャンネルマップ

チャンネルマップ
PCM から、有効なチャンネルマップの情報を取得することができます。

チャンネルマップ関連の関数は、チャンネルマップ をご覧ください。
チャンネルマップの情報取得
//開いた PCM から
snd_pcm_chmap_query_t **snd_pcm_query_chmaps(snd_pcm_t *pcm);

//カード番号などを指定
snd_pcm_chmap_query_t **snd_pcm_query_chmaps_from_hw(int card,
    int dev, int subdev, snd_pcm_stream_t stream);

//解放
void snd_pcm_free_chmaps(snd_pcm_chmap_query_t **maps);

開いた PCM から取得する方法と、カード・デバイス・サブデバイス・ストリーム方向を指定して、取得する方法があります。

snd_pcm_chmap_query_t 構造体のポインタの配列、または NULL が返ります。
返ったポインタは、snd_pcm_free_chmaps() で解放します。

(snd_pcm_chmap_query_t *) の値が NULL で、データの終端になります。
snd_pcm_chmap_query_t
typedef struct snd_pcm_chmap_query {
    enum snd_pcm_chmap_type type;
    snd_pcm_chmap_t map;
} snd_pcm_chmap_query_t;

//各チャンネルマップ

typedef struct snd_pcm_chmap {
    unsigned int channels; //チャンネル数
    unsigned int pos[0];   //チャンネル位置
} snd_pcm_chmap_t;

snd_pcm_chmap_query_t の type は、チャンネル位置を交換できるかどうかのタイプです。

SND_CHMAP_TYPE_NONE未指定
SND_CHMAP_TYPE_FIXED固定
SND_CHMAP_TYPE_VAR自由に交換可能
SND_CHMAP_TYPE_PAIREDペアで交換可能

snd_pcm_chmap_t が、各チャンネルマップの情報です。

pos の配列は、チャンネル数分あります。
実際は、enum snd_pcm_chmap_position の値が格納されています。

enum snd_pcm_chmap_position {
    SND_CHMAP_UNKNOWN = 0, //未定義
    SND_CHMAP_NA,   //無音
    SND_CHMAP_MONO,
    SND_CHMAP_FL,   //Front left
    SND_CHMAP_FR,
    SND_CHMAP_RL,   //Rear left
    SND_CHMAP_RR,
    ...

ステレオ 2ch なら、FL と FR になります。
プログラム
指定した PCM で有効な、チャンネルマップの一覧を出力します。

$ cc -o 12-chmap 12-chmap.c -lasound

int main(int argc,char **argv)
{
    snd_pcm_t *pcm;
    snd_pcm_chmap_query_t **ppmap,**ptr,*chmap;
    unsigned int i;

    if(snd_pcm_open(&pcm,
        (argc >= 2)? argv[1]: "default", SND_PCM_STREAM_PLAYBACK, 0))
    {
        printf("open error\n");
        return 1;
    }

    //チャンネルマップ

    ppmap = snd_pcm_query_chmaps(pcm);
    if(!ppmap) goto END;

    for(ptr = ppmap; *ptr; ptr++)
    {
        chmap = *ptr;

        printf("type: %s\n", snd_pcm_chmap_type_name(chmap->type));
        printf("channels: %u\n", chmap->map.channels);

        for(i = 0; i < chmap->map.channels; i++)
        {
            printf("[%u] '%s' '%s'\n", i,
                snd_pcm_chmap_name(chmap->map.pos[i]),
                snd_pcm_chmap_long_name(chmap->map.pos[i]));
        }

        printf("------\n");
    } 

    snd_pcm_free_chmaps(ppmap);

    //
END:
    snd_pcm_close(pcm);

    return 0;
}
実行結果
type: FIXED
channels: 2
[0] 'FL' 'Front Left'
[1] 'FR' 'Front Right'
------

アナログ出力の場合、チャンネル位置は固定で、2ch (左、右) となっています。
HDMI
$ ./12-chmap hdmi

type: VAR
channels: 2
[0] 'FL' 'Front Left'
[1] 'FR' 'Front Right'
------

HDMI の場合は、タイプが VAR なので、チャンネル位置が自由に交換可能になっています。

つまり、左右のチャンネル位置を入れ替えることができます。

snd_pcm_set_chmap() を使うと、現在のチャンネルマップを変更することができます。