diff --git a/examples/audio_mux/src/app_conf.h b/examples/audio_mux/src/app_conf.h index e320774b..3cd60ee2 100644 --- a/examples/audio_mux/src/app_conf.h +++ b/examples/audio_mux/src/app_conf.h @@ -50,7 +50,7 @@ #endif #ifndef appconfUSB_ENABLED -#define appconfUSB_ENABLED (appconfUSB_INPUT || appconfI2S_OUTPUT) +#define appconfUSB_ENABLED (appconfUSB_INPUT || appconfUSB_OUTPUT) #endif #ifndef appconfUSB_AUDIO_ENABLED diff --git a/examples/ffd/ext/ffd_usb_audio_testing.cmake b/examples/ffd/ext/ffd_usb_audio_testing.cmake index 7e429722..878370f7 100644 --- a/examples/ffd/ext/ffd_usb_audio_testing.cmake +++ b/examples/ffd/ext/ffd_usb_audio_testing.cmake @@ -12,6 +12,7 @@ set(BYPASS_AUDIOPIPELINE_DEFINITIONS appconfAUDIO_PIPELINE_SKIP_IC_AND_VNR=1 appconfAUDIO_PIPELINE_SKIP_NS=1 appconfAUDIO_PIPELINE_SKIP_AGC=1 + appconfLOWPOWER_ENABLED=0 ) #********************** diff --git a/examples/ffd/inference/wanson/wanson_inf_eng_port.c b/examples/ffd/inference/wanson/wanson_inf_eng_port.c index 337a6364..801a3e5a 100644 --- a/examples/ffd/inference/wanson/wanson_inf_eng_port.c +++ b/examples/ffd/inference/wanson/wanson_inf_eng_port.c @@ -96,42 +96,42 @@ void wanson_engine_proc_keyword_result(const char **text, int id) } } -#if appconfSSD1306_DISPLAY_ENABLED - // some temporary fixes to the strings returned - switch (id) { - case 50: - // Clear the display - ssd1306_display_ascii_to_bitmap("\0"); - break; - case 3: - // fix capital "On" - ssd1306_display_ascii_to_bitmap("Switch on the TV\0"); - break; - case 15: - // fix lower case "speed" - // fix word wrapping - ssd1306_display_ascii_to_bitmap("Speed up the fan\0"); - break; - case 16: - // fix lower case "slow" - ssd1306_display_ascii_to_bitmap("Slow down the fan\0"); - break; - case 17: - // fix lower case "set" - // fix word wrapping - ssd1306_display_ascii_to_bitmap("Set higher temperature\0"); - break; - case 18: - // fix lower case "set" - // fix word wrapping - ssd1306_display_ascii_to_bitmap("Set lower temperature\0"); - break; - default: - if(text != NULL) { - ssd1306_display_ascii_to_bitmap((char *)*text); - } - } -#endif +// #if appconfSSD1306_DISPLAY_ENABLED +// // some temporary fixes to the strings returned +// switch (id) { +// case 50: +// // Clear the display +// ssd1306_display_ascii_to_bitmap("\0"); +// break; +// case 3: +// // fix capital "On" +// ssd1306_display_ascii_to_bitmap("Switch on the TV\0"); +// break; +// case 15: +// // fix lower case "speed" +// // fix word wrapping +// ssd1306_display_ascii_to_bitmap("Speed up the fan\0"); +// break; +// case 16: +// // fix lower case "slow" +// ssd1306_display_ascii_to_bitmap("Slow down the fan\0"); +// break; +// case 17: +// // fix lower case "set" +// // fix word wrapping +// ssd1306_display_ascii_to_bitmap("Set higher temperature\0"); +// break; +// case 18: +// // fix lower case "set" +// // fix word wrapping +// ssd1306_display_ascii_to_bitmap("Set lower temperature\0"); +// break; +// default: +// if(text != NULL) { +// ssd1306_display_ascii_to_bitmap((char *)*text); +// } +// } +// #endif } int32_t inference_engine_create(uint32_t priority, void *args) diff --git a/examples/ffd/src/app_conf.h b/examples/ffd/src/app_conf.h index ef3a9fe4..0c728729 100644 --- a/examples/ffd/src/app_conf.h +++ b/examples/ffd/src/app_conf.h @@ -11,6 +11,7 @@ #define appconfINTENT_MODEL_RUNNER_SAMPLES_PORT 3 #define appconfI2C_MASTER_RPC_PORT 4 +#define appconfPOWER_STATE_PORT 12 #define appconfWANSON_READY_SYNC_PORT 16 /* Application tile specifiers */ @@ -57,6 +58,11 @@ #define appconfINTENT_QUEUE_LEN 10 #endif +/* Maximum number of detected intents to hold */ +#ifndef appconfWAKEUP_TRIGGER_LEN +#define appconfWAKEUP_TRIGGER_LEN 1 +#endif + /* External wakeup pin edge on intent found. 0 for rising edge, 1 for falling edge */ #ifndef appconfINTENT_WAKEUP_EDGE_TYPE #define appconfINTENT_WAKEUP_EDGE_TYPE 0 @@ -95,6 +101,15 @@ #define appconfAUDIO_PIPELINE_SKIP_IC_AND_VNR 0 #endif +#ifndef appconfLOWPOWER_ENABLED +#define appconfLOWPOWER_ENABLED 1 +#endif + +#define appconfPOWER_VNR_THRESHOLD (0.5) +#define appconfPOWER_LOW_ENERGY_THRESHOLD (0.2) +#define appconfPOWER_HIGH_ENERGY_THRESHOLD (4.0) +#define appconfPOWER_FULL_HOLD_DURATION (3000) // milliseconds + #ifndef appconfAUDIO_PIPELINE_SKIP_NS #define appconfAUDIO_PIPELINE_SKIP_NS 0 #endif @@ -160,6 +175,7 @@ #define appconfQSPI_FLASH_TASK_PRIORITY (configMAX_PRIORITIES - 1) #define appconfSSD1306_TASK_PRIORITY (configMAX_PRIORITIES / 2 - 1) #define appconfLED_HEARTBEAT_TASK_PRIORITY (configMAX_PRIORITIES / 2 - 1) +#define appconfPOWER_STATUS_PRIORITY (configMAX_PRIORITIES / 2 - 1) #include "app_conf_check.h" diff --git a/examples/ffd/src/audio_pipeline/audio_pipeline.c b/examples/ffd/src/audio_pipeline/audio_pipeline.c index c7e28cf4..614983e9 100644 --- a/examples/ffd/src/audio_pipeline/audio_pipeline.c +++ b/examples/ffd/src/audio_pipeline/audio_pipeline.c @@ -23,6 +23,10 @@ /* App headers */ #include "app_conf.h" #include "audio_pipeline/audio_pipeline.h" +#include "power/power_state.h" + +#define VNR_AGC_THRESHOLD (0.5) +#define EMA_ENERGY_ALPHA (0.25) /* Note: Changing the order here will effect the channel order for * audio_pipeline_input() and audio_pipeline_output() @@ -30,15 +34,14 @@ typedef struct { int32_t samples[appconfAUDIO_PIPELINE_CHANNELS][appconfAUDIO_PIPELINE_FRAME_ADVANCE]; int32_t mic_samples_passthrough[appconfAUDIO_PIPELINE_CHANNELS][appconfAUDIO_PIPELINE_FRAME_ADVANCE]; - int32_t vnr_pred_flag; + float_s32_t vnr_pred; + float_s32_t ema_energy; } frame_data_t; #if appconfAUDIO_PIPELINE_FRAME_ADVANCE != 240 #error This pipeline is only configured for 240 frame advance #endif -#define VNR_AGC_THRESHOLD (0.5) - typedef struct ic_stage_ctx { ic_state_t state; } ic_stage_ctx_t; @@ -61,6 +64,10 @@ static vnr_pred_stage_ctx_t DWORD_ALIGNED vnr_pred_stage_state = {}; static ns_stage_ctx_t DWORD_ALIGNED ns_stage_state = {}; static agc_stage_ctx_t DWORD_ALIGNED agc_stage_state = {}; +static uq2_30 ema_energy_alpha_q30 = Q30(EMA_ENERGY_ALPHA); + +static power_data_t* power_app_data = 0; + static void *audio_pipeline_input_i(void *input_app_data) { frame_data_t *frame_data; @@ -71,7 +78,8 @@ static void *audio_pipeline_input_i(void *input_app_data) (int32_t **)frame_data->samples, 2, appconfAUDIO_PIPELINE_FRAME_ADVANCE); - frame_data->vnr_pred_flag = 0; + frame_data->vnr_pred = f32_to_float_s32(0.0); + frame_data->ema_energy = f32_to_float_s32(0.0); memcpy(frame_data->mic_samples_passthrough, frame_data->samples, sizeof(frame_data->mic_samples_passthrough)); @@ -81,7 +89,13 @@ static void *audio_pipeline_input_i(void *input_app_data) static int audio_pipeline_output_i(frame_data_t *frame_data, void *output_app_data) { - return audio_pipeline_output(output_app_data, + power_app_data->vnr_pred = float_s32_to_float(frame_data->vnr_pred); + power_app_data->ema_energy = float_s32_to_float(frame_data->ema_energy); + + //NOTE: passing power_app_data to callback instead of output_app_data. + // They should be the same pointer. + assert(power_app_data == output_app_data); + return audio_pipeline_output(power_app_data, (int32_t **)frame_data->samples, 4, appconfAUDIO_PIPELINE_FRAME_ADVANCE); @@ -115,13 +129,7 @@ static void stage_vnr_and_ic(frame_data_t *frame_data) vnr_inference(&ie_output, &feature_patch); vnr_pred_state->output_vnr_pred = float_s32_ema(vnr_pred_state->output_vnr_pred, ie_output, vnr_pred_state->pred_alpha_q30); -#if 0 - rtos_printf("VNR OUTPUT PRED: %ld %d\n", vnr_pred_stage_state.vnr_pred_state.output_vnr_pred.mant, vnr_pred_stage_state.vnr_pred_state.output_vnr_pred.exp); - rtos_printf("VNR INPUT PRED: %ld %d\n", vnr_pred_stage_state.vnr_pred_state.input_vnr_pred.mant, vnr_pred_stage_state.vnr_pred_state.input_vnr_pred.exp); -#endif - - float_s32_t agc_vnr_threshold = f32_to_float_s32(VNR_AGC_THRESHOLD); - frame_data->vnr_pred_flag = float_s32_gt(vnr_pred_stage_state.vnr_pred_state.output_vnr_pred, agc_vnr_threshold); + frame_data->vnr_pred = vnr_pred_stage_state.vnr_pred_state.output_vnr_pred; ic_adapt(&ic_stage_state.state, vnr_pred_stage_state.vnr_pred_state.input_vnr_pred); @@ -142,6 +150,16 @@ static void stage_ns(frame_data_t *frame_data) frame_data->samples[0]); memcpy(frame_data->samples, ns_output, appconfAUDIO_PIPELINE_FRAME_ADVANCE * sizeof(int32_t)); #endif + +#if appconfLOWPOWER_ENABLED + // Compute exponential moving average of frame energy + bfp_s32_t B; + bfp_s32_init(&B, &frame_data->samples[0][0], -31, appconfAUDIO_PIPELINE_FRAME_ADVANCE, 1); + float_s32_t energy = float_s64_to_float_s32(bfp_s32_energy(&B)); + frame_data->ema_energy = float_s32_ema(frame_data->ema_energy, energy, ema_energy_alpha_q30); +#else + frame_data->ema_energy = f32_to_float_s32(0.0);; +#endif } static void stage_agc(frame_data_t *frame_data) @@ -152,7 +170,9 @@ static void stage_agc(frame_data_t *frame_data) int32_t DWORD_ALIGNED agc_output[appconfAUDIO_PIPELINE_FRAME_ADVANCE]; configASSERT(AGC_FRAME_ADVANCE == appconfAUDIO_PIPELINE_FRAME_ADVANCE); - agc_stage_state.md.vnr_flag = frame_data->vnr_pred_flag; + agc_stage_state.md.vnr_flag = float_s32_gt(frame_data->vnr_pred, f32_to_float_s32(VNR_AGC_THRESHOLD)); + + agc_process_frame( &agc_stage_state.state, @@ -201,6 +221,7 @@ void audio_pipeline_init( initialize_pipeline_stages(); + power_app_data = (power_data_t *) output_app_data; generic_pipeline_init((pipeline_input_t)audio_pipeline_input_i, (pipeline_output_t)audio_pipeline_output_i, input_app_data, diff --git a/examples/ffd/src/main.c b/examples/ffd/src/main.c index 2913617b..f77feaff 100644 --- a/examples/ffd/src/main.c +++ b/examples/ffd/src/main.c @@ -29,10 +29,14 @@ #include "xcore_device_memory.h" #include "ssd1306_rtos_support.h" #include "intent_handler/intent_handler.h" +#include "power/power_state.h" +#include "power/power_status.h" extern void startup_task(void *arg); extern void tile_common_init(chanend_t c); +static power_data_t wakeup_app_data = {}; + //void uart_write(char data) {} //API for Wanson's Debug __attribute__((weak)) @@ -71,10 +75,14 @@ int audio_pipeline_output(void *output_app_data, size_t ch_count, size_t frame_count) { - (void) output_app_data; - + power_state_t power_state = POWER_STATE_FULL; +#if appconfLOWPOWER_ENABLED + power_state = power_state_data_add((power_data_t *)output_app_data); +#endif #if appconfINFERENCE_ENABLED - inference_engine_sample_push((int32_t *)output_audio_frames, frame_count); + if (power_state == POWER_STATE_FULL) { + inference_engine_sample_push((int32_t *)output_audio_frames, frame_count); + } #endif return AUDIO_PIPELINE_FREE_FRAME; @@ -87,6 +95,14 @@ void vApplicationMallocFailedHook(void) for(;;); } +// static void mem_analysis(void) +// { +// for (;;) { +// rtos_printf("Tile[%d]:\n\tMinimum heap free: %d\n\tCurrent heap free: %d\n", THIS_XCORE_TILE, xPortGetMinimumEverFreeHeapSize(), xPortGetFreeHeapSize()); +// vTaskDelay(pdMS_TO_TICKS(5000)); +// } +// } + __attribute__((weak)) void startup_task(void *arg) { @@ -121,13 +137,20 @@ void startup_task(void *arg) rtos_intertile_rx_data(intertile_ctx, &ret, sizeof(ret)); } #endif - audio_pipeline_init(NULL, NULL); + audio_pipeline_init(NULL, &wakeup_app_data); +#if appconfLOWPOWER_ENABLED + power_state_init(); +#endif #endif #if ON_TILE(0) led_heartbeat_create(appconfLED_HEARTBEAT_TASK_PRIORITY, NULL); +#if appconfLOWPOWER_ENABLED + power_status_create(appconfPOWER_STATUS_PRIORITY, NULL); +#endif #endif + //mem_analysis(); vTaskSuspend(NULL); while(1){;} /* Trap */ } diff --git a/examples/ffd/src/power/power_state.c b/examples/ffd/src/power/power_state.c new file mode 100644 index 00000000..cab3aba7 --- /dev/null +++ b/examples/ffd/src/power/power_state.c @@ -0,0 +1,53 @@ +// Copyright (c) 2022 XMOS LIMITED. This Software is subject to the terms of the +// XMOS Public License: Version 1 + +/* STD headers */ +#include +#include + +/* FreeRTOS headers */ +#include "FreeRTOS.h" +#include "task.h" + +/* App headers */ +#include "app_conf.h" +#include "platform/driver_instances.h" +#include "power/power_state.h" + +static TimerHandle_t power_state_timer; +static power_state_t power_state = POWER_STATE_FULL; + +void vWakeupStateCallback(TimerHandle_t pxTimer) +{ + power_state_set(POWER_STATE_LOW); + xTimerStop(power_state_timer, 0); +} + +void power_state_set(power_state_t state) { + if (state != power_state) { + power_state = state; + rtos_intertile_tx(intertile_ctx, appconfPOWER_STATE_PORT, &power_state, sizeof(power_state)); + } +} + +void power_state_init() { + power_state_timer = xTimerCreate( + "disp_reset", + pdMS_TO_TICKS(appconfPOWER_FULL_HOLD_DURATION), + pdFALSE, + NULL, + vWakeupStateCallback); + + power_state_set(POWER_STATE_LOW); +} + +power_state_t power_state_data_add(power_data_t *data) { + if ((data->ema_energy >= appconfPOWER_HIGH_ENERGY_THRESHOLD) || + ((data->ema_energy >= appconfPOWER_LOW_ENERGY_THRESHOLD) && + (data->vnr_pred >= appconfPOWER_VNR_THRESHOLD))) { + power_state_set(POWER_STATE_FULL); + xTimerReset(power_state_timer, 0); + } + + return power_state; +} diff --git a/examples/ffd/src/power/power_state.h b/examples/ffd/src/power/power_state.h new file mode 100644 index 00000000..789d09a4 --- /dev/null +++ b/examples/ffd/src/power/power_state.h @@ -0,0 +1,21 @@ +// Copyright (c) 2022 XMOS LIMITED. This Software is subject to the terms of the +// XMOS Public License: Version 1 + +#ifndef POWER_STATE_H_ +#define POWER_STATE_H_ + +typedef struct { + float vnr_pred; + float ema_energy; +} power_data_t; + +typedef enum power_state { + POWER_STATE_LOW, + POWER_STATE_FULL +} power_state_t; + +void power_state_init(); +void power_state_set(power_state_t state); +power_state_t power_state_data_add(power_data_t *data); + +#endif /* POWER_STATE_H_ */ diff --git a/examples/ffd/src/power/power_status.c b/examples/ffd/src/power/power_status.c new file mode 100644 index 00000000..21f51a29 --- /dev/null +++ b/examples/ffd/src/power/power_status.c @@ -0,0 +1,50 @@ +// Copyright (c) 2022 XMOS LIMITED. This Software is subject to the terms of the +// XMOS Public License: Version 1 + +/* STD headers */ +#include +#include +#include + +/* FreeRTOS headers */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* App headers */ +#include "app_conf.h" +#include "ssd1306_rtos_support.h" +#include "power/power_state.h" +#include "power/power_status.h" + +static void proc_power_status(void *args) { + + while(1) { + power_state_t power_state = 0; + size_t len_rx = 0; + + len_rx = rtos_intertile_rx_len(intertile_ctx, appconfPOWER_STATE_PORT, RTOS_OSAL_WAIT_FOREVER); + configASSERT(len_rx == sizeof(power_state)); + + rtos_intertile_rx_data(intertile_ctx, &power_state, sizeof(power_state)); + if (power_state == POWER_STATE_LOW) { + ssd1306_display_ascii_to_bitmap("Low power\0"); + rtos_printf("POWER_MODE: %d, Low\n", power_state); + } else if (power_state == POWER_STATE_FULL) { + ssd1306_display_ascii_to_bitmap("Full power\0"); + rtos_printf("POWER_MODE: %d, Full\n", power_state); + } + } +} + +int32_t power_status_create(uint32_t priority, void *args) +{ + xTaskCreate((TaskFunction_t)proc_power_status, + "proc_power_status", + RTOS_THREAD_STACK_SIZE(proc_power_status), + args, + priority, + NULL); + + return 0; +} diff --git a/examples/ffd/src/power/power_status.h b/examples/ffd/src/power/power_status.h new file mode 100644 index 00000000..699c99f3 --- /dev/null +++ b/examples/ffd/src/power/power_status.h @@ -0,0 +1,9 @@ +// Copyright (c) 2022 XMOS LIMITED. This Software is subject to the terms of the +// XMOS Public License: Version 1 + +#ifndef POWER_STATUS_H_ +#define POWER_STATUS_H_ + +int32_t power_status_create(uint32_t priority, void *args); + +#endif /* POWER_STATUS_H_ */ diff --git a/examples/ffd/src/rtos_conf/FreeRTOSConfig.h b/examples/ffd/src/rtos_conf/FreeRTOSConfig.h index 6fb5f634..c68ecccf 100644 --- a/examples/ffd/src/rtos_conf/FreeRTOSConfig.h +++ b/examples/ffd/src/rtos_conf/FreeRTOSConfig.h @@ -47,7 +47,7 @@ your application. */ #define configTOTAL_HEAP_SIZE 64*1024 #endif #if ON_TILE(1) -#define configTOTAL_HEAP_SIZE 64*1024 +#define configTOTAL_HEAP_SIZE 74*1024 #endif #define configAPPLICATION_ALLOCATED_HEAP 0 diff --git a/examples/stlp/audio_pipeline/audio_pipeline.cmake b/examples/stlp/audio_pipeline/audio_pipeline.cmake index c3710fe7..4d2e718d 100644 --- a/examples/stlp/audio_pipeline/audio_pipeline.cmake +++ b/examples/stlp/audio_pipeline/audio_pipeline.cmake @@ -1,3 +1,32 @@ +## Create custom stlp audiopipeline +add_library(xcore_sdk_app_stlp_audio_pipeline_fixed_delay_aec_2x_2y_no_comms INTERFACE) +target_sources(xcore_sdk_app_stlp_audio_pipeline_fixed_delay_aec_2x_2y_no_comms + INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/src/fixed_delay/audio_pipeline_t0.c + ${CMAKE_CURRENT_LIST_DIR}/src/fixed_delay/audio_pipeline_t1.c + ${CMAKE_CURRENT_LIST_DIR}/src/fixed_delay/aec/aec_process_frame_1thread.c +) +target_include_directories(xcore_sdk_app_stlp_audio_pipeline_fixed_delay_aec_2x_2y_no_comms + INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/api + ${CMAKE_CURRENT_LIST_DIR}/src/fixed_delay +) +target_link_libraries(xcore_sdk_app_stlp_audio_pipeline_fixed_delay_aec_2x_2y_no_comms + INTERFACE + core::general + rtos::freertos + rtos::sw_services::generic_pipeline + fwk_voice::aec + fwk_voice::agc + fwk_voice::ic + fwk_voice::ns + fwk_voice::vnr::features + fwk_voice::vnr::inference +) + +## Create an alias +add_library(sln_voice::app::stlp::ap::fixed_delay ALIAS xcore_sdk_app_stlp_audio_pipeline_fixed_delay_aec_2x_2y_no_comms) + ## Create custom stlp audiopipeline add_library(sln_voice_app_stlp_audio_pipeline_adec_aec_2x_2y_no_comms INTERFACE) @@ -33,9 +62,6 @@ target_link_libraries(sln_voice_app_stlp_audio_pipeline_adec_aec_2x_2y_no_comms ## Create an alias add_library(sln_voice::app::stlp::ap::adec ALIAS sln_voice_app_stlp_audio_pipeline_adec_aec_2x_2y_no_comms) - - - ## Create custom stlp audiopipeline add_library(sln_voice_app_stlp_audio_pipeline_adec_aec_2x_2y_no_comms_altarch INTERFACE) target_sources(sln_voice_app_stlp_audio_pipeline_adec_aec_2x_2y_no_comms_altarch diff --git a/examples/stlp/audio_pipeline/src/fixed_delay/aec/aec_memory_pool.h b/examples/stlp/audio_pipeline/src/fixed_delay/aec/aec_memory_pool.h new file mode 100644 index 00000000..f19e2c1f --- /dev/null +++ b/examples/stlp/audio_pipeline/src/fixed_delay/aec/aec_memory_pool.h @@ -0,0 +1,54 @@ +// Copyright 2022 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. + +#ifndef AEC_MEMORY_POOL_H +#define AEC_MEMORY_POOL_H + +#include "audio_pipeline_dsp.h" +#include "xmath/xmath.h" + +//Memory pool definition +typedef struct { + /** Memory pointed to by aec_shared_state_t::y and aec_shared_state_t::Y*/ + int32_t mic_input_frame[AEC_MAX_Y_CHANNELS][AEC_PROC_FRAME_LENGTH + AEC_FFT_PADDING]; + /** Memory pointed to by aec_shared_state_t::x and aec_shared_state_t::X. Also reused for main filter + * aec_state_t::T*/ + int32_t ref_input_frame[AEC_MAX_X_CHANNELS][AEC_PROC_FRAME_LENGTH + AEC_FFT_PADDING]; + /** Memory pointed to by aec_shared_state_t::prev_y*/ + int32_t mic_prev_samples[AEC_MAX_Y_CHANNELS][AEC_PROC_FRAME_LENGTH - AEC_FRAME_ADVANCE]; + /** Memory pointed to by aec_shared_state_t::prev_x*/ + int32_t ref_prev_samples[AEC_MAX_X_CHANNELS][AEC_PROC_FRAME_LENGTH - AEC_FRAME_ADVANCE]; + /** Memory pointed to by main filter aec_state_t::H_hat, aec_shared_state_t::X_fifo, main filter + * aec_state_t::X_fifo_1d and shadow filter aec_state_t::X_fifo_1d*/ + complex_s32_t phase_pool_H_hat_X_fifo[((AEC_MAX_Y_CHANNELS*AEC_MAX_X_CHANNELS*AEC_MAIN_FILTER_PHASES) + (AEC_MAX_X_CHANNELS*AEC_MAIN_FILTER_PHASES)) * AEC_FD_FRAME_LENGTH]; + /** Memory pointed to by main filter aec_state_t::Error and aec_state_t::error*/ + complex_s32_t Error[AEC_MAX_Y_CHANNELS][AEC_FD_FRAME_LENGTH]; + /** Memory pointed to by main filter aec_state_t::Y_hat and aec_state_t::y_hat*/ + complex_s32_t Y_hat[AEC_MAX_Y_CHANNELS][AEC_FD_FRAME_LENGTH]; + /** Memory pointed to by main_filter aec_state_t::X_energy*/ + int32_t X_energy[AEC_MAX_X_CHANNELS][AEC_FD_FRAME_LENGTH]; + /** Memory pointed to by aec_shared_state_t::sigma_XX*/ + int32_t sigma_XX[AEC_MAX_X_CHANNELS][AEC_FD_FRAME_LENGTH]; + /** Memory pointed to by main filter aec_state_t::inv_X_energy*/ + int32_t inv_X_energy[AEC_MAX_X_CHANNELS][AEC_FD_FRAME_LENGTH]; + /** Memory pointed to by main filter aec_state_t::overlap*/ + int32_t overlap[AEC_MAX_Y_CHANNELS][AEC_UNUSED_TAPS_PER_PHASE*2]; +}aec_memory_pool_t; + +typedef struct { + /** Memory pointed to by shadow filter aec_state_t::H_hat*/ + complex_s32_t phase_pool_H_hat[AEC_MAX_Y_CHANNELS * AEC_MAX_X_CHANNELS * AEC_SHADOW_FILTER_PHASES * AEC_FD_FRAME_LENGTH]; + /** Memory pointed to by shadow filter aec_state_t::Error and aec_state_t::error*/ + complex_s32_t Error[AEC_MAX_Y_CHANNELS][AEC_FD_FRAME_LENGTH]; + /** Memory pointed to by shadow filter aec_state_t::Y_hat and aec_state_t::y_hat*/ + complex_s32_t Y_hat[AEC_MAX_Y_CHANNELS][AEC_FD_FRAME_LENGTH]; + /** Memory pointed to by shadow filter aec_state_t::T*/ + complex_s32_t T[AEC_MAX_X_CHANNELS][AEC_FD_FRAME_LENGTH]; + /** Memory pointed to by shadow_filter aec_state_t::X_energy*/ + int32_t X_energy[AEC_MAX_X_CHANNELS][AEC_FD_FRAME_LENGTH]; + /** Memory pointed to by shadow_filter aec_state_t::inv_X_energy*/ + int32_t inv_X_energy[AEC_MAX_X_CHANNELS][AEC_FD_FRAME_LENGTH]; + /** Memory pointed to by shadow filter aec_state_t::overlap*/ + int32_t overlap[AEC_MAX_Y_CHANNELS][AEC_UNUSED_TAPS_PER_PHASE*2]; +}aec_shadow_filt_memory_pool_t; +#endif diff --git a/examples/stlp/audio_pipeline/src/fixed_delay/aec/aec_process_frame_1thread.c b/examples/stlp/audio_pipeline/src/fixed_delay/aec/aec_process_frame_1thread.c new file mode 100644 index 00000000..240925de --- /dev/null +++ b/examples/stlp/audio_pipeline/src/fixed_delay/aec/aec_process_frame_1thread.c @@ -0,0 +1,221 @@ +// Copyright 2021-2022 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. + +#include +#include +#include "aec_defines.h" +#include "aec_api.h" + +/* This is an example of processing one frame of data through the AEC pipeline stage. The example runs on 1 thread and + * can be compiled for both bare metal and x86. + */ +static unsigned X_energy_recalc_bin = 0; +void aec_process_frame_1thread( + aec_state_t *main_state, + aec_state_t *shadow_state, + int32_t (*output_main)[AEC_FRAME_ADVANCE], + int32_t (*output_shadow)[AEC_FRAME_ADVANCE], + const int32_t (*y_data)[AEC_FRAME_ADVANCE], + const int32_t (*x_data)[AEC_FRAME_ADVANCE]) +{ + // Read number of mic and reference channels. These are specified as part of the configuration when aec_init() is called. + int num_y_channels = main_state->shared_state->num_y_channels; //Number of mic channels + int num_x_channels = main_state->shared_state->num_x_channels; //Number of reference channels + + // Set up the input BFP structures main_state->shared_state->y and main_state->shared_state->x to point to the new frame. + // Initialise some other BFP structures that need to be initialised at the beginning of each frame + aec_frame_init(main_state, shadow_state, y_data, x_data); + + // Calculate Exponential moving average (EMA) energy of the mic and reference input. + for(int ch=0; chshared_state->y_ema_energy[ch], &main_state->shared_state->y[ch], + AEC_PROC_FRAME_LENGTH - AEC_FRAME_ADVANCE, AEC_FRAME_ADVANCE, &main_state->shared_state->config_params); + } + for(int ch=0; chshared_state->x_ema_energy[ch], &main_state->shared_state->x[ch], + AEC_PROC_FRAME_LENGTH - AEC_FRAME_ADVANCE, AEC_FRAME_ADVANCE, &main_state->shared_state->config_params); + } + + // Calculate mic input spectrum for all num_y_channels of mic input + /* The spectrum calculation is done in place. Taking mic input as example, after the aec_forward_fft() call + * main_state->shared_state->Y[ch].data and main_state->shared_state->y[ch].data point to the same memory address. + * The spectral representation of the input is used after this function. Time domain input + * BFP structure main_state->shared_state->y should not be used. + * main_state->shared_state->Y[ch].data points to AEC_PROC_FRAME_LENGTH/2 + 1 complex 32bit spectrum samples, + * which represent the spectrum samples from DC to Nyquist frequency. + * Same is true for reference spectrum samples pointed to by main_state->shared_state->X[ch].data + * as well. + */ + for(int ch=0; chshared_state->Y[ch], &main_state->shared_state->y[ch]); + } + // Calculate reference input spectrum for all num_x_channels of reference input + for(int ch=0; chshared_state->X[ch], &main_state->shared_state->x[ch]); + } + + // Calculate sum of X energy over X FIFO phases for all num_x_channels reference channels + /* AEC data structures store a single copy of the X FIFO that is shared between the main and shadow filter. + * Since main filter phases main_state->num_phases are more than the shadow filter phases shadow_state->num_phases, + * X FIFO holds main_state->num_phases most recent frames of reference input spectrum, where the frames are ordered + * from most recent to least recent. For shadow filter operation, out of this shared X FIFO, the first shadow_state->num_phases + * frames are considered. + */ + for(int ch=0; chX_energy[ch] points to AEC_PROC_FRAME_LENGTH/2 + 1 real 32bit values where value at index n is + * the nth X sample's energy summed over main_state->num_phases number of frames in the X FIFO. + */ + aec_calc_X_fifo_energy(main_state, ch, X_energy_recalc_bin); + + // Calculate sum of X energy for shadow filter + /* BFP struct shadow_state->X_energy[ch] points to AEC_PROC_FRAME_LENGTH/2 + 1 real 32bit values where value at index n is + * the nth X sample's energy summed over shadow_state->num_phases number of frames in the X FIFO. + */ + aec_calc_X_fifo_energy(shadow_state, ch, X_energy_recalc_bin); + } + + // Increment X_energy_recalc_bin to the next sample index. + /* Passing X_energy_recalc_bin to aec_calc_X_fifo_energy() ensures that energy of sample at index X_energy_recalc_bin + * is recalculated without the speed optimisations so that quantisation error can be kept in check + */ + X_energy_recalc_bin += 1; + if(X_energy_recalc_bin == (AEC_PROC_FRAME_LENGTH/2) + 1) { // Wrap around to 0 on completing one (AEC_PROC_FRAME_LENGTH/2) + 1 samples pass. + X_energy_recalc_bin = 0; + } + + // Update X-FIFO and calculate sigma_XX. + /* Add the current X frame to the X FIFO and remove the oldest X frame from the X FIFO. + * Also, calculate state->shared_state->sigma_XX. sigma_XX is the EMA of current X frame energy. + * It is later used to time smooth the X_energy while calculating the normalisation spectrum + */ + for(int ch=0; chshared_state->X_fifo BFP struct to main_state->X_fifo_1d and shadow_state->X_fifo_1d BFP structs + /* The updated state->shared_state->X_FIFO BFP structures are copied to an alternate set of BFP structs present in the + * main and shadow filter state structure, that are used to efficiently access the X FIFO in the Error computation and filter + * update steps. + */ + aec_update_X_fifo_1d(main_state); + aec_update_X_fifo_1d(shadow_state); + + // Calculate error spectrum and estimated mic spectrum for main and shadow adaptive filters + for(int ch=0; chError[ch] and main_state->Y_hat[ch] are updated + aec_calc_Error_and_Y_hat(main_state, ch); + + // shadow_state->Error[ch] and shadow_state->Y_hat[ch] are updated + aec_calc_Error_and_Y_hat(shadow_state, ch); + } + + // Calculate time domain error and time domain estimated mic input from their spectrums calculated in the previous step. + /* The time domain estimated mic_input (y_hat) is used to calculate the average coherence between y and y_hat in aec_calc_coherence. + * Only the estimated mic input calculated using the main filter is needed for coherence calculation, so the y_hat calculation is + * done only for main filter. + */ + for(int ch=0; cherror[ch], &main_state->Error[ch]); + aec_inverse_fft(&shadow_state->error[ch], &shadow_state->Error[ch]); + aec_inverse_fft(&main_state->y_hat[ch], &main_state->Y_hat[ch]); + } + + // Calculate average coherence and average slow moving coherence between mic and estimated mic time domain signals + for(int ch=0; chshared_state->coh_mu_state[ch].coh and main_state->shared_state->coh_mu_state[ch].coh_slow are updated + aec_calc_coherence(main_state, ch); + } + + // Calculate AEC filter time domain output. This is the output sent to downstream pipeline stages + for(int ch=0; cherror_ema_energy[ch], &temp, 0, AEC_FRAME_ADVANCE, &main_state->shared_state->config_params); + } + + // Convert shadow and main filters error back to frequency domain since subsequent AEC functions will use the error spectrum. + // The error spectrum is later used to compute T values which are then used while updating the adaptive filter. + for(int ch=0; chError[ch] is updated + aec_forward_fft(&main_state->Error[ch], &main_state->error[ch]); + + // shadow_state->Error[ch] is updated + aec_forward_fft(&shadow_state->Error[ch], &shadow_state->error[ch] + ); + } + + // Calculate energies of mic input and error spectrum of main and shadow filters. + // These energy values are later used in aec_compare_filters_and_calc_mu() to estimate how well the filters are performing. + for(int ch=0; choverall_Error[ch] is updated + aec_calc_freq_domain_energy(&main_state->overall_Error[ch], &main_state->Error[ch]); + + // shadow_state->overall_Error[ch] is updated + aec_calc_freq_domain_energy(&shadow_state->overall_Error[ch], &shadow_state->Error[ch]); + + // main_state->shared_state->overall_Y[ch] is updated + aec_calc_freq_domain_energy(&main_state->shared_state->overall_Y[ch], &main_state->shared_state->Y[ch]); + } + + // Compare and update filters. Calculate adaption step_size mu + /* At this point we're ready to check how well the filters are performing and update them if needed. + * + * main_state->shared_state->shadow_filter_params are updated to indicate the current state of filter comparison algorithm. + * main_state->H_hat, main_state->Error, shadow_state->H_hat, shadow_state->Error are optionally updated depending on the update needed. + * + * After the filter comparison and update step, the adaption step size mu is calculated for main and shadow filter. + * main_state->mu and shadow_state->mu are updated. + */ + aec_compare_filters_and_calc_mu( + main_state, + shadow_state); + + // Calculate smoothed reference FIFO energy that is later used to scale the X FIFO in the filter update step. + // This calculation is done differently for main and shadow filters, so a flag indicating filter type is specified as one of the input arguments. + for(int ch=0; chinv_X_energy[ch] is updated. + aec_calc_normalisation_spectrum(main_state, ch, 0); + + // shadow_state->inv_X_energy[ch] is updated. + aec_calc_normalisation_spectrum(shadow_state, ch, 1); + } + + for(int ych=0; ychmu, state->Error and state->inv_X_energy. + for(int xch=0; xchT[ch] is updated + aec_calc_T(main_state, ych, xch); + + // shadow_state->T[ch] is updated + aec_calc_T(shadow_state, ych, xch); + } + // Update filters + + // Update main_state->H_hat + aec_filter_adapt(main_state, ych); + + // Update shadow_state->H_hat + aec_filter_adapt(shadow_state, ych); + } +} diff --git a/examples/stlp/audio_pipeline/src/fixed_delay/audio_pipeline_dsp.h b/examples/stlp/audio_pipeline/src/fixed_delay/audio_pipeline_dsp.h new file mode 100644 index 00000000..7e012a2a --- /dev/null +++ b/examples/stlp/audio_pipeline/src/fixed_delay/audio_pipeline_dsp.h @@ -0,0 +1,103 @@ +// Copyright (c) 2022 XMOS LIMITED. This Software is subject to the terms of the +// XMOS Public License: Version 1 + +#ifndef AUDIO_PIPELINE_DSP_H_ +#define AUDIO_PIPELINE_DSP_H_ + +#include +#include "FreeRTOS.h" +#include "stream_buffer.h" +#include "app_conf.h" +#include + +/* Pipeline config */ +#define AP_MAX_Y_CHANNELS (2) +#define AP_MAX_X_CHANNELS (2) +#define AP_FRAME_ADVANCE (240) + +/* AEC config */ +#define AEC_MAX_Y_CHANNELS (AP_MAX_Y_CHANNELS) +#define AEC_MAX_X_CHANNELS (AP_MAX_X_CHANNELS) +#define AEC_MAIN_FILTER_PHASES (10) +#define AEC_SHADOW_FILTER_PHASES (5) + +/* Delay buffer config */ +#define MAX_DELAY_BUF_CHANNELS (2) +#define DELAY_BUF_MAX_DELAY_MS ( 150 ) +#define DELAY_BUF_MAX_DELAY_SAMPLES ( 16000*DELAY_BUF_MAX_DELAY_MS/1000 ) + +#include "aec_api.h" +#include "aec/aec_memory_pool.h" +#include "agc_api.h" +#include "ic_api.h" +#include "ns_api.h" +#include "vnr_features_api.h" +#include "vnr_inference_api.h" + + +/* Note: Changing the order here will effect the channel order for + * audio_pipeline_input() and audio_pipeline_output() + */ +typedef struct { + int32_t samples[appconfAUDIO_PIPELINE_CHANNELS][appconfAUDIO_PIPELINE_FRAME_ADVANCE]; + int32_t aec_reference_audio_samples[appconfAUDIO_PIPELINE_CHANNELS][appconfAUDIO_PIPELINE_FRAME_ADVANCE]; + int32_t mic_samples_passthrough[appconfAUDIO_PIPELINE_CHANNELS][appconfAUDIO_PIPELINE_FRAME_ADVANCE]; + + /* Below is additional context needed by other stages on a per frame basis */ + int32_t vnr_pred_flag; + float_s32_t max_ref_energy; + float_s32_t aec_corr_factor; + int32_t ref_active_flag; +} frame_data_t; + +typedef struct stage_delay_ctx { + StreamBufferHandle_t delay_buf; +} stage_delay_ctx_t; + +typedef struct aec_ctx { + aec_state_t DWORD_ALIGNED aec_main_state; + aec_state_t DWORD_ALIGNED aec_shadow_state; + aec_shared_state_t DWORD_ALIGNED aec_shared_state; + uint8_t DWORD_ALIGNED aec_main_memory_pool[sizeof(aec_memory_pool_t)]; + uint8_t DWORD_ALIGNED aec_shadow_memory_pool[sizeof(aec_shadow_filt_memory_pool_t)]; +} aec_ctx_t; + +typedef struct ic_stage_ctx { + ic_state_t DWORD_ALIGNED state; +} ic_stage_ctx_t; + +typedef struct vnr_pred_stage_ctx { + vnr_pred_state_t vnr_pred_state; +} vnr_pred_stage_ctx_t; + +typedef struct ns_stage_ctx { + ns_state_t DWORD_ALIGNED state; +} ns_stage_ctx_t; + +typedef struct agc_stage_ctx { + agc_meta_data_t md; + agc_state_t DWORD_ALIGNED state; +} agc_stage_ctx_t; + +/** + * Delay buffer contains the configured buffer delay size + 1 frame worth of audio + * When appconfINPUT_SAMPLES_MIC_DELAY_MS is positive, the mic is delayed + * When appconfINPUT_SAMPLES_MIC_DELAY_MS is negative, the mic is "advanced" by delaying ref + */ +#define ABS(A) ((A >= 0) ? A : -A) +#define AP_INPUT_SAMPLES_MIC_DELAY_SIZE_PER_CHAN ( 16000*ABS(appconfINPUT_SAMPLES_MIC_DELAY_MS)/1000 ) +#define AP_INPUT_SAMPLES_MIC_DELAY_CHAN_CNT ( (appconfINPUT_SAMPLES_MIC_DELAY_MS > 0) ? AEC_MAX_Y_CHANNELS : AEC_MAX_X_CHANNELS ) +#define AP_INPUT_SAMPLES_MIC_DELAY_SIZE_CHAN ( AP_INPUT_SAMPLES_MIC_DELAY_SIZE_PER_CHAN * AP_INPUT_SAMPLES_MIC_DELAY_CHAN_CNT ) +#define AP_INPUT_SAMPLES_MIC_DELAY_SIZE_CUR_FRAME_WORDS ( AP_INPUT_SAMPLES_MIC_DELAY_CHAN_CNT * appconfAUDIO_PIPELINE_FRAME_ADVANCE) +#define AP_INPUT_SAMPLES_MIC_DELAY_CUR_FRAME_BYTES ( AP_INPUT_SAMPLES_MIC_DELAY_SIZE_CUR_FRAME_WORDS * sizeof(int32_t)) +#define AP_INPUT_SAMPLES_MIC_DELAY_BUF_SIZE_BYTES ( AP_INPUT_SAMPLES_MIC_DELAY_SIZE_CHAN * sizeof(int32_t) ) + +void aec_process_frame_1thread( + aec_state_t *main_state, + aec_state_t *shadow_state, + int32_t (*output_main)[AEC_FRAME_ADVANCE], + int32_t (*output_shadow)[AEC_FRAME_ADVANCE], + const int32_t (*y_data)[AEC_FRAME_ADVANCE], + const int32_t (*x_data)[AEC_FRAME_ADVANCE]); + +#endif /* AUDIO_PIPELINE_DSP_H_ */ diff --git a/examples/stlp/audio_pipeline/src/fixed_delay/audio_pipeline_t0.c b/examples/stlp/audio_pipeline/src/fixed_delay/audio_pipeline_t0.c new file mode 100644 index 00000000..53c77806 --- /dev/null +++ b/examples/stlp/audio_pipeline/src/fixed_delay/audio_pipeline_t0.c @@ -0,0 +1,193 @@ +// Copyright (c) 2022 XMOS LIMITED. This Software is subject to the terms of the +// XMOS Public License: Version 1 + +/* STD headers */ +#include +#include +#include + +/* FreeRTOS headers */ +#include "FreeRTOS.h" +#include "task.h" +#include "timers.h" +#include "queue.h" +#include "stream_buffer.h" + +/* Library headers */ +#include "generic_pipeline.h" +#include "aec_api.h" +#include "agc_api.h" +#include "ic_api.h" +#include "ns_api.h" +#include "vnr_features_api.h" +#include "vnr_inference_api.h" + +/* App headers */ +#include "app_conf.h" +#include "audio_pipeline.h" +#include "audio_pipeline_dsp.h" + +#if appconfAUDIO_PIPELINE_FRAME_ADVANCE != 240 +#error This pipeline is only configured for 240 frame advance +#endif + +#define VNR_AGC_THRESHOLD (0.5) + +#if ON_TILE(0) +static ic_stage_ctx_t DWORD_ALIGNED ic_stage_state = {}; +static vnr_pred_stage_ctx_t DWORD_ALIGNED vnr_pred_stage_state = {}; +static ns_stage_ctx_t DWORD_ALIGNED ns_stage_state = {}; +static agc_stage_ctx_t DWORD_ALIGNED agc_stage_state = {}; + +static void *audio_pipeline_input_i(void *input_app_data) +{ + frame_data_t *frame_data; + + frame_data = pvPortMalloc(sizeof(frame_data_t)); + memset(frame_data, 0x00, sizeof(frame_data_t)); + + size_t bytes_received = 0; + bytes_received = rtos_intertile_rx_len( + intertile_ctx, + appconfAUDIOPIPELINE_PORT, + portMAX_DELAY); + + xassert(bytes_received == sizeof(frame_data_t)); + + rtos_intertile_rx_data( + intertile_ctx, + frame_data, + bytes_received); + + return frame_data; +} + +static int audio_pipeline_output_i(frame_data_t *frame_data, + void *output_app_data) +{ + return audio_pipeline_output(output_app_data, + (int32_t **)frame_data->samples, + 6, + appconfAUDIO_PIPELINE_FRAME_ADVANCE); +} + +static void stage_vnr_and_ic(frame_data_t *frame_data) +{ +#if appconfAUDIO_PIPELINE_SKIP_IC_AND_VAD +#else + int32_t DWORD_ALIGNED ic_output[appconfAUDIO_PIPELINE_FRAME_ADVANCE]; + ic_filter(&ic_stage_state.state, + frame_data->samples[0], + frame_data->samples[1], + ic_output); + + // VNR + bfp_s32_t feature_patch; + int32_t feature_patch_data[VNR_PATCH_WIDTH * VNR_MEL_FILTERS]; + float_s32_t ie_output; + vnr_pred_state_t *vnr_pred_state = &vnr_pred_stage_state.vnr_pred_state; + + vnr_extract_features(&vnr_pred_state->feature_state[0], &feature_patch, + feature_patch_data, &ic_stage_state.state.Y_bfp[0]); + vnr_inference(&ie_output, &feature_patch); + vnr_pred_state->input_vnr_pred = float_s32_ema(vnr_pred_state->input_vnr_pred, ie_output, vnr_pred_state->pred_alpha_q30); + + vnr_extract_features(&vnr_pred_state->feature_state[1], &feature_patch, + feature_patch_data, &ic_stage_state.state.Error_bfp[0]); + vnr_inference(&ie_output, &feature_patch); + vnr_pred_state->output_vnr_pred = float_s32_ema(vnr_pred_state->output_vnr_pred, ie_output, vnr_pred_state->pred_alpha_q30); + + float_s32_t agc_vnr_threshold = f32_to_float_s32(VNR_AGC_THRESHOLD); + frame_data->vnr_pred_flag = float_s32_gt(vnr_pred_stage_state.vnr_pred_state.output_vnr_pred, agc_vnr_threshold); + + ic_adapt(&ic_stage_state.state, vnr_pred_stage_state.vnr_pred_state.input_vnr_pred); + + /* Intentionally ignoring comms ch from here on out */ + memcpy(frame_data->samples, ic_output, appconfAUDIO_PIPELINE_FRAME_ADVANCE * sizeof(int32_t)); +#endif +} + +static void stage_ns(frame_data_t *frame_data) +{ +#if appconfAUDIO_PIPELINE_SKIP_NS +#else + int32_t DWORD_ALIGNED ns_output[appconfAUDIO_PIPELINE_FRAME_ADVANCE]; + configASSERT(NS_FRAME_ADVANCE == appconfAUDIO_PIPELINE_FRAME_ADVANCE); + ns_process_frame( + &ns_stage_state.state, + ns_output, + frame_data->samples[0]); + memcpy(frame_data->samples, ns_output, appconfAUDIO_PIPELINE_FRAME_ADVANCE * sizeof(int32_t)); +#endif +} + +static void stage_agc(frame_data_t *frame_data) +{ +#if appconfAUDIO_PIPELINE_SKIP_AGC +#else + int32_t DWORD_ALIGNED agc_output[appconfAUDIO_PIPELINE_FRAME_ADVANCE]; + configASSERT(AGC_FRAME_ADVANCE == appconfAUDIO_PIPELINE_FRAME_ADVANCE); + + agc_stage_state.md.vnr_flag = frame_data->vnr_pred_flag; + agc_stage_state.md.aec_ref_power = frame_data->max_ref_energy; + agc_stage_state.md.aec_corr_factor = frame_data->aec_corr_factor; + + agc_process_frame( + &agc_stage_state.state, + agc_output, + frame_data->samples[0], + &agc_stage_state.md); + memcpy(frame_data->samples, agc_output, appconfAUDIO_PIPELINE_FRAME_ADVANCE * sizeof(int32_t)); +#endif +} + +static void initialize_pipeline_stages(void) +{ + ic_init(&ic_stage_state.state); + + vnr_pred_state_t *vnr_pred_state = &vnr_pred_stage_state.vnr_pred_state; + vnr_feature_state_init(&vnr_pred_state->feature_state[0]); + vnr_feature_state_init(&vnr_pred_state->feature_state[1]); + vnr_inference_init(); + vnr_pred_state->pred_alpha_q30 = Q30(0.97); + vnr_pred_state->input_vnr_pred = f32_to_float_s32(0.5); + vnr_pred_state->output_vnr_pred = f32_to_float_s32(0.5); + + ns_init(&ns_stage_state.state); + + agc_init(&agc_stage_state.state, &AGC_PROFILE_ASR); + agc_stage_state.md.aec_ref_power = AGC_META_DATA_NO_AEC; + agc_stage_state.md.aec_corr_factor = AGC_META_DATA_NO_AEC; +} + +void audio_pipeline_init( + void *input_app_data, + void *output_app_data) +{ + const int stage_count = 3; + + const pipeline_stage_t stages[] = { + (pipeline_stage_t)stage_vnr_and_ic, + (pipeline_stage_t)stage_ns, + (pipeline_stage_t)stage_agc, + }; + + const configSTACK_DEPTH_TYPE stage_stack_sizes[] = { + configMINIMAL_STACK_SIZE + RTOS_THREAD_STACK_SIZE(stage_vnr_and_ic) + RTOS_THREAD_STACK_SIZE(audio_pipeline_input_i), + configMINIMAL_STACK_SIZE + RTOS_THREAD_STACK_SIZE(stage_ns), + configMINIMAL_STACK_SIZE + RTOS_THREAD_STACK_SIZE(stage_agc) + RTOS_THREAD_STACK_SIZE(audio_pipeline_output_i), + }; + + initialize_pipeline_stages(); + + generic_pipeline_init((pipeline_input_t)audio_pipeline_input_i, + (pipeline_output_t)audio_pipeline_output_i, + input_app_data, + output_app_data, + stages, + (const size_t*) stage_stack_sizes, + appconfAUDIO_PIPELINE_TASK_PRIORITY, + stage_count); +} + +#endif /* ON_TILE(0)*/ diff --git a/examples/stlp/audio_pipeline/src/fixed_delay/audio_pipeline_t1.c b/examples/stlp/audio_pipeline/src/fixed_delay/audio_pipeline_t1.c new file mode 100644 index 00000000..272e98fa --- /dev/null +++ b/examples/stlp/audio_pipeline/src/fixed_delay/audio_pipeline_t1.c @@ -0,0 +1,177 @@ +// Copyright (c) 2022 XMOS LIMITED. This Software is subject to the terms of the +// XMOS Public License: Version 1 + +/* STD headers */ +#include +#include +#include + +/* FreeRTOS headers */ +#include "FreeRTOS.h" +#include "task.h" +#include "timers.h" +#include "queue.h" +#include "stream_buffer.h" + +/* Library headers */ +#include "generic_pipeline.h" + +/* App headers */ +#include "app_conf.h" +#include "audio_pipeline.h" +#include "audio_pipeline_dsp.h" + +#if appconfAUDIO_PIPELINE_FRAME_ADVANCE != 240 +#error This pipeline is only configured for 240 frame advance +#endif + +#if ON_TILE(1) +#if appconfINPUT_SAMPLES_MIC_DELAY_MS != 0 +static stage_delay_ctx_t DWORD_ALIGNED delay_buf_state = {}; +#endif +static aec_ctx_t DWORD_ALIGNED aec_state = {}; + + +static void *audio_pipeline_input_i(void *input_app_data) +{ + frame_data_t *frame_data; + + frame_data = pvPortMalloc(sizeof(frame_data_t)); + memset(frame_data, 0x00, sizeof(frame_data_t)); + + audio_pipeline_input(input_app_data, + (int32_t **)frame_data->aec_reference_audio_samples, + 4, + appconfAUDIO_PIPELINE_FRAME_ADVANCE); + + frame_data->vnr_pred_flag = 0; + + memcpy(frame_data->samples, frame_data->mic_samples_passthrough, sizeof(frame_data->samples)); + + return frame_data; +} + +static int audio_pipeline_output_i(frame_data_t *frame_data, + void *output_app_data) +{ + rtos_intertile_tx(intertile_ctx, + appconfAUDIOPIPELINE_PORT, + frame_data, + sizeof(frame_data_t)); + return AUDIO_PIPELINE_FREE_FRAME; +} + +static void stage_delay(frame_data_t *frame_data) +{ +#if appconfAUDIO_PIPELINE_SKIP_STATIC_DELAY +#else +#if (appconfINPUT_SAMPLES_MIC_DELAY_MS > 0) /* Delay mics */ + size_t bytes_sent = xStreamBufferSend( + delay_buf_state.delay_buf, + &frame_data->samples, + AP_INPUT_SAMPLES_MIC_DELAY_CUR_FRAME_BYTES, + 0); + + configASSERT(bytes_sent == AP_INPUT_SAMPLES_MIC_DELAY_CUR_FRAME_BYTES); + + if (xStreamBufferBytesAvailable(delay_buf_state.delay_buf) > AP_INPUT_SAMPLES_MIC_DELAY_BUF_SIZE_BYTES) { + size_t bytes_rx = xStreamBufferReceive( + delay_buf_state.delay_buf, + &frame_data->samples, + AP_INPUT_SAMPLES_MIC_DELAY_CUR_FRAME_BYTES, + 0); + + configASSERT(bytes_rx == AP_INPUT_SAMPLES_MIC_DELAY_CUR_FRAME_BYTES); + } +#elif (appconfINPUT_SAMPLES_MIC_DELAY_MS < 0) /* Delay Ref*/ + size_t bytes_sent = xStreamBufferSend( + delay_buf_state.delay_buf, + &frame_data->aec_reference_audio_samples, + AP_INPUT_SAMPLES_MIC_DELAY_CUR_FRAME_BYTES, + 0); + + configASSERT(bytes_sent == AP_INPUT_SAMPLES_MIC_DELAY_CUR_FRAME_BYTES); + + if (xStreamBufferBytesAvailable(delay_buf_state.delay_buf) > AP_INPUT_SAMPLES_MIC_DELAY_BUF_SIZE_BYTES) { + size_t bytes_rx = xStreamBufferReceive( + delay_buf_state.delay_buf, + &frame_data->aec_reference_audio_samples, + AP_INPUT_SAMPLES_MIC_DELAY_CUR_FRAME_BYTES, + 0); + + configASSERT(bytes_rx == AP_INPUT_SAMPLES_MIC_DELAY_CUR_FRAME_BYTES); + } +#else /* Delay None */ +#endif +#endif /* appconfAUDIO_PIPELINE_SKIP_DELAY */ +} + +static void stage_aec(frame_data_t *frame_data) +{ +#if appconfAUDIO_PIPELINE_SKIP_AEC +#else + int32_t DWORD_ALIGNED stage1_output[AEC_MAX_Y_CHANNELS][appconfAUDIO_PIPELINE_FRAME_ADVANCE]; + + aec_process_frame_1thread( + &aec_state.aec_main_state, + &aec_state.aec_shadow_state, + stage1_output, + NULL, + frame_data->samples, + frame_data->aec_reference_audio_samples); + + frame_data->max_ref_energy = aec_calc_max_input_energy( + frame_data->aec_reference_audio_samples, + aec_state.aec_main_state.shared_state->num_x_channels); + frame_data->aec_corr_factor = aec_calc_corr_factor(&aec_state.aec_main_state, 0); + memcpy(frame_data->samples, stage1_output, AEC_MAX_Y_CHANNELS * appconfAUDIO_PIPELINE_FRAME_ADVANCE * sizeof(int32_t)); +#endif +} + +static void initialize_pipeline_stages(void) +{ +#if (appconfINPUT_SAMPLES_MIC_DELAY_MS != 0) + configASSERT(AP_INPUT_SAMPLES_MIC_DELAY_BUF_SIZE_BYTES > 0); + delay_buf_state.delay_buf = xStreamBufferCreate((size_t)AP_INPUT_SAMPLES_MIC_DELAY_BUF_SIZE_BYTES + AP_INPUT_SAMPLES_MIC_DELAY_CUR_FRAME_BYTES, 0); + configASSERT(delay_buf_state.delay_buf); +#endif + + aec_init(&aec_state.aec_main_state, + &aec_state.aec_shadow_state, + &aec_state.aec_shared_state, + &aec_state.aec_main_memory_pool[0], + &aec_state.aec_shadow_memory_pool[0], + AEC_MAX_Y_CHANNELS, + AEC_MAX_X_CHANNELS, + AEC_MAIN_FILTER_PHASES, + AEC_SHADOW_FILTER_PHASES); +} + +void audio_pipeline_init( + void *input_app_data, + void *output_app_data) +{ + const int stage_count = 2; + + const pipeline_stage_t stages[] = { + (pipeline_stage_t)stage_delay, + (pipeline_stage_t)stage_aec, + }; + + const configSTACK_DEPTH_TYPE stage_stack_sizes[] = { + configMINIMAL_STACK_SIZE + RTOS_THREAD_STACK_SIZE(stage_delay) + RTOS_THREAD_STACK_SIZE(audio_pipeline_input_i), + configMINIMAL_STACK_SIZE + RTOS_THREAD_STACK_SIZE(stage_aec) + RTOS_THREAD_STACK_SIZE(audio_pipeline_output_i), + }; + + initialize_pipeline_stages(); + + generic_pipeline_init((pipeline_input_t)audio_pipeline_input_i, + (pipeline_output_t)audio_pipeline_output_i, + input_app_data, + output_app_data, + stages, + (const size_t*) stage_stack_sizes, + appconfAUDIO_PIPELINE_TASK_PRIORITY, + stage_count); +} +#endif /* ON_TILE(1) */ diff --git a/examples/stlp/src/app_conf.h b/examples/stlp/src/app_conf.h index 4a6c3283..5d015cc6 100644 --- a/examples/stlp/src/app_conf.h +++ b/examples/stlp/src/app_conf.h @@ -28,6 +28,12 @@ /* If in channel sample format, appconfAUDIO_PIPELINE_FRAME_ADVANCE == MIC_ARRAY_CONFIG_SAMPLES_PER_FRAME*/ #define appconfAUDIO_PIPELINE_FRAME_ADVANCE MIC_ARRAY_CONFIG_SAMPLES_PER_FRAME +/** + * A positive delay will delay mics + * A negative delay will delay ref + */ +#define appconfINPUT_SAMPLES_MIC_DELAY_MS 0 + #ifdef appconfPIPELINE_BYPASS #define appconfAUDIO_PIPELINE_SKIP_STATIC_DELAY 1 #define appconfAUDIO_PIPELINE_SKIP_AEC 1 diff --git a/examples/stlp/src/main.c b/examples/stlp/src/main.c index 6520acd0..54264a95 100644 --- a/examples/stlp/src/main.c +++ b/examples/stlp/src/main.c @@ -103,7 +103,7 @@ void audio_pipeline_input(void *input_app_data, } if (mic_from_usb) { - ch_count += 2; /* mic frames */ + ch_cnt += 2; /* mic frames */ } /* @@ -113,7 +113,7 @@ void audio_pipeline_input(void *input_app_data, usb_audio_recv(intertile_ctx, frame_count, usb_mic_audio_frame, - ch_count); + ch_cnt); #endif #if appconfI2S_ENABLED diff --git a/examples/stlp/stlp.cmake b/examples/stlp/stlp.cmake index 52b80090..a51f87ca 100644 --- a/examples/stlp/stlp.cmake +++ b/examples/stlp/stlp.cmake @@ -46,18 +46,38 @@ set(APP_COMMON_LINK_LIBRARIES sdk::lib_src ) -set(STLP_PIPELINES - adec - adec_altarch -) +#********************** +# Pipeline Options +# By default only these targets are created: +# example_stlp_int_fixed_delay +# example_stlp_ua_adec +#********************** +option(ENABLE_ALL_STLP_PIPELINES "Create all STLP pipeline configurations" OFF) + +if(ENABLE_ALL_STLP_PIPELINES) + set(STLP_PIPELINES_INT + fixed_delay + adec + adec_altarch + ) + + set(STLP_PIPELINES_UA + fixed_delay + adec + adec_altarch + ) +else() + set(STLP_PIPELINES_INT + fixed_delay + ) + + set(STLP_PIPELINES_UA + adec + ) +endif() #********************** # XMOS Example Design Targets #********************** include(${CMAKE_CURRENT_LIST_DIR}/stlp_int.cmake) include(${CMAKE_CURRENT_LIST_DIR}/stlp_ua.cmake) - -#********************** -# XMOS Development Targets -#********************** -include(${CMAKE_CURRENT_LIST_DIR}/stlp_dev.cmake) diff --git a/examples/stlp/stlp_dev.cmake b/examples/stlp/stlp_dev.cmake deleted file mode 100644 index 5e8f4d33..00000000 --- a/examples/stlp/stlp_dev.cmake +++ /dev/null @@ -1,210 +0,0 @@ - -set(STLP_DEV_PIPELINES - adec - adec_altarch -) - -option(DEBUG_STLP_USB_MIC_INPUT "Enable stlp usb mic input" OFF) - -set(STLP_UA_COMPILE_DEFINITIONS - ${APP_COMPILE_DEFINITIONS} - appconfI2S_ENABLED=0 - appconfUSB_ENABLED=1 - appconfAEC_REF_DEFAULT=appconfAEC_REF_USB -) - -set(STLP_INT_COMPILE_DEFINITIONS - ${APP_COMPILE_DEFINITIONS} - appconfI2S_ENABLED=1 - appconfUSB_ENABLED=0 - appconfAEC_REF_DEFAULT=appconfAEC_REF_I2S -) - -if(DEBUG_STLP_USB_MIC_INPUT) - list(APPEND STLP_UA_COMPILE_DEFINITIONS appconfMIC_SRC_DEFAULT=appconfMIC_SRC_USB) - list(APPEND STLP_UA_COMPILE_DEFINITIONS appconfUSB_AUDIO_TESTING=appconfUSB_AUDIO_TESTING) -endif() - -foreach(STLP_AP ${STLP_PIPELINES}) - #********************** - # Tile Targets - #********************** - set(TARGET_NAME tile0_example_stlp_dev_ua_${STLP_AP}) - add_executable(${TARGET_NAME} EXCLUDE_FROM_ALL) - target_sources(${TARGET_NAME} PUBLIC ${APP_SOURCES}) - target_include_directories(${TARGET_NAME} PUBLIC ${APP_INCLUDES}) - target_compile_definitions(${TARGET_NAME} - PUBLIC - ${STLP_UA_COMPILE_DEFINITIONS} - THIS_XCORE_TILE=0 - ) - target_compile_options(${TARGET_NAME} PRIVATE ${APP_COMPILER_FLAGS}) - target_link_libraries(${TARGET_NAME} - PUBLIC - ${APP_COMMON_LINK_LIBRARIES} - sln_voice::app::stlp::xcore_ai_explorer - sln_voice::app::stlp::ap::${STLP_AP} - ) - target_link_options(${TARGET_NAME} PRIVATE ${APP_LINK_OPTIONS}) - unset(TARGET_NAME) - - set(TARGET_NAME tile1_example_stlp_dev_ua_${STLP_AP}) - add_executable(${TARGET_NAME} EXCLUDE_FROM_ALL) - target_sources(${TARGET_NAME} PUBLIC ${APP_SOURCES}) - target_include_directories(${TARGET_NAME} PUBLIC ${APP_INCLUDES}) - target_compile_definitions(${TARGET_NAME} - PUBLIC - ${STLP_UA_COMPILE_DEFINITIONS} - THIS_XCORE_TILE=1 - ) - target_compile_options(${TARGET_NAME} PRIVATE ${APP_COMPILER_FLAGS}) - target_link_libraries(${TARGET_NAME} - PUBLIC - ${APP_COMMON_LINK_LIBRARIES} - sln_voice::app::stlp::xcore_ai_explorer - sln_voice::app::stlp::ap::${STLP_AP} - ) - target_link_options(${TARGET_NAME} PRIVATE ${APP_LINK_OPTIONS}) - unset(TARGET_NAME) - - #********************** - # Merge binaries - #********************** - merge_binaries(example_stlp_dev_ua_${STLP_AP} tile0_example_stlp_dev_ua_${STLP_AP} tile1_example_stlp_dev_ua_${STLP_AP} 1) - - #********************** - # Create run and debug targets - #********************** - create_run_target(example_stlp_dev_ua_${STLP_AP}) - create_debug_target(example_stlp_dev_ua_${STLP_AP}) - create_flash_app_target(example_stlp_dev_ua_${STLP_AP}) - - #********************** - # Filesystem support targets - #********************** - if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL Windows) - add_custom_command( - OUTPUT example_stlp_dev_fat_ua_${STLP_AP}.fs - COMMAND ${CMAKE_COMMAND} -E make_directory %temp%/fatmktmp/fs - COMMAND ${CMAKE_COMMAND} -E copy demo.txt %temp%/fatmktmp/fs/demo.txt - COMMAND fatfs_mkimage --input=%temp%/fatmktmp --output=example_stlp_dev_fat_ua_${STLP_AP}.fs - BYPRODUCTS %temp%/fatmktmp - DEPENDS example_stlp_dev_ua_${STLP_AP} - COMMENT - "Create filesystem" - WORKING_DIRECTORY - ${CMAKE_CURRENT_LIST_DIR}/filesystem_support - VERBATIM - ) - else() - add_custom_command( - OUTPUT example_stlp_dev_fat_ua_${STLP_AP}.fs - COMMAND bash -c "tmp_dir=$(mktemp -d) && fat_mnt_dir=$tmp_dir && mkdir -p $fat_mnt_dir && mkdir $fat_mnt_dir/fs && cp ./demo.txt $fat_mnt_dir/fs/demo.txt && fatfs_mkimage --input=$tmp_dir --output=example_stlp_dev_fat_ua_${STLP_AP}.fs" - DEPENDS example_stlp_dev_ua_${STLP_AP} - COMMENT - "Create filesystem" - WORKING_DIRECTORY - ${CMAKE_CURRENT_LIST_DIR}/filesystem_support - VERBATIM - ) - endif() - - add_custom_target(flash_fs_example_stlp_dev_ua_${STLP_AP} - COMMAND xflash --quad-spi-clock 50MHz --factory example_stlp_dev_ua_${STLP_AP}.xe --boot-partition-size 0x100000 --data ${CMAKE_CURRENT_LIST_DIR}/filesystem_support/example_stlp_dev_fat_ua_${STLP_AP}.fs - DEPENDS example_stlp_dev_fat_ua_${STLP_AP}.fs - COMMENT - "Flash filesystem" - VERBATIM - ) - - #********************** - # Tile Targets - #********************** - set(TARGET_NAME tile0_example_stlp_dev_int_${STLP_AP}) - add_executable(${TARGET_NAME} EXCLUDE_FROM_ALL) - target_sources(${TARGET_NAME} PUBLIC ${APP_SOURCES}) - target_include_directories(${TARGET_NAME} PUBLIC ${APP_INCLUDES}) - target_compile_definitions(${TARGET_NAME} - PUBLIC - ${STLP_INT_COMPILE_DEFINITIONS} - THIS_XCORE_TILE=0 - ) - target_compile_options(${TARGET_NAME} PRIVATE ${APP_COMPILER_FLAGS}) - target_link_libraries(${TARGET_NAME} - PUBLIC - ${APP_COMMON_LINK_LIBRARIES} - sln_voice::app::stlp::xcore_ai_explorer - sln_voice::app::stlp::ap::${STLP_AP} - ) - target_link_options(${TARGET_NAME} PRIVATE ${APP_LINK_OPTIONS}) - unset(TARGET_NAME) - - set(TARGET_NAME tile1_example_stlp_dev_int_${STLP_AP}) - add_executable(${TARGET_NAME} EXCLUDE_FROM_ALL) - target_sources(${TARGET_NAME} PUBLIC ${APP_SOURCES}) - target_include_directories(${TARGET_NAME} PUBLIC ${APP_INCLUDES}) - target_compile_definitions(${TARGET_NAME} - PUBLIC - ${STLP_INT_COMPILE_DEFINITIONS} - THIS_XCORE_TILE=1 - ) - target_compile_options(${TARGET_NAME} PRIVATE ${APP_COMPILER_FLAGS}) - target_link_libraries(${TARGET_NAME} - PUBLIC - ${APP_COMMON_LINK_LIBRARIES} - sln_voice::app::stlp::xcore_ai_explorer - sln_voice::app::stlp::ap::${STLP_AP} - ) - target_link_options(${TARGET_NAME} PRIVATE ${APP_LINK_OPTIONS}) - unset(TARGET_NAME) - - #********************** - # Merge binaries - #********************** - merge_binaries(example_stlp_dev_int_${STLP_AP} tile0_example_stlp_dev_int_${STLP_AP} tile1_example_stlp_dev_int_${STLP_AP} 1) - - #********************** - # Create run and debug targets - #********************** - create_run_target(example_stlp_dev_int_${STLP_AP}) - create_debug_target(example_stlp_dev_int_${STLP_AP}) - create_flash_app_target(example_stlp_dev_int_${STLP_AP}) - - #********************** - # Filesystem support targets - #********************** - if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL Windows) - add_custom_command( - OUTPUT example_stlp_dev_fat_int_${STLP_AP}.fs - COMMAND ${CMAKE_COMMAND} -E make_directory %temp%/fatmktmp/fs - COMMAND ${CMAKE_COMMAND} -E copy demo.txt %temp%/fatmktmp/fs/demo.txt - COMMAND fatfs_mkimage --input=%temp%/fatmktmp --output=example_stlp_dev_fat_int_${STLP_AP}.fs - BYPRODUCTS %temp%/fatmktmp - DEPENDS example_stlp_dev_int_${STLP_AP} - COMMENT - "Create filesystem" - WORKING_DIRECTORY - ${CMAKE_CURRENT_LIST_DIR}/filesystem_support - VERBATIM - ) - else() - add_custom_command( - OUTPUT example_stlp_dev_fat_int_${STLP_AP}.fs - COMMAND bash -c "tmp_dir=$(mktemp -d) && fat_mnt_dir=$tmp_dir && mkdir -p $fat_mnt_dir && mkdir $fat_mnt_dir/fs && cp ./demo.txt $fat_mnt_dir/fs/demo.txt && fatfs_mkimage --input=$tmp_dir --output=example_stlp_dev_fat_int_${STLP_AP}.fs" - DEPENDS example_stlp_dev_int_${STLP_AP} - COMMENT - "Create filesystem" - WORKING_DIRECTORY - ${CMAKE_CURRENT_LIST_DIR}/filesystem_support - VERBATIM - ) - endif() - - add_custom_target(flash_fs_example_stlp_dev_int_${STLP_AP} - COMMAND xflash --quad-spi-clock 50MHz --factory example_stlp_dev_int_${STLP_AP}.xe --boot-partition-size 0x100000 --data ${CMAKE_CURRENT_LIST_DIR}/filesystem_support/example_stlp_dev_fat_int_${STLP_AP}.fs - DEPENDS example_stlp_dev_fat_int_${STLP_AP}.fs - COMMENT - "Flash filesystem" - VERBATIM - ) -endforeach() diff --git a/examples/stlp/stlp_int.cmake b/examples/stlp/stlp_int.cmake index 9dc2c548..94b91f37 100644 --- a/examples/stlp/stlp_int.cmake +++ b/examples/stlp/stlp_int.cmake @@ -11,7 +11,7 @@ set(STLP_INT_COMPILE_DEFINITIONS MIC_ARRAY_CONFIG_MCLK_FREQ=12288000 ) -foreach(STLP_AP ${STLP_PIPELINES}) +foreach(STLP_AP ${STLP_PIPELINES_INT}) #********************** # Tile Targets #********************** diff --git a/examples/stlp/stlp_ua.cmake b/examples/stlp/stlp_ua.cmake index 9b5c0ca3..ba4da195 100644 --- a/examples/stlp/stlp_ua.cmake +++ b/examples/stlp/stlp_ua.cmake @@ -26,7 +26,7 @@ if(DEBUG_STLP_USB_MIC_INPUT_PIPELINE_BYPASS) endif() query_tools_version() -foreach(STLP_AP ${STLP_PIPELINES}) +foreach(STLP_AP ${STLP_PIPELINES_UA}) #********************** # Tile Targets #********************** diff --git a/tools/ci/build_examples.sh b/tools/ci/build_examples.sh index 41445af0..73686448 100644 --- a/tools/ci/build_examples.sh +++ b/tools/ci/build_examples.sh @@ -23,8 +23,10 @@ examples=( "audio_mux example_audio_mux No XCORE_AI_EXPLORER xmos_cmake_toolchain/xs3a.cmake" "stlp_int_adec example_stlp_int_adec Yes XK_VOICE_L71 xmos_cmake_toolchain/xs3a.cmake" "stlp_int_adec_altarch example_stlp_int_adec_altarch Yes XK_VOICE_L71 xmos_cmake_toolchain/xs3a.cmake" + "stlp_int_fixed_delay example_stlp_int_fixed_delay Yes XK_VOICE_L71 xmos_cmake_toolchain/xs3a.cmake" "stlp_ua_adec example_stlp_ua_adec Yes XK_VOICE_L71 xmos_cmake_toolchain/xs3a.cmake" "stlp_ua_adec_altarch example_stlp_ua_adec_altarch Yes XK_VOICE_L71 xmos_cmake_toolchain/xs3a.cmake" + "stlp_ua_fixed_delay example_stlp_ua_fixed_delay Yes XK_VOICE_L71 xmos_cmake_toolchain/xs3a.cmake" "ffd example_ffd Yes XK_VOICE_L71 xmos_cmake_toolchain/xs3a.cmake" ) @@ -43,7 +45,7 @@ for ((i = 0; i < ${#examples[@]}; i += 1)); do (cd ${path}; rm -rf build_${board}) (cd ${path}; mkdir -p build_${board}) - (cd ${path}/build_${board}; log_errors cmake ../ -DCMAKE_TOOLCHAIN_FILE=${toolchain_file} -DBOARD=${board}; log_errors make ${app_target} -j) + (cd ${path}/build_${board}; log_errors cmake ../ -DCMAKE_TOOLCHAIN_FILE=${toolchain_file} -DBOARD=${board} -DENABLE_ALL_STLP_PIPELINES=1; log_errors make ${app_target} -j) (cd ${path}/build_${board}; cp ${app_target}.xe ${DIST_DIR}) if [ "$run_fs_target" = "Yes" ]; then echo '======================================================' diff --git a/tools/ci/build_tests.sh b/tools/ci/build_tests.sh index a43a781b..a7a5696b 100644 --- a/tools/ci/build_tests.sh +++ b/tools/ci/build_tests.sh @@ -40,6 +40,6 @@ for ((i = 0; i < ${#examples[@]}; i += 1)); do (cd ${path}; rm -rf build_${board}) (cd ${path}; mkdir -p build_${board}) - (cd ${path}/build_${board}; log_errors cmake ../ -DCMAKE_TOOLCHAIN_FILE=${toolchain_file} -DBOARD=${board} ${optional_cache_entry}; log_errors make ${make_target} -j) + (cd ${path}/build_${board}; log_errors cmake ../ -DCMAKE_TOOLCHAIN_FILE=${toolchain_file} -DBOARD=${board} -DENABLE_ALL_STLP_PIPELINES=1 ${optional_cache_entry}; log_errors make ${make_target} -j) (cd ${path}/build_${board}; cp ${make_target}.xe ${DIST_DIR}/example_${name}_test.xe) done