Hide navigation sidebar
Hide table of contents sidebar
Skip to content
Back to top
Toggle table of contents sidebar

# AEC

## AEC API Functions

group AEC API Functions

  Functions

  void aec_init(
    aec_state_t *aec_state,
    unsigned num_y_channels,
    unsigned num_x_channels,
    unsigned num_main_filter_phases,
    unsigned num_shadow_filter_phases,
    const aec_task_distribution_t *tdist,
  )

    Initialise the AEC for a given configuration.

    This initializes the aggregated AEC state for the supplied runtime configuration (number of channels and filter phases). Call once at startup, and again whenever the AEC configuration changes.

    During initialisation, `aec_init()` binds the AEC internal BFP structures to memory provided by the AEC memory pools. The amount of memory consumed depends on the runtime configuration.

    Preconditions

      The runtime configuration must be a subset of compile-time limits. This means:

      - num_y_channels <= AEC_MAX_Y_CHANNELS

      - num_x_channels <= AEC_MAX_X_CHANNELS

      - Total phase-pool demand should not exceed pool capacity, i.e.: (num_y_channels * num_x_channels * num_main_filter_phases) + (num_x_channels * num_main_filter_phases) <= (AEC_MAX_Y_CHANNELS * AEC_MAX_X_CHANNELS * AEC_MAIN_FILTER_PHASES) + (AEC_MAX_X_CHANNELS * AEC_MAIN_FILTER_PHASES)

      - and (num_y_channels * num_x_channels * num_shadow_filter_phases) <= (AEC_MAX_Y_CHANNELS * AEC_MAX_X_CHANNELS * AEC_SHADOW_FILTER_PHASES)

    Example

          aec_state_t aec;
          unsigned y_chans = 2, x_chans = 2;
          unsigned main_phases = 10, shadow_phases = 5;

          // Use a library-provided default schedule (2ch, 1 thread)
          aec_init(&aec, y_chans, x_chans, main_phases, shadow_phases, &aec_tdist_chans2_threads1);

          // Or, passing a custom schedule generated via setting `AEC_SCHEDULE_CONFIG` in CMake
          // extern aec_task_distribution_t tdist;
          // aec_init(&aec, y_chans, x_chans, main_phases, shadow_phases, &tdist);

    Note

    The caller must provide memory pools sized for the maximum compile-time AEC configuration (AEC_MAX_Y_CHANNELS, AEC_MAX_X_CHANNELS, AEC_MAIN_FILTER_PHASES, AEC_SHADOW_FILTER_PHASES). `aec_init()` assigns memory from these pools based on the runtime configuration supplied. The memory pools must remain valid for the lifetime of the AEC instance. Any change to the number of channels or filter phases requires calling `aec_init()` again to rebind internal state to the memory pools. See aec_memory_pool_t and aec_shadow_filt_memory_pool_t for details on memory pool sizing and usage.

    Parameters:

      - aec_state – [inout] AEC state object

      - num_y_channels – [in] Number of microphone input channels

      - num_x_channels – [in] Number of reference input channels

      - num_main_filter_phases – [in] Number of phases in the main filter

      - num_shadow_filter_phases – [in] Number of phases in the shadow filter

      - tdist – [in] Work distribution to use for scheduling AEC work across hardware threads in `aec_process_frame()`. Use a library default for 2ch, 1 or 2 threads, otherwise provide an application-defined schedule.

  void aec_process_frame(
    aec_state_t *aec_state,
    int32_t (*output_main)[AEC_FRAME_ADVANCE],
    int32_t (*output_shadow)[AEC_FRAME_ADVANCE],
    int32_t (*y_data)[AEC_FRAME_ADVANCE],
    int32_t (*x_data)[AEC_FRAME_ADVANCE],
  )

    Process a frame of microphone samples using the AEC.

    This function performs acoustic echo cancellation on a frame of input microphone samples. It uses the input reference data frame to model the room echo characteristics and adapt the internal main and shadow filters.

    Parameters:

      - aec_state – [inout] AEC state structure

      - output_main – [inout] Output from processing the mic input through the main filter

      - output_shadow – [inout] Output from processing the mic input through the shadow filter

      - y_data – [in] Input microphone data frame

      - x_data – [in] Input reference data frame

  uint32_t aec_detect_input_activity(
    const int32_t (*input_data)[AEC_FRAME_ADVANCE],
    float_s32_t active_threshold,
    int32_t num_channels,
  )

    Detect activity on input channels.

    This function implements a quick check for detecting activity on the input channels. It detects signal presence by checking if the maximum sample in the time domain input frame is above a given threshold.

    Parameters:

      - input_data – [in] Pointer to input data frame. Input is assumed to be in Q1.31 fixed point format.

      - active_threshold – [in] Threshold for detecting signal activity

      - num_channels – [in] Number of input data channels

    Returns:

      0 if no signal activity on the input channels, 1 if activity detected on the input channels

  void aec_calc_freq_domain_energy(
    float_s32_t *fd_energy,
    const bfp_complex_s32_t *input,
  )

    Calculate energy in the spectrum.

    This function calculates the energy of frequency domain data used in the AEC. Frequency domain data in AEC is in the form of complex 32bit vectors and energy is calculated as the squared magnitude of the input vector.

    Parameters:

      - fd_energy – [out] energy of the input spectrum

      - input – [in] input spectrum BFP structure

  void aec_reset_state(aec_state_t *aec_state)

    Reset parts of aec state structure.

    This function resets parts of AEC state so that the echo canceller starts adapting from a zero filter.

    Parameters:

      - aec_state – [inout] AEC state structure

  float_s32_t aec_calc_max_input_energy(
    const int32_t (*input_data)[AEC_FRAME_ADVANCE],
    int num_channels,
  )

    Calculate the energy of the input signal.

    This function calculates the sum of the energy across all samples of the time domain input channel and returns the maximum energy across all channels.

    Parameters:

      - input_data – [in] Pointer to the input data buffer. The input is assumed to be in Q1.31 fixed point format.

      - num_channels – [in] Number of input channels.

    Returns:

      Maximum energy in float_s32_t format.

  float_s32_t aec_calc_corr_factor(aec_filter_state_t *state, unsigned ch)

    Calculate a correlation metric between the microphone input and estimated microphone signal.

    This function calculates a metric of resemblance between the mic input and the estimated mic signal. The correlation metric, along with reference signal energy is used to infer presence of near and far end signals in the AEC mic input.

    Parameters:

      - state – [in] AEC state structure. `state->y` and `state->y_hat` are used to calculate the correlation metric

      - ch – [in] mic channel index for which to calculate the metric

    Returns:

      correlation metric in float_s32_t format

## AEC Defines

group AEC #define constants

  Defines

  AEC_MAIN_FILTER_PHASES

    Maximum number of main-filter phases per adaptive filter at compile time.

    This sets the compile-time capacity for the main adaptive filter and is used to size internal state and memory pools (see aec_memory_pool_t). It gets overridden by an autogenerated header (`aec_conf.h`) when using AEC custom schedule generation via CMake.

    The `num_main_filter_phases` passed to `aec_init()` must satisfy aec_phase_pool_capacity.

  AEC_SHADOW_FILTER_PHASES

    Maximum number of shadow-filter phases per adaptive filter at compile time.

    This sets the compile-time capacity for the shadow adaptive filter and is used to size internal state and memory pools (see aec_shadow_filt_memory_pool_t). It gets overridden by an autogenerated header (`aec_conf.h`) when using AEC custom schedule generation via CMake.

    The `num_shadow_filter_phases` passed to `aec_init()` must satisfy aec_phase_pool_capacity.

  AEC_MAX_Y_CHANNELS

    Maximum number of microphone input channels at compile time. Microphone input to the AEC refers to the input from the device’s microphones from which AEC removes the echo created in the room by the device’s loudspeakers.

    AEC functions follow the convention of using \(y\) and \(Y\) for referring to time domain and frequency domain representation of microphone input.

    The `num_y_channels` passed into `aec_init()` call should be less than or equal to AEC_MAX_Y_CHANNELS, and satisfy the capacity rule in aec_phase_pool_capacity.

    This macro is used to size compile-time data structures (see aec_state_t, aec_memory_pool_t). It gets overridden by an autogenerated header (`aec_conf.h`) when using AEC custom schedule generation via CMake. The implementation operates on the runtime value configured via `aec_init()`.

  AEC_MAX_X_CHANNELS

    Maximum number of reference (X) input channels at compile time.

    Reference input is a copy of the device’s loudspeaker output used by the AEC to model echo paths between loudspeakers and microphones.

    AEC uses the convention \(x\) (time domain) and \(X\) (frequency domain) for reference signals.

    The `num_x_channels` passed to `aec_init()` must be <= AEC_MAX_X_CHANNELS and satisfy the capacity rule in aec_phase_pool_capacity.

    This macro is used to size compile-time data structures (see aec_state_t, aec_memory_pool_t). It gets overridden by an autogenerated header (`aec_conf.h`) when using AEC custom schedule generation via CMake. The implementation operates on the runtime value configured via `aec_init()`.

  AEC_FRAME_ADVANCE

    AEC frame size This is the number of samples of new data that the AEC works on every frame. 240 samples at 16kHz is 15msec. Every frame, the echo canceller takes in 15msec of mic and reference data and generates 15msec of echo cancelled output.

  AEC_PROC_FRAME_LENGTH

    Time domain samples block length used internally in AEC’s block LMS algorithm

  AEC_FD_FRAME_LENGTH

    Number of bins of spectrum data computed when doing a DFT of a AEC_PROC_FRAME_LENGTH length time domain vector. The AEC_FD_FRAME_LENGTH spectrum values represent the bins from DC to Nyquist.

  AEC_LIB_MAX_PHASES

    Maximum total number of phases supported in the AEC library This is the maximum number of total phases supported in the AEC library. Total phases are calculated by summing phases across adaptive filters for all x-y pairs.

    For example. for a 2 y-channels, 2 x-channels, 10 phases per x channel configuration, there are 4 adaptive filters, H_haty0x0, H_haty0x1, H_haty1x0 and H_haty1x1, each filter having 10 phases, so the total number of phases is 40. When aec_init() is called to initialise the AEC, the num_y_channels, num_x_channels and num_main_filter_phases parameters passed in should be such that num_y_channels * num_x_channels * num_main_filter_phases is less than equal to AEC_LIB_MAX_PHASES.

    This define is only used when defining data structures within the AEC state structure. The AEC algorithm implementation uses the num_main_filter_phases and num_shadow_filter_phases values that are passed into aec_init().

  AEC_UNUSED_TAPS_PER_PHASE

    Overlap data length

  AEC_FFT_PADDING

    Extra 2 samples you need to allocate in time domain so that the full spectrum (DC to nyquist) can be stored after the in-place FFT. NOT USER MODIFIABLE.

  AEC_LIB_MAX_THREADS

    Maximum number of hardware threads supported by the AEC.

    This compile-time limit bounds the number of threads that a task distribution schedule can target (see aec_task_distribution_t). Custom schedules generated via CMake (`AEC_SCHEDULE_CONFIG`) must set `<num_hw_threads>` <= AEC_LIB_MAX_THREADS.

## AEC Data Structures and Enums

group AEC Data Structure and Enum Definitions

  Defines

  REF_ACTIVE_THRESHOLD_DB

    Reference input level above which it is considered active

  Enums

  enum aec_adaption_e

    Values:

    enumerator AEC_ADAPTION_AUTO

      Compute filter adaption config every frame.

    enumerator AEC_ADAPTION_FORCE_ON

      Filter adaption always ON.

    enumerator AEC_ADAPTION_FORCE_OFF

      Filter adaption always OFF.

  enum shadow_state_e

    Values:

    enumerator LOW_REF

      Not much reference so no point in acting on AEC filter logic.

    enumerator ERROR

      something has gone wrong, zero shadow filter

    enumerator ZERO

      shadow filter has been reset multiple times, zero shadow filter

    enumerator RESET

      copy main filter to shadow filter

    enumerator EQUAL

      main filter and shadow filter are similar

    enumerator SIGMA

      shadow filter bit better than main, reset sigma_xx for faster convergence

    enumerator COPY

      shadow filter much better, copy to main

  struct coherence_mu_config_params_t

    Public Members

    float_s32_t coh_alpha

      Update rate of `coh`.

    float_s32_t coh_slow_alpha

      Update rate of `coh_slow`.

    float_s32_t coh_thresh_slow

      Adaption frozen if coh below (coh_thresh_slow*coh_slow)

    float_s32_t coh_thresh_abs

      Adaption frozen if coh below coh_thresh_abs.

    float_s32_t erle_thresh

      ERLE threshold

    uq2_30 erle_alpha_rise

      ERLE alpha when bigger

    uq2_30 erle_alpha_fall

      ERLE alpha when smaller

    float_s32_t mu_scalar

      Scalefactor for scaling the calculated mu.

    float_s32_t eps

      Parameter to avoid divide by 0 in coh calculation.

    float_s32_t thresh_minus20dB

      -20dB threshold

    unsigned mu_coh_time

      Number of frames after low coherence, adaption frozen for.

    unsigned mu_erle_time

      Number of frames after low erle, adaption frozen for.

    unsigned mu_shad_time

      Number of frames after shadow filter use, the adaption is fast for

    aec_adaption_e adaption_config

      Filter adaption mode. Auto, force ON or force OFF

    int32_t force_adaption_mu_q30

      Fixed mu value used when filter adaption is forced ON

  struct shadow_filt_config_params_t

    Public Members

    float_s32_t shadow_sigma_thresh

      threshold for resetting sigma_XX.

    float_s32_t shadow_copy_thresh

      threshold for copying shadow filter.

    float_s32_t shadow_reset_thresh

      threshold for resetting shadow filter.

    float_s32_t shadow_delay_thresh

      threshold for turning off shadow filter reset if reference delay is large

    float_s32_t shadow_mu

      fixed mu value used during shadow filter adaption.

    int32_t shadow_better_thresh

      Number of times shadow filter needs to be better before it gets copied to main filter.

    int32_t shadow_zero_thresh

      Number of times shadow filter is reset by copying the main filter to it before it gets zeroed.

    int32_t shadow_reset_timer

      Number of frames between zeroing resets of shadow filter.

  struct aec_core_config_params_t

    Public Members

    int bypass

      bypass AEC flag.

    int gamma_log2

      parameter for deriving the gamma value that used in normalisation spectrum calculation. gamma is calculated as 2^gamma_log2

    uint32_t sigma_xx_shift

      parameter used for deriving the alpha value used while calculating EMA of X_energy to calculate sigma_XX.

    float_s32_t delta_adaption_force_on

      delta value used in normalisation spectrum computation when adaption is forced as always ON.

    float_s32_t delta_min

      Lower limit of delta computed using fractional regularisation.

    uint32_t coeff_index

      coefficient index used to track H_hat index when sending H_hat values over the host control interface.

    uq2_30 ema_alpha_q30

      alpha used while calculating y_ema_energy, x_ema_energy and error_ema_energy.

  struct aec_config_params_t
    #include <aec_state.h>

    AEC control parameters.

    This structure contains control parameters that the user can modify at run time.

    Public Members

    coherence_mu_config_params_t coh_mu_conf

      Coherence mu related control params.

    shadow_filt_config_params_t shadow_filt_conf

      Shadow filter related control params.

    aec_core_config_params_t aec_core_conf

      All AEC control params except those for coherence mu and shadow filter.

  struct coherence_mu_params_t

    Public Members

    float_s32_t coh

      Moving average coherence.

    float_s32_t coh_slow

      Slow moving average coherence.

    float_s32_t erle

      Current ERLE.

    float_s32_t mov_erle

      Slow moving average ERLE.

    int32_t mu_coh_timer

      Timer for tracking number of frames adaption is frozen for.

    int32_t mu_shad_count

      Counter for tracking number of frames shadow filter has been used in.

    float_s32_t coh_mu[AEC_MAX_X_CHANNELS]

      Coherence mu.

  struct shadow_filter_params_t

    Public Members

    int32_t shadow_flag[AEC_MAX_Y_CHANNELS]

      shadow_state_e enum indicating shadow filter status

    int shadow_reset_count[AEC_MAX_Y_CHANNELS]

      counter for tracking shadow filter resets

    int shadow_better_count[AEC_MAX_Y_CHANNELS]

      counter for tracking shadow filter copy to main filter

  struct aec_shared_filter_state_t
    #include <aec_state.h>

    AEC shared state structure.

    Data structures holding AEC persistent state that is common between main filter and shadow filter. aec_filter_state_t::shared_state for both main and shadow filter point to the common aec_shared_t structure. [aec_shared_filter_state_t]

    Public Members

    bfp_complex_s32_t X_fifo[AEC_MAX_X_CHANNELS][AEC_LIB_MAX_PHASES]

      BFP array pointing to the reference input spectrum phases. The term phase refers to the spectrum data for a frame. Multiple phases means multiple frames of data.

      For example, 10 phases would mean the 10 most recent frames of data. Each phase spectrum, pointed to by X_fifo[i][j]->data is stored as a length AEC_FD_FRAME_LENGTH, complex 32bit array.

      The phases are ordered from most recent to least recent in the X_fifo. For example, for an AEC configuration of 2 x-channels and 10 phases per x channel, 10 frames of X data spectrum is stored in the X_fifo. For a given x channel, say x channel 0, X_fifo[0][0] points to the most recent frame’s X spectrum and X_fifo[0][9] points to the last phase, i.e the least recent frame’s X spectrum.

    bfp_complex_s32_t X[AEC_MAX_X_CHANNELS]

      BFP array pointing to reference input signal spectrum. The X data values are stored as a length AEC_FD_FRAME_LENGTH complex 32bit array per x channel.

    bfp_complex_s32_t Y[AEC_MAX_Y_CHANNELS]

      BFP array pointing to mic input signal spectrum. The Y data values are stored as a length AEC_FD_FRAME_LENGTH complex 32bit array per y channel.

    bfp_s32_t y[AEC_MAX_Y_CHANNELS]

      BFP array pointing to time domain mic input processing block. The y data values are stored as length AEC_PROC_FRAME_LENGTH, 32bit integer array per y channel.

    bfp_s32_t x[AEC_MAX_X_CHANNELS]

      BFP array pointing to time domain reference input processing block. The x data values are stored as length AEC_PROC_FRAME_LENGTH, 32bit integer array per x channel.

    bfp_s32_t prev_y[AEC_MAX_Y_CHANNELS]

      BFP array pointing to time domain mic input values from the previous frame. These are put together with the new samples received in the current frame to make a AEC_PROC_FRAME_LENGTH processing block. The prev_y data values are stored as length (AEC_PROC_FRAME_LENGTH - AEC_FRAME_ADVANCE), 32bit integer array per y channel.

    bfp_s32_t prev_x[AEC_MAX_X_CHANNELS]

      BFP array pointing to time domain reference input values from the previous frame. These are put together with the new samples received in the current frame to make a AEC_PROC_FRAME_LENGTH processing block. The prev_x data values are stored as length (AEC_PROC_FRAME_LENGTH - AEC_FRAME_ADVANCE), 32bit integer array per x channel.

    bfp_s32_t sigma_XX[AEC_MAX_X_CHANNELS]

      BFP array pointing to sigma_XX values which are the weighted average of the X_energy signal. The sigma_XX data is stored as 32bit integer array of length AEC_FD_FRAME_LENGTH

    float_s32_t y_ema_energy[AEC_MAX_Y_CHANNELS]

      Exponential moving average of the time domain mic signal energy. This is calculated by calculating energy per sample and summing across all samples. Stored in a y channels array with every value stored as a 32bit integer mantissa and exponent.

    float_s32_t x_ema_energy[AEC_MAX_X_CHANNELS]

      Exponential moving average of the time domain reference signal energy. This is calculated by calculating energy per sample and summing across all samples. Stored in a x channels array with every value stored as a 32bit integer mantissa and exponent.

    float_s32_t overall_Y[AEC_MAX_Y_CHANNELS]

      Energy of the mic input spectrum. This is calculated by calculating the energy per bin and summing across all bins. Stored in a y channels array with every value stored as a 32bit integer mantissa and exponent.

    float_s32_t overall_Yhat[AEC_MAX_Y_CHANNELS]

      Energy of the estimated mic input spectrum. This is calculated by calculating the energy per bin and summing across all bins. Stored in a y channels array with every value stored as a 32bit integer mantissa and exponent.

    float_s32_t sum_X_energy[AEC_MAX_X_CHANNELS]

      Sum of the X_energy across all bins for a given x channel. Stored in a x channels array with every value stored as a 32bit integer mantissa and exponent.

    int32_t ref_active_flag

      Reference active flag. Indicates if the reference signal is active or not for any x channel.

    coherence_mu_params_t coh_mu_state[AEC_MAX_Y_CHANNELS]

      Structure containing coherence mu calculation related parameters.

    shadow_filter_params_t shadow_filter_params

      Structure containing shadow filter related parameters.

    aec_config_params_t config_params

      Structure containing AEC control parameters. These are initialised to the default values and can be changed at runtime by the user.

    unsigned num_y_channels

      Number of mic input channels that the AEC is configured for. This is the input parameter num_y_channels that aec_init() gets called with.

    unsigned num_x_channels

      Number of reference input channels that the AEC is configured for. This is the input parameter num_x_channels that aec_init() gets called with.

    unsigned X_energy_recalc_bin

      bin index for which the sum of X energy over all the X FIFO phases is re-calculated in the current frame. The index increments from 0 to AEC_PROC_FRAME_LENGTH/2, then decrements back to 0 over successive frames.

  struct aec_filter_state_t
    #include <aec_state.h>

    [aec_shared_filter_state_t]

    AEC filter state structure.

    Data structures holding AEC filter persistent state. There are 2 instances of aec_filter_state_t maintained within AEC; one for main filter and one for shadow filter specific state. [aec_filter_state_t]

    Public Members

    bfp_complex_s32_t Y_hat[AEC_MAX_Y_CHANNELS]

      BFP array pointing to estimated mic signal spectrum. The Y_data data values are stored as length AEC_FD_FRAME_LENGTH, complex 32bit array per y channel.

    bfp_complex_s32_t Error[AEC_MAX_Y_CHANNELS]

      BFP array pointing to adaptive filter error signal spectrum. The Error data is stored as length AEC_FD_FRAME_LENGTH, complex 32bit array per y channel.

    bfp_complex_s32_t H_hat[AEC_MAX_Y_CHANNELS][AEC_LIB_MAX_PHASES]

      BFP array pointing to the adaptive filter spectrum. The filter spectrum is stored as a num_y_channels x total_phases_across_all_x_channels array where each H_hat[i][j] entry points to the spectrum of a single phase.

      Number of phases in the filter refers to its tail length. A filter with more phases would be able to model a longer echo thereby causing better echo cancellation.

      For example, for a 2 y-channels, 3 x-channels, 10 phases per x channel configuration, the filter spectrum phases are stored in a 2x30 array. For a given y channel, say y channel 0, H_hat[0][0] to H_hat[0][9] points to 10 phases of H_haty0x0, H_hat[0][10] to H_hat[0][19] points to 10 phases of H_haty0x1 and H_hat[0][20] to H_hat[0][29] points to 10 phases of H_haty0x2.

      Each filter phase data which is pointed to by H_hat[i][j].data is stored as AEC_FD_FRAME_LENGTH complex 32bit array.

    bfp_complex_s32_t X_fifo_1d[AEC_LIB_MAX_PHASES]

      BFP array pointing to all phases of reference input spectrum across all x channels. Here, the reference input spectrum is saved in a 1 dimensional array of phases, with x channel 0 phases followed by x channel 1 phases and so on. For example, for a 2 x-channels, 10 phases per x channel configuration, X_fifo_1d[0] to X_fifo_1d[9] points to the 10 phases for channel 0 and X_fifo[10] to X_fifo[19] points to the 10 phases for channel 1.

      Each X data spectrum phase pointed to by X_fifo_1d[i][j].data is stored as length AEC_FD_FRAME_LENGTH complex 32bit array.

    bfp_complex_s32_t T[AEC_MAX_X_CHANNELS]

      BFP array pointing to T values which are stored as a length AEC_FD_FRAME_LENGTH, complex array per x channel.

    bfp_s32_t inv_X_energy[AEC_MAX_X_CHANNELS]

      BFP array pointing to the normalisation spectrum which are stored as a length AEC_FD_FRAME_LENGTH, 32bit integer array per x channel.

    bfp_s32_t X_energy[AEC_MAX_X_CHANNELS]

      BFP array pointing to the X_energy data which is the energy per bin of the X spectrum summed over all phases of the X data. X_energy data is stored as a length AEC_FD_FRAME_LENGTH, integer 32bit array per x channel.

    bfp_s32_t overlap[AEC_MAX_Y_CHANNELS]

      BFP array pointing to time domain overlap data values which are used in the overlap add operation done while calculating the echo canceller time domain output. Stored as a length 32, 32 bit integer array per y channel.

    bfp_s32_t y_hat[AEC_MAX_Y_CHANNELS]

      BFP array pointing to the time domain estimated mic signal. Stored as length AEC_PROC_FRAME_LENGTH, 32 bit integer array per y channel.

    bfp_s32_t error[AEC_MAX_Y_CHANNELS]

      BFP array pointing to the time domain adaptive filter error signal. Stored as length AEC_PROC_FRAME_LENGTH, 32 bit integer array per y channel.

    float_s32_t mu[AEC_MAX_Y_CHANNELS][AEC_MAX_X_CHANNELS]

      mu values for every x-y pair stored as 32 bit integer mantissa and 32 bit integer exponent

    float_s32_t error_ema_energy[AEC_MAX_Y_CHANNELS]

      Exponential moving average of the time domain adaptive filter error signal energy. Stored in an x channels array with every value stored as a 32bit integer mantissa and exponent.

    float_s32_t overall_Error[AEC_MAX_Y_CHANNELS]

      Energy of the adaptive filter error spectrum. Stored in a y channels array with every value stored as a 32bit integer mantissa and exponent.

    float_s32_t max_X_energy[AEC_MAX_X_CHANNELS]

      Maximum X energy across all values of X_energy for a given x channel. Stored in an x channels array with every value stored as a 32bit integer mantissa and exponent.

    float_s32_t delta_scale

      fractional regularisation scalefactor.

    float_s32_t delta

      delta parameter used in the normalisation spectrum calculation.

    aec_shared_filter_state_t *shared_state

      pointer to the state data shared between main and shadow filter.

    unsigned num_phases

      Number of filter phases per x-y pair that AEC filter is configured for. This is the input argument num_main_filter_phases or num_shadow_filter_phases, depending on which filter the aec_filter_state_t is instantiated for, passed in aec_init() call.

  struct aec_state_t
    #include <aec_state.h>

    [aec_filter_state_t]

    AEC state struct.

    Data structure holding AEC module’s persistent state.

    Public Members

    aec_filter_state_t main_state

      AEC main filter state

    aec_filter_state_t shadow_state

      AEC shadow filter state

    aec_shared_filter_state_t shared_state

      AEC state shared between the main and shadow filter

    aec_memory_pool_t main_mem_pool

      Memory pool for the AEC main filter

    aec_shadow_filt_memory_pool_t shadow_mem_pool

      Memory pool for the AEC shadow filter

## AEC Scheduling Data Structures

group AEC Scheduling Types

  Defines

  AEC_LIB_MAX_CHANNELS

    Maximum channel count used by scheduling tables.

    Computed as max(AEC_MAX_Y_CHANNELS, AEC_MAX_X_CHANNELS). This defines the upper bound for the channel dimension in the precomputed task–channel schedules within aec_task_distribution_t.

  Variables

  const aec_task_distribution_t aec_tdist_chans2_threads1

    Default schedule for running up to 2Y, 2X channels AEC on 1 hardware thread.

    Usage:

    - Pass &aec_tdist_chans2_threads1 to aec_init() via the `tdist` argument.

  const aec_task_distribution_t aec_tdist_chans2_threads2

    Default schedule for running up to 2Y, 2X channels AEC on 2 hardware threads.

    Usage:

    - Pass &aec_tdist_chans2_threads2 to aec_init() via the `tdist` argument.

  struct aec_par_tasks_t
    #include <aec_schedule.h>

    Data structures for distributing AEC work across hardware threads.

    The task distribution scheme covers two scenarios:

    1. Distribute multiple unique tasks across multiple hardware threads. For example, for 3 tasks and 2 threads, distribute [task0, task1, task2] across [Thread0, Thread1].

    2. Distribute (task, channel) pairs across multiple hardware threads. For example, for 3 tasks, 2 channels, and 2 threads, distribute [(task0, ch0), (task0, ch1), (task1, ch0), (task1, ch1), (task2, ch0), (task2, ch1)] across [Thread0, Thread1].

    The number of channels used when defining the (task, channel) pairs is fixed to AEC_LIB_MAX_CHANNELS (i.e., max(AEC_MAX_Y_CHANNELS, AEC_MAX_X_CHANNELS)).

    Entry used when distributing tasks across hardware threads.

    Public Members

    int task

      Task index.

    int is_active

      Flag indicating whether the task is active on that thread. The task runs on the thread only when `is_active` is 1.

  struct aec_par_tasks_and_channels_t
    #include <aec_schedule.h>

    Entry used when distributing (task, channel) pairs across hardware threads.

    Public Members

    int task

      Task index.

    int channel

      Channel index.

    int is_active

      Flag indicating whether the (task, channel) pair is active on that thread. The pair runs on the thread only when `is_active` is 1.

  struct aec_task_distribution_t
    #include <aec_schedule.h>

    Precomputed schedules for mapping AEC work to hardware threads.

    Provides lookup tables for several configurations:

    - Distributing (task, channel) pairs across threads. For example, distributing 3 tasks, each running 2 channels, over 2 hardware threads

    - Distributing unique tasks (no channel dimension) across threads. For example, distributing 3 tasks over 2 hardware threads

    For each configuration, the corresponding `passes_*` value gives the number of passes required to execute all work items. The 2D arrays are indexed as [thread][work_item]. The second dimension (e.g., 3 * AEC_LIB_MAX_CHANNELS) is sized (upper bound) for the worst case where a single thread performs all work items (one pass per work item). When multiple threads are available, the corresponding `passes_*` value indicates how many passes are actually required to cover all work items with the given `thread_count`.

    Public Members

    unsigned thread_count

      Number of hardware threads this schedule targets (should be <= AEC_LIB_MAX_THREADS)

    unsigned passes_for_3_tasks_and_channels

      Passes needed to cover all (3 tasks × channels) work items.

    aec_par_tasks_and_channels_t par_3_tasks_and_channels[AEC_LIB_MAX_THREADS][3 * AEC_LIB_MAX_CHANNELS]

      Schedule for 3 tasks, AEC_LIB_MAX_CHANNELS channels, scheduled across AEC_LIB_MAX_THREADS threads

    unsigned passes_for_2_tasks_and_channels

      Passes needed to cover all (3 tasks × channels) work items.

    aec_par_tasks_and_channels_t par_2_tasks_and_channels[AEC_LIB_MAX_THREADS][2 * AEC_LIB_MAX_CHANNELS]

      Schedule for 2 tasks, AEC_LIB_MAX_CHANNELS channels, scheduled across AEC_LIB_MAX_THREADS threads

    unsigned passes_for_1_tasks_and_channels

      Passes needed to cover all (1 task × channels) work items.

    aec_par_tasks_and_channels_t par_1_tasks_and_channels[AEC_LIB_MAX_THREADS][1 * AEC_LIB_MAX_CHANNELS]

      Schedule for 1 task, AEC_LIB_MAX_CHANNELS channels, scheduled across AEC_LIB_MAX_THREADS threads

    unsigned passes_for_3_tasks

      Passes needed to cover 3 unique tasks (no channel dimension).

    aec_par_tasks_t par_3_tasks[AEC_LIB_MAX_THREADS][3]

      Schedule for 3 unique tasks (no channel dimension), scheduled across AEC_LIB_MAX_THREADS threads

    unsigned passes_for_2_tasks

      Passes needed to cover 2 unique tasks (no channel dimension).

    aec_par_tasks_t par_2_tasks[AEC_LIB_MAX_THREADS][2]

      Schedule for 2 unique tasks (no channel dimension), scheduled across AEC_LIB_MAX_THREADS threads

## AEC Memory Pool

group AEC memory pool
  struct aec_memory_pool_t
    #include <aec_memory_pool.h>

    aec_memory_pool_t

    Memory pool for AEC main filter and shared state buffers.

    This pool provides contiguous storage for all BFP (block floating-point from `lib_xcore_math`) structures used by the main filter (`aec_filter_state_t`) and the shared filter state (`aec_shared_filter_state_t`). The `aec_init()` function initializes the BFP structures in the AEC state structures to point to memory buffers from this pool during AEC initialisation.

    The memory pool allocates storage based on AEC compile-time configuration parameters:

    - AEC_MAX_Y_CHANNELS

    - AEC_MAX_X_CHANNELS

    - AEC_MAIN_FILTER_PHASES

    - AEC_SHADOW_FILTER_PHASES

    The same pool can be used to initialize AEC for any runtime configuration (passed as arguments to `aec_init()`) that is a subset of the compile-time configuration (See aec_phase_pool_capacity).

    Note

    This structure exists to own memory, not to describe layout. The memory pool acts as a linear allocation arena used by `aec_init()` to initialise BFP structures in the AEC filter state structures. Memory is assigned sequentially from the pool based on the runtime configuration (number of channels and filter phases), and does not have a fixed or semantic mapping to the individual fields of this struct. The named members of this struct exist only to reserve sufficient contiguous storage at compile time. They must not be interpreted as backing specific components of `aec_filter_state_t`/`aec_shared_filter_state_t` and should never be accessed directly. After initialisation, all access to this memory occurs exclusively through the BFP structures owned by the AEC state.

    Public Members

    int32_t mic_input_frame[AEC_MAX_Y_CHANNELS][AEC_PROC_FRAME_LENGTH + AEC_FFT_PADDING]

      Memory pointed to by aec_shared_filter_state_t::y and aec_shared_filter_state_t::Y

    int32_t ref_input_frame[AEC_MAX_X_CHANNELS][AEC_PROC_FRAME_LENGTH + AEC_FFT_PADDING]

      Memory pointed to by aec_shared_filter_state_t::x and aec_shared_filter_state_t::X. Also reused for main filter aec_filter_state_t::T

    int32_t mic_prev_samples[AEC_MAX_Y_CHANNELS][AEC_PROC_FRAME_LENGTH - AEC_FRAME_ADVANCE]

      Memory pointed to by aec_shared_filter_state_t::prev_y

    int32_t ref_prev_samples[AEC_MAX_X_CHANNELS][AEC_PROC_FRAME_LENGTH - AEC_FRAME_ADVANCE]

      Memory pointed to by aec_shared_filter_state_t::prev_x

    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_filter_state_t::H_hat, aec_shared_filter_state_t::X_fifo, main filter aec_filter_state_t::X_fifo_1d and shadow filter aec_filter_state_t::X_fifo_1d

    complex_s32_t Error[AEC_MAX_Y_CHANNELS][AEC_FD_FRAME_LENGTH]

      Memory pointed to by main filter aec_filter_state_t::Error and aec_filter_state_t::error

    complex_s32_t Y_hat[AEC_MAX_Y_CHANNELS][AEC_FD_FRAME_LENGTH]

      Memory pointed to by main filter aec_filter_state_t::Y_hat and aec_filter_state_t::y_hat

    int32_t X_energy[AEC_MAX_X_CHANNELS][AEC_FD_FRAME_LENGTH]

      Memory pointed to by main_filter aec_filter_state_t::X_energy

    int32_t sigma_XX[AEC_MAX_X_CHANNELS][AEC_FD_FRAME_LENGTH]

      Memory pointed to by aec_shared_filter_state_t::sigma_XX

    int32_t inv_X_energy[AEC_MAX_X_CHANNELS][AEC_FD_FRAME_LENGTH]

      Memory pointed to by main filter aec_filter_state_t::inv_X_energy

    int32_t overlap[AEC_MAX_Y_CHANNELS][AEC_UNUSED_TAPS_PER_PHASE * 2]

      Memory pointed to by main filter aec_filter_state_t::overlap

  struct aec_shadow_filt_memory_pool_t
    #include <aec_memory_pool.h>

    aec_shadow_filt_memory_pool_t

    Memory pool for AEC shadow filter.

    This pool provides contiguous storage for all BFP (block floating-point from `lib_xcore_math`) structures used by the AEC shadow filter (`aec_filter_state_t`). The `aec_init()` function initializes the BFP structures in the AEC state structures to point to memory buffers from this pool during AEC initialisation.

    The memory pool allocates storage based on AEC compile-time configuration parameters:

    - AEC_MAX_Y_CHANNELS

    - AEC_MAX_X_CHANNELS

    - AEC_MAIN_FILTER_PHASES

    - AEC_SHADOW_FILTER_PHASES

    The same pool can be used to initialize AEC for any runtime configuration (passed as arguments to `aec_init()`) that is a subset of the compile-time configuration (See aec_phase_pool_capacity).

    Note

    This structure exists to own memory, not to describe layout. The memory pool acts as a linear allocation arena used by `aec_init()` to initialise BFP structures in the AEC filter state structures. Memory is assigned sequentially from the pool based on the runtime configuration (number of channels and filter phases), and does not have a fixed or semantic mapping to the individual fields of this struct. The named members of this struct exist only to reserve sufficient contiguous storage at compile time. They must not be interpreted as backing specific components of `aec_filter_state_t`/`aec_shared_filter_state_t` and should never be accessed directly. After initialisation, all access to this memory occurs exclusively through the BFP structures owned by the AEC state.

    Public Members

    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_filter_state_t::H_hat

    complex_s32_t Error[AEC_MAX_Y_CHANNELS][AEC_FD_FRAME_LENGTH]

      Memory pointed to by shadow filter aec_filter_state_t::Error and aec_filter_state_t::error

    complex_s32_t Y_hat[AEC_MAX_Y_CHANNELS][AEC_FD_FRAME_LENGTH]

      Memory pointed to by shadow filter aec_filter_state_t::Y_hat and aec_filter_state_t::y_hat

    complex_s32_t T[AEC_MAX_X_CHANNELS][AEC_FD_FRAME_LENGTH]

      Memory pointed to by shadow filter aec_filter_state_t::T

    int32_t X_energy[AEC_MAX_X_CHANNELS][AEC_FD_FRAME_LENGTH]

      Memory pointed to by shadow_filter aec_filter_state_t::X_energy

    int32_t inv_X_energy[AEC_MAX_X_CHANNELS][AEC_FD_FRAME_LENGTH]

      Memory pointed to by shadow_filter aec_filter_state_t::inv_X_energy

    int32_t overlap[AEC_MAX_Y_CHANNELS][AEC_UNUSED_TAPS_PER_PHASE * 2]

      Memory pointed to by shadow filter aec_filter_state_t::overlap