Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e49253e1 authored by Varun Balaraj's avatar Varun Balaraj Committed by Garmond Leung
Browse files

hal: Adding Pan-Scale, downmix mixer control support.

Add support in HAL to send mix matrix params using downmix,
Pan-Scale mixer controls. Add new interactive usecases and
also add support to open and teardown for interactive streams.
Add support in test app for supporting up to 9 concurrent
streams. Add support for mixer matrix params handling.

Change-Id: I0dc5b908ee779b2b2c526a67609c057f591f26e7
parent 45929186
Loading
Loading
Loading
Loading
+17 −1
Original line number Diff line number Diff line
@@ -236,6 +236,17 @@ struct audio_device_config_param {
   struct audio_device_cfg_param dev_cfg_params;
};

typedef struct mix_matrix_params {
    uint16_t num_output_channels;
    uint16_t num_input_channels;
    uint8_t has_output_channel_map;
    uint32_t output_channel_map[AUDIO_CHANNEL_COUNT_MAX];
    uint8_t has_input_channel_map;
    uint32_t input_channel_map[AUDIO_CHANNEL_COUNT_MAX];
    uint8_t has_mixer_coeffs;
    float mixer_coeffs[AUDIO_CHANNEL_COUNT_MAX][AUDIO_CHANNEL_COUNT_MAX];
} mix_matrix_params_t;

typedef union {
    struct source_tracking_param st_params;
    struct sound_focus_param sf_params;
@@ -248,6 +259,7 @@ typedef union {
    struct audio_adsp_event adsp_event_params;
    struct audio_out_channel_map_param channel_map_param;
    struct audio_device_cfg_param device_cfg;
    struct mix_matrix_params mm_params;
} audio_extn_param_payload;

typedef enum {
@@ -264,7 +276,11 @@ typedef enum {
    AUDIO_EXTN_PARAM_ADSP_STREAM_CMD,
    /* param to set input channel map for playback stream */
    AUDIO_EXTN_PARAM_OUT_CHANNEL_MAP,
    AUDIO_EXTN_PARAM_DEVICE_CONFIG
    AUDIO_EXTN_PARAM_DEVICE_CONFIG,
    /* Pan/scale params to be set on ASM */
    AUDIO_EXTN_PARAM_OUT_MIX_MATRIX_PARAMS,
    /* Downmix params to be set on ADM */
    AUDIO_EXTN_PARAM_CH_MIX_MATRIX_PARAMS
} audio_extn_param_id;

#endif /* AUDIO_DEFS_H */
+8 −0
Original line number Diff line number Diff line
@@ -1379,6 +1379,14 @@ int audio_extn_out_set_param_data(struct stream_out *out,
            ret = audio_extn_utils_set_channel_map(out,
                    (struct audio_out_channel_map_param *)(payload));
            break;
        case AUDIO_EXTN_PARAM_OUT_MIX_MATRIX_PARAMS:
            ret = audio_extn_utils_set_pan_scale_params(out,
                    (struct mix_matrix_params *)(payload));
            break;
        case AUDIO_EXTN_PARAM_CH_MIX_MATRIX_PARAMS:
            ret = audio_extn_utils_set_downmix_params(out,
                    (struct mix_matrix_params *)(payload));
            break;
        default:
            ALOGE("%s:: unsupported param_id %d", __func__, param_id);
            break;
+10 −0
Original line number Diff line number Diff line
@@ -103,6 +103,10 @@
#define AUDIO_OUTPUT_FLAG_TIMESTAMP 0x10000
#endif

#ifndef AUDIO_OUTPUT_FLAG_INTERACTIVE
#define AUDIO_OUTPUT_FLAG_INTERACTIVE 0x40000
#endif

#ifndef COMPRESS_METADATA_NEEDED
#define audio_extn_parse_compress_metadata(out, parms) (0)
#else
@@ -892,6 +896,12 @@ int audio_extn_utils_compress_correct_drift(
int audio_extn_utils_set_channel_map(
            struct stream_out *out,
            struct audio_out_channel_map_param *channel_map_param);
int audio_extn_utils_set_pan_scale_params(
            struct stream_out *out,
            struct mix_matrix_params *mm_params);
int audio_extn_utils_set_downmix_params(
            struct stream_out *out,
            struct mix_matrix_params *mm_params);
#ifdef AUDIO_HW_LOOPBACK_ENABLED
/* API to create audio patch */
int audio_extn_hw_loopback_create_audio_patch(struct audio_hw_device *dev,
+118 −1
Original line number Diff line number Diff line
@@ -102,6 +102,10 @@
/* ToDo: Check and update a proper value in msec */
#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50

#ifndef MAX_CHANNELS_SUPPORTED
#define MAX_CHANNELS_SUPPORTED 8
#endif

struct string_to_enum {
    const char *name;
    uint32_t value;
@@ -122,6 +126,7 @@ const struct string_to_enum s_flag_name_to_enum_table[] = {
    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH),
    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_TIMESTAMP),
    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_VOIP_RX),
    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_INTERACTIVE),
    STRING_TO_ENUM(AUDIO_INPUT_FLAG_NONE),
    STRING_TO_ENUM(AUDIO_INPUT_FLAG_FAST),
    STRING_TO_ENUM(AUDIO_INPUT_FLAG_HW_HOTWORD),
@@ -821,6 +826,9 @@ static int send_app_type_cfg_for_device(struct audio_device *adev,
    int snd_device = split_snd_device, snd_device_be_idx = -1;
    int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
    char value[PROPERTY_VALUE_MAX] = {0};
    struct streams_io_cfg *s_info = NULL;
    struct listnode *node = NULL;
    int direct_app_type = 0;

    ALOGV("%s: usecase->out_snd_device %s, usecase->in_snd_device %s, split_snd_device %s",
          __func__, platform_get_snd_device_name(usecase->out_snd_device),
@@ -837,6 +845,7 @@ static int send_app_type_cfg_for_device(struct audio_device *adev,
        (usecase->id != USECASE_AUDIO_PLAYBACK_MULTI_CH) &&
        (usecase->id != USECASE_AUDIO_PLAYBACK_ULL) &&
        (usecase->id != USECASE_AUDIO_PLAYBACK_VOIP) &&
        (!is_interactive_usecase(usecase->id)) &&
        (!is_offload_usecase(usecase->id)) &&
        (usecase->type != PCM_CAPTURE)) {
        ALOGV("%s: a rx/tx/loopback path where app type cfg is not required %d", __func__, usecase->id);
@@ -917,6 +926,17 @@ static int send_app_type_cfg_for_device(struct audio_device *adev,
        }
        sample_rate = usecase->stream.out->app_type_cfg.sample_rate;

        /* Interactive streams are supported with only direct app type id.
         * Get Direct profile app type and use it for interactive streams
         */
        list_for_each(node, &adev->streams_output_cfg_list) {
            s_info = node_to_item(node, struct streams_io_cfg, list);
            if (s_info->flags.out_flags == AUDIO_OUTPUT_FLAG_DIRECT)
                direct_app_type = s_info->app_type_cfg.app_type;
        }
        if (usecase->stream.out->flags == AUDIO_OUTPUT_FLAG_INTERACTIVE)
            app_type = direct_app_type;
        else
            app_type = usecase->stream.out->app_type_cfg.app_type;
        app_type_cfg[len++] = app_type;
        app_type_cfg[len++] = acdb_dev_id;
@@ -2160,3 +2180,100 @@ int audio_extn_utils_set_channel_map(
exit:
    return ret;
}

int audio_extn_utils_set_pan_scale_params(
            struct stream_out *out,
            struct mix_matrix_params *mm_params)
{
    int ret = -EINVAL, i = 0, j = 0;

    if (mm_params == NULL && out != NULL) {
        ALOGE("%s:: Invalid mix matrix params", __func__);
        goto exit;
    }

    if (mm_params->num_output_channels > MAX_CHANNELS_SUPPORTED ||
        mm_params->num_output_channels <= 0 ||
        mm_params->num_input_channels > MAX_CHANNELS_SUPPORTED ||
        mm_params->num_input_channels <= 0)
        goto exit;

    out->pan_scale_params.num_output_channels = mm_params->num_output_channels;
    out->pan_scale_params.num_input_channels = mm_params->num_input_channels;
    out->pan_scale_params.has_output_channel_map =
                                        mm_params->has_output_channel_map;
    for (i = 0; i < mm_params->num_output_channels; i++)
        out->pan_scale_params.output_channel_map[i] =
                                         mm_params->output_channel_map[i];

    out->pan_scale_params.has_input_channel_map =
                                         mm_params->has_input_channel_map;
    for (i = 0; i < mm_params->num_input_channels; i++)
        out->pan_scale_params.input_channel_map[i] =
                                         mm_params->input_channel_map[i];

    out->pan_scale_params.has_mixer_coeffs = mm_params->has_mixer_coeffs;
    for (i = 0; i < mm_params->num_output_channels; i++)
        for (j = 0; j < mm_params->num_input_channels; j++) {
            //Convert the channel coefficient gains in Q14 format
            out->pan_scale_params.mixer_coeffs[i][j] =
                               mm_params->mixer_coeffs[i][j] * (2 << 13);
        }

    ret = platform_set_stream_pan_scale_params(out->dev->platform,
                                               out->pcm_device_id,
                                               out->pan_scale_params);

exit:
    return ret;
}

int audio_extn_utils_set_downmix_params(
            struct stream_out *out,
            struct mix_matrix_params *mm_params)
{
    int ret = -EINVAL, i = 0, j = 0;
    struct audio_usecase *usecase = NULL;

    if (mm_params == NULL && out != NULL) {
        ALOGE("%s:: Invalid mix matrix params", __func__);
        goto exit;
    }

    if (mm_params->num_output_channels > MAX_CHANNELS_SUPPORTED ||
        mm_params->num_output_channels <= 0 ||
        mm_params->num_input_channels > MAX_CHANNELS_SUPPORTED ||
        mm_params->num_input_channels <= 0)
        goto exit;

    usecase = get_usecase_from_list(out->dev, out->usecase);
    out->downmix_params.num_output_channels = mm_params->num_output_channels;
    out->downmix_params.num_input_channels = mm_params->num_input_channels;

    out->downmix_params.has_output_channel_map =
                                        mm_params->has_output_channel_map;
    for (i = 0; i < mm_params->num_output_channels; i++) {
        out->downmix_params.output_channel_map[i] =
                                          mm_params->output_channel_map[i];
    }

    out->downmix_params.has_input_channel_map =
                                        mm_params->has_input_channel_map;
    for (i = 0; i < mm_params->num_input_channels; i++)
        out->downmix_params.input_channel_map[i] =
                                          mm_params->input_channel_map[i];

    out->downmix_params.has_mixer_coeffs = mm_params->has_mixer_coeffs;
    for (i = 0; i < mm_params->num_output_channels; i++)
        for (j = 0; j < mm_params->num_input_channels; j++)
            out->downmix_params.mixer_coeffs[i][j] =
                               mm_params->mixer_coeffs[i][j];

    ret = platform_set_stream_downmix_params(out->dev->platform,
                                             out->pcm_device_id,
                                             usecase->out_snd_device,
                                             out->downmix_params);

exit:
    return ret;
}
+74 −2
Original line number Diff line number Diff line
@@ -318,6 +318,15 @@ const char * const use_case_table[AUDIO_USECASE_MAX] = {

    [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
    [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
    /* For Interactive Audio Streams */
    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
    [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
};

static const audio_usecase_t offload_usecases[] = {
@@ -332,6 +341,17 @@ static const audio_usecase_t offload_usecases[] = {
    USECASE_AUDIO_PLAYBACK_OFFLOAD9,
};

static const audio_usecase_t interactive_usecases[] = {
    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
    USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
};

#define STRING_TO_ENUM(string) { #string, string }

struct string_to_enum {
@@ -2149,6 +2169,50 @@ static void stop_compressed_output_l(struct stream_out *out)
    }
}

bool is_interactive_usecase(audio_usecase_t uc_id)
{
    unsigned int i;
    for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
        if (uc_id == interactive_usecases[i])
            return true;
    }
    return false;
}

static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
{
    audio_usecase_t ret_uc = USECASE_INVALID;
    unsigned int intract_uc_index;
    unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);

    ALOGV("%s: num_usecase: %d", __func__, num_usecase);
    for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
        if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
            adev->interactive_usecase_state |= 0x1 << intract_uc_index;
            ret_uc = interactive_usecases[intract_uc_index];
            break;
        }
    }

    ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
    return ret_uc;
}

static void free_interactive_usecase(struct audio_device *adev,
                                 audio_usecase_t uc_id)
{
    unsigned int interact_uc_index;
    unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);

    for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
        if (interactive_usecases[interact_uc_index] == uc_id) {
            adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
            break;
        }
    }
    ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
}

bool is_offload_usecase(audio_usecase_t uc_id)
{
    unsigned int i;
@@ -2814,7 +2878,9 @@ static size_t out_get_buffer_size(const struct audio_stream *stream)
{
    struct stream_out *out = (struct stream_out *)stream;

    if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
    if (is_interactive_usecase(out->usecase)) {
        return out->config.period_size;
    } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
        if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
            return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
        else
@@ -5180,7 +5246,10 @@ int adev_open_output_stream(struct audio_hw_device *dev,

        channels = audio_channel_count_from_out_mask(out->channel_mask);

        if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
        if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
            out->usecase = get_interactive_usecase(adev);
            out->config = pcm_config_low_latency;
        } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
            out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
            out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
                                               out->flags);
@@ -5411,6 +5480,9 @@ void adev_close_output_stream(struct audio_hw_device *dev __unused,

    out->a2dp_compress_mute = false;

    if (is_interactive_usecase(out->usecase))
        free_interactive_usecase(adev, out->usecase);

    if (out->convert_buffer != NULL) {
        free(out->convert_buffer);
        out->convert_buffer = NULL;
Loading