feat(model): modify model loader to reduce model bin size for esp32

This commit is contained in:
sxy 2022-08-15 15:03:18 +08:00
parent 34e264eb5a
commit 6b21fdf970
13 changed files with 36 additions and 274 deletions

View File

@ -2,6 +2,7 @@ if(IDF_TARGET STREQUAL "esp32")
set(COMPONENT_ADD_INCLUDEDIRS
esp-tts/esp_tts_chinese/include
include/esp32
src/include
)
set(COMPONENT_SRCS
src/esp_mn_speech_commands.c
@ -40,6 +41,7 @@ elseif(${IDF_TARGET} STREQUAL "esp32s2")
set(COMPONENT_ADD_INCLUDEDIRS
esp-tts/esp_tts_chinese/include
include/esp32
src/include
)
set(COMPONENT_SRCS
src/esp_process_sdkconfig.c
@ -62,6 +64,7 @@ elseif(${IDF_TARGET} STREQUAL "esp32s3")
set(COMPONENT_ADD_INCLUDEDIRS
esp-tts/esp_tts_chinese/include
include/esp32s3
src/include
)
set(COMPONENT_SRCS
src/esp_mn_speech_commands.c

View File

@ -1,79 +0,0 @@
#pragma once
typedef struct
{
char **model_name; // the name of models, like "wn9_hilexin"(wakenet9, hilexin), "mn5_en"(multinet5, english)
char *partition_label; // partition label used to save the files of model
int num; // the number of models
} srmodel_list_t;
#define MODEL_NAME_MAX_LENGTH 64
/**
* @brief Return all avaliable models in spiffs or selected in Kconfig.
*
* @param partition_label The spiffs label defined in your partition file used to save models.
*
* @return all avaliable models in spiffs,save as srmodel_list_t.
*/
srmodel_list_t* esp_srmodel_init(const char* partition_label);
/**
* @brief Free srmodel_list_t and unregister SPIFFS filesystem if open SPIFFS filesystem.
*
* @param models The srmodel_list_t point allocated by esp_srmodel_init function.
*
* @return all avaliable models in spiffs,save as srmodel_list_t.
*/
void esp_srmodel_deinit(srmodel_list_t *models);
/**
* @brief Return the first model name containing the specified keywords
* If keyword is NULL, we will ignore the keyword.
*
* @param models The srmodel_list_t point allocated by esp_srmodel_init function.
* @param keyword1 The specified keyword1 , like ESP_WN_PREDIX(the prefix of wakenet),
* ESP_MN_PREFIX(the prefix of multinet),
*
* @param keyword2 The specified keyword2, like ESP_MN_ENGLISH(the english multinet)
* ESP_MN_CHINESE(the chinese multinet)
* "alexa" (the "alexa" wakenet)
* @return return model name if can find one model name containing the keywords otherwise return NULL.
*/
char *esp_srmodel_filter(srmodel_list_t *models, const char *keyword1, const char *keyword2);
/**
* @brief Check whether the specified model name exists or not.
*
* @param models The srmodel_list_t point allocated by esp_srmodel_init function.
* @param model_name The specified model name
* @return return index in models if model name exists otherwise return -1
*/
int esp_srmodel_exists(srmodel_list_t *models, char *model_name);
/**
* @brief Initialize and mount SPIFFS filesystem, return all avaliable models in spiffs.
*
* @param partition_label The spiffs label defined in your partition file used to save models.
*
* @return all avaliable models in spiffs,save as srmodel_list_t.
*/
srmodel_list_t *srmodel_spiffs_init(const char* partition_label);
/**
* @brief unregister SPIFFS filesystem and free srmodel_list_t.
*
* @param models The srmodel_list_t point allocated by srmodel_spiffs_init function.
*
* @return all avaliable models in spiffs,save as srmodel_list_t.
*/
void srmodel_spiffs_deinit(srmodel_list_t *models);
/**
* @brief Return base path of srmodel spiffs
*
* @return the base path od srmodel spiffs
*/
char *get_model_base_path(void);

View File

@ -1,158 +0,0 @@
// Copyright 2015-2022 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include "esp_err.h"
#include "esp_mn_iface.h"
/*
esp_mn_node_t is a singly linked list which is used to manage speech commands.
It is easy to add one speech command into linked list and remove one speech command from linked list.
*/
/**
* @brief Initialze the speech commands singly linked list.
*
* @return
* - ESP_OK Success
* - ESP_ERR_NO_MEM No memory
* - ESP_ERR_INVALID_STATE The Speech Commands link has been initialized
*/
esp_err_t esp_mn_commands_alloc(void);
/**
* @brief Clear the speech commands linked list and free root node.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE The Speech Commands link has not been initialized
*/
esp_err_t esp_mn_commands_free(void);
/**
* @brief Add one speech commands with phoneme string and command ID
*
* @param command_id The command ID
* @param phoneme_string The phoneme string of the speech commands
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE Fail
*/
esp_err_t esp_mn_commands_add(int command_id, char *phoneme_string);
/**
* @brief Modify one speech commands with new phoneme string
*
* @param old_phoneme_string The old phoneme string of the speech commands
* @param new_phoneme_string The new phoneme string of the speech commands
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE Fail
*/
esp_err_t esp_mn_commands_modify(char *old_phoneme_string, char *new_phoneme_string);
/**
* @brief Remove one speech commands by phoneme string
*
* @param phoneme_string The phoneme string of the speech commands
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE Fail
*/
esp_err_t esp_mn_commands_remove(char *phoneme_string);
/**
* @brief Clear all speech commands in linked list
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE Fail
*/
esp_err_t esp_mn_commands_clear(void);
/**
* @brief Get phrase from index, which is the depth from the phrase node to root node
*
* @Warning: The first phrase index is 0, the second phrase index is 1, and so on.
*
* @return
* - esp_mn_phrase_t* Success
* - NULL Fail
*/
esp_mn_phrase_t *esp_mn_commands_get_from_index(int index);
/**
* @brief Get phrase from phoneme string
*
* @return
* - esp_mn_phrase_t* Success
* - NULL Fail
*/
esp_mn_phrase_t *esp_mn_commands_get_from_string(const char *phoneme_string);
/**
* @brief Update the speech commands of MultiNet
*
* @Warning: Must be used after [add/remove/modify/clear] function,
* otherwise the language model of multinet can not be updated.
*
* @param multinet The multinet handle
* @param model_data The model object to query
*
* @return
* - NULL Success
* - others The list of error phrase which can not be parsed by multinet.
*/
esp_mn_error_t *esp_mn_commands_update(const esp_mn_iface_t *multinet, const model_iface_data_t *model_data);
/**
* @brief Print the MultiNet Speech Commands.
*/
void esp_mn_print_commands(void);
/**
* @brief Initialze the esp_mn_phrase_t struct by command id and phoneme string .
*
* @return the pointer of esp_mn_phrase_t
*/
esp_mn_phrase_t *esp_mn_phrase_alloc(int command_id, char *phoneme_string);
/**
* @brief Free esp_mn_phrase_t pointer.
*
* @param phrase The esp_mn_phrase_t pointer
*/
void esp_mn_phrase_free(esp_mn_phrase_t *phrase);
/**
* @brief Initialze the esp_mn_node_t struct by esp_mn_phrase_t pointer.
*
* @return the pointer of esp_mn_node_t
*/
esp_mn_node_t *esp_mn_node_alloc(esp_mn_phrase_t *phrase);
/**
* @brief Free esp_mn_node_t pointer.
*
* @param node The esp_mn_node_free pointer
*/
void esp_mn_node_free(esp_mn_node_t *node);
/**
* @brief Print phrase linked list.
*/
void esp_mn_commands_print(void);

View File

@ -1,23 +0,0 @@
#pragma once
#include "esp_err.h"
#include "esp_mn_iface.h"
/**
* @brief Check chip config to ensure optimum performance
*/
void check_chip_config(void);
/**
* @brief Update the speech commands of MultiNet by menuconfig
*
* @param multinet The multinet handle
*
* @param model_data The model object to query
*
* @param langugae The language of MultiNet
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE Fail
*/
esp_err_t esp_mn_commands_update_from_sdkconfig(esp_mn_iface_t *multinet, const model_iface_data_t *model_data);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -876,7 +876,7 @@ char *get_id_name_en(int i)
#endif
}
esp_err_t esp_mn_commands_update_from_sdkconfig(esp_mn_iface_t *multinet, const model_iface_data_t *model_data)
esp_mn_error_t* esp_mn_commands_update_from_sdkconfig(esp_mn_iface_t *multinet, const model_iface_data_t *model_data)
{
esp_mn_commands_alloc();
int total_phrase_num = 0;
@ -902,7 +902,6 @@ esp_err_t esp_mn_commands_update_from_sdkconfig(esp_mn_iface_t *multinet, const
char *token = strtok(command_str_temp, ",");
while (token != NULL) {
int len = strlen(token);
if (total_phrase_num > ESP_MN_MAX_PHRASE_NUM) {
ESP_LOGE(TAG, "The number of speech commands phrase must less than ESP_MN_MAX_PHRASE_NUM");
free(command_str_temp);

View File

@ -20,4 +20,4 @@ void check_chip_config(void);
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE Fail
*/
esp_err_t esp_mn_commands_update_from_sdkconfig(esp_mn_iface_t *multinet, const model_iface_data_t *model_data);
esp_mn_error_t* esp_mn_commands_update_from_sdkconfig(esp_mn_iface_t *multinet, const model_iface_data_t *model_data);

View File

@ -76,4 +76,19 @@ void srmodel_spiffs_deinit(srmodel_list_t *models);
*
* @return the base path od srmodel spiffs
*/
char *get_model_base_path(void);
char *get_model_base_path(void);
#ifdef ESP_PLATFORM
#include "dl_lib_coefgetter_if.h"
/**
* @brief Return model_coeff_getter_t pointer base on model_name
*
* @warning Just support ESP32 to load old wakenet
*
* @param model_name The model name
*
* @return model_coeff_getter_t pointer or NULL
*/
model_coeff_getter_t* srmodel_get_model_coeff(char *model_name);
#endif

View File

@ -79,8 +79,7 @@ srmodel_list_t *read_models_form_spiffs(esp_vfs_spiffs_conf_t *conf)
srmodel_list_t* srmodel_spiffs_init(const char *partition_label)
{
printf(" \n");
ESP_LOGI(TAG, "Initializing models from SPIFFS, partition label: %s", partition_label);
ESP_LOGI(TAG, "\nInitializing models from SPIFFS, partition label: %s\n", partition_label);
esp_vfs_spiffs_conf_t conf = {
.base_path = SRMODE_BASE_PATH,
@ -185,6 +184,12 @@ void srmodel_config_deinit(srmodel_list_t *models)
}
}
model_coeff_getter_t* srmodel_get_model_coeff(char *model_name)
{
model_coeff_getter_t *gettercb = &WAKENET_COEFF;
return gettercb;
}
#endif
char *get_model_base_path(void)
@ -200,7 +205,7 @@ int set_model_base_path(const char *base_path)
return 1;
}
char* join_path(char* dirname, char *filename)
char* _join_path_(const char* dirname, const char *filename)
{
if (dirname == NULL || filename == NULL)
return NULL;
@ -223,8 +228,8 @@ srmodel_list_t* srmodel_sdcard_init(const char *base_path)
{
printf("Initializing models from path: %s\n", base_path);
set_model_base_path(base_path);
struct dirent *ret, *sub_ret;
DIR *dir, *sub_dir;
struct dirent *ret;
DIR *dir;
dir = opendir(base_path);
srmodel_list_t *models = NULL;
int model_num = 0;
@ -238,8 +243,8 @@ srmodel_list_t* srmodel_sdcard_init(const char *base_path)
{ // NULL if reach the end of directory
if (ret->d_type == DT_DIR) { // if d_type is directory
char *sub_path = join_path(base_path, ret->d_name);
char *info_file = join_path(sub_path, "_MODEL_INFO_");
char *sub_path = _join_path_(base_path, ret->d_name);
char *info_file = _join_path_(sub_path, "_MODEL_INFO_");
fp = fopen(info_file, "r");
if (fp != NULL) {
model_num ++; // If _MODLE_INFO_ file exists, model_num ++
@ -271,8 +276,8 @@ srmodel_list_t* srmodel_sdcard_init(const char *base_path)
{ // NULL if reach the end of directory
if (ret->d_type == DT_DIR) { // if d_type is directory
char *sub_path = join_path(base_path, ret->d_name);
char *info_file = join_path(sub_path, "_MODEL_INFO_");
char *sub_path = _join_path_(base_path, ret->d_name);
char *info_file = _join_path_(sub_path, "_MODEL_INFO_");
fp = fopen(info_file, "r");
if (fp != NULL) {
memcpy(models->model_name[idx], ret->d_name, strlen(ret->d_name));
@ -337,7 +342,7 @@ void esp_srmodel_deinit(srmodel_list_t *models)
char *_esp_strstr_(const char *haystack, const char *needle)
{
if (needle == NULL) return haystack;
else return strstr(haystack, needle);
else return (char *)strstr(haystack, needle);
}
char *esp_srmodel_filter(srmodel_list_t *models, const char *keyword1, const char *keyword2)