From af3f18b4896ad97f0f8a9625e6c76672a90a5aa9 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 23 Nov 2020 15:31:10 +0100 Subject: [PATCH] acp: add channel layout and map channels --- spa/plugins/alsa/acp/acp.c | 71 +++++++++++++++++++++++++++++++++++++- spa/plugins/alsa/acp/acp.h | 47 ++++++++++++++++++++++++- 2 files changed, 116 insertions(+), 2 deletions(-) diff --git a/spa/plugins/alsa/acp/acp.c b/spa/plugins/alsa/acp/acp.c index 2b004ece8..c970361d9 100644 --- a/spa/plugins/alsa/acp/acp.c +++ b/spa/plugins/alsa/acp/acp.c @@ -32,6 +32,75 @@ void *_acp_log_data; #define VOLUME_ACCURACY (PA_VOLUME_NORM/100) /* don't require volume adjustments to be perfectly correct. don't necessarily extend granularity in software unless the differences get greater than this level */ +static const uint32_t channel_table[PA_CHANNEL_POSITION_MAX] = { + [PA_CHANNEL_POSITION_MONO] = ACP_CHANNEL_MONO, + + [PA_CHANNEL_POSITION_FRONT_LEFT] = ACP_CHANNEL_FL, + [PA_CHANNEL_POSITION_FRONT_RIGHT] = ACP_CHANNEL_FR, + [PA_CHANNEL_POSITION_FRONT_CENTER] = ACP_CHANNEL_FC, + + [PA_CHANNEL_POSITION_REAR_CENTER] = ACP_CHANNEL_RC, + [PA_CHANNEL_POSITION_REAR_LEFT] = ACP_CHANNEL_RL, + [PA_CHANNEL_POSITION_REAR_RIGHT] = ACP_CHANNEL_RR, + + [PA_CHANNEL_POSITION_LFE] = ACP_CHANNEL_LFE, + [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = ACP_CHANNEL_FLC, + [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = ACP_CHANNEL_FRC, + + [PA_CHANNEL_POSITION_SIDE_LEFT] = ACP_CHANNEL_SL, + [PA_CHANNEL_POSITION_SIDE_RIGHT] = ACP_CHANNEL_SR, + + [PA_CHANNEL_POSITION_AUX0] = ACP_CHANNEL_CUSTOM_START + 1, + [PA_CHANNEL_POSITION_AUX1] = ACP_CHANNEL_CUSTOM_START + 2, + [PA_CHANNEL_POSITION_AUX2] = ACP_CHANNEL_CUSTOM_START + 3, + [PA_CHANNEL_POSITION_AUX3] = ACP_CHANNEL_CUSTOM_START + 4, + [PA_CHANNEL_POSITION_AUX4] = ACP_CHANNEL_CUSTOM_START + 5, + [PA_CHANNEL_POSITION_AUX5] = ACP_CHANNEL_CUSTOM_START + 6, + [PA_CHANNEL_POSITION_AUX6] = ACP_CHANNEL_CUSTOM_START + 7, + [PA_CHANNEL_POSITION_AUX7] = ACP_CHANNEL_CUSTOM_START + 8, + [PA_CHANNEL_POSITION_AUX8] = ACP_CHANNEL_CUSTOM_START + 9, + [PA_CHANNEL_POSITION_AUX9] = ACP_CHANNEL_CUSTOM_START + 10, + [PA_CHANNEL_POSITION_AUX10] = ACP_CHANNEL_CUSTOM_START + 11, + [PA_CHANNEL_POSITION_AUX11] = ACP_CHANNEL_CUSTOM_START + 12, + [PA_CHANNEL_POSITION_AUX12] = ACP_CHANNEL_CUSTOM_START + 13, + [PA_CHANNEL_POSITION_AUX13] = ACP_CHANNEL_CUSTOM_START + 14, + [PA_CHANNEL_POSITION_AUX14] = ACP_CHANNEL_CUSTOM_START + 15, + [PA_CHANNEL_POSITION_AUX15] = ACP_CHANNEL_CUSTOM_START + 16, + [PA_CHANNEL_POSITION_AUX16] = ACP_CHANNEL_CUSTOM_START + 17, + [PA_CHANNEL_POSITION_AUX17] = ACP_CHANNEL_CUSTOM_START + 18, + [PA_CHANNEL_POSITION_AUX18] = ACP_CHANNEL_CUSTOM_START + 19, + [PA_CHANNEL_POSITION_AUX19] = ACP_CHANNEL_CUSTOM_START + 20, + [PA_CHANNEL_POSITION_AUX20] = ACP_CHANNEL_CUSTOM_START + 21, + [PA_CHANNEL_POSITION_AUX21] = ACP_CHANNEL_CUSTOM_START + 22, + [PA_CHANNEL_POSITION_AUX22] = ACP_CHANNEL_CUSTOM_START + 23, + [PA_CHANNEL_POSITION_AUX23] = ACP_CHANNEL_CUSTOM_START + 24, + [PA_CHANNEL_POSITION_AUX24] = ACP_CHANNEL_CUSTOM_START + 25, + [PA_CHANNEL_POSITION_AUX25] = ACP_CHANNEL_CUSTOM_START + 26, + [PA_CHANNEL_POSITION_AUX26] = ACP_CHANNEL_CUSTOM_START + 27, + [PA_CHANNEL_POSITION_AUX27] = ACP_CHANNEL_CUSTOM_START + 28, + [PA_CHANNEL_POSITION_AUX28] = ACP_CHANNEL_CUSTOM_START + 29, + [PA_CHANNEL_POSITION_AUX29] = ACP_CHANNEL_CUSTOM_START + 30, + [PA_CHANNEL_POSITION_AUX30] = ACP_CHANNEL_CUSTOM_START + 31, + [PA_CHANNEL_POSITION_AUX31] = ACP_CHANNEL_CUSTOM_START + 32, + + [PA_CHANNEL_POSITION_TOP_CENTER] = ACP_CHANNEL_TC, + + [PA_CHANNEL_POSITION_TOP_FRONT_LEFT] = ACP_CHANNEL_TFL, + [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT] = ACP_CHANNEL_TFR, + [PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = ACP_CHANNEL_TFC, + + [PA_CHANNEL_POSITION_TOP_REAR_LEFT] = ACP_CHANNEL_TRL, + [PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = ACP_CHANNEL_TRR, + [PA_CHANNEL_POSITION_TOP_REAR_CENTER] = ACP_CHANNEL_TRC, +}; + +static inline uint32_t channel_pa2acp(pa_channel_position_t channel) +{ + if (channel < 0 || (size_t)channel >= SPA_N_ELEMENTS(channel_table)) + return ACP_CHANNEL_UNKNOWN; + return channel_table[channel]; +} + const char *acp_available_str(enum acp_available status) { switch (status) { @@ -89,7 +158,7 @@ static void init_device(pa_card *impl, pa_alsa_device *dev, pa_alsa_direction_t dev->device.format.channels = m->channel_map.channels; pa_cvolume_reset(&dev->real_volume, m->channel_map.channels); for (i = 0; i < m->channel_map.channels; i++) - dev->device.format.map[i]= m->channel_map.map[i]; + dev->device.format.map[i]= channel_pa2acp(m->channel_map.map[i]); dev->direction = direction; dev->proplist = pa_proplist_new(); pa_proplist_update(dev->proplist, PA_UPDATE_REPLACE, m->proplist); diff --git a/spa/plugins/alsa/acp/acp.h b/spa/plugins/alsa/acp/acp.h index c7969b80e..7bf060e07 100644 --- a/spa/plugins/alsa/acp/acp.h +++ b/spa/plugins/alsa/acp/acp.h @@ -43,6 +43,7 @@ extern "C" { #endif #define ACP_INVALID_INDEX ((uint32_t)-1) +#define ACP_MAX_CHANNELS 64 struct acp_dict_item { const char *key; @@ -56,12 +57,56 @@ struct acp_dict { const struct acp_dict_item *items; }; +enum acp_channel { + ACP_CHANNEL_UNKNOWN, /**< unspecified */ + ACP_CHANNEL_NA, /**< N/A, silent */ + + ACP_CHANNEL_MONO, /**< mono stream */ + + ACP_CHANNEL_FL, /**< front left */ + ACP_CHANNEL_FR, /**< front right */ + ACP_CHANNEL_FC, /**< front center */ + ACP_CHANNEL_LFE, /**< LFE */ + ACP_CHANNEL_SL, /**< side left */ + ACP_CHANNEL_SR, /**< side right */ + ACP_CHANNEL_FLC, /**< front left center */ + ACP_CHANNEL_FRC, /**< front right center */ + ACP_CHANNEL_RC, /**< rear center */ + ACP_CHANNEL_RL, /**< rear left */ + ACP_CHANNEL_RR, /**< rear right */ + ACP_CHANNEL_TC, /**< top center */ + ACP_CHANNEL_TFL, /**< top front left */ + ACP_CHANNEL_TFC, /**< top front center */ + ACP_CHANNEL_TFR, /**< top front right */ + ACP_CHANNEL_TRL, /**< top rear left */ + ACP_CHANNEL_TRC, /**< top rear center */ + ACP_CHANNEL_TRR, /**< top rear right */ + ACP_CHANNEL_RLC, /**< rear left center */ + ACP_CHANNEL_RRC, /**< rear right center */ + ACP_CHANNEL_FLW, /**< front left wide */ + ACP_CHANNEL_FRW, /**< front right wide */ + ACP_CHANNEL_LFE2, /**< LFE 2 */ + ACP_CHANNEL_FLH, /**< front left high */ + ACP_CHANNEL_FCH, /**< front center high */ + ACP_CHANNEL_FRH, /**< front right high */ + ACP_CHANNEL_TFLC, /**< top front left center */ + ACP_CHANNEL_TFRC, /**< top front right center */ + ACP_CHANNEL_TSL, /**< top side left */ + ACP_CHANNEL_TSR, /**< top side right */ + ACP_CHANNEL_LLFE, /**< left LFE */ + ACP_CHANNEL_RLFE, /**< right LFE */ + ACP_CHANNEL_BC, /**< bottom center */ + ACP_CHANNEL_BLC, /**< bottom left center */ + ACP_CHANNEL_BRC, /**< bottom right center */ + ACP_CHANNEL_CUSTOM_START = 0x10000, +}; + struct acp_format { uint32_t flags; uint32_t format_mask; uint32_t rate_mask; uint32_t channels; - uint32_t map[64]; + uint32_t map[ACP_MAX_CHANNELS]; }; #define ACP_DICT_INIT(items,n_items) (struct acp_dict) { 0, n_items, items }