cancel
Showing results for 
Search instead for 
Did you mean: 

Acoustic Echo Canceler problems on a Cortex-M7 processor (STM32H743ZI)

ANcub
Associate

Good day,

We are working on an Audio application and we would like to use the Nucleo-H743ZI board and the libAcoustic_EC_CM7F_GCC_ot.a library but we have hit a bit of a snag and I am hoping someone will assist us with solving the issue.

We bought the BlueCoin (https://www.st.com/en/evaluation-tools/steval-bcnkt01v1.html) to test the acoustic echo canceler after attending an ST seminar and played with it and we were satisfied with the results that we were getting and after that we managed to get the Nucleo-H743ZI board and connected it to our existing hardware design with a stereo WM8731 codec.

In this system the Codec (WM8731) is connected to 2 speakers (Left and Right HPOUT) and 2 electret microphones (Left and right LINEIN). This codec is configured as the master and drives the SAI at 16kHz receiving and transmitting PCM data in standard I2s format.

The audio playback works well that is playing microphone input directly to the speaker, the problem starts when I run the acoustic echo cancellation algorithm (libAcoustic_EC_CM7F_GCC_ot.a) . I have followed the FP-AUD-SMARTMIC1 (https://www.st.com/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32-ode-function-pack-sw/fp-aud-smartmic1.html) example but the audio output is distorted please find recording attached within (Supposed to be voice saying "1 2 3").

Code run-down:

1. IDE - Atollic TrueStudio for STM32 V9.1.0

2. Import the libAcoustic_EC_CM7F_GCC_ot.a from the FP-AUD-SMARTMIC1 function pack 

3. Configure the Codec as the I2S master at 16kHz sample rate standard I2S format and SAI1 on the STM32H743ZI as the slave, so the Codec drives the clock and Frame sync pins.

4. Play known audio to speaker (AudioSample ) on one channel (LEFT) and record input from electret microphone on the same channel using interrupt driven transmit and receive (HAL_SAI_Receive_IT(), HAL_SAI_Transmit_IT())

5. In the while loop wait until 16 samples (equal to 1ms at 16kHz) have been received and transmitted

6. Use Echo signal (AudioSample) and input PCM data (from LEFT channel) as inputs to AcousticEC_Data_Input() and run AcousticEC_Process() when the former returns 1

7. Play AEC algorithm output PCM data to the other channel (RIGHT) – Result: distorted sound

What I have tried to do:

• Increase the stack and heap size

• Use the libAcoustic_EC_CM4F_GCC_ot.a

• Use 32-bit aligned variables (ALIGN_32BYTES)

• Change the FPU type between FPv5-SP-D16 and FPv5-D16

• Implemented and then removed the SAI DMA 

• Changed from Atollic TrueStudio to AC6 SW v2.1

Having tried all of these possible solutions the audio output from the AEC algorithm is still corrupt. Is there anything that I am missing.

Your assistance will be greatly appreciated.

Kind Regards,

Alexander

main.c

  HAL_NVIC_SetPriority((IRQn_Type)EXTI1_IRQn, 0x0C, 0);
  HAL_NVIC_EnableIRQ((IRQn_Type)EXTI1_IRQn);
 
  EC_DeInit();
  Codec_Setup();
  EC_Init();
 
  HAL_Delay(500);
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
 
  HAL_SAI_Receive_IT(&hsai_BlockB1, (uint8_t *)audioRX, I2S_BUFFER_SIZE);
  HAL_SAI_Transmit_IT(&hsai_BlockA1, (uint8_t *)audioRX, I2S_BUFFER_SIZE);
 
  while (1)
  {
	  if(audio_get_ec_block(0, &__nearEnd[0], &__farEnd[0]) == 0)
	  {
		  if(AcousticEC_Data_Input(__nearEnd, __farEnd, __result, (AcousticEC_Handler_t *)&EchoHandlerInstance))
		  {
			  SW_AEC_Task_Start();
			  _aecStatus = ALGO_ACTIVATION_EC;
		  }
	  }
 
  /* USER CODE END WHILE */
 
  /* USER CODE BEGIN 3 */
 
  }
  /* USER CODE END 3 */
 
}

Initialization of the Echo Canceler.

uint32_t EC_Init(void)
{
  uint32_t error_value = 0;
  EchoHandlerInstance.tail_length = ACOUSTIC_EC_TAIL_LENGTH;
  EchoHandlerInstance.preprocess_init = ACOUSTIC_EC_PREPROCESS_ENABLE;
  EchoHandlerInstance.ptr_primary_channels=1;
  EchoHandlerInstance.ptr_reference_channels=1;
  EchoHandlerInstance.ptr_output_channels=1;
  AcousticEC_getMemorySize(&EchoHandlerInstance);
  EchoHandlerInstance.pInternalMemory = (uint32_t *)malloc(EchoHandlerInstance.internal_memory_size);
 
  if(EchoHandlerInstance.pInternalMemory == NULL)
  {
    while(1); /*Error Management*/
  }
 
  error_value = AcousticEC_Init((AcousticEC_Handler_t *)&EchoHandlerInstance);
 
  if(error_value != 0)
  {
    while(1); /*Error Management*/
  }
 
  EchoConfigInstance.preprocess_state = ACOUSTIC_EC_PREPROCESS_ENABLE;// UserAudioStatus.AECStatus.Denoiser;
  EchoConfigInstance.AGC_value = 0;       // UserAudioStatus.AECStatus.AGCValue;
  EchoConfigInstance.noise_suppress_default = -15;      /* Default: -15 */
  EchoConfigInstance.echo_suppress_default = -40;       /* Default: -40 */
  EchoConfigInstance.echo_suppress_active = -15;        /* Default: -15 */
  EchoConfigInstance.residual_echo_remove = 1;          /* Default: 1   */
 
  error_value = AcousticEC_setConfig((AcousticEC_Handler_t *)&EchoHandlerInstance, (AcousticEC_Config_t *) &EchoConfigInstance);
 
  if(error_value != 0)
  {
    while(1); /*Error Management*/
  }
 
  //Internals.AudioOutRdPtr = 0;
  return error_value;
}

Low Priority task for processing the AEC algorithm

void SW_AEC_Task_Callback(void)
{
  int i = 0;
  AcousticEC_Process((AcousticEC_Handler_t *)&EchoHandlerInstance);
  _aecStatus &= ~ALGO_ACTIVATION_EC;
  for(i = 0; i < ACOUSTIC_EC_SAMPLE_SIZE; i++)
  {
	  result[resultHeadPtr++] = __result[i];
	  if(resultHeadPtr >= AUDIO_SAMPLE_BUFFER_SIZE)
		  resultHeadPtr = 0;
  }
}

0 REPLIES 0