[MM32软件] 【EV Board (MM32L0136C7P)测评】+利用I2S播放Flash中的PCM文件

[复制链接]
 楼主| coslight 发表于 2022-12-3 09:16 | 显示全部楼层 |阅读模式
<
本帖最后由 coslight 于 2022-12-3 09:23 编辑

通过I2S播放flash中的音乐文件
本测试是在前一个测试的基础上,利用shell终端和ymodem将音乐文件存储到spi flash中,然后通过shell 终端启动I2S来播放存储在flash中的音乐文件。
1、文件制作
由于这款控制器是CM0内核,处理能力有限,所以只能播放WAV或PCM这类不需要解压缩操作的音频文件,这里选择采用PCM文件,因为处理起来相当的简单。
PCM(Pulse Code Modulation)编码,即通过脉冲编码调制方法生成数字音频数据的技术或格式,是一种无损编码格式,是音频模拟信号数字化的一种方法,需要经过采样、量化和编码过程,以实现音频模拟信号数字化。简单说,PCM文件中存储的就是AD量化后的音频数据,通常为16位的有符号数,我们也不用做处理,读出这些文件直接通过I2S送给DA输出就可以了。当然还是有一些特殊性的,不过这里不详细讨论了,感兴趣的同学可以上网查找一下。
这里我们还需要两个软件,一个为ffmpeg,一个可以将mp3文件转换为我们需要的pcm格式的文件。另一个是CoolEdit,这个工具软件可以播放音频文件,也可以剪辑音频文件,贼方便。
1)Mp3转PCM
我们利用ffmpeg 实现这个功能,前面我们说,控制器能力有限,我们这里也尽量简化PCM文件的格式,稍有音质损失也是可以接受的。所以选择为单通道,8K采样率的输出格式,我们可以采用下面的命令,
.\ffmpeg -i 音乐名称.mp3 -f s16le -ar 8000 -ac 1 -acodec pcm_s16le 输出音频名称.pcm
通常一首3分钟左右的mp3,转换为单通道8K采样率的pcm文件通常在3M字节左右的文件,这个对于我们来说太大了,我们必须要剪裁一下才可以。
2)PCM文件剪裁
打开Cooledit工具软件,载入刚才转换好的PCM文件,这里要注意,因为这个PCM文件中是没有格式的,所以我们需要选择好格式,如下图所示。
c1e02b4104a1beefa93bc60695a680ed 3d2f060c82ef176a620d9654973e5882
打开音频文件后,我们可以试听,也可以剪裁,由于我们的flash一共才1M字节,所以我们必须剪裁到整首歌的绝大部份,直到小于1M为止,最好不要超过900K了,不一会儿用串口ymodem下载的时间也是超级长。
2、通过I2S来播放音乐文件
2.1 硬件接口
253998a1de1ff93a3b73b517847e9d29
通过硬件原理图可见,I2S接口功占用5个IO口,分别为PC2,PC4,PC5,PC6,PC7。由于PC4,5,7三个IO口和SLCD的驱动引脚复用了,所以这里必须注意,需要将SW1和SW2的开关拨到右侧,使能I2S的连接。
2.2 I2S接口初始化
为了简化实现过程,我这里选择采用中断方式来完成,因此I2S接口的配置为:
  1. /* I2S. */
  2. #define BOARD_I2S_PORT SPI1
  3. #define BOARD_I2S_FREQ CLOCK_APB2_FREQ
  4. #define BOARD_I2S_SAMPLE_RATE 8000u
  5. #define BOARD_I2S_DATA_WIDTH I2S_DataWidth_16b
  6. #define BOARD_I2S_PROTOCOL I2S_Protocol_PHILIPS
  7. #define BOARD_I2S_CPOL I2S_Polarity_0
  8. #define BOARD_I2S_IRQHandler SPI1_IRQHandler
  9. #define BOARD_I2S_IRQn SPI1_IRQn

因为我们的PCM文件为单通道,8K采样率,16位采样宽度,因此,配置参数如上。
初始化I2S为主机发送模式,产生MCLK信号。
  1. /* setup I2S master module. */
  2. I2S_Master_Init_Type i2s_master_init;
  3. i2s_master_init.ClockFreqHz = BOARD_I2S_FREQ;
  4. i2s_master_init.SampleRate = BOARD_I2S_SAMPLE_RATE;
  5. i2s_master_init.DataWidth = BOARD_I2S_DATA_WIDTH;
  6. i2s_master_init.Protocol = BOARD_I2S_PROTOCOL;
  7. i2s_master_init.EnableMCLK = true;
  8. i2s_master_init.Polarity = BOARD_I2S_CPOL;
  9. i2s_master_init.XferMode = I2S_XferMode_TxOnly;
  10. I2S_InitMaster(BOARD_I2S_PORT, &i2s_master_init);
  11. /* Enable I2S tx buffer empty interrupt. */
  12. I2S_EnableInterrupts(BOARD_I2S_PORT, I2S_INT_TX_EMPTY, true);
  13. NVIC_EnableIRQ(BOARD_I2S_IRQn);

2.3 I2S中断函数
I2S中断中判断当前的传输通道,让后切换到下一个通道去传输数据,实际是先左通道,在右通道,如此交替下去。
由于是单通道,所以读取一次数据分别传递给左右两个通道,相当于让他们发出相同的声音。
所在右通道传输完成的时候,我们从flash中读取两个字节,构成一个16位的音频数据,所以数据指针每次都是加2的,直到文件尾部,关闭I2S,结束播放。
  1. /* I2S interrupt handler. */
  2. void BOARD_I2S_IRQHandler(void)
  3. {
  4. static int16_t data = 0;
  5. /* Get interrupt status. */
  6. uint32_t flag = I2S_GetInterruptStatus(BOARD_I2S_PORT);
  7. if (0u != (flag & I2S_INT_TX_EMPTY) )
  8. {
  9. if (I2S_Channel_Left != I2S_GetXferChannel(BOARD_I2S_PORT) )
  10. {
  11. app_i2s_put_data_left(data); /* Send right data, buffer put left data to prepare next send. */
  12. }
  13. else
  14. {
  15. app_i2s_put_data_right(data); /* Send left data, buffer put right data to prepare next send. */
  16. sfud_read(sfud_get_device(SFUD_SPI_DEVICE_INDEX), FlashDestination + APP_SFUD_PAGE_SIZE, 2, (uint8_t *)&data);
  17. FlashDestination+=2;
  18. if(FlashDestination >= musicl)
  19. {
  20. I2S_Enable(BOARD_I2S_PORT, false);
  21. }
  22. if((FlashDestination % 1000 ) < 500)
  23. {
  24. GPIO_WriteBit(BOARD_LED1_GPIO_PORT, BOARD_LED1_GPIO_PIN, 1u);
  25. GPIO_WriteBit(BOARD_LED2_GPIO_PORT, BOARD_LED2_GPIO_PIN, 0u);
  26. }
  27. else
  28. {
  29. GPIO_WriteBit(BOARD_LED1_GPIO_PORT, BOARD_LED1_GPIO_PIN, 0u);
  30. GPIO_WriteBit(BOARD_LED2_GPIO_PORT, BOARD_LED2_GPIO_PIN, 1u);
  31. }
  32. }
  33. }
  34. /* Clear interrupt status. */
  35. I2S_ClearInterruptStatus(BOARD_I2S_PORT, flag);
  36. }

3)shell的使用
   建立一个shell命令,用来启动音乐播放。
  1. int play(int argc, char *argv[])
  2. {
  3. uint8_t musiclen[10];
  4. uint8_t i;
  5. short int *data_ptr = (short int *)tab_1024;
  6. shellPrint(&shell, "play music in spiflash\n\r");
  7. sfud_err err;
  8. FlashDestination = 0;
  9. /* sfud read. */
  10. err = sfud_read(sfud_get_device(SFUD_SPI_DEVICE_INDEX), 128, 10, musiclen);
  11. for(i=0;i<10;i++)
  12. {
  13. if(musiclen[i] == 0xff)
  14. {
  15. musiclen[i] = '\0';
  16. }
  17. }
  18. Str2Int(musiclen, &musicl);
  19. if(musicl ==0 & musicl > 1024*1024 - 256)
  20. {
  21. shellPrint(&shell, "music lenth error %d\n\r", musicl);
  22. return -1;
  23. }
  24. GPIO_WriteBit(BOARD_LED0_GPIO_PORT, BOARD_LED0_GPIO_PIN, 0); /* led on. */
  25. I2S_Enable(BOARD_I2S_PORT, true);
  26. while(musicl > FlashDestination)
  27. {
  28. }
  29. GPIO_WriteBit(BOARD_LED0_GPIO_PORT, BOARD_LED0_GPIO_PIN, 1); /* led on. */
  30. return 0;
  31. }
  32. SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), play, play, play a music in flash);

3、测试运行效果
在shell终端输入play命令后,回车执行,我将在扬声器中听到我们播放的音乐。
ffe4cb9f043f36d70b4cea50686611d7
1968b381fc35ceb2e449279840ffe939
视频

代码: shell+ymodem+i2s.rar (42.79 KB, 下载次数: 24)




chenjun89 发表于 2022-12-3 09:17 来自手机 | 显示全部楼层
s
不错,下载参考一下,谢谢分享。
 楼主| coslight 发表于 2022-12-3 09:20 | 显示全部楼层
s
chenjun89 发表于 2022-12-3 09:17
不错,下载参考一下,谢谢分享。

谢谢鼓励,一起交流
 楼主| coslight 发表于 2022-12-3 09:21 | 显示全部楼层
s
视频没有显示出来,不知道啥意思,把地址在重新贴一下
https://v.youku.com/v_show/id_XNTkyNTUxNjQyNA==.html
 楼主| coslight 发表于 2022-12-3 09:25 | 显示全部楼层
s
重新又编辑了一下,现在可以了
zhanzr21 发表于 2022-12-3 21:50 | 显示全部楼层
s
音频处理软件推荐 Audacity
你值得拥有
 楼主| coslight 发表于 2022-12-4 09:34 | 显示全部楼层
s
zhanzr21 发表于 2022-12-3 21:50
音频处理软件推荐 Audacity
你值得拥有

不错的软件,收藏一下.
xu@xupt 发表于 2022-12-7 16:13 | 显示全部楼层
s
参考学习一下
weifeng90 发表于 2022-12-7 17:43 来自手机 | 显示全部楼层
s
最高采样率位数可以做到多少位呢?
Innercourage 发表于 2022-12-10 10:08 | 显示全部楼层
s
不错的软件,收藏一下.
tpgf 发表于 2023-1-3 09:05 | 显示全部楼层
s
我们常用的利用I2S播放Flash的文件中,都支持什么类型的文件呢
qcliu 发表于 2023-1-3 09:18 | 显示全部楼层
s
这种带显示屏显示的文件 是不是能过快刷新的吧
drer 发表于 2023-1-3 09:29 | 显示全部楼层
s
请问pcm文件的格式如何进行简化呢
coshi 发表于 2023-1-3 09:40 | 显示全部楼层
s
PCM 是脉冲编码调制文件。 PCM文件具有流媒体特性,是数字通信的编码方式之一
kxsi 发表于 2023-1-3 09:47 | 显示全部楼层
s
PCM文件被广泛用于素材保存及音乐欣赏,CD、DVD以及我们常见的 WAV文件中均有应用
wiba 发表于 2023-1-3 10:19 | 显示全部楼层
s
PCM文件能够一边读一边播放,而不需要把这个文件全部读出后然后回放
 楼主| coslight 发表于 2023-1-3 13:27 | 显示全部楼层
s
wiba 发表于 2023-1-3 10:19
PCM文件能够一边读一边播放,而不需要把这个文件全部读出后然后回放

全读出来不可能,内存不够用,都是一边读一边放
caigang13 发表于 2023-1-3 21:10 来自手机 | 显示全部楼层
s
PCM文件的采样率只能这么高吗?
 楼主| coslight 发表于 2023-1-4 08:12 | 显示全部楼层
s
caigang13 发表于 2023-1-3 21:10
PCM文件的采样率只能这么高吗?

可以提高,但是文件会变大,播放时间就更短了,如果存储空间足够的话,可以选择采样率更高的,甚至是立体声的也可以
Jacquetry 发表于 2023-1-5 17:12 | 显示全部楼层
s

最高采样率位数可以做到多少位呢?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

61

主题

928

帖子

5

粉丝
快速回复 在线客服 返回列表 返回顶部