DAC+DMA+TIM实现音频播放问题记录
目录
- 1. 概述
- 2. 音频采样率
- 2.1 定时器触发周期
- 2.2 音频文件的格式
- 3. DAC的左对齐和右对齐
- 3.1 为什么要使用左对齐
- 3.2 左对齐数据的读写
- 3.3 音频数据的使用
- 3.3.1 16bit数据和12位DAC的失真问题
- 3.3.2 音频数据的符号位处理
- 4. 单双声道的理解
- 5. DMA无法进入中断
- 6. 测试播放效果
- 6.1 测试单音
- 6.2 测试播放人声
- 7. 音频文件制作
1. 概述
本文主要记录下音频播放实现过程中遇到的问题。音频文件存储在外部FLASH中,SPI+DMA读取到MCU中,然后进行DAC转换后输入到NS4165B音频功率放大器(数据手册)。第一次接触音频,遇到很多零碎问题,有些问题很基础,主要是学习单片机时不够扎实,统一记录在这里。
先贴三篇参考的文章,都是此方案的实现:
基于STM32的DAC实现音频波形的输出
STM32F103使用TIM DMA DAC实现播放WAV音乐
基于STM32F103C8T6片内Flash的音频播放(DAC通道)
通过这三篇文章,有了一个整体的概念。
2. 音频采样率
2.1 定时器触发周期
DAC使用定时器作为触发源,参考的三篇文章,对定时器的周期设置描述比较少。定时器的周期应该设置多少呢?
定时器计时时间到,进行一次DAC转换,所以应该与音频的采样速率相同。
更多时候是采用DAC,使用I2S通信,可以直接设置音频采样率:
而定时器,则需要自己计算下预分频和计数值:
仿真查看系统时钟0x44AA200 = 72M,修改为预分频12M,再750计数,正好是16K
使用正弦进行测试,每一小段正好为16K
2.2 音频文件的格式
在音频文件的头信息中,包括了单双声道、采样速率等信息。
从第45字节开始,才是采样的音频数据:
具体描述如下:
扩展链接:
1.多媒体文件格式(五):PCM / WAV 格式。
2.PCM音频数据。
3. DAC的左对齐和右对齐
以往ADC也好,DAC也好,以往都是用右对齐,也没关注过左对齐有什么用,使用上有什么区别。
3.1 为什么要使用左对齐
在8位单片机中,超过8位的数据,就要占用H和L两个寄存器。左、右对齐,就对应了H存放高八位和L存放低八位。当对转换精度要求不高时,通过设置左对齐,只读H寄存器取高八位,加快速度。
而在32位单片机,寄存器基本是16位和32位,都是读取一次寄存器,并不存在上述的只读一次H加快速度了。那么左对齐是不是就没用了呢?在这里恰巧用到了左对齐。
参考链接:ADC数据存储:左对齐和右对齐。
3.2 左对齐数据的读写
最常用的是右对齐,数据寄存器如下:
使用时直接对寄存器进行读取即可。而左对齐数据寄存器如下:
设置为左对齐模式,在数据处理时需要进行处理。若寄存器里左对齐的数据值X,则X>>4才是实际的数据。
单片机是按照地址进行读写,并不会因为我们设置了左右对齐,直接将我们的数据放到有效位。
3.3 音频数据的使用
3.3.1 16bit数据和12位DAC的失真问题
我的音频文件是16位,而DAC是12位,那么就要对16位数据进行取舍,所以转换音频数据的高12位。
这个时候如果使用右对齐,需要对每一个音频数据进行移位操作,因为音频数据很大,是比较浪费时间的。那么使用左对齐,就不必进行移位,直接赋值音频数据就可以了。
经过这样处理后,有明显噪音。将音频重新采样为8bit后,能够正常播放,怀疑是16bit忽略低4位导致的。但实际并不是,这个失真是相对使用16位DAC,而使用精度较差的DAC,高精度采样数据,并不会失真,反而可能会更好。这一点,可以通过简单计算理解:
- 假设参考电压3V,实际电压2V,计算12位DAC和16位DAC的采样值。
- 然后忽略16位采样值的低四位,也就是>> 4,与12位DAC的采样值对比。
3.3.2 音频数据的符号位处理
上一小节提到16bit有杂音,改为8bit重新对音频采样,就可以正常播放了。这是因为16位音频数据是有符号的,在使用DAC进行转换时,需要考虑去除符号位。
STM32F103.12位DAC输出16位WAV语音文件
简单的程序将int16_t数组转换为uint16_t
4. 单双声道的理解
单双声道 – DMA每传输一次,地址偏移size,所以配置中size改为字
下一次传输的地址将是前一次传输的地址递增 1个数据宽度、2个数据宽度或 4个数据宽度
【STM32】 DMA原理,步骤超细详解,一文看懂DMA
5. DMA无法进入中断
调试DMA+TIM+DAC实现音频输出,发现无法进入DMA中断,芯片为国民技术N32G45。
一定要先使能DMA通道中断,再使能DMA通道。
6. 测试播放效果
直接播放flash存放的开机音乐等,噪音较大,且波形不是规律的,不易分析。
6.1 测试单音
直接测试flash内的音频,无法播放可能有很多原因。可以先测试单音:通过调整正弦的频率,让喇叭发出不同的声音。
在1 2 3 4 5 6 7的在声乐中的的频率各是多少?帖子中,得到以下频率:
A:440Hz a:880Hz B:493.88Hz b:987.76Hz C∶523.25Hz c:1046.50Hz D: 587.33Hz d:1174.66Hz E∶659.25Hz e:1318.51Hz F∶698.46Hz f:1396.92Hz G∶783.99Hz g:1567.98Hz
再看正弦数组:
一个正弦周期是32个采样点,那么要发哪个声音,就用频率 * 32得到DAC用作触发的定时器频率。定时器预分频为12M,所以再用12M/频率,就得到计数值。
A * 32 12M/(A * 32) a * 32 12M/(a * 32)
A:440Hz a:880Hz 14080 852 28160 426.13
B:493.88Hz b:987.76Hz 15804.16 759 31608 379.65
C∶523.25Hz c:1046.50Hz 16744 716.67 33488 358.33
D: 587.33Hz d:1174.66Hz 18794.56 638.48 37589 319.24
E∶659.25Hz e:1318.51Hz 21096 568.82 42192 284.41
F∶698.46Hz f:1396.92Hz 22350.72 536.91 44701 268.45
G∶783.99Hz g:1567.98Hz 25087.68 478.31 50175 239.16
只要传入计数值即可:
6.2 测试播放人声
为了能够容易感受到调试过程中声音的变化效果,需要使用人声。
在线文字转语音,语音合成,真人语音合成-在线工具
生成后将数据放到const数组即可进行测试。
7. 音频文件制作
自己选一个音乐片段,生成音频文件:Goldwave生成wave音频数据。
DAC+DMA+TIM实现音频播放问题记录相关推荐
- dma接收双缓存 stm32_STM32和WM8960 I2S 利用DMA双缓冲音频播放和录音(二)
前面简单讲解了WM8960语音芯片工作方式,WM8960做master,之前参数配置ADC/DAC采样速率的是44.1K,有点问题,现在改为16K,下面会解释为什么要改成16K. WM8960参数配置 ...
- STM32 DAC + DMA + TIM 输出正弦波,三角波,方波信号
硬件平台:STM32F4 库类型:标准库. 参考:[二代示波器教程]第12章 示波器设计-DAC信号发生器的实现 DAC框图如下: 通过TIM触发DAC转换,转换完成后通过DMA输出. DMA通道框图 ...
- STM32 DAC DMA 使用
目的:STM32 DAC DMA 环形发送音频数据:(ffmpeg.exe 可以将一些常见的音频文件转为原始数据,很强大): 用到的外设:DAC ,TIM,DMA DCA配置 TIM配置 加入代码 H ...
- moodeaudio 源码_MoodeAudio 音频播放器上手配置
MoodeAudio 是运行于树莓派等开发板的高品质音频播放系统.与 Volumio 类似,又有些许不同.它们声音表现是基本一致的,各种配置选项差别不大,MoodeAudio 所提供的选项稍多,播放功 ...
- 基于STM32F103C8T6片内Flash的音频播放(DAC通道)
基于STM32F103C8T6片内Flash的音频播放(DAC通道) 一.STM32的DAC通道介绍 1.DAC 简介 2.STM32中的DAC主要特点 3.DAC 功能框图剖析 4.DAC配置 二. ...
- 原创:Android应用开发记录-Andorid歌词秀(3)使用的Service的音频播放器
在下文中我们实现的简单的音乐播放功能. 原创:Android应用开发记录-Andorid歌词秀(2)先来一个音频播放器 但是这样的方式在程序退出后播放也会停止,为了解决这个问题,使用的Service类 ...
- 基于STM32的flash读写和DAC音频播放
一.STM32的flash读写 1.利用STM32CUBEMX创建工程 之前有过很多次创建工程的例子,这里大致过程如下: 2.keil中添加代码及修改配置 在flash.c中添加如下代码, 在main ...
- DMA-DAC音频播放调试笔记
文章目录 前言 一.工具 1.语音合成 2.语音格式转换 2.1 在线转换 2.2 Audition转换 2.3 [SOX工具](https://sourceforge.net/projects/so ...
- 第38章 I2S—音频播放与录音输入—零死角玩转STM32-F429系列
第38章 I2S-音频播放与录音输入 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/ ...
最新文章
- 帧率配置_《骑马与砍杀2》配置探究:CPU显卡怎么搭配达到理想画质和帧数?...
- 升级oracle spu,Oracle 2017改变:新补丁更新(RU和RUR),新的版本(Release 18和19)
- 关于机器学习的一些推荐
- 对话:在敏捷中,是否可以仍然用需求来替代用户故事?
- 总结 | 计算机视觉领域最常见几中损失函数
- VTK:图片之ImageHybridMedian2D
- SQL Server配置支持中文
- 国防科技大学计算机学院少将,国防科技大学新任副校长兼教育长晋升少将,前任是计算机权威专家...
- msf实战提权windows_ATTamp;CK实战 | 红队评估一(上)
- JSK-369 字符逆序【入门】
- 电驴(easyMule)自动关机工具
- springboot test
- Java 接口编程题练习_JAVA学习日记每天进步一点点之接口再学习和内部类、编程题练习、异常学习...
- 腾讯云服务器架设mir2
- 微信小程序网易云音乐
- C#打开文件夹加载图片
- 利用selenium 爬取豆瓣 武林外传数据并且完成 数据可视化 情绪分析
- 101 Ruby Code Factoids
- 计量经济学(stata)笔记1 记录每天的进步
- C/C++,定时关机代码和取消定时关机(应用范畴)
热门文章
- springmvc返回html页面_深入浅出SpringMVC系列~
- java.sql 拒绝连接_java.sql.SQLException: ORA-01017: 用户名/口令无效; 登录被拒绝
- python操作库_python操作数据库
- md5修改工具_【q001】如何校验文件的MD5
- c语言解三元一次方程组_一次二次反比例,一山更比一山高?二次函数三大解析式详解...
- c语言10000以内最大的质数,for语句计算输出10000以内最大素数怎么搞最简单??各位大神们...
- linux查看u盘的分区,在Linux下访问windows分区以及U盘
- hessian无法获取连接_PPPoE拨号设置完成后无法上网解决方法【详解】
- vue获取接口数据_c#中HttpWebRequest调用接口获取数据
- ggplot2作图4