ESP-WROOM-32 I2S音频信号幅度读取异常

DEV2021
Posts: 5
Joined: Thu Apr 18, 2024 11:52 am

ESP-WROOM-32 I2S音频信号幅度读取异常

Postby DEV2021 » Thu Apr 18, 2024 12:33 pm

音频信号发生器输出的AES音频信号,通过CS8416转换为i2s音频信号,BCK、WS、SDATAT三路信号分别接ESP-WROOM-32开发板32、25、33引脚。
信号源产生的音频信号为采样率48KHz、24bit量化精度、双声道。
通过CS8416转换输出,输出格式选择为i2s,BCK设置为64fs(3.072M),因为i2s数据为MSB格式,因此可以兼容32、24、20、16四种采样精度。

通过以下代码获取ESP32 i2s接口采集的数据最大幅度:

#include <driver/i2s.h>

//I2S音频数据采样率48K
#define I2S_SAMPLE_RATE (48000)
//音频数据缓冲区大小
#define I2S_BUF_SIZE (1024)

//ESP32 i2s信号输入引脚GPIO编号
#define I2S_PIN_BCK (32)
#define I2S_PIN_WS (25)
#define I2S_PIN_SDATA (33)

//I2S数据读取缓冲区(左右声道)
int32_t i2s_buffer[I2S_BUF_SIZE * 2];

//左声道和右声道最大振幅
int16_t max_left_amplitude = INT16_MIN;
int16_t max_right_amplitude = INT16_MIN;


void setup() {
Serial.begin(9600);

//配置I2S接口
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_SLAVE | I2S_MODE_RX), //设置为I2S从设备模式,接收数据
.sample_rate = I2S_SAMPLE_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
.intr_alloc_flags = 0,
.dma_buf_count = 8,
.dma_buf_len = I2S_BUF_SIZE,
.use_apll = false
};

//安装I2S驱动
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);

//配置I2S pins
i2s_pin_config_t pin_config = {
.bck_io_num = I2S_PIN_BCK, //BCK引脚
.ws_io_num = I2S_PIN_WS, //WS引脚
.data_out_num = I2S_PIN_NO_CHANGE, //SDATA输出引脚
.data_in_num = I2S_PIN_SDATA //SDATA输入引脚
};
i2s_set_pin(I2S_NUM_0, &pin_config);

//启动I2S接口
i2s_zero_dma_buffer(I2S_NUM_0);
i2s_start(I2S_NUM_0);

}

void loop()
{
size_t bytes_read = 0;
i2s_read(I2S_NUM_0, i2s_buffer, I2S_BUF_SIZE * 2 * sizeof(int32_t), &bytes_read, portMAX_DELAY);

//左声道和右声道最大振幅复位
max_left_amplitude = INT16_MIN;
max_right_amplitude = INT16_MIN;

for (size_t i = 0; i < bytes_read / sizeof(int32_t); i += 2)
{
//左右声道数据取高16位
int16_t left_sample = (i2s_buffer >> 16) & 0xFFFF;
int16_t right_sample = (i2s_buffer[i + 1] >> 16) & 0xFFFF;

//获取音频幅度最大振幅
if (max_left_amplitude < abs(left_sample)) {
max_left_amplitude = abs(left_sample);
}
if (max_right_amplitude < abs(right_sample)) {
max_right_amplitude = abs(right_sample);
}
}

//振幅数值转换为分贝值
//以0dBFS为参考电平
//16位量化,最大幅度为2^15-1
float max_left_db = 20 * log10(max_left_amplitude / 32767.0);
float max_right_db = 20 * log10(max_right_amplitude / 32767.0);

//输出左右声道的最大振幅
Serial.printf("L=%4.0fdB R=%4.0fdB\r\n", max_left_db, max_right_db);

delay(20);
}


运行上述代码,信号发生器产生幅度为-20dB的音频信号,打印输出的信号最高幅度与信号频率如下:

1KHz -20dB
2KHz -21dB
3KHz -22dB
4KHz -24dB
5KHz -25dB
6KHz -26dB
8KHz -27dB
10KHz -28dB
12-20KHz -29dB

也即是:随着频率的升高,读取到的音频数据最高幅度在降低。

信号发生器输出的信号同时送其它测试仪器,没有这种情况存在。

在设置1KHz-12KHz任意一种频率,然后保持频率不变,以1dB为单位更改信号幅度,打印输出的信号幅度同样以1dB进行变化。

前级音频信号幅度的变化,只会导致音频数据产生变化,但音频数据通过泰克等测试仪测试,以及其它音频监测设备测试,不存在频率升高导致幅度降低的情况。

i2s数据输入ESP32,即使舍弃低位,也只是在精度上有所变化,不会对音量幅度产生大的影响。

程序对32位数据全部处理,得到的结果也是一样。


对于目前这种结果,不清楚是什么原因导致,是否ESP32内部对输入的i2s音频数据重新进行了处理?

期待技术帮助,谢谢!

DEV2021
Posts: 5
Joined: Thu Apr 18, 2024 11:52 am

Re: ESP-WROOM-32 I2S音频信号幅度读取异常

Postby DEV2021 » Fri Apr 19, 2024 5:34 am

问题原因找到了,与CS8416 02寄存器EMPH_CNTL去加重设置相关,改成000或100问题解决。

Who is online

Users browsing this forum: No registered users and 42 guests