ESP8266 软件实现 Delta-sigma(ΔΣ)调制器 并通过I2S接口输出编码流
一、关于Delta-sigma(ΔΣ)调制器
Delta-sigma(ΔΣ)调制器是Delta-sigma转换器的核心部件。如下所示为一个简单的一阶Delta-sigma调制器,该调制器产生一个1bit比特流。将该比特流脉冲输入低通滤波器,从滤波器输出端口可以获得比特流信号的平均电平,该电平代表了调制器的输入电平。

一阶Delta-sigma调制器的实例时序如下:

在该实例中,时钟频率(此处等于采样率)为输入信号的64倍。根据采样定理,转换器需要至少2倍于有效信号最高频率的采样率,而Delta-sigma转换器则需要比传统转换器高得多的采样频率来产生足够数量的比特流脉冲,相同条件下提高调制器的时钟频率,则可以获得更高的精度。
二、降低量化噪声
可以看出,比特流的平均电平(经过低通滤波后的电平)只会在某个精度范围内接近于原始电平,而永远不会完全相同,输出信号永远叠加着量化噪声。
一种降低量化噪音的方法是:增加时钟频率(过采样)。例如,假设现有一个带宽为20kHz的音频信号,一个典型的PCM采样率为48kHz,而典型的Delta-sigma转换器的时钟频率高达 64 x 48kHz = 3.072 MHz,即相当于64倍的过采样。
另一种更好的解决方案是:采用高阶的Delta-sigma调制器。一般来说,一阶调制器在高频段产生较多噪声功率,如果输入信号电平接近动态范围,则这种效应最为显著。采样高阶调制器可获得较一阶调制器更低的噪声。
三、二阶Delta-sigma调制器
典型的二阶delta-sigma调制器如下图所示:

该类型的调制器产生的比特流更加接近于理想的比例脉冲信号,因此可带来如下优势:增大输入信号带宽、降低采样频率、增加转换精度(抑制量化噪声)。
理论上高于2阶的delta-sigma调制器是可行的,但无法通过简单地增加差分积分单元实现,其根本原因是由2个以上积分器产生的相位误差将使降低系统的稳定性。
成熟的商业的音频ADC往往采用5阶甚至以上的delta-sigma调制器,使用64倍的过采样,其架构与本文所述有所不同,但基本原理是相同的。
四、软件实现二阶Delta-sigma调制器
通过上文对二阶delta-sigma调制器的描述,我们可以容易得出该调制器的数字实现。这里采用C语言实现DSP(digital signal process)。
int32_t w; /* Data Flow path */ , i2v = ; /* Integrator 1 and 2 */ ; /* Latch */
对每个比特位的处理过程如下。对输入电平w迭代n次可得出任意采样率的调制输出。
#define HW (32767) [Input: w] ) w -= HW; else w += HW; /* Difference 1 */ w += i1v; i1v = w; /* Integrator 1 */ ) w -= HW; else w += HW; /* Difference 2 */ w += i2v; i2v = w; /* Integrator 2 */ latch_reg = w; /* Latch */ b = (w > ); /* Comparator */ [Output to bitstream: b]
五、ESP8266的I2S输出端口
由于I2S接口具有串行数据连续传输而不断流的特性,因此在提高时钟频率的情况下,I2S接口可用于输出delta-sigma调制器的比特流。除I2S接口外,其它具有连续串行输出特性的接口同样可以承担输出比特流的工作。
ESP8266芯片提供了I2S PHY及接口,可配置工作于较高的时钟频率,SER并串转换器(串行移位器)可将并行字节通过端口串行地发送出去。对于比特流输出的实现而言,我们只关心I2S的数据输出端口SDAT,至于LRCLK和BCLK信号则完全抛弃。将I2S传输格式配置为每声道16bit全数据(双声道),则每个I2S传送周期(传输一次所有声道的PCM采样)可发送32个比特位。
这里先将delta-sigma调制输出的比特流的每32位伪装成4字节的PCM音频采样数据,通过DMA传输到I2S总线,而I2S模块中的ser模块再将伪装的PCM采样数据串行化输出,最终从SDAT端口得到完整的比特流信号。
调制得出的比特流可预先压入FIFO缓冲器,在I2S时钟的驱动下,以慢于软件调制速率的节拍从FIFO取出数据,这样就保证了输出比特流的连续性。
函数samp_to_delta_sigma()实现了将输入电平s调制为32bit比特流。简单计算调制器的采样率如下:
Fs = Fs(Input) * 32,其中Fs(Input)为输入数字信号的采样率。
对于PCM音频数据,若原始采样率为48kHz,则该delta-sigma调制器的采样率可达:
Fs = 48kHz * 32 = 1.536MHz
则要求I2S总线的BCLK时钟频率至少达到:
Fmin = 1.536MHz。
int32_t
samp_to_delta_sigma(short s)
{
int w;
, i2v = ;
;
int i;
;
; i<; i++)
{
val<<=;
w=s;
) w -= HW; else w += HW; /* Difference 1 */
w += i1v; i1v = w; /* Integrator 1 */
) w -= HW; else w += HW; /* Difference 2 */
w += i2v; i2v = w; /* Integrator 2 */
latch_reg = w; /* Latch */
) val|=; /* comparator */
}
return val;
}
从上面简单计算可以看出,当调制器迭代次数与I2S传输周期的有效位数相同时,将I2S驱动请求的采样率配置为输入信号的原始采样率即可确保时钟正确。
本文采用espressif NONOS SDK提供的I2S驱动库。首先调用I2sInit()初始化I2S接口,再调用I2sSetRate()设置采样率。对于每个输入信号采样s,通过调用i2sPushSample( samp_to_delta_sigma(s) )即可实现delta-sigma调制和比特流输出。
如下为一个实例,该例程调制采样率为48kHZ的PCM音频信号并输出:
I2sInit(); I2sSetRate(, ); ; i < size; i++) i2sPushSample( samp_to_delta_sigma(s[i]) );
六、CPU负载评估
仍以原始采样率为48kHz的PCM音频数据为例,从第五节已经得出,FIFO输出侧(I2S端口)最小带宽为 W1 = 1.536 * 10^(6) / 1024^2 ≈ 1.5 (MBits/s)。对于FIFO输入侧(软件调制器),为便于计算,先设CPU执行一次samp_to_delta_sigma()函数的平均用时为T0 (s),则软件调制的输出带宽为 W2 = 32 / T0 / 1024^2 (MBits/s)。
若系统能稳定工作,则要求I2S端口实际带宽Wf与W1、W2满足如下关系(正常情况下W1 = Wf,以确保正确还原比特流信号的时钟频率):
W1 <= Wf < W2
一旦条件满足,CPU将得到空闲时间:
Tfree = 1 / [(W2 - Wf) * 1024^2] (s)
这是因为系统运行中,除起始状态外FIFO将永远保持非空状态。Tfree可以代表用于运行其它任务的空闲时间长度(包括任务调度切换的时间)。若其它操作占用超过Tfree的运行时间,则可能导致FIFO输入侧带宽不足,从而造成FIFO下溢出,使得输出中断。
T0的决定因素非常复杂,需要考虑生成的汇编指令、整个CPU的运行状态(如时钟主频,cache状态等)和输入的数字信号,因此只能得出平均值T0,将T0代入上式即可得出近似的Tfree时间。
七、应用价值
在音频应用领域,该方法可通过简单的一阶RC滤波电路,直接从I2S接口得出模拟音频信号,从而省去成本较高的DAC芯片。除此之外,加入简单的功率输出和滤波电路,即可实现Class-D数字功放,如下图所示。

ESP8266 软件实现 Delta-sigma(ΔΣ)调制器 并通过I2S接口输出编码流的更多相关文章
- C#软件设计——小话设计模式原则之:接口隔离原则ISP
前言:有朋友问我,设计模式原则这些东西在园子里都讨论烂了,一搜一大把的资料,还花这么大力气去整这个干嘛.博主不得不承认,园子里确实很多这方面的文章,并且不乏出色的博文.博主的想法是,既然要完善知识体系 ...
- ESP8266开发之旅 基础篇② 如何安装ESP8266的Arduino开发环境
授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...
- ESP8266开发之旅 基础篇③ ESP8266与Arduino的开发说明
授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...
- sigma网格中水平压力梯度误差及其修正
1.水平梯度误差产生 sigma坐标系下,笛卡尔坐标内水平梯度项对应形式为 \[\begin{equation} \left. \frac{\partial }{\partial x} \right| ...
- 水平梯度在sigma坐标对应形式
sigma 坐标变换 一般 \(\sigma\) 坐标转换方程为 \[\sigma = \frac{z-\eta}{D} = \frac{z-\eta}{H+\eta} \] 转换后水深 z 范围由原 ...
- C#软件设计——小话设计模式原则之:依赖倒置原则DIP
前言:很久之前就想动笔总结下关于软件设计的一些原则,或者说是设计模式的一些原则,奈何被各种bootstrap组件所吸引,一直抽不开身.群里面有朋友问博主是否改行做前端了,呵呵,其实博主是想做“全战”, ...
- C#软件设计——小话设计模式原则之:单一职责原则SRP
前言:上篇C#软件设计——小话设计模式原则之:依赖倒置原则DIP简单介绍了下依赖倒置的由来以及使用,中间插了两篇WebApi的文章,这篇还是回归正题,继续来写写设计模式另一个重要的原则:单一职责原则. ...
- C#软件设计——小话设计模式原则之:开闭原则OCP
前言:这篇继续来看看开闭原则.废话少说,直接入正题. 软件设计原则系列文章索引 C#软件设计——小话设计模式原则之:依赖倒置原则DIP C#软件设计——小话设计模式原则之:单一职责原则SRP C#软件 ...
- Google首席软件工程师Joshua Bloch谈如何设计一款优秀的API【附PPT】
编者按]随着近来软件规模的日益庞大,API编程接口的设计变的越来越重要.良好的接口设计可以降低系统各部分之间的相互依赖,提高组成单元的内聚性,降低组成单元间的耦合度,从而提高系统的维护性和稳定性. J ...
随机推荐
- php正则表达式提取img alt/title标签并替换
有时我们需要对富文本编辑器中的img标签进行必要的处理以满足网站自身的需要,比如:根据站点关键词对页面内img的alt标签设定关键词,以下为提取并替换alt/title标签内容的正则: $title ...
- FM与PM信号的表现形式
角度调制可以写成如下形式: $u(t)=A_c cos(2\pi f_c t + \phi (t) )$ $A_c cos(2\pi f_c t)$是载波,调制信号控制$\phi (t)$. 对于PM ...
- webRTC中音频相关的netEQ(一):概述
上篇文章(语音通信中终端上的时延(latency)及减小方法)说从本篇开始会切入webRTC中的netEQ主题,netEQ是webRTC中音频技术方面的两大核心技术之一(另一核心技术是音频的前后处理, ...
- maven向本地仓库导入jar包
如果maven工程的依赖jar包在网上找不到,那么只能自己打包,然后传到本地仓库,可以使用如下命令 mvn install:install-file -DgroupId=com.redis.redis ...
- ABBYY FineReader 14OCR解锁
ABBYY FineReader 14是2017年新推的文字处理编辑软件,能够将图像扫描转换成文档处理.不论是在使用群体方面还是功能特性方面都是极好的. •确保扫描仪正确地连接到电脑,并将其打开.查阅 ...
- rocketmq (一)运行原理以及使用问题
使用消息中间件可以解决高并发,那是因为消息中间件可以将消息缓存到队列之中. 但是 当消息 过多的时候,几万,几十万...消息中间件也可能会宕机,所以我们可以对消息中间件进行集群,在之前的activem ...
- JAVA的DES加密解密在windows上测试一切正常,在linux上异常
windows上加解密正常,linux上加密正常,解密时发生 如下异常,异常信息如下: [ERROR] 2018-10-15 09:30:35,998 method:com.iscas.ippc.co ...
- Mono的CustomConditionAttribute使用
1.Mono的CustomConditionAttribute使用有诸多的限制,没有在XML中定义来的灵活 2.CustomConditionAttribute定义的子类必须和ExtensionAtt ...
- WordPress版微信小程序2.6版发布
WordPress版微信小程序的完善和升级的工作一直都在进行中,我争取保证一个月可以出一个版本,希望通过一点点的改进,让这个开源产品日趋完美. 同时,pro版WordPress微信小程序也在紧锣密鼓的 ...
- Ubuntu下安装Snap
介绍 Snap是一个全新的软件包架构,它与其它包管理器的区别在于snap安装的app互相之间是高度隔离的,减少了互相引用. 避免了很多冲突问题. 不过这也导致了其占用的磁盘比较多. 安装 apt in ...