687 lines
25 KiB
C
687 lines
25 KiB
C
/*
|
|
* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above
|
|
* copyright notice, this list of conditions and the following
|
|
* disclaimer in the documentation and/or other materials provided
|
|
* with the distribution.
|
|
* * Neither the name of The Linux Foundation nor the names of its
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
|
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
|
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
#define LOG_TAG "source_track"
|
|
/*#define LOG_NDEBUG 0*/
|
|
#define LOG_NDDEBUG 0
|
|
|
|
#include <errno.h>
|
|
#include <math.h>
|
|
#include <cutils/log.h>
|
|
|
|
#include "audio_hw.h"
|
|
#include "platform.h"
|
|
#include "platform_api.h"
|
|
#include "voice_extn.h"
|
|
#include <stdlib.h>
|
|
#include <cutils/str_parms.h>
|
|
|
|
#ifdef SOURCE_TRACKING_ENABLED
|
|
/* Audio Paramater Key to identify the list of start angles.
|
|
* Starting angle (in degrees) defines the boundary starting angle for each sector.
|
|
*/
|
|
#define AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES "SoundFocus.start_angles"
|
|
/* Audio Paramater Key to identify the list of enable flags corresponding to each sector.
|
|
*/
|
|
#define AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS "SoundFocus.enable_sectors"
|
|
/* Audio Paramater Key to identify the gain step value to be applied to all enabled sectors.
|
|
*/
|
|
#define AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP "SoundFocus.gain_step"
|
|
/* Audio Paramater Key to identify the list of voice activity detector outputs corresponding
|
|
* to each sector.
|
|
*/
|
|
#define AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD "SourceTrack.vad"
|
|
/* Audio Paramater Key to identify the direction (in degrees) of arrival for desired talker
|
|
* (dominant source of speech).
|
|
*/
|
|
#define AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH "SourceTrack.doa_speech"
|
|
/* Audio Paramater Key to identify the list of directions (in degrees) of arrival for
|
|
* interferers (interfering noise sources).
|
|
*/
|
|
#define AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE "SourceTrack.doa_noise"
|
|
/* Audio Paramater Key to identify the list of sound strength indicators at each degree
|
|
* of the horizontal plane referred to by a full circle (360 degrees).
|
|
*/
|
|
#define AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY "SourceTrack.polar_activity"
|
|
|
|
#define BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES 0x1
|
|
#define BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS 0x2
|
|
#define BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP 0x4
|
|
#define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD 0x8
|
|
#define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH 0x10
|
|
#define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE 0x20
|
|
#define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY 0x40
|
|
|
|
#define BITMASK_AUDIO_PARAMETER_KEYS_SOUND_FOCUS \
|
|
(BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES |\
|
|
BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS |\
|
|
BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP)
|
|
|
|
#define BITMASK_AUDIO_PARAMETER_KEYS_SOURCE_TRACKING \
|
|
(BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD |\
|
|
BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH |\
|
|
BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE |\
|
|
BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY)
|
|
|
|
#define MAX_STR_SIZE 2048
|
|
|
|
extern struct audio_device_to_audio_interface audio_device_to_interface_table[];
|
|
extern int audio_device_to_interface_table_len;
|
|
|
|
static int add_audio_intf_name_to_mixer_ctl(audio_devices_t device, char *mixer_ctl_name,
|
|
struct audio_device_to_audio_interface *table, int len)
|
|
{
|
|
int ret = 0;
|
|
int i;
|
|
|
|
if (table == NULL) {
|
|
ALOGE("%s: table is NULL", __func__);
|
|
|
|
ret = -EINVAL;
|
|
goto done;
|
|
}
|
|
|
|
if (mixer_ctl_name == NULL) {
|
|
ret = -EINVAL;
|
|
goto done;
|
|
}
|
|
|
|
for (i=0; i < len; i++) {
|
|
if (device == table[i].device) {
|
|
strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH);
|
|
strlcat(mixer_ctl_name, table[i].interface_name, MIXER_PATH_MAX_LENGTH);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == len) {
|
|
ALOGE("%s: Audio Device not found in the table", __func__);
|
|
|
|
ret = -EINVAL;
|
|
}
|
|
done:
|
|
return ret;
|
|
}
|
|
|
|
static bool is_stt_supported_snd_device(snd_device_t snd_device)
|
|
{
|
|
bool ret = false;
|
|
|
|
switch (snd_device) {
|
|
case SND_DEVICE_IN_HANDSET_DMIC:
|
|
case SND_DEVICE_IN_HANDSET_DMIC_AEC:
|
|
case SND_DEVICE_IN_HANDSET_DMIC_NS:
|
|
case SND_DEVICE_IN_HANDSET_DMIC_AEC_NS:
|
|
case SND_DEVICE_IN_HANDSET_STEREO_DMIC:
|
|
case SND_DEVICE_IN_HANDSET_QMIC:
|
|
case SND_DEVICE_IN_VOICE_DMIC:
|
|
case SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE:
|
|
case SND_DEVICE_IN_HEADSET_MIC_FLUENCE:
|
|
case SND_DEVICE_IN_SPEAKER_DMIC:
|
|
case SND_DEVICE_IN_SPEAKER_DMIC_AEC:
|
|
case SND_DEVICE_IN_SPEAKER_DMIC_NS:
|
|
case SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS:
|
|
case SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE:
|
|
case SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE:
|
|
case SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE:
|
|
case SND_DEVICE_IN_SPEAKER_QMIC_AEC:
|
|
case SND_DEVICE_IN_SPEAKER_QMIC_NS:
|
|
case SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS:
|
|
case SND_DEVICE_IN_VOICE_SPEAKER_DMIC:
|
|
case SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BROADSIDE:
|
|
case SND_DEVICE_IN_VOICE_SPEAKER_QMIC:
|
|
ret = true;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
audio_devices_t get_input_audio_device(audio_devices_t device)
|
|
{
|
|
audio_devices_t in_device = device;
|
|
|
|
switch (device) {
|
|
case AUDIO_DEVICE_OUT_EARPIECE:
|
|
case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
|
|
in_device = AUDIO_DEVICE_IN_BUILTIN_MIC;
|
|
break;
|
|
case AUDIO_DEVICE_OUT_SPEAKER:
|
|
in_device = AUDIO_DEVICE_IN_BACK_MIC;
|
|
break;
|
|
case AUDIO_DEVICE_OUT_WIRED_HEADSET:
|
|
in_device = AUDIO_DEVICE_IN_WIRED_HEADSET;
|
|
break;
|
|
case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
|
|
in_device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return in_device;
|
|
}
|
|
|
|
static int derive_mixer_ctl_from_usecase_intf(const struct audio_device *adev,
|
|
char *mixer_ctl_name) {
|
|
struct audio_usecase *usecase = NULL;
|
|
audio_devices_t in_device;
|
|
int ret = 0;
|
|
|
|
if (mixer_ctl_name == NULL) {
|
|
ALOGE("%s: mixer_ctl_name is NULL", __func__);
|
|
|
|
ret = -EINVAL;
|
|
goto done;
|
|
}
|
|
|
|
if (voice_is_in_call(adev)) {
|
|
strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH);
|
|
strlcat(mixer_ctl_name, "Voice Tx", MIXER_PATH_MAX_LENGTH);
|
|
usecase = get_usecase_from_list(adev,
|
|
get_usecase_id_from_usecase_type(adev, VOICE_CALL));
|
|
} else if (voice_extn_compress_voip_is_active(adev)) {
|
|
strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH);
|
|
strlcat(mixer_ctl_name, "Voice Tx", MIXER_PATH_MAX_LENGTH);
|
|
usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
|
|
} else {
|
|
strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH);
|
|
strlcat(mixer_ctl_name, "Audio Tx", MIXER_PATH_MAX_LENGTH);
|
|
usecase = get_usecase_from_list(adev, get_usecase_id_from_usecase_type(adev, PCM_CAPTURE));
|
|
}
|
|
|
|
if (usecase && (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
|
|
if (is_stt_supported_snd_device(usecase->in_snd_device)) {
|
|
in_device = get_input_audio_device(usecase->devices);
|
|
ret = add_audio_intf_name_to_mixer_ctl(in_device, mixer_ctl_name,
|
|
audio_device_to_interface_table, audio_device_to_interface_table_len);
|
|
} else {
|
|
ALOGE("%s: Sound Focus/Source Tracking not supported on the input sound device (%s)",
|
|
__func__, platform_get_snd_device_name(usecase->in_snd_device));
|
|
|
|
ret = -EINVAL;
|
|
}
|
|
} else {
|
|
ALOGE("%s: No use case is active which supports Sound Focus/Source Tracking",
|
|
__func__);
|
|
|
|
ret = -EINVAL;
|
|
}
|
|
|
|
done:
|
|
return ret;
|
|
}
|
|
|
|
static int parse_soundfocus_sourcetracking_keys(struct str_parms *parms)
|
|
{
|
|
char *value = NULL;
|
|
int len;
|
|
int ret = 0, err;
|
|
char *kv_pairs = str_parms_to_str(parms);
|
|
|
|
if(kv_pairs == NULL) {
|
|
ret = -ENOMEM;
|
|
ALOGE("[%s] key-value pair is NULL",__func__);
|
|
goto done;
|
|
}
|
|
|
|
ALOGV_IF(kv_pairs != NULL, "%s: enter: %s", __func__, kv_pairs);
|
|
|
|
len = strlen(kv_pairs);
|
|
value = (char*)calloc(len, sizeof(char));
|
|
if(value == NULL) {
|
|
ret = -ENOMEM;
|
|
ALOGE("%s: failed to allocate memory", __func__);
|
|
|
|
goto done;
|
|
}
|
|
|
|
err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES,
|
|
value, len);
|
|
if (err >= 0) {
|
|
str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES);
|
|
ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES;
|
|
}
|
|
|
|
err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS,
|
|
value, len);
|
|
if (err >= 0) {
|
|
str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS);
|
|
ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS;
|
|
}
|
|
|
|
err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP,
|
|
value, len);
|
|
if (err >= 0) {
|
|
str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP);
|
|
ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP;
|
|
}
|
|
|
|
err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD,
|
|
value, len);
|
|
if (err >= 0) {
|
|
str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD);
|
|
ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD;
|
|
}
|
|
|
|
err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH,
|
|
value, len);
|
|
if (err >= 0) {
|
|
str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH);
|
|
ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH;
|
|
}
|
|
|
|
err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE,
|
|
value, len);
|
|
if (err >= 0) {
|
|
str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE);
|
|
ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE;
|
|
}
|
|
|
|
err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY,
|
|
value, len);
|
|
if (err >= 0) {
|
|
str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY);
|
|
ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY;
|
|
}
|
|
|
|
done:
|
|
if (kv_pairs)
|
|
free(kv_pairs);
|
|
if(value != NULL)
|
|
free(value);
|
|
ALOGV("%s: returning bitmask = %d", __func__, ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int get_soundfocus_sourcetracking_data(const struct audio_device *adev,
|
|
const int bitmask,
|
|
struct sound_focus_param *sound_focus_data,
|
|
struct source_tracking_param *source_tracking_data)
|
|
{
|
|
struct mixer_ctl *ctl;
|
|
char sound_focus_mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = "Sound Focus";
|
|
char source_tracking_mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = "Source Tracking";
|
|
int ret = -EINVAL;
|
|
int count;
|
|
|
|
if (bitmask & BITMASK_AUDIO_PARAMETER_KEYS_SOUND_FOCUS) {
|
|
/* Derive the mixer control name based on the use case and the audio interface
|
|
* for the corresponding audio device
|
|
*/
|
|
ret = derive_mixer_ctl_from_usecase_intf(adev, sound_focus_mixer_ctl_name);
|
|
if (ret != 0) {
|
|
ALOGE("%s: Could not get Sound Focus Params", __func__);
|
|
|
|
goto done;
|
|
} else {
|
|
ALOGV("%s: Mixer Ctl name: %s", __func__, sound_focus_mixer_ctl_name);
|
|
}
|
|
|
|
ctl = mixer_get_ctl_by_name(adev->mixer, sound_focus_mixer_ctl_name);
|
|
if (!ctl) {
|
|
ALOGE("%s: Could not get ctl for mixer cmd - %s",
|
|
__func__, sound_focus_mixer_ctl_name);
|
|
|
|
ret = -EINVAL;
|
|
goto done;
|
|
} else {
|
|
ALOGV("%s: Getting Sound Focus Params", __func__);
|
|
|
|
mixer_ctl_update(ctl);
|
|
count = mixer_ctl_get_num_values(ctl);
|
|
if (count != sizeof(struct sound_focus_param)) {
|
|
ALOGE("%s: mixer_ctl_get_num_values() invalid sound focus data size", __func__);
|
|
|
|
ret = -EINVAL;
|
|
goto done;
|
|
}
|
|
|
|
ret = mixer_ctl_get_array(ctl, (void *)sound_focus_data, count);
|
|
if (ret != 0) {
|
|
ALOGE("%s: mixer_ctl_get_array() failed to get Sound Focus Params", __func__);
|
|
|
|
ret = -EINVAL;
|
|
goto done;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bitmask & BITMASK_AUDIO_PARAMETER_KEYS_SOURCE_TRACKING) {
|
|
/* Derive the mixer control name based on the use case and the audio interface
|
|
* for the corresponding audio device
|
|
*/
|
|
ret = derive_mixer_ctl_from_usecase_intf(adev, source_tracking_mixer_ctl_name);
|
|
if (ret != 0) {
|
|
ALOGE("%s: Could not get Source Tracking Params", __func__);
|
|
|
|
goto done;
|
|
} else {
|
|
ALOGV("%s: Mixer Ctl name: %s", __func__, source_tracking_mixer_ctl_name);
|
|
}
|
|
|
|
ctl = mixer_get_ctl_by_name(adev->mixer, source_tracking_mixer_ctl_name);
|
|
if (!ctl) {
|
|
ALOGE("%s: Could not get ctl for mixer cmd - %s",
|
|
__func__, source_tracking_mixer_ctl_name);
|
|
|
|
ret = -EINVAL;
|
|
goto done;
|
|
} else {
|
|
ALOGV("%s: Getting Source Tracking Params", __func__);
|
|
|
|
mixer_ctl_update(ctl);
|
|
count = mixer_ctl_get_num_values(ctl);
|
|
if (count != sizeof(struct source_tracking_param)) {
|
|
ALOGE("%s: mixer_ctl_get_num_values() invalid source tracking data size", __func__);
|
|
|
|
ret = -EINVAL;
|
|
goto done;
|
|
}
|
|
|
|
ret = mixer_ctl_get_array(ctl, (void *)source_tracking_data, count);
|
|
if (ret != 0) {
|
|
ALOGE("%s: mixer_ctl_get_array() failed to get Source Tracking Params", __func__);
|
|
|
|
ret = -EINVAL;
|
|
goto done;
|
|
}
|
|
}
|
|
}
|
|
|
|
done:
|
|
return ret;
|
|
}
|
|
|
|
static void send_soundfocus_sourcetracking_params(struct str_parms *reply,
|
|
const int bitmask,
|
|
const struct sound_focus_param sound_focus_data,
|
|
const struct source_tracking_param source_tracking_data)
|
|
{
|
|
int i = 0;
|
|
char value[MAX_STR_SIZE] = "";
|
|
|
|
if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES) {
|
|
for (i = 0; i < MAX_SECTORS; i++) {
|
|
if ((i >=4) && (sound_focus_data.start_angle[i] == 0xFFFF))
|
|
continue;
|
|
if (i)
|
|
snprintf(value + strlen(value), MAX_STR_SIZE - strlen(value) - 1, ",");
|
|
snprintf(value + strlen(value), MAX_STR_SIZE - strlen(value) - 1, "%d", sound_focus_data.start_angle[i]);
|
|
}
|
|
str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES, value);
|
|
}
|
|
|
|
strlcpy(value, "", sizeof(""));
|
|
if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS) {
|
|
for (i = 0; i < MAX_SECTORS; i++) {
|
|
if ((i >=4) && (sound_focus_data.enable[i] == 0xFF))
|
|
continue;
|
|
if (i)
|
|
snprintf(value + strlen(value), MAX_STR_SIZE - strlen(value) - 1, ",");
|
|
snprintf(value + strlen(value), MAX_STR_SIZE - strlen(value) - 1, "%d", sound_focus_data.enable[i]);
|
|
}
|
|
str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS, value);
|
|
}
|
|
|
|
if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP)
|
|
str_parms_add_int(reply, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP, sound_focus_data.gain_step);
|
|
|
|
strlcpy(value, "", sizeof(""));
|
|
if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD) {
|
|
for (i = 0; i < MAX_SECTORS; i++) {
|
|
if ((i >=4) && (source_tracking_data.vad[i] == 0xFF))
|
|
continue;
|
|
if (i)
|
|
snprintf(value + strlen(value), MAX_STR_SIZE - strlen(value) - 1, ",");
|
|
snprintf(value + strlen(value), MAX_STR_SIZE - strlen(value) - 1, "%d", source_tracking_data.vad[i]);
|
|
}
|
|
str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD, value);
|
|
}
|
|
|
|
if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH)
|
|
str_parms_add_int(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH, source_tracking_data.doa_speech);
|
|
|
|
strlcpy(value, "", sizeof(""));
|
|
if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE) {
|
|
snprintf(value, MAX_STR_SIZE,
|
|
"%d,%d,%d", source_tracking_data.doa_noise[0], source_tracking_data.doa_noise[1], source_tracking_data.doa_noise[2]);
|
|
str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE, value);
|
|
}
|
|
|
|
strlcpy(value, "", sizeof(""));
|
|
if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY) {
|
|
for (i = 0; i < 360; i++) {
|
|
if (i)
|
|
snprintf(value + strlen(value), MAX_STR_SIZE - strlen(value) - 1, ",");
|
|
snprintf(value + strlen(value), MAX_STR_SIZE - strlen(value) - 1, "%d", source_tracking_data.polar_activity[i]);
|
|
}
|
|
str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY, value);
|
|
}
|
|
}
|
|
|
|
int audio_extn_get_soundfocus_data(const struct audio_device *adev,
|
|
struct sound_focus_param *payload)
|
|
{
|
|
int ret = 0;
|
|
int bitmask =0;
|
|
struct sound_focus_param *sound_focus_data = payload;
|
|
|
|
bitmask = BITMASK_AUDIO_PARAMETER_KEYS_SOUND_FOCUS;
|
|
|
|
ret = get_soundfocus_sourcetracking_data(adev, bitmask,
|
|
sound_focus_data, NULL);
|
|
|
|
return ret ;
|
|
}
|
|
|
|
int audio_extn_get_sourcetrack_data(const struct audio_device *adev,
|
|
struct source_tracking_param *payload)
|
|
{
|
|
int ret = 0;
|
|
int bitmask = 0;
|
|
struct source_tracking_param *source_tracking_data = payload;
|
|
|
|
bitmask = BITMASK_AUDIO_PARAMETER_KEYS_SOURCE_TRACKING;
|
|
|
|
ret = get_soundfocus_sourcetracking_data(adev, bitmask,
|
|
NULL, source_tracking_data);
|
|
|
|
return ret ;
|
|
}
|
|
|
|
void audio_extn_source_track_get_parameters(const struct audio_device *adev,
|
|
struct str_parms *query,
|
|
struct str_parms *reply)
|
|
{
|
|
int bitmask = 0, ret = 0;
|
|
struct sound_focus_param sound_focus_data;
|
|
struct source_tracking_param source_tracking_data;
|
|
|
|
memset(&sound_focus_data, 0xFF, sizeof(struct sound_focus_param));
|
|
memset(&source_tracking_data, 0xFF, sizeof(struct source_tracking_param));
|
|
|
|
// Parse the input parameters string for Source Tracking keys
|
|
bitmask = parse_soundfocus_sourcetracking_keys(query);
|
|
if (bitmask) {
|
|
// Get the parameter values from the backend
|
|
ret = get_soundfocus_sourcetracking_data(adev, bitmask, &sound_focus_data, &source_tracking_data);
|
|
if (ret == 0) {
|
|
// Construct the return string with key, value pairs
|
|
send_soundfocus_sourcetracking_params(reply, bitmask, sound_focus_data, source_tracking_data);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int set_source_track_data(struct audio_device *adev,
|
|
struct sound_focus_param *sound_focus_param)
|
|
{
|
|
int i, ret, count;
|
|
struct mixer_ctl *ctl;
|
|
char sound_focus_mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = "Sound Focus";
|
|
|
|
/* Derive the mixer control name based on the use case and the audio h/w
|
|
* interface name for the corresponding audio device
|
|
*/
|
|
ret = derive_mixer_ctl_from_usecase_intf(adev, sound_focus_mixer_ctl_name);
|
|
if (ret != 0) {
|
|
ALOGE("%s: Could not set Sound Focus Params:%d", __func__, ret);
|
|
return ret;
|
|
} else {
|
|
ALOGV("%s: Mixer Ctl name: %s", __func__, sound_focus_mixer_ctl_name);
|
|
}
|
|
|
|
ctl = mixer_get_ctl_by_name(adev->mixer, sound_focus_mixer_ctl_name);
|
|
if (!ctl) {
|
|
ALOGE("%s: Could not get ctl for mixer cmd - %s",
|
|
__func__, sound_focus_mixer_ctl_name);
|
|
ret = -EINVAL;
|
|
return ret;
|
|
} else {
|
|
ALOGV("%s: Setting Sound Focus Params", __func__);
|
|
|
|
for (i = 0; i < MAX_SECTORS;i++) {
|
|
ALOGV("%s: start_angles[%d] = %d", __func__, i, sound_focus_param->start_angle[i]);
|
|
}
|
|
for (i = 0; i < MAX_SECTORS;i++) {
|
|
ALOGV("%s: enable_sectors[%d] = %d", __func__, i, sound_focus_param->enable[i]);
|
|
}
|
|
ALOGV("%s: gain_step = %d", __func__, sound_focus_param->gain_step);
|
|
|
|
mixer_ctl_update(ctl);
|
|
count = mixer_ctl_get_num_values(ctl);
|
|
if (count != sizeof(struct sound_focus_param)) {
|
|
ALOGE("%s: mixer_ctl_get_num_values() invalid data size", __func__);
|
|
return ret;
|
|
}
|
|
|
|
// Set the parameters on the mixer control derived above
|
|
ret = mixer_ctl_set_array(ctl, (void *)sound_focus_param, count);
|
|
if (ret != 0) {
|
|
ALOGE("%s: mixer_ctl_set_array() failed to set Sound Focus Params:%d",
|
|
__func__, ret);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int audio_extn_set_soundfocus_data(struct audio_device *adev,
|
|
struct sound_focus_param *payload)
|
|
{
|
|
int ret = 0;
|
|
struct sound_focus_param *sound_focus_data = payload;
|
|
|
|
ret = set_source_track_data(adev, sound_focus_data);
|
|
|
|
return ret ;
|
|
}
|
|
|
|
void audio_extn_source_track_set_parameters(struct audio_device *adev,
|
|
struct str_parms *parms)
|
|
{
|
|
int len, ret;
|
|
char *value = NULL;
|
|
char *kv_pairs = str_parms_to_str(parms);
|
|
|
|
if(kv_pairs == NULL) {
|
|
ret = -ENOMEM;
|
|
ALOGE("[%s] key-value pair is NULL",__func__);
|
|
goto done;
|
|
}
|
|
|
|
len = strlen(kv_pairs);
|
|
value = (char*)calloc(len, sizeof(char));
|
|
if(value == NULL) {
|
|
ret = -ENOMEM;
|
|
ALOGE("%s: failed to allocate memory", __func__);
|
|
|
|
goto done;
|
|
}
|
|
|
|
// Parse the input parameter string for Source Tracking key, value pairs
|
|
ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES,
|
|
value, len);
|
|
if (ret >= 0) {
|
|
char *saveptr, *tok;
|
|
int i = 0, val;
|
|
struct sound_focus_param sound_focus_param;
|
|
|
|
memset(&sound_focus_param, 0xFF, sizeof(struct sound_focus_param));
|
|
|
|
str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES);
|
|
tok = strtok_r(value, ",", &saveptr);
|
|
while ((i < MAX_SECTORS) && (tok != NULL)) {
|
|
if (sscanf(tok, "%d", &val) == 1) {
|
|
sound_focus_param.start_angle[i++] = (uint16_t)val;
|
|
}
|
|
tok = strtok_r(NULL, ",", &saveptr);
|
|
}
|
|
|
|
ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS,
|
|
value, len);
|
|
if (ret >= 0) {
|
|
str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS);
|
|
tok = strtok_r(value, ",", &saveptr);
|
|
i = 0;
|
|
while ((i < MAX_SECTORS) && (tok != NULL)) {
|
|
if (sscanf(tok, "%d", &val) == 1) {
|
|
sound_focus_param.enable[i++] = (uint8_t)val;
|
|
}
|
|
tok = strtok_r(NULL, ",", &saveptr);
|
|
}
|
|
} else {
|
|
ALOGE("%s: SoundFocus.enable_sectors key not found", __func__);
|
|
|
|
goto done;
|
|
}
|
|
|
|
ret = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP, &val);
|
|
if (ret >= 0) {
|
|
str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP);
|
|
sound_focus_param.gain_step = (uint16_t)val;
|
|
} else {
|
|
ALOGE("%s: SoundFocus.gain_step key not found", __func__);
|
|
|
|
goto done;
|
|
}
|
|
|
|
set_source_track_data(adev, &sound_focus_param);
|
|
}
|
|
|
|
done:
|
|
if (kv_pairs)
|
|
free(kv_pairs);
|
|
if(value != NULL)
|
|
free(value);
|
|
return;
|
|
}
|
|
#endif /* SOURCE_TRACKING_ENABLED end */
|