基于FPGA设计的音乐播放器

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


基于FPGA设计的音乐播放器

本文将介绍如何使用FPGA和PCM5102音频解码模块来制作音乐播放器,从生成PCM格式的音频文件开始,到如何编写I2S总线协议代码,音频数据的储存等。

一、生成PCM音频格式的音乐文件

1.PCM音频文件格式

PCM(Pulse Code Modulation,脉冲编码调制)音频数据是未经压缩的音频采样数据裸流,它是由模拟信号经过采样、量化、编码转换成的标准数字音频数据。PCM音频的几个关键参数如下。

参数 描述
采样率(Sample Rate) 表示一帧音频数据的出现频率,在每一个周期期间内,传输完所有声道的音频信息。常用的有44.1kHz
量化位数(Sample Size) 表示对音频数据的量化位数,即单个通道的位宽。常用的有16bit,24bit,32bit
通道个数(Channels ) 表示音频数据的通道个数,双通道即可完成立体声效果,但双通道不一定是立体声,而立体声一定是多通道
数据符号(Sign) 表示音频数据是否带符号,有符号和无符号数的表示范围不同。例如当位宽为8bit时,有符号的话表示范围为-128 ~ 127,无符号是0 ~ 255

简单介绍如下:假设正弦波形为音频模拟信号,发出的声音为"滴",按照如图所示的采样、量化、编码为32bit有符号的数据,即为单通道PCM音频数据。
在这里插入图片描述
当然我们制作音乐播放器肯定不是只能播放出"滴",所以需要先生成满足需求的音频数据,就选取周杰伦的七里香钢琴曲作为音频源文件。下载WAV格式的音频文件,这里可以使用qq音乐下载MP3格式后,在进行音频转码为WAVE格式,如图所示。
在这里插入图片描述

2.Matlab读取WAV文件

当音频转码完成后,生成的WAV文件可直接使用matlab进行读取,使用函数audioread即可,下面附上完整读取、采样、量化、进制转换代码。

%% 读取wav音频文件,写入mif/coe
clear all ;
clc ;
wav  = audioread('周杰伦 - 七里香(钢琴版).wav') ;
% 低采样
sr = 3 ;
m = floor( max(wav) ) / 3 ;
wav_catch = zeros(m , 2) ;
wav_catch(: , 1) = wav(1:m , 1) ;
wav_catch(: , 2) = wav(1:m , 2) ;
save wav_catch wav_catch ;
% 截取部分时间,同时增大幅度值,位宽为32bit
l = 16384 ;
audio_l = wav_catch(1:l , 1) * 2^31 ;
audio_r = wav_catch(1:l , 2) * 2^31 ;
% 十进制 -> 十六进制
audio_l(find(audio_l<0)) = audio_l(find(audio_l<0)) + 2^32 ;
audio_r(find(audio_r<0)) = audio_r(find(audio_r<0)) + 2^32 ;
audio_l_hex = dec2hex(audio_l) ;
audio_r_hex = dec2hex(audio_r) ;

其中各个模块已经给出了中文注释,由于负数在FPGA中是以补码的形式进行储存,对于其中的十进制转换十六进制有不懂的地方可自行百度。到这里就已经得到了满足PCM格式的音频数据文件,由于数据量过大,如若使用ROM来存储,将会耗费大量的BRAM资源以及底层逻辑资源,甚至造成资源不够的情况。

当然若使用此种方式,需要生成COE或MIF文件可参考MATLAB生成COE或MIF文件代码
在本设计中需要完整的播放整个音乐文件,即使已经将采样率压缩到16KHz,FPGA上的ROM资源依然不够,所以采用SD卡的方式,或是通过串口写入到FLASH上面进行音频文件的储存,该部分内容会在后续完成后上传。

2022/03/22 毕业论文初稿完成,得闲,不愿荒废时光,却又找不到什么实际意义的事情,随便记录一下,留着以后怀念。

二、音频文件储存

1.ROM存储简单音频文件

本来之前想把整首曲子存储在sd卡或是ddr里面,然中间很多事情耽搁了,现在又投身工作了,难以抽身。无意间看到有私信求更,才想起来,那就简单的更完吧。

在FPGA中,只读存储器ROM(read only memory)常用于存放初始数据。ROM中的数据需要先进行初始化,即要先将数据写入到ROM内部的存储单元中,然后系统正常工作时,只能读出其中存储的数据,而不能写入信息,且其中储存的数据掉电不会丢失。由前面章节介绍可知,我们需要在ROM中存入音频数据,格式为PCM音频数据格式,如下图所示。

在这里插入图片描述

为了体现立体声的效果,我们设计传输两个声道的音频信息,选用双声道的数据格式。音频数据都选用正弦波形数据,其播放出来的声音为“滴”,但两个声道传输的正弦波形数据的幅度不同,在播放时两边声音的音量大小不同。设计时先使用Matlab生成幅度变化满足需求的音频数据,并创建内存初始化(mif)文件,将正弦波数据写入。然后使用EDA工具quartus直接调用已经封装好的ROM存储器IP核,如图所示。
我们设定ROM的输出端口位宽为32bit,指定存储器的深度为256,表示本IP核可以存储256个32bit位宽的音频数据。通过载入mif文件为存储器提供存储器初始化数据,并编写仿真文件对该ROM进行测试验证。

在这里插入图片描述

如下图所示为ROM的功能仿真波形图。从图中可知,左右声道中传输的数据不同,故在经过PCM5102解码模块解码后的音频信息中,可以明显的感受到立体声效果,这是由于双耳播放的音频不同导致的。
在这里插入图片描述

2. I2S数据传输协议

PCM5102解码模块是基于I2S传输协议,选择左对齐模式下的I2S传输协议进行代码编写和功能仿真。
首先,I2S总线共拥有三条数据信号线,一条系统时钟线,各信号简要介绍如下:
(1)BCK:串行时钟信号,每一个脉冲周期对应于数字音频文件中的每一位数据,所以也称为位同步时钟信号。在本设计中,声道数为2,音频数据位宽为32位,那么BCK的频率可通过如下公式计算:
在这里插入图片描述

其中f(lrck)为采样频率。
(2)LRCK:声道选择信号,用于切换左右声道的数据,也称为帧同步信号。命令选择线表明了正在被传输的声道,LRCK为低电平表示正在传输的是左声道的数据,LRCK为高电平表示正在传输的是右声道的数据。该信号的频率即是采样频率。
(3)SDIN:串行数据信号,即将音频数据按照串行的方式进行传输,先传输数据的最高位,最低位的位置则是依赖于数据的有效位数,本设计中有效位数是32位,那么不存在无效位,传输前音频数据都应转换为二进制补码的形式。
(4)SCK:系统时钟信号,当处于主模式时,可用于为外部设备提供系统时钟,工作为从模式时,不可用。

本文根据解码模块的系统时钟要求,如下图所示,图片来自pcm5102模块文档说明。我们选择采样时钟为16KHz,系统时钟为4.096MHz,进行时序设计。
在这里插入图片描述
其中基于i2s协议的数据发送代码如下:

module I2S_SEND (
        input           clk     ,   // 50M
        input           rstn    ,
        input   [31:0]  audio_l ,
        input   [31
  • 19
    点赞
  • 161
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

庐州学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值