梳理一下各大平台使用的resample算法

  • 前言
  • Smarc对Interpolation和Decimation的执著
  • CCRMA & speex
  • sox & deadbeef
  • WebRTC
  • ffmpeg
  • Secret Rabbit Code
  • 参考

前言

转采样属于数字信号重建的范畴,整数倍的升降采样可以通过插值抽取+带限滤波的方法【1】,并且通过级联来实现任意比值的采样率转换。这里需要对奈奎斯特采样定理,以及数字信号时频关系有比较清晰的理解。还有一种方法是插值,插值的方法比较多,在参考里有一阶保持FOH、零阶保持ZOH、三次样条函数spline和sinc函数,引用的博文中有比较直观的分析和事例。那么在各大平台,最后都是用什么实现的resample重建呢?

Smarc对Interpolation和Decimation的执著

来自法国的Smarc的内核是经典的数字信号差值抽取方法,能够支持任意采样率,众所周知,48k到44.1k的互相转采样是个挑战,在SMARC method详细的讲述的算法的特点,通过因式分解和多相、多阶实现降低了FIR的阶数,提高了算法效率。简单的翻译一些文中的思想如下:
经典的香农插值抽取法虽然便于理解,但碍于为了实现非整数(有理数)比的转采样,滤波器级数可能长的无法用于实现,文中举了一个例子,可以这样理解 44100 48000 = 147 160 \frac{44100}{48000}=\frac{147}{160} 4800044100​=160147​那么两个频率的最小公倍数为: 44100 ∗ 160 = 48000 ∗ 147 = 7056000 = 7.056 M 44100*160=48000*147=7056000=7.056M 44100∗160=48000∗147=7056000=7.056M
为了满足48000->44100的变换,满足截止频率22.05k的设计要求,需要FIR的阶数38560,这个抽头和延时是无法接受,这个计算是利用smarc内置的remez方法。smarc则采样了多级滤波器的设计思想,规避了长延时的问题,每一级采用很小的系数比,同时结合多相滤波的实现,进一步优化算法。对于降采样抽取:

#mermaid-svg-t9aO2SUUDavT2Ih3 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-t9aO2SUUDavT2Ih3 .error-icon{fill:#552222;}#mermaid-svg-t9aO2SUUDavT2Ih3 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-t9aO2SUUDavT2Ih3 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-t9aO2SUUDavT2Ih3 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-t9aO2SUUDavT2Ih3 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-t9aO2SUUDavT2Ih3 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-t9aO2SUUDavT2Ih3 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-t9aO2SUUDavT2Ih3 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-t9aO2SUUDavT2Ih3 .marker.cross{stroke:#333333;}#mermaid-svg-t9aO2SUUDavT2Ih3 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-t9aO2SUUDavT2Ih3 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-t9aO2SUUDavT2Ih3 .cluster-label text{fill:#333;}#mermaid-svg-t9aO2SUUDavT2Ih3 .cluster-label span{color:#333;}#mermaid-svg-t9aO2SUUDavT2Ih3 .label text,#mermaid-svg-t9aO2SUUDavT2Ih3 span{fill:#333;color:#333;}#mermaid-svg-t9aO2SUUDavT2Ih3 .node rect,#mermaid-svg-t9aO2SUUDavT2Ih3 .node circle,#mermaid-svg-t9aO2SUUDavT2Ih3 .node ellipse,#mermaid-svg-t9aO2SUUDavT2Ih3 .node polygon,#mermaid-svg-t9aO2SUUDavT2Ih3 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-t9aO2SUUDavT2Ih3 .node .label{text-align:center;}#mermaid-svg-t9aO2SUUDavT2Ih3 .node.clickable{cursor:pointer;}#mermaid-svg-t9aO2SUUDavT2Ih3 .arrowheadPath{fill:#333333;}#mermaid-svg-t9aO2SUUDavT2Ih3 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-t9aO2SUUDavT2Ih3 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-t9aO2SUUDavT2Ih3 .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-t9aO2SUUDavT2Ih3 .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-t9aO2SUUDavT2Ih3 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-t9aO2SUUDavT2Ih3 .cluster text{fill:#333;}#mermaid-svg-t9aO2SUUDavT2Ih3 .cluster span{color:#333;}#mermaid-svg-t9aO2SUUDavT2Ih3 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-t9aO2SUUDavT2Ih3 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

1
1
1/M
x(n)
h(n)
w(n)
M decimation
y(n)

经过低通滤波消除混叠频率后就可以抽取除想要的新采样。

CCRMA & speex

搜了一下外文网站,能够完整讲述插值重建的就是斯坦福大学的这篇Digital Audio Resampling Home Page,文中讲述了带限插值的原理。简单的翻译一下,根据奈奎斯特和傅里叶变换的知识,时域信号可以被重建:
x ( t ) ^ ≜ ∑ n = − ∞ ∞ x ( n T s ) h s ( t − n T s ) ≡ = x ( t ) \hat{x(t)} \triangleq\sum_{n=-\infty}^{\infty}x(nT_s)h_s(t-nT_s)\equiv=x(t) x(t)^​≜n=−∞∑∞​x(nTs​)hs​(t−nTs​)≡=x(t)
这里的 h s ( t ) ≜ s i n c ( F s t ) ≜ s i n ( π F s t ) π F s t h_s(t)\triangleq sinc(F_st)\triangleq \frac{sin(\pi F_st)}{\pi F_st} hs​(t)≜sinc(Fs​t)≜πFs​tsin(πFs​t)​
s i n c sinc sinc函数的神奇就不赘述,但这个公式这么干是不行滴,因为正负无穷谁也受不了,所以还得加个窗,减小纹波和过冲。文中利用凯撒窗来评估对截取5个过零点的sinc函数卷积的频响比较,截取拼接了一下,效果变化很明显。
如果要利用这个公式进行新采样率 F s ′ F_s^\prime Fs′​的抽取,可以改写: x ( n T s ′ ) = ∑ n = − ∞ ∞ x ( n T s ) h s ( n T s ′ − n T s ) = ∑ n = − ∞ ∞ x ( n T s ) h s ( n ( T s ′ − T s ) ) \begin{aligned} x(nT_s^\prime)&=\sum_{n=-\infty}^{\infty}x(nT_s)h_s(nT_s^\prime-nT_s)\\ &=\sum_{n=-\infty}^{\infty}x(nT_s)h_s(n(T_s^\prime-T_s)) \end{aligned} x(nTs′​)​=n=−∞∑∞​x(nTs​)hs​(nTs′​−nTs​)=n=−∞∑∞​x(nTs​)hs​(n(Ts′​−Ts​))​据此,首先准备sinc函数的样点,找了一张图:

如果能对准备好的 h s ( t ) h_s(t) hs​(t)样点进行插值,那么就可以根据公式求出累加后的新采样点 x ( n T s ′ ) x(nT_s^\prime) x(nTs′​),这里假设 ρ = F s ′ F s \rho=\frac{F_s^\prime}{F_s} ρ=Fs​Fs′​​, ρ \rho ρ小于1意味着降采样, ρ \rho ρ大于1则是升采样。这相当于设计一个低通滤波器,那么这个滤波器实际上只需要存储半边的系数。那么剩下来的问题就是这个插值如何计算了。原文写的很节略,刚开始看的云山雾绕,不如先回归公式,假设就使用一个矩形窗,截断无限长的冲激响应。 x ′ ( n ) ≜ ∑ n = − N N x ( n ) h s ( n T s ′ − n T s ) ≜ ∑ n = − N N x ( n ) h s ( n ( T s ′ − T s ) ) ≜ ∑ n = − N N x ( n ) h s ( n + ( T s ′ − T s ) T s ) \begin{aligned} x^\prime(n)&\triangleq\sum_{n=-N}^{N}x(n)h_s(nT_s^\prime-nT_s)\\ &\triangleq\sum_{n=-N}^{N}x(n)h_s(n(T_s^\prime-T_s))\\ &\triangleq\sum_{n=-N}^{N}x(n)h_s(n+\frac{(T_s^\prime-T_s)}{T_s}) \end{aligned} x′(n)​≜n=−N∑N​x(n)hs​(nTs′​−nTs​)≜n=−N∑N​x(n)hs​(n(Ts′​−Ts​))≜n=−N∑N​x(n)hs​(n+Ts​(Ts′​−Ts​)​)​
上面这个卷积不是因果系统,这点跟插值抽取一样的特性。只要输入 2 N + 1 2N+1 2N+1个输入序列,同时能求得偏离 h s ( n ) h_s(n) hs​(n)的插值,即可以算出来转采样之后的点。具体实现细节不追了。

sox & deadbeef

从它github主页上的描述

 for real-time resampling, libsoxr may have a higher latency
than non-FFT based resamplers.  For example, when using the `High Quality'
configuration to resample between 44100Hz and 48000Hz, the latency is
around 1000 output samples, i.e. roughly 20ms (though passband and FFT-
size configuration parameters may be used to reduce this figure).

推测这是个频域的转采样算法,据说是被deadbeef采用的,但实时性一般,

WebRTC

webRtc也有sinc带限转采样方法,对于整数的也有抽取和插值的方法。稍微多说的是早期的webrtc是不支持多媒体44.1族的采样率。在AOSP的webrtc代码里能找到sinc框架。

ffmpeg

早期用的是libavcodec,后来改用libswresample,GitHub有源码可供分析

Secret Rabbit Code

这个平台借用一个客户的评价“完胜大部分主流”,那这个平台里的用到的就是插值方法:

  1. ZOH插值
  2. 线性插值
  3. sinc插值

其中前两种是简单的,但声音质量一般,后一种是“完美”插值重建,而且还分为fast/medium/quality三种滤波器插值系数可选,满足用户不同的需求,是一个比较成熟的实现平台。

参考

1.采样率变换和多速率filter
2.【 MATLAB 】MATLAB 实现模拟信号采样后的重建(三)一阶保持(FOH)内插
3.【 MATLAB 】MATLAB 实现模拟信号采样后的重建(三)应用三次样条函数spline实现内插
4.【 MATLAB 】MATLAB 实现模拟信号采样后的重建(二)零阶保持(ZOH)
5.【 MATLAB 】MATLAB 实现模拟信号采样后的重建(一)
【信号与系统学习笔记】—— 采样与恢复(内插重建方法解析)
数字信号处理之内插
零阶保持器(ZOH)
Resampling Audio Algorithms
Secret Rabbit Code
Resampling from hydrogenaudio
Resampling from dspguru
Digital Audio Resampling Home Page
FFmpeg/libswresample/
Planet CCRMA at home
CCRMA:libresample
shibatch SSRC
chirlu /soxr
重采样Resample 的一些研究记录
What is DeaDBeeF?
speex
Speex编码器中回声消除算法的分析与评估
[WebRTC架构分析]采样率转换

梳理一下各大平台使用的sample rate convert算法相关推荐

  1. 基于数据智能的区域教育大平台建设与应用实践

    点击上方蓝字关注我们 基于数据智能的区域教育大平台建设与应用实践 贺相春, 郭绍青 西北师范大学教育技术学院,甘肃 兰州 730070   摘要:数据智能引领是新时期区域教育大平台建设与应用的重要方向 ...

  2. 建议收藏!全面梳理非交易类平台产品设计原则

    琳琅满目,光彩照人.这是现在商品世界的写照. 产能过剩,超额满足.这是当下社会现状的真实. 平台型产品,作为互联网的中坚力量,是我们普通用户透过网络触摸商品和社会的媒介. 可以说,每家公司都有一颗做平 ...

  3. ActiveState Komodo IDE v5.2.1.34168 最新版for Linux/Mac OS/Windows 全5大平台

    ActiveState Komodo IDE v5.2.1.34168 最新版for Linux/Mac OS/Windows 全5大平台 转载于:https://www.cnblogs.com/ga ...

  4. 平台和计算机技术,两大平台技术提升及优势功能PK对比

    一.平台技术提升及优势功能PK对比 在PK之前,一定要先看完这两个关于迅驰2和PUMA平台的基础知识介绍文章:<绝杀迅驰2?AMD全新PUMA平台混合交火本全国首测>和<性能狂飙!M ...

  5. 国内各大平台的推荐算法,看到360的时候笑喷了……

    网友整理的各大平台推荐算法!

  6. 各大媒体优劣对比_信息流投放广告丨各大平台的信息流都有什么特点与弊端

    相信很多企业都做过信息流的广告推广,那么各位广告主都做过哪些平台的信息流呢?今天我们来看一看各大平台的信息流都有什么特点与弊端吧! 1.社交类代表:微博粉丝通.广点通(16年更名腾讯社交广告).陌陌. ...

  7. 前端学习与“IT界大佬告诉你,程序员接私活的7大平台利器”

    mark一下,博主名称"前端入门到精通",博客标题:"IT界大佬告诉你,程序员接私活的7大平台利器" https://blog.csdn.net/zwjweb/ ...

  8. 【开发者平台汇总】-各大平台开发者及开放平台集锦

    下面是我搜集的各大平台开发者平台开放平台集锦,当然,也有不全的地方 华为开发者平台 https://developer.huawei.com/consumer/cn/ https://develope ...

  9. [SEO知识]如何通过SEO思维收割各大平台的流量?

    如何通过SEO思维收割各大平台的流量? 做运营思维不能一成不变,要做到目标不变,方法常变,多多参考热点,学会逆向思维,运用到各个行业,各种产品上,SEO搜索引流就是纯SEO思维,就好像很多人,去百度搜 ...

最新文章

  1. php png jpg,php如何将png转换成jpg-PHP问题
  2. 对人脑而言,阅读计算机代码和阅读语言有何不同?
  3. K-means算法详解及python代码实现
  4. anglar ajax执行2次的原因,angular2 router’解决问题被执行两次
  5. python字符串变量s的值是python网络爬虫_【Python爬虫作业】-字符串
  6. 关于大型网站技术演进的思考(四)--存储的瓶颈(4)
  7. close wait 过多原因_time_wait 详解和解决方案
  8. linux命令stat,查看文件详细信息
  9. access统计各职务人数_2019年一建通过人数超15万?一建证书真的不值钱了?
  10. linux下rpm包安装jdk,linux jdk rpm包安装
  11. sql常用函数详解(一)——字符串截取
  12. matpower安装问题
  13. html页面排版会乱,窗口缩放导致页面排版错乱的解决方法
  14. php is_subclass_of,PHP中的is_subclass_of()函数
  15. Model和ModelMap的区别,以及背后那个男人~
  16. linux系统hostapd强制使用40MHz频宽
  17. Robocup3d比赛环境的搭建及常用函数简介
  18. ServU:无法访问servu服务器
  19. SuppressWarnings的使用、作用、用法
  20. ProjectDay04

热门文章

  1. List中addAll()方法简介
  2. mac上免token一键登录跳板机
  3. 今夏潮人必备的网红榨汁机,给你恋爱般的爆炸“快感”~丨钛空舱
  4. Java 的静态工厂方法
  5. 2020年,我想给Android手机加个需求,不知道Google怎么看?
  6. Python_sobel边缘检测
  7. 数学之美:信息的度量和作用 KL散度 自信息 熵 相对熵 KL divergence entropy
  8. MySQL的复合查询
  9. Python计算机视觉——图像处理基础
  10. 计算机网络 常见笔试面试题