ESP2-I2S音频播放笔记

ESP32的I2S设计的比较奇怪,或者也可以说比较强大。I2S在我们印象中是用来传输音频数字信号的通信接口,但是参考ESP32的数据手册会发现远远不止如此。初次看他这部分的手册总是会把人看的云里雾里。

ESP32的硬件I2S可以实现功能主要有以下几个场景:

  • 驱动LCD液晶屏
  • 可以连接CAMERA
  • 可以连接内部DA实现音频播放
  • 可以连接内部AD实现录音

下面笔记记录的都是和音频播放相关,其他模式暂时没做讨论。

ESP32一共有两个I2S:I2S0、I2S1。

但是只有I2S0支持连接内部ADC和DAC,也就是要实现录音和播放只能使用I2S0。

当   I2S—ADC 要把I2S0配置为主机接收模式

当   I2S—DAC 要把I2S0配置为主机发送模式

I2S的时钟源有两个:

  • PLL_D2_CLK(ADC/DAC模式下要使用该时钟)
  • APLL_CLK 

使用ESP32-IDF配置音频播放的时候,不需要手动指定哪底层已经封装好了

I2S  FIFO读写:

ESP32的FIFO读写长度都是按照32位来的。而对FIFO的操作方式有两种:一种是通过CPU直接进行操作;另一种是通过DMA进行读写操作。音频播放呢就是把写入FIFO中的数据通过DMA搬到DA然后输出一个模拟量。录音就是通过DMA把AD采集到的值搬倒FIFO里面去,然后读走保存。

关于FIFO的配置还涉及到单声道双声道的问题,可以去研读esp32参考手册。

音频播放位数问题:

理论上我们采集的音频使用的AD位数越高,失真率就越小,播放出来音质就会越高。但是ESP32有个限制就是DA输出是8位的,也就是不管你用16位音源还是12位或者8位音源最终都会被转成8位的送到DAC去播放。所以这个也限制了ESP32使用内部DA播放做不到太好的音质。

播放的音频文件也没必要用16位采样的音源,浪费存储空间,数据还要进行转换才能送入DA播放。

音频播放初始化代码:

把音频数据进行转换的代码:

我们的音频PCM数据采样位数是8位,但是在DMA传输过程中,最少是一次传输16位(前面提到FIFO按照32位来读写和这里不矛盾,低16位会自动被填充0)。那么我们就要把8位的数据转换成16位的,再送去FIFO。

这里我自己加了个音量转换,最终送出去的数据,会根据音量大小进行成比例的放大缩小。

最后就是播放音频的代码:

播放的思路,就是分段从我的音频table里面读数据,读回来以后进行数据转换,然后再写入i2s缓冲区中,等待DMA把他都搬入DA,重复执行直到播放完毕。

您可能还喜欢...

4 条回复

  1. 江毅说道:

    请问 i2s_write 这个函数哪里来的,是不是这决定输出的是什么?

  2. xixihaha说道:

    请问我乘以一个小于1的音量,声音为什么会失真呢

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注