Which filter should I use for Echo Cancellation? #2096
-
| Problem DescriptionHi, Thanks for your lib. It's very useful. I have build a device with one I2S Mic and one I2S speaker with ESP32S3. Based "streams-i2s-i2s" example, it's done quickly. But I found the MIC is very sensitive, there would be echo when I set the speaker load. Which filter should I use for Echo Cancellation? Ziv Device DescriptionSelf made board, core is ESP32-S3 Sketch/**
   @file streams-i2s-i2s-2.ino
   @brief Copy audio from I2S to I2S: We use 2 different i2s ports!
   @author Phil Schatzmann
   @copyright GPLv3
*/
#include <Wire.h>
#include "AudioTools.h"
AudioInfo IN_info(16000, 2, 32);
AudioInfo OUT_info(16000, 2, 32);
I2SStream in;
I2SStream out;
StreamCopy copier(out, in); // copies sound into i2s
//FormatConverterStream converter(in);  // or use converter(out)
//StreamCopy copier(out, converter);       //        copier(converter, sound);
// HT513 音量
uint16_t Volume;
// 最小音量
#define LOWESTVOLUME 1
#define TOLENCE 16
#define HT513_ADDR_L 0x6c
/**
   @brief  ht513写寄存器
   @param  addr 寄存器地址
   @param  val 要写的值
   @retval None
*/
void HT513_WriteOneByte(uint8_t addr, uint8_t val)
{
  Wire.beginTransmission(HT513_ADDR_L);
  Wire.write(addr);
  Wire.write(val);
  int ack = Wire.endTransmission(true);
  Serial.print("Ack ");
  Serial.println(ack, HEX);
}
/**
   @brief  ht513读寄存器
   @param  addr 寄存器地址
   @retval 读取到的寄存器值
*/
uint8_t HT513_ReadOneByte(uint8_t addr)
{
  uint8_t temp = 0;
  Wire.beginTransmission(HT513_ADDR_L);
  Wire.write(addr);
  Wire.endTransmission(false);
  uint8_t bytesReceived = 0;
  bytesReceived = Wire.requestFrom(HT513_ADDR_L, (uint8_t)1, true);
  if (bytesReceived == 1) {
    temp = Wire.read();
  }
  else {
    Serial.println("Read Error ");
  }
  return temp;
}
// Arduino Setup
void setup(void) {
  delay(5000);
  // HT513 SD Pin 需要设置为 High
  pinMode(8, OUTPUT);
  digitalWrite(8, HIGH);
  analogReadResolution(9);
  // Open Serial
  Serial.begin(115200);
  // change to Warning to improve the quality
  //AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
  Wire.begin(18, 17);
  int nDevices;
  byte error, address;
  Serial.println("Scanning...");
  nDevices = 0;
  for ( address = 1; address < 127; address++ ) {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    if (error == 0) {
      Serial.print("I2C device found at address 0x");
      if (address < 16) {
        Serial.print("0");
      }
      Serial.println(address, HEX);
      nDevices++;
    }
    else if (error == 4) {
      Serial.print("Unknow error at address 0x");
      if (address < 16) {
        Serial.print("0");
      }
      Serial.println(address, HEX);
    }
  }
  if (nDevices == 0) {
    Serial.println("No I2C devices found\n");
  }
  else {
    Serial.println("done\n");
  }
  //  设置 SD 为LOW
  HT513_WriteOneByte(0x12, 0b11110000);
  // 设置数据格式为 I2S, 32Bits
  HT513_WriteOneByte(0x13, 0b00000000);
  // 读取音量设置
  Volume = analogRead(3);
  uint8_t Vol=(Volume,0,511,0x07,0xff);
  HT513_WriteOneByte(0x16, Vol);
  HT513_WriteOneByte(0x15, Vol);
  Serial.println(Volume, HEX);
  // 调整声道
  HT513_WriteOneByte(0x17, 0b10110000);
  Serial.println("++++++++++++++++");
  //  设置 SD 为HIGH
  HT513_WriteOneByte(0x12, 0b11110100);
  uint8_t Value = HT513_ReadOneByte(0x12);
  Serial.println(Value, HEX);
  Value = HT513_ReadOneByte(0x13);
  Serial.println(Value, HEX);
  Value = HT513_ReadOneByte(0x16);
  Serial.println(Value, HEX);
  Value = HT513_ReadOneByte(0x17);
  Serial.println(Value, HEX);
  // Define Converter
  //converter.begin(IN_info, OUT_info);
  // start I2S in
  Serial.println("starting I2S...");
  auto config_in = in.defaultConfig(RX_MODE);
  config_in.copyFrom(IN_info);
  config_in.i2s_format = I2S_STD_FORMAT;
  config_in.is_master = true;
  config_in.port_no = 1;
  config_in.pin_bck = 37;
  config_in.pin_ws = 38;
  config_in.pin_data = 36;
  // config_in.fixed_mclk = sample_rate * 256
  // config_in.pin_mck = 2
  in.begin(config_in);
  // start I2S out
  auto config_out = out.defaultConfig(TX_MODE);
  config_out.copyFrom(OUT_info);
  config_out.i2s_format = I2S_STD_FORMAT;
  config_out.is_master = true;
  config_out.port_no = 0;
  config_out.pin_bck = 15;
  config_out.pin_ws = 6;
  config_out.pin_data = 7;
  config_out.pin_mck = 16;
  out.begin(config_out);
  Serial.println("I2S started...");
}
// Arduino loop - copy sound to out
void loop() {
  copier.copy();
  if (abs(analogRead(3) - Volume) > TOLENCE) {
    // 读取音量设置
    Volume = analogRead(3);
    //  设置 SD 为LOW
    HT513_WriteOneByte(0x12, 0b11110000);
    uint8_t Vol=map(Volume,0,511,0x07,0xff);
    HT513_WriteOneByte(0x16, Vol);
    //  设置 SD 为HIGH
    HT513_WriteOneByte(0x12, 0b11110100);
    Serial.print(analogRead(3), HEX);
    Serial.print("  ");
    Serial.print(Volume, HEX);
    Serial.print("  ");
    Serial.println(Vol, HEX);
  }
}Other Steps to ReproduceNo response What is your development environment (incl. core version info)Arduino 2.3.6 I have checked existing issues, discussions and online documentation
 | 
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
| I guess your issue is rather audio feed-back than echo. Here is some theoretical advice: 
 | 
Beta Was this translation helpful? Give feedback.
-
| I use VolumeStream to reduce the sensitivity of the microphone. If the output sound after AMP(HT513), there still would be echo. | 
Beta Was this translation helpful? Give feedback.
I guess your issue is rather audio feed-back than echo.
Here is some theoretical advice: