blob: 08d6ff4a7a5f6cd18209dc6b12bcdcd1336ccd86 [file] [log] [blame]
/*
* Copyright (c) 2020-2021, 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.
*
* Changes from Qualcomm Innovation Center are provided under the following license:
*
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
*/
#ifndef SOUND_TRIGGER_UTILS_H
#define SOUND_TRIGGER_UTILS_H
#include "PalDefs.h"
#include "ListenSoundModelLib.h"
#define MAX_KW_USERS_NAME_LEN (2 * MAX_STRING_LEN)
#define MAX_CONF_LEVEL_VALUE 100
enum {
SML_PARSER_SUCCESS = 0,
SML_PARSER_ERROR = 1,
SML_PARSER_NOT_SUPPORTED_VERSION,
SML_PARSER_ID_NOT_EXIST,
SML_PARSER_NOT_ALIGNED_SIZE,
SML_PARSER_SIZE_MISSMATCH,
SML_PARSER_VALUE_MISSMATCH,
SML_PARSER_REF_UNINIT_VALUE,
SML_PARSER_OUT_OF_RANGE,
SML_PARSER_WRONG_MODEL,
SML_PARSER_WRONG_VALUE,
SML_PARSER_DELETING_LAST_KEYWORD,
SML_PARSER_KEYWORD_NOT_FOUND,
SML_PARSER_USER_NOT_FOUND,
SML_PARSER_USER_ALREADY_EXIST,
SML_PARSER_KEYWORD_USER_PAIR_EXIST,
SML_PARSER_KEYWORD_USER_PAIR_NOT_EXIST,
SML_PARSER_ACTIVE_USER_REMOVE_UDK,
SML_PARSER_KEYWORD_ALREADY_EXIST,
SML_PARSER_NOTHING_TO_CHANGE,
};
enum {
SML_COMPARATOR_ERROR = -1,
SML_COMPARATOR_SAME = 0,
SML_COMPARATOR_DIFF = 1,
};
enum {
SML_V3_MAX_PAYLOAD = 10000000,
SML_V3_MIN_KEYWORDS = 1,
SML_V3_MAX_KEYWORDS = 1,
SML_V3_MIN_USERS = 0,
SML_V3_MAX_USERS = 1,
};
enum {
SML_GLOBAL_HEADER_MAGIC_NUMBER = 0x00180cc8, // SML03
SML_MAX_MODEL_NUM = 3,
SML_MAX_STRING_LEN = 200,
};
typedef enum {
ST_SM_ID_SVA_NONE = 0x0000,
ST_SM_ID_SVA_F_STAGE_GMM = 0x0001,
ST_SM_ID_SVA_S_STAGE_PDK = 0x0002,
ST_SM_ID_SVA_S_STAGE_USER = 0x0004,
ST_SM_ID_SVA_S_STAGE_RNN = 0x0008,
SML_ID_SVA_S_STAGE_UBM = 0x0010,
SML_ID_SVA_F_STAGE_INTERNAL = 0x0020,
ST_SM_ID_SVA_S_STAGE_UDK = 0x0040,
ST_SM_ID_SVA_S_STAGE_KWD = 0x004A, // S_STAGE_PDK | S_STAGE_RNN | S_STAGE_UDK
ST_SM_ID_SVA_END = 0x00F0,
ST_SM_ID_CUSTOM_START = 0x0100,
ST_SM_ID_CUSTOM_END = 0xF000,
} listen_model_indicator_enum;
typedef enum {
ST_MODULE_TYPE_NONE = 0, // Internal Constant for initialization
ST_MODULE_TYPE_GMM = 3,
ST_MODULE_TYPE_PDK5 = 5,
ST_MODULE_TYPE_PDK6 = 6,
ST_MODULE_TYPE_PDK = 100, // Internal constant for local use indicating
// both PDK5 and PDK6
ST_MODULE_TYPE_HW = 101, // Internal constant to identify hotword module
ST_MODULE_TYPE_CUSTOM_1 = 102, // Reserved for Custom Engine 1
ST_MODULE_TYPE_CUSTOM_2 = 103, // Reserved for Custom Engine 2
} st_module_type_t;
typedef struct _SML_GlobalHeaderType {
uint32_t magicNumber; // Magic number
uint32_t payloadBytes; // Payload bytes size
uint32_t modelVersion; // Model version
} SML_GlobalHeaderType;
typedef struct _SML_HeaderTypeV3 {
uint32_t numModels; // number of models
uint32_t keywordSpellLength; // length of keyword spell ( include '\0' )
uint32_t userNameLength; // length of user name ( include '\0' )
char keywordSpell[SML_MAX_STRING_LEN]; // keyword spell
char userName[SML_MAX_STRING_LEN]; // user name
} SML_HeaderTypeV3;
typedef struct _SML_BigSoundModelTypeV3 {
uint16_t versionMajor;
uint16_t versionMinor;
uint32_t offset; // start address of model data
uint32_t size; // model size
listen_model_indicator_enum type; // type : Lower 1 byte : 1Stage KW model,
// 2Stage KW model,
// 2Stage User Model
// Upper 1 byte : 3rd Party - 1Stage KW model,
// 2Stage KW model,
// 2Stage User Model
}SML_BigSoundModelTypeV3;
typedef struct _SML_ModelTypeV3 {
SML_HeaderTypeV3 header; // header for v3 model
SML_BigSoundModelTypeV3 *modelInfo; // model info, used for dynamic memory allocation.
uint8_t* rawData; // actual model data
} SML_ModelTypeV3;
// all of model versions about SML
typedef enum _SML_ModelVersion {
SML_MODEL_V2 = 0x0200,
SML_MODEL_V3 = 0x0300,
} SML_ModelVersion;
// universial SML model structure
typedef struct _SML_ModelType {
SML_GlobalHeaderType header; // global header
union _sml_model {
SML_ModelTypeV3 SMLModelV3; // sml3.0 -- kwihyuk
} SMLModel;
} SML_ModelType;
#define ST_MAX_SOUND_MODELS 10
#define ST_MAX_KEYWORDS 10
#define ST_MAX_USERS 10
enum st_param_key {
ST_PARAM_KEY_CONFIDENCE_LEVELS,
ST_PARAM_KEY_HISTORY_BUFFER_CONFIG,
ST_PARAM_KEY_KEYWORD_INDICES,
ST_PARAM_KEY_TIMESTAMP,
ST_PARAM_KEY_DETECTION_PERF_MODE,
ST_PARAM_KEY_CONTEXT_RECOGNITION_INFO,
ST_PARAM_KEY_CONTEXT_EVENT_INFO,
};
typedef enum st_param_key st_param_key_t;
struct __attribute__((__packed__)) st_param_header
{
st_param_key_t key_id;
uint32_t payload_size;
};
typedef enum {
AUDIO_CONTEXT_EVENT_STOPPED,
AUDIO_CONTEXT_EVENT_STARTED,
AUDIO_CONTEXT_EVENT_DETECTED
} AUDIO_CONTEXT_EVENT_TYPE;
struct __attribute__((__packed__)) acd_per_context_cfg {
uint32_t context_id;
uint32_t threshold;
uint32_t step_size;
};
struct __attribute__((__packed__)) acd_recognition_cfg {
uint32_t version;
uint32_t num_contexts;
/* followed by array of acd_per_context_cfg[acd_per_context_cfg] */
};
struct __attribute__((__packed__)) acd_per_context_event_info {
uint32_t context_id;
uint32_t event_type;
uint32_t confidence_score;
uint64_t detection_ts;
};
struct __attribute__((__packed__)) acd_context_event {
uint32_t version;
uint64_t detection_ts;
uint32_t num_contexts;
/* followed by an array of acd_per_context_event_info[num_contexts] */
};
struct __attribute__((__packed__)) st_user_levels
{
uint32_t user_id;
uint8_t level;
};
struct __attribute__((__packed__)) st_keyword_levels
{
uint8_t kw_level;
uint32_t num_user_levels;
struct st_user_levels user_levels[ST_MAX_USERS];
};
struct __attribute__((__packed__)) st_sound_model_conf_levels
{
listen_model_indicator_enum sm_id;
uint32_t num_kw_levels;
struct st_keyword_levels kw_levels[ST_MAX_KEYWORDS];
};
struct __attribute__((__packed__)) st_confidence_levels_info
{
uint32_t version; /* value: 0x1 */
uint32_t num_sound_models;
struct st_sound_model_conf_levels conf_levels[ST_MAX_SOUND_MODELS];
};
struct __attribute__((__packed__)) st_user_levels_v2
{
uint32_t user_id;
int32_t level;
};
struct __attribute__((__packed__)) st_keyword_levels_v2
{
int32_t kw_level;
uint32_t num_user_levels;
struct st_user_levels_v2 user_levels[ST_MAX_USERS];
};
struct __attribute__((__packed__)) st_sound_model_conf_levels_v2
{
listen_model_indicator_enum sm_id;
uint32_t num_kw_levels;
struct st_keyword_levels_v2 kw_levels[ST_MAX_KEYWORDS];
};
struct __attribute__((__packed__)) st_confidence_levels_info_v2
{
uint32_t version; /* value: 0x02 */
uint32_t num_sound_models;
struct st_sound_model_conf_levels_v2 conf_levels[ST_MAX_SOUND_MODELS];
};
struct __attribute__((__packed__)) st_hist_buffer_info
{
uint32_t version; /* value: 0x02 */
uint32_t hist_buffer_duration_msec;
uint32_t pre_roll_duration_msec;
};
struct __attribute__((__packed__)) st_keyword_indices_info
{
uint32_t version; /* value: 0x01 */
uint32_t start_index; /* in bytes */
uint32_t end_index; /* in bytes */
};
struct __attribute__((__packed__)) st_timestamp_info
{
uint32_t version; /* value: 0x01 */
uint64_t first_stage_det_event_time; /* in nanoseconds */
uint64_t second_stage_det_event_time; /* in nanoseconds */
};
struct __attribute__((__packed__)) st_det_perf_mode_info
{
uint32_t version; /* value: 0x01 */
uint32_t mode; /* 0 -Low Power, 1 -High performance */
};
typedef enum st_sound_model_type {
ST_SM_TYPE_NONE,
ST_SM_TYPE_KEYWORD_DETECTION,
ST_SM_TYPE_USER_VERIFICATION,
ST_SM_TYPE_CUSTOM_DETECTION,
ST_SM_TYPE_MAX
}st_sound_model_type_t;
typedef enum st_param_id_type {
LOAD_SOUND_MODEL = 0,
UNLOAD_SOUND_MODEL,
WAKEUP_CONFIG,
BUFFERING_CONFIG,
ENGINE_RESET,
MODULE_VERSION,
CUSTOM_CONFIG,
MAX_PARAM_IDS
} st_param_id_type_t;
#define ST_DEBUG_DUMP_LOCATION "/data/vendor/audio"
#define ST_DBG_DECLARE(args...) args
#define ST_DBG_FILE_OPEN_WR(fptr, fpath, fname, fextn, fcount) \
do {\
char fptr_fn[100];\
\
snprintf(fptr_fn, sizeof(fptr_fn), "%s/%s_%d.%s", fpath, fname, fcount, fextn);\
fptr = fopen(fptr_fn, "wb");\
if (!fptr) { \
ALOGE("%s: File open failed %s: %s", \
__func__, fptr_fn, strerror(errno)); \
} \
} while (0)
#define ST_DBG_FILE_CLOSE(fptr) \
do {\
if (fptr) { fclose (fptr); }\
} while (0)
#define ST_DBG_FILE_WRITE(fptr, buf, buf_size) \
do {\
if (fptr) {\
size_t ret_bytes = fwrite(buf, 1, buf_size, fptr);\
if (ret_bytes != (size_t)buf_size) {\
ALOGE("%s: fwrite %zu < %zu", __func__,\
ret_bytes, (size_t)buf_size);\
}\
fflush(fptr);\
}\
} while (0)
/* Listen Sound Model Library APIs */
typedef listen_status_enum (*smlib_getSoundModelHeader_t)
(
listen_model_type *pSoundModel,
listen_sound_model_header *pListenSoundModelHeader
);
typedef listen_status_enum (*smlib_releaseSoundModelHeader_t)
(
listen_sound_model_header *pListenSoundModelHeader
);
typedef listen_status_enum (*smlib_getKeywordPhrases_t)
(
listen_model_type *pSoundModel,
uint16_t *numKeywords,
keywordId_t *keywords
);
typedef listen_status_enum (*smlib_getUserNames_t)
(
listen_model_type *pSoundModel,
uint16_t *numUsers,
userId_t *users
);
typedef listen_status_enum (*smlib_getMergedModelSize_t)
(
uint16_t numModels,
listen_model_type *pModels[],
uint32_t *nOutputModelSize
);
typedef listen_status_enum (*smlib_mergeModels_t)
(
uint16_t numModels,
listen_model_type *pModels[],
listen_model_type *pMergedModel
);
typedef listen_status_enum (*smlib_getSizeAfterDeleting_t)
(
listen_model_type *pInputModel,
keywordId_t keywordId,
userId_t userId,
uint32_t *nOutputModelSize
);
typedef listen_status_enum (*smlib_deleteFromModel_t)
(
listen_model_type *pInputModel,
keywordId_t keywordId,
userId_t userId,
listen_model_type *pResultModel
);
class SoundTriggerUUID {
public:
SoundTriggerUUID();
SoundTriggerUUID & operator=(SoundTriggerUUID &rhs);
bool operator<(const SoundTriggerUUID &rhs) const;
bool CompareUUID(const struct st_uuid uuid) const;
static int StringToUUID(const char* str, SoundTriggerUUID& UUID);
uint32_t timeLow;
uint16_t timeMid;
uint16_t timeHiAndVersion;
uint16_t clockSeq;
uint8_t node[6];
};
class SoundModelLib {
public:
static std::shared_ptr<SoundModelLib> GetInstance();
SoundModelLib & operator=(SoundModelLib &rhs) = delete;
SoundModelLib();
~SoundModelLib();
smlib_getSoundModelHeader_t GetSoundModelHeader_;
smlib_releaseSoundModelHeader_t ReleaseSoundModelHeader_;
smlib_getKeywordPhrases_t GetKeywordPhrases_;
smlib_getUserNames_t GetUserNames_;
smlib_getMergedModelSize_t GetMergedModelSize_;
smlib_mergeModels_t MergeModels_;
smlib_getSizeAfterDeleting_t GetSizeAfterDeleting_;
smlib_deleteFromModel_t DeleteFromModel_;
private:
static std::shared_ptr<SoundModelLib> sml_;
void *sml_lib_handle_;
};
class SoundModelInfo {
public:
SoundModelInfo();
SoundModelInfo(SoundModelInfo &rhs) = delete;
SoundModelInfo & operator=(SoundModelInfo &rhs);
~SoundModelInfo();
int32_t SetKeyPhrases(listen_model_type *model, uint32_t num_phrases);
int32_t SetUsers(listen_model_type *model, uint32_t num_users);
int32_t SetConfLevels(uint16_t num_user_kw_pairs, uint16_t *num_users_per_kw,
uint16_t **user_kw_pair_flags);
void SetModelData(uint8_t *data, uint32_t size) {
if (sm_data_) {
free(sm_data_);
sm_data_ = nullptr;
}
sm_size_ = size;
if (!sm_size_)
return;
sm_data_ = (uint8_t*) calloc(1, sm_size_);
if (!sm_data_)
return;
memcpy(sm_data_, data, sm_size_);
}
void UpdateConfLevel(uint32_t index, uint8_t conf_level) {
if (index < cf_levels_size_)
cf_levels_[index] = conf_level;
}
int32_t UpdateConfLevelArray(uint8_t *conf_levels, uint32_t cfl_size);
void ResetDetConfLevels() {
memset(det_cf_levels_, 0, cf_levels_size_);
}
void UpdateDetConfLevel(uint32_t index, uint8_t conf_level) {
if (index < cf_levels_size_)
det_cf_levels_[index] = conf_level;
}
uint8_t* GetModelData() { return sm_data_; };
uint32_t GetModelSize() { return sm_size_; };
char** GetKeyPhrases() { return keyphrases_; };
char** GetConfLevelsKwUsers() { return cf_levels_kw_users_; };
uint8_t* GetConfLevels() { return cf_levels_; };
uint8_t* GetDetConfLevels() { return det_cf_levels_; };
uint32_t GetConfLevelsSize() { return cf_levels_size_; };
uint32_t GetNumKeyPhrases() { return num_keyphrases_; };
static void AllocArrayPtrs(char ***arr, uint32_t arr_len, uint32_t elem_len);
static void FreeArrayPtrs(char **arr, uint32_t arr_len);
private:
uint8_t *sm_data_;
uint32_t sm_size_;
uint32_t num_keyphrases_;
uint32_t num_users_;
char **keyphrases_;
char **users_;
char **cf_levels_kw_users_;
uint8_t *cf_levels_;
uint8_t *det_cf_levels_;
uint32_t cf_levels_size_;
};
#endif // SOUND_TRIGGER_UTILS_H