打印
[MM32软件]

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

[复制链接]
2020|24
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 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文件中是没有格式的,所以我们需要选择好格式,如下图所示。

打开音频文件后,我们可以试听,也可以剪裁,由于我们的flash一共才1M字节,所以我们必须剪裁到整首歌的绝大部份,直到小于1M为止,最好不要超过900K了,不一会儿用串口ymodem下载的时间也是超级长。
2、通过I2S来播放音乐文件
2.1 硬件接口

通过硬件原理图可见,I2S接口功占用5个IO口,分别为PC2,PC4,PC5,PC6,PC7。由于PC4,5,7三个IO口和SLCD的驱动引脚复用了,所以这里必须注意,需要将SW1和SW2的开关拨到右侧,使能I2S的连接。
2.2 I2S接口初始化
为了简化实现过程,我这里选择采用中断方式来完成,因此I2S接口的配置为:
/* I2S. */
#define BOARD_I2S_PORT SPI1
#define BOARD_I2S_FREQ CLOCK_APB2_FREQ
#define BOARD_I2S_SAMPLE_RATE 8000u
#define BOARD_I2S_DATA_WIDTH I2S_DataWidth_16b
#define BOARD_I2S_PROTOCOL I2S_Protocol_PHILIPS
#define BOARD_I2S_CPOL I2S_Polarity_0
#define BOARD_I2S_IRQHandler SPI1_IRQHandler
#define BOARD_I2S_IRQn SPI1_IRQn

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

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

3)shell的使用
   建立一个shell命令,用来启动音乐播放。
int play(int argc, char *argv[])
{
uint8_t musiclen[10];
uint8_t i;
short int *data_ptr = (short int *)tab_1024;
shellPrint(&shell, "play music in spiflash\n\r");
sfud_err err;
FlashDestination = 0;
/* sfud read. */
err = sfud_read(sfud_get_device(SFUD_SPI_DEVICE_INDEX), 128, 10, musiclen);
for(i=0;i<10;i++)
{
if(musiclen[i] == 0xff)
{
musiclen[i] = '\0';
}
}
Str2Int(musiclen, &musicl);
if(musicl ==0 & musicl > 1024*1024 - 256)
{
shellPrint(&shell, "music lenth error %d\n\r", musicl);
return -1;
}
GPIO_WriteBit(BOARD_LED0_GPIO_PORT, BOARD_LED0_GPIO_PIN, 0); /* led on. */
I2S_Enable(BOARD_I2S_PORT, true);
while(musicl > FlashDestination)
{
}
GPIO_WriteBit(BOARD_LED0_GPIO_PORT, BOARD_LED0_GPIO_PIN, 1); /* led on. */
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), play, play, play a music in flash);

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


视频

代码: shell+ymodem+i2s.rar (42.79 KB)




使用特权

评论回复
沙发
chenjun89| | 2022-12-3 09:17 | 只看该作者
不错,下载参考一下,谢谢分享。

使用特权

评论回复
板凳
coslight|  楼主 | 2022-12-3 09:20 | 只看该作者
chenjun89 发表于 2022-12-3 09:17
不错,下载参考一下,谢谢分享。

谢谢鼓励,一起交流

使用特权

评论回复
地板
coslight|  楼主 | 2022-12-3 09:21 | 只看该作者
视频没有显示出来,不知道啥意思,把地址在重新贴一下
https://v.youku.com/v_show/id_XNTkyNTUxNjQyNA==.html

使用特权

评论回复
5
coslight|  楼主 | 2022-12-3 09:25 | 只看该作者
重新又编辑了一下,现在可以了

使用特权

评论回复
6
zhanzr21| | 2022-12-3 21:50 | 只看该作者
音频处理软件推荐 Audacity
你值得拥有

使用特权

评论回复
7
coslight|  楼主 | 2022-12-4 09:34 | 只看该作者
zhanzr21 发表于 2022-12-3 21:50
音频处理软件推荐 Audacity
你值得拥有

不错的软件,收藏一下.

使用特权

评论回复
8
xu@xupt| | 2022-12-7 16:13 | 只看该作者
参考学习一下

使用特权

评论回复
9
weifeng90| | 2022-12-7 17:43 | 只看该作者
最高采样率位数可以做到多少位呢?

使用特权

评论回复
10
Innercourage| | 2022-12-10 10:08 | 只看该作者
不错的软件,收藏一下.

使用特权

评论回复
11
tpgf| | 2023-1-3 09:05 | 只看该作者
我们常用的利用I2S播放Flash的文件中,都支持什么类型的文件呢

使用特权

评论回复
12
qcliu| | 2023-1-3 09:18 | 只看该作者
这种带显示屏显示的文件 是不是能过快刷新的吧

使用特权

评论回复
13
drer| | 2023-1-3 09:29 | 只看该作者
请问pcm文件的格式如何进行简化呢

使用特权

评论回复
14
coshi| | 2023-1-3 09:40 | 只看该作者
PCM 是脉冲编码调制文件。 PCM文件具有流媒体特性,是数字通信的编码方式之一

使用特权

评论回复
15
kxsi| | 2023-1-3 09:47 | 只看该作者
PCM文件被广泛用于素材保存及音乐欣赏,CD、DVD以及我们常见的 WAV文件中均有应用

使用特权

评论回复
16
wiba| | 2023-1-3 10:19 | 只看该作者
PCM文件能够一边读一边播放,而不需要把这个文件全部读出后然后回放

使用特权

评论回复
17
coslight|  楼主 | 2023-1-3 13:27 | 只看该作者
wiba 发表于 2023-1-3 10:19
PCM文件能够一边读一边播放,而不需要把这个文件全部读出后然后回放

全读出来不可能,内存不够用,都是一边读一边放

使用特权

评论回复
18
caigang13| | 2023-1-3 21:10 | 只看该作者
PCM文件的采样率只能这么高吗?

使用特权

评论回复
19
coslight|  楼主 | 2023-1-4 08:12 | 只看该作者
caigang13 发表于 2023-1-3 21:10
PCM文件的采样率只能这么高吗?

可以提高,但是文件会变大,播放时间就更短了,如果存储空间足够的话,可以选择采样率更高的,甚至是立体声的也可以

使用特权

评论回复
20
Jacquetry| | 2023-1-5 17:12 | 只看该作者

最高采样率位数可以做到多少位呢?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

61

主题

928

帖子

5

粉丝