mirror of
https://github.com/espressif/esp-sr.git
synced 2025-09-15 15:28:44 +08:00
300 lines
12 KiB
C++
300 lines
12 KiB
C++
/* test_mean.c: Implementation of a testable component.
|
|
|
|
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
|
|
|
Unless required by applicable law or agreed to in writing, this
|
|
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
CONDITIONS OF ANY KIND, either express or implied.
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "string.h"
|
|
#include <limits.h>
|
|
#include "unity.h"
|
|
#include "esp_log.h"
|
|
#include "esp_timer.h"
|
|
#include "model_path.h"
|
|
#include "esp_wn_iface.h"
|
|
#include "esp_wn_models.h"
|
|
#include "esp_afe_sr_models.h"
|
|
#include "dl_lib_convq_queue.h"
|
|
#include <sys/time.h>
|
|
|
|
#if (CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32P4)
|
|
#include "esp_nsn_models.h"
|
|
#include "esp_nsn_iface.h"
|
|
#endif
|
|
|
|
#define ARRAY_SIZE_OFFSET 8 // Increase this if audio_sys_get_real_time_stats returns ESP_ERR_INVALID_SIZE
|
|
#define AUDIO_SYS_TASKS_ELAPSED_TIME_MS 1000 // Period of stats measurement
|
|
|
|
static const char *TAG = "AFE_TEST";
|
|
static int detect_cnt = 0;
|
|
static int fetch_task_flag = 0;
|
|
|
|
|
|
void test_afe_by_config(afe_config_t *afe_config, int frame_num, int* memory, float* cpu, int idx)
|
|
{
|
|
int start_size = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
|
int start_internal_size = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
|
int first_end_size = 0;
|
|
int end_size = 0;
|
|
int mem_leak = 0;
|
|
uint32_t feed_cpu_time = 0;
|
|
uint32_t fetch_cpu_time = 0;
|
|
uint32_t start=0, end = 0;
|
|
int loop = 3;
|
|
int feed_chunksize = 0;
|
|
int create_size = 0;
|
|
int create_internal_size = 0;
|
|
|
|
for (int i=0; i<loop; i++) {
|
|
// init config and handle
|
|
esp_afe_sr_iface_t *afe_handle = esp_afe_handle_from_config(afe_config);
|
|
// afe_config_print(afe_config);
|
|
esp_afe_sr_data_t *afe_data = afe_handle->create_from_config(afe_config);
|
|
|
|
create_size = start_size - heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
|
create_internal_size = start_internal_size - heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
|
|
|
// run afe feed
|
|
feed_chunksize = afe_handle->get_feed_chunksize(afe_data);
|
|
int feed_nch = afe_handle->get_feed_channel_num(afe_data);
|
|
|
|
int16_t *feed_buff = (int16_t *) malloc(feed_chunksize * sizeof(int16_t) * feed_nch);
|
|
start = esp_timer_get_time();
|
|
for (int j=0; j<frame_num; j++) {
|
|
afe_handle->feed(afe_data, feed_buff);
|
|
}
|
|
end = esp_timer_get_time();
|
|
feed_cpu_time += end - start;
|
|
|
|
//run afe fetch
|
|
start = esp_timer_get_time();
|
|
while(1) {
|
|
afe_fetch_result_t *res = afe_handle->fetch_with_delay(afe_data, 1 / portTICK_PERIOD_MS);
|
|
if (res->ret_value != ESP_OK) {
|
|
break;
|
|
}
|
|
}
|
|
end = esp_timer_get_time();
|
|
fetch_cpu_time += end - start;
|
|
free(feed_buff);
|
|
afe_handle->destroy(afe_data);
|
|
end_size = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
|
|
|
if (i==0) {
|
|
first_end_size = end_size;
|
|
}
|
|
mem_leak = start_size - end_size;
|
|
ESP_LOGI(TAG, "create&destroy times:%d, memory leak:%d\n", i, mem_leak);
|
|
}
|
|
uint32_t feed_data_time = loop * frame_num * feed_chunksize / 16 * 1000; // us
|
|
memory[idx*2] = create_internal_size;
|
|
memory[idx*2+1] = create_size - create_internal_size;
|
|
cpu[idx*2] = feed_cpu_time*1.0/feed_data_time;
|
|
cpu[idx*2+1] = fetch_cpu_time*1.0/feed_data_time;
|
|
printf("Internal RAM: %d, PSRAM:%d, feed cpu loading:%f, fetch cpu loading:%f\n",
|
|
memory[idx*2], memory[idx*2+1], cpu[idx*2], cpu[idx*2+1]);
|
|
TEST_ASSERT_EQUAL(true, mem_leak < 1000 && end_size == first_end_size);
|
|
}
|
|
|
|
TEST_CASE(">>>>>>>> AFE create/destroy API & memory leak <<<<<<<<", "[afe]")
|
|
{
|
|
const char *input_format[6] = {"MR", "MMNR"};
|
|
afe_type_t afe_type[2] = {AFE_TYPE_SR, AFE_TYPE_VC};
|
|
afe_mode_t afe_mode[2] = {AFE_MODE_LOW_COST, AFE_MODE_HIGH_PERF};
|
|
int count = 0;
|
|
int memory[512];
|
|
float cpu[512];
|
|
|
|
// test all setting
|
|
srmodel_list_t *models = esp_srmodel_init("model");
|
|
for (int format_id=0; format_id<2; format_id++) {
|
|
for (int type_id=0; type_id<2; type_id++) {
|
|
for (int mode_id=0; mode_id<2; mode_id++) {
|
|
for (int aec_init = 0; aec_init < 2; aec_init++) {
|
|
for (int se_init = 0; se_init < 2; se_init++) {
|
|
for (int ns_init = 0; ns_init < 2; ns_init++) {
|
|
for (int vad_init = 0; vad_init < 2; vad_init++) {
|
|
for (int wakenet_init = 0; wakenet_init < 2; wakenet_init++) {
|
|
printf("format: %s, type: %d, mode: %d, memory size:%d %d\n",
|
|
input_format[format_id], afe_type[type_id], afe_mode[mode_id], heap_caps_get_free_size(MALLOC_CAP_8BIT), count);
|
|
afe_config_t *afe_config = afe_config_init(input_format[format_id], models, afe_type[type_id], afe_mode[mode_id]);
|
|
afe_config->aec_init = aec_init;
|
|
afe_config->se_init = se_init;
|
|
afe_config->ns_init = ns_init;
|
|
afe_config->vad_init = vad_init;
|
|
afe_config->wakenet_init = wakenet_init;
|
|
test_afe_by_config(afe_config, 4, memory, cpu, count);
|
|
afe_config_free(afe_config);
|
|
count++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (int idx=0; idx<256; idx++) {
|
|
printf("Internal RAM: %d, PSRAM:%d, feed cpu loading:%f, fetch cpu loading:%f\n",
|
|
memory[idx*2], memory[idx*2+1], cpu[idx*2], cpu[idx*2+1]);
|
|
}
|
|
printf("AFE create/destroy API & memory leak test done\n");
|
|
}
|
|
|
|
TEST_CASE(">>>>>>>> AFE default setting <<<<<<<<", "[afe_benchmark]")
|
|
{
|
|
const char *input_format[6] = {"MR", "MMNR"};
|
|
afe_type_t afe_type[2] = {AFE_TYPE_SR, AFE_TYPE_VC};
|
|
afe_mode_t afe_mode[2] = {AFE_MODE_LOW_COST, AFE_MODE_HIGH_PERF};
|
|
int count = 0;
|
|
int memory[16];
|
|
float cpu[16];
|
|
|
|
// test all setting
|
|
srmodel_list_t *models = esp_srmodel_init("model");
|
|
for (int format_id=0; format_id<2; format_id++) {
|
|
for (int type_id=0; type_id<2; type_id++) {
|
|
for (int mode_id=0; mode_id<2; mode_id++) {
|
|
printf("format: %s, type: %d, mode: %d, memory size:%d %d\n",
|
|
input_format[format_id], afe_type[type_id], afe_mode[mode_id], heap_caps_get_free_size(MALLOC_CAP_8BIT), count);
|
|
afe_config_t *afe_config = afe_config_init(input_format[format_id], models, afe_type[type_id], afe_mode[mode_id]);
|
|
test_afe_by_config(afe_config, 8, memory, cpu, count);
|
|
afe_config_free(afe_config);
|
|
count++;
|
|
}
|
|
}
|
|
}
|
|
count = 0;
|
|
for (int format_id=0; format_id<2; format_id++) {
|
|
for (int type_id=0; type_id<2; type_id++) {
|
|
for (int mode_id=0; mode_id<2; mode_id++) {
|
|
|
|
printf("--------format: %s, type: %s, mode: %s------------\n", input_format[format_id], type_id==0? "SR": "VC", mode_id==0? "LOW_COST": "HIGH_PERF");
|
|
printf("Internal RAM: %d, PSRAM:%d, feed cpu loading:%f, fetch cpu loading:%f\n",
|
|
memory[count*2], memory[count*2+1], cpu[count*2], cpu[count*2+1]);
|
|
count++;
|
|
}
|
|
}
|
|
}
|
|
printf("test done\n");
|
|
}
|
|
|
|
|
|
void test_feed_Task(void *arg)
|
|
{
|
|
afe_task_into_t *afe_task_info = (afe_task_into_t *)arg;
|
|
esp_afe_sr_iface_t *afe_handle = afe_task_info->afe_handle;
|
|
esp_afe_sr_data_t *afe_data = afe_task_info->afe_data;
|
|
|
|
int feed_chunksize = afe_handle->get_feed_chunksize(afe_data);
|
|
int feed_nch = afe_handle->get_feed_channel_num(afe_data);
|
|
int sample_per_ms = afe_handle->get_samp_rate(afe_data) / 1000;
|
|
int16_t *i2s_buff = (int16_t *) malloc(feed_chunksize * sizeof(int16_t) * feed_nch);
|
|
assert(i2s_buff);
|
|
ESP_LOGI(TAG, "feed task start\n");
|
|
int count = 0;
|
|
|
|
while (1) {
|
|
count ++;
|
|
afe_handle->feed(afe_data, i2s_buff);
|
|
vTaskDelay((feed_chunksize / sample_per_ms) / portTICK_PERIOD_MS);
|
|
if (count > 100) {
|
|
break;
|
|
}
|
|
}
|
|
if (i2s_buff) {
|
|
free(i2s_buff);
|
|
}
|
|
ESP_LOGI(TAG, "feed task quit\n");
|
|
vTaskDelete(NULL);
|
|
}
|
|
|
|
void test_fetch_Task(void *arg)
|
|
{
|
|
// esp_afe_sr_iface_t *afe_handle = &ESP_AFE_SR_HANDLE;
|
|
afe_task_into_t *afe_task_info = (afe_task_into_t *)arg;
|
|
esp_afe_sr_iface_t *afe_handle = afe_task_info->afe_handle;
|
|
esp_afe_sr_data_t *afe_data = afe_task_info->afe_data;
|
|
detect_cnt = 0;
|
|
fetch_task_flag = 1;
|
|
while (1) {
|
|
afe_fetch_result_t* res = afe_handle->fetch(afe_data);
|
|
if (!res || res->ret_value == ESP_FAIL) {
|
|
break;
|
|
}
|
|
|
|
if (res->wakeup_state == WAKENET_DETECTED) {
|
|
detect_cnt++;
|
|
}
|
|
}
|
|
|
|
// TEST_ASSERT_EQUAL(true, detect_cnt > 0);
|
|
ESP_LOGI(TAG, "detect task quit\n");
|
|
fetch_task_flag = 0;
|
|
vTaskDelete(NULL);
|
|
}
|
|
|
|
TEST_CASE("afe performance test (1ch)", "[afe_perf]")
|
|
{
|
|
const char *input_format = "MR";
|
|
afe_type_t afe_type = AFE_TYPE_VC;
|
|
afe_mode_t afe_model[2] = {AFE_MODE_HIGH_PERF, AFE_MODE_LOW_COST};
|
|
|
|
// test all setting
|
|
srmodel_list_t *models = esp_srmodel_init("model");
|
|
|
|
for (int mode_id=0; mode_id<2; mode_id++) {
|
|
afe_config_t *afe_config = afe_config_init(input_format, models, afe_type, afe_model[mode_id]);
|
|
if (afe_config->wakenet_init && afe_config->wakenet_model_name) {
|
|
esp_afe_sr_iface_t *afe_handle = esp_afe_handle_from_config(afe_config);
|
|
esp_afe_sr_data_t *afe_data = afe_handle->create_from_config(afe_config);
|
|
afe_task_into_t task_info;
|
|
task_info.afe_data = afe_data;
|
|
task_info.afe_handle = afe_handle;
|
|
task_info.feed_task = NULL;
|
|
task_info.fetch_task = NULL;
|
|
fetch_task_flag = 1;
|
|
xTaskCreatePinnedToCore(test_feed_Task, "feed_task", 8 * 1024, (void *)(&task_info), 5, &task_info.feed_task, 0);
|
|
xTaskCreatePinnedToCore(test_fetch_Task, "fetch_task", 8 * 1024, (void *)(&task_info), 5, &task_info.fetch_task, 0);
|
|
while (fetch_task_flag) {
|
|
vTaskDelay(32 / portTICK_PERIOD_MS);
|
|
}
|
|
}
|
|
afe_config_free(afe_config);
|
|
}
|
|
esp_srmodel_deinit(models);
|
|
}
|
|
|
|
TEST_CASE("afe performance test (2ch)", "[afe_perf]")
|
|
{
|
|
const char *input_format = "MMR";
|
|
afe_type_t afe_type = AFE_TYPE_VC;
|
|
afe_mode_t afe_model[2] = {AFE_MODE_HIGH_PERF, AFE_MODE_LOW_COST};
|
|
|
|
// test all setting
|
|
srmodel_list_t *models = esp_srmodel_init("model");
|
|
|
|
for (int mode_id=0; mode_id<2; mode_id++) {
|
|
afe_config_t *afe_config = afe_config_init(input_format, models, afe_type, afe_model[mode_id]);
|
|
if (afe_config->wakenet_init && afe_config->wakenet_model_name) {
|
|
esp_afe_sr_iface_t *afe_handle = esp_afe_handle_from_config(afe_config);
|
|
esp_afe_sr_data_t *afe_data = afe_handle->create_from_config(afe_config);
|
|
afe_task_into_t task_info;
|
|
task_info.afe_data = afe_data;
|
|
task_info.afe_handle = afe_handle;
|
|
task_info.feed_task = NULL;
|
|
task_info.fetch_task = NULL;
|
|
fetch_task_flag = 1;
|
|
xTaskCreatePinnedToCore(&test_feed_Task, "feed_task", 8 * 1024, (void *)(&task_info), 5, &task_info.feed_task, 0);
|
|
xTaskCreatePinnedToCore(&test_fetch_Task, "fetch_task", 8 * 1024, (void *)(&task_info), 5, &task_info.fetch_task, 0);
|
|
while (fetch_task_flag) {
|
|
vTaskDelay(32 / portTICK_PERIOD_MS);
|
|
}
|
|
}
|
|
afe_config_free(afe_config);
|
|
}
|
|
esp_srmodel_deinit(models);
|
|
} |