DAC+DMA+TIM实现音频播放问题记录

Posted 何事误红尘

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DAC+DMA+TIM实现音频播放问题记录相关的知识,希望对你有一定的参考价值。

目录

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,高精度采样数据,并不会失真,反而可能会更好。这一点,可以通过简单计算理解:

  1. 假设参考电压3V,实际电压2V,计算12位DAC和16位DAC的采样值。
  2. 然后忽略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实现音频播放问题记录的主要内容,如果未能解决你的问题,请参考以下文章

STM32 M4 Cortex WAV 播放器 SD 卡 DMA DAC

STM32之DAC音频播放

重学STM32---DAC+DMA+TIM

STM32cubemx教程 DAC+TIM+DMA

STM32cubemx教程 DAC+TIM+DMA

STM32 TIM DAC 和 DMA