乐鑫技术交流
直播中

周必镜

7年用户 930经验值
私信 关注
[问答]

关于音频I2S通讯中DMA bufsize最大为4092的相关问题求解

您好:
我正在使用 esp-idf-v5.2,为 esp32-s3 编译,开发板为ESP32-S3_DevKitM-1。
我在外部连接了pcm1808 芯片作为从机为S3传输音频帧。

我已经了解的如下:尽管pcm1808 发送的数据宽度为 I2S_DATA_BIT_WIDTH_24BIT (24位3字节),但实际ESP I2S DMA buffer仍然是按照每个数据4字节的宽度用i2s_dma_calloc申请到内存,我的应用中只需要I2S接收单声道音频,所以只需要一个左声道,由于 DMA bufsize 最大为4092,是否也就是限制了我的通道配置中dma_frame_num最大只能1023,也就是每帧最大1023个样本?
1023 *声道数*4字节位宽 = 4092

但事实上我需要在随后的音频帧处理中用到 ESP dsp库的FFT函数处理,FFT处理的样本数为2的n次方,1024个样本数是我需要的,512个显然对于我的应用不够。在这种情况下我是否无法从I2S DMA buffer得到1024个样本数据呢?如果是真的这样的话我也许只能再补0凑足1024个样本数再进行FFT计算。

我的I2S 初始化代码如下:
代码:
// 新建I2S通道配置、新建I2S通道,新建I2S std配置、初始换通道的std模式static void i2s_example_init_std_duplex(void){       // i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_SLAVE);    i2s_chan_config_t chan_cfg = {        .id = I2S_NUM_AUTO,            .role = I2S_ROLE_MASTER,              .dma_desc_num = 2,                          .dma_frame_num = 1024,                                                       .auto_clear = false,                         .intr_priority = 0,                      };    ESP_ERROR_CHECK(i2s_new_channel( chan_cfg, NULL,  rx_chan));     i2s_std_config_t std_cfg = {        // .clk_cfg  = I2S_STD_CLK_DEFAULT_CONFIG(PCM1808_SAMPLE_RATE),        .clk_cfg.sample_rate_hz = PCM1808_SAMPLE_RATE,        .clk_cfg.clk_src = I2S_CLK_SRC_DEFAULT, // I2S_CLK_SRC_EXTERNAL,        .clk_cfg.mclk_multiple = I2S_MULTIPLE,        .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_24BIT, I2S_SLOT_MODE_STEREO),        .slot_cfg.slot_mode = I2S_SLOT_MODE_MONO,        .slot_cfg.slot_mask = I2S_STD_SLOT_LEFT,        .slot_cfg.bit_shift = true,        .slot_cfg.left_align = false,        .gpio_cfg = {            .mclk = I2S_STD_MCLK_EXTERNAL_IO1, // some codecs may require mclk signal, this example doesn't need it            .bclk = I2S_BCLK_IO1,            .ws = I2S_STD_WS_IO1,            .dout = I2S_STD_DOUT_IO1,            .din = I2S_STD_DIN_IO1, // In duplex mode, bind output and input to a same gpio can loopback internally            .invert_flags = {                .mclk_inv = false,                .bclk_inv = false,                .ws_inv = false,            },        },    };        ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_chan,  std_cfg));}
得到的调试信息包含:
D (34676) i2s_common: rx channel is registered on I2S0 successfully
W (34676) i2s_common: dma frame num is out of dma buffer size, limited to 10
D (34676) i2s_common: DMA malloc info: dma_desc_num = 2, dma_desc_buf_size = data_bit_width = 4092
D (34696) i2s_std: Clock division info: [sclk] 160000000 Hz [mdiv] 13 [mclk]] 1536000 Hz
D (34706) i2s_common: MCLK is pinned to GPIO42 on I2S0
D (34706) i2s_std: The rx channel on I2S0 has been initialized to STD mode successfully
D (34716) i2s_common: i2s rx channel enabled

我的另一个问题是:
以上初始化代码在编译中出现了警告:

In function 'i2s_example_init_std_duplex':
warning: initialized field overwritten [-Woverride-init]
70 | .slot_cfg.slot_mode = I2S_SLOT_MODE_MONO,
| ^~~~~~~~~~~~~~~~~~
note: (near initialization for 'std_cfg.slot_cfg.slot_mode')
warning: initialized field overwritten [-Woverride-init]
71 | .slot_cfg.slot_mask = I2S_STD_SLOT_LEFT,
| ^~~~~~~~~~~~~~~~~
note: (near initialization for 'std_cfg.slot_cfg.slot_mask')
warning: initialized field overwritten [-Woverride-init]
73 | .slot_cfg.bit_shift = true,
| ^~~~
note: (near initialization for 'std_cfg.slot_cfg.bit_shift')
warning: initialized field overwritten [-Woverride-init]
74 | .slot_cfg.left_align = false,

请问这是我代码中两个配置函数使用的顺序问题吗?


                                                                                                                                               

回帖(1)

陈敏

2024-7-19 14:37:49
您好!您的问题涉及到ESP32-S3的I2S通信和DMA缓冲区大小。让我们逐步分析您的问题。

1. **PCM1808数据宽度**:PCM1808发送的数据宽度为24位(3字节),这意味着每个音频样本需要3字节的存储空间。

2. **ESP I2S DMA缓冲区**:尽管PCM1808发送的数据宽度为24位,但ESP32-S3的I2S DMA缓冲区仍然按照每个数据4字节的宽度进行分配。这是因为ESP32-S3的I2S DMA引擎需要对齐内存地址,以便更高效地处理数据。

3. **单声道音频**:您的应用中只需要接收单声道音频,这意味着每个音频帧只需要一个左声道的样本。

4. **DMA bufsize限制**:您提到DMA bufsize最大为4092字节。这意味着在这种情况下,您可以分配的最大缓冲区大小为4092字节。

5. **计算dma_frame_num**:根据您的描述,我们可以计算dma_frame_num的最大值。由于每个音频样本需要3字节,而每个帧包含一个左声道样本,我们可以这样计算:

   `dma_frame_num = DMA_bufsize / (声道数 * 位宽)`

   将已知的值代入公式:

   `dma_frame_num = 4092 / (1 * 3)`

   `dma_frame_num ≈ 1364`

   这意味着在这种情况下,dma_frame_num的最大值约为1364。

6. **结论**:根据您的需求和限制,dma_frame_num的最大值约为1364,而不是1023。这是因为每个音频样本需要3字节,而不是4字节。因此,您可以在您的应用中设置dma_frame_num为1364,以便充分利用4092字节的DMA缓冲区。

希望这能帮助您解决问题。如果您还有其他问题或需要进一步的帮助,请随时告诉我!
举报

更多回帖

发帖
×
20
完善资料,
赚取积分