音频处理中的变调和时间拉伸(一)

2023-10-31 23:30

本文主要是介绍音频处理中的变调和时间拉伸(一),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

介绍

很多用过磁带或者塑胶唱片的人都会对于一种现象感到熟悉:当我们快放或者慢放音频的时候,如果我们用两倍速度快放,除了会使得音频播放时间减少一半,还会使得音高升高一个八度,听起来音频中的人声会很像卡通动画人物的声音。同时,如果慢放会使得播放时长增长并且降低相应比例的音高。

以前使用模拟音频录音技术的时候,这种现象可以通过设置错误的播放速度来复现。现在,在数字信号处理领域,同样的现象可以通过重采样来实现。

重采样会同时改变音频的播放时长与音高,但是有时人们会有需求:只改变音高或者只改变播放时长。这类技术会被称为:

  • time/pitch scaling,
  • time/pitch shifting,
  • time stretching.

应用

Time scaling 可以慢放音乐速度,方便大家跟着跳舞或者拍视频再或者练习乐器。慢放讲话录音可以帮助人们转写,或者学习语言,盲人可能会使用快放来播放一些音频书籍来节约时间。视频网站上的倍速播放页需要音频跟着加倍但是不会变调。

类似的,在卡拉OK或者练习唱歌的时候,调整音乐的音调或者key,可以更好的匹配演唱者的声线。或者用来调音,百万调音师你们懂得。

最后,有些人可能想要通过改变他们自己声音的音调来实现身份隐藏。

实现方式

目前有两种实现上述技术的基本方式,即在时域处理或者频域处理

时域处理方式直接操作采样数据,比如后面要介绍的SOLA算法。时域处理的优势在于实现非常直接(straight-forward),因为音频数据处理时的采样格式跟它播放时或者录制时相同。缺点在于会产生一些人造回响导致失真,并且随着更大的时间调整,失真更明显。比如时间伸缩超过15%时。

频域处理是将采样声音转换为短时的 频率/振幅 成分然后在频域信息上来做伸缩,相位声码器是这类方法的一个典型。频域处理的优势在于可以支持更复杂的声音调整给出更好的听感,因为人类听力根本上只是基于频率的。

然而,由于它们明显的强大和优雅,频域处理实现起来更加复杂,计算复杂度更高。所以受限于计算资源,比如cpu速度和内存等。

SOLA

SOLA即 Synchronous-OverLap-Add,同步交叠相加法。通过将声音数据切成一系列的很短的长约几十到几百毫秒的片段,然后将这些片段通过一定的手段:跳过某些内容或者重复某些内容,重新排列起来达到比原始音频更长或者更短的播放时间。使用相同思路的算法还有TDHS(Time-Domain Harmonic Sampling),WSOLA和PSOLA,他们的区别在于实现细节。

为了避免在两个片段连接处的声音出现过于明显的断裂感,两个片段会有一定的重叠部分,所以声音的振幅从一个片段到另一个片段是渐变的,所以SOLA名字中有OverLap-Add部分。

最简单的SOLA实现可以使用统一的片段长度,然后每隔一段均匀的间隔来取一段片段。如果你想让声音缩短10%的长度,假设我们使用100毫秒(+叠加的长度)的片段长度,然后以110毫秒为间隔,从原始音频中取片段,然后将这些片段通过叠加连接起来,你就获得了想要的效果。同样的如果要延长10%的长度,选择100毫秒的片段,然后每隔90毫秒取一个片段,最后连接起来即可。是不是很简单呢?

然而,实际应用中的SOLA实现起来并没有那么简单。选取片段的时候不管片段内容的话,即使采用了渐变叠加的方法还是会由于过大的不连贯而出现噪音。(注:这里的不连贯是指的采样点不构成一个波形,虽然其实采样点实际上是连贯的,但是不构成波形的话,发出的声音也是噪音)

实现考虑

为了满足音质要求,SOLA在实现上需要在选择片段时,使得相邻片段之间交叠部分尽量相似。

实际上,音频流每次处理一个片段,为了使得相邻两个片段之间更匹配,在选择下一个片段的时候,可以在一个合适的窗口范围内来寻找。一种寻找最匹配片段的方法是通过计算上一个片段结尾部分和窗口内的待选片段的开头部分的互相关性,具有最高互相(cross-correlation)关值的两个片段的头尾是最相似的。这些片段最后通过交叠的方式连接在一起,形成了新的音频流,并且与原始的音频流长度不同。

SOLA的总体算法如下图所示。图中坐标轴的范围是可以任意设定的,所代表的时间单位仅做示意。在算法执行过程中,原始的音频会被切成合适长度的若干片段。新的片段会在与前一片段合适的间隔后被选出,从而获得想要的伸缩效果。

图1
在图1中,第一个片段从0开始,然后长度是7个时间单位,首尾各有一个时间单位的交叠部分。每隔9个时间单位取一个片段,最终的时间伸缩比例为 (7-2)/9 = 0.555,也就表示相对原始音频缩短了44.5%的时长。

然而,实际上在取片段时,并不是严格按照名义上的时间间隔来取的,而是取自以时间间隔处为中心的一个窗口范围内。比如图1中的“New Sequence”实际上是取自第8个时间单位到第10个时间单位之间,以便让新的片段和前一个片段在交叠时可以更好的重合。在图1下半部分我们可以看到交叠后的结果。

互相关函数对于评估音频片段的相似度很有效,并且也易于实现。同时,还有一些其它的相似度测量函数也被提出。其中一种方式是将片段的边缘与声音的节拍对齐,如果声音有一定的节拍并且可以被检测到,那么这种方式可以降低产生的类似混响感的人工处理痕迹。还有一种方式是评估频域频谱的相似度,而不是时域的波形相似度。

SOLA只需要基础的加法和乘法,因此可以使用整型或者定点数运算来实现,防止浮点数运算不被支持或者效率不高。

多声道处理

处理立体声时,片段交叠操作应当是在多个声道同样的位置进行的,如果我们单独处理每个声道,最终可能会造成声道之间错位。

所以我们可以同时处理所有声道,比如,可以将所有声道相加后再通过互相关函数找到共同的最优的片段获取点。

使用SOLA进行变调

SOLA只有拉伸功能,但是如果和重采样技术结合起来就可以实现变调功能了,很简单,假如要升高八度,只需要下采样音频到原始长度的一半,然后再使用SOLA拉伸到原始长度即可。

修音痕迹与参数

使用SOLA处理过的音频会有一点点回声的痕迹,这种痕迹会随着拉伸的幅度的增大而变得更加明显。

有一种减轻回声痕迹的方式是通过根据被处理音频的基本频率来选择处理片段时长。(这里的基本频率不是f0,意思是被处理音频的节拍频率)

处理时窗口范围的选择也会影响音质,越宽的窗口范围一般会获得更好的交叠音频的匹配度。但是,太宽的话产生的音频会不稳定,听起来像是在“漂移”。

交叠长度,一般是整个处理片段长度的一部分。通常使用线性的响度变化会表现的更好。

这篇关于音频处理中的变调和时间拉伸(一)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/318855

相关文章

Python实现批量CSV转Excel的高性能处理方案

《Python实现批量CSV转Excel的高性能处理方案》在日常办公中,我们经常需要将CSV格式的数据转换为Excel文件,本文将介绍一个基于Python的高性能解决方案,感兴趣的小伙伴可以跟随小编一... 目录一、场景需求二、技术方案三、核心代码四、批量处理方案五、性能优化六、使用示例完整代码七、小结一、

Python中 try / except / else / finally 异常处理方法详解

《Python中try/except/else/finally异常处理方法详解》:本文主要介绍Python中try/except/else/finally异常处理方法的相关资料,涵... 目录1. 基本结构2. 各部分的作用tryexceptelsefinally3. 执行流程总结4. 常见用法(1)多个e

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

PHP应用中处理限流和API节流的最佳实践

《PHP应用中处理限流和API节流的最佳实践》限流和API节流对于确保Web应用程序的可靠性、安全性和可扩展性至关重要,本文将详细介绍PHP应用中处理限流和API节流的最佳实践,下面就来和小编一起学习... 目录限流的重要性在 php 中实施限流的最佳实践使用集中式存储进行状态管理(如 Redis)采用滑动

MyBatis-plus处理存储json数据过程

《MyBatis-plus处理存储json数据过程》文章介绍MyBatis-Plus3.4.21处理对象与集合的差异:对象可用内置Handler配合autoResultMap,集合需自定义处理器继承F... 目录1、如果是对象2、如果需要转换的是List集合总结对象和集合分两种情况处理,目前我用的MP的版本

Python自动化处理PDF文档的操作完整指南

《Python自动化处理PDF文档的操作完整指南》在办公自动化中,PDF文档处理是一项常见需求,本文将介绍如何使用Python实现PDF文档的自动化处理,感兴趣的小伙伴可以跟随小编一起学习一下... 目录使用pymupdf读写PDF文件基本概念安装pymupdf提取文本内容提取图像添加水印使用pdfplum

C# LiteDB处理时间序列数据的高性能解决方案

《C#LiteDB处理时间序列数据的高性能解决方案》LiteDB作为.NET生态下的轻量级嵌入式NoSQL数据库,一直是时间序列处理的优选方案,本文将为大家大家简单介绍一下LiteDB处理时间序列数... 目录为什么选择LiteDB处理时间序列数据第一章:LiteDB时间序列数据模型设计1.1 核心设计原则

基于Redis自动过期的流处理暂停机制

《基于Redis自动过期的流处理暂停机制》基于Redis自动过期的流处理暂停机制是一种高效、可靠且易于实现的解决方案,防止延时过大的数据影响实时处理自动恢复处理,以避免积压的数据影响实时性,下面就来详... 目录核心思路代码实现1. 初始化Redis连接和键前缀2. 接收数据时检查暂停状态3. 检测到延时过

Java利用@SneakyThrows注解提升异常处理效率详解

《Java利用@SneakyThrows注解提升异常处理效率详解》这篇文章将深度剖析@SneakyThrows的原理,用法,适用场景以及隐藏的陷阱,看看它如何让Java异常处理效率飙升50%,感兴趣的... 目录前言一、检查型异常的“诅咒”:为什么Java开发者讨厌它1.1 检查型异常的痛点1.2 为什么说

Python利用PySpark和Kafka实现流处理引擎构建指南

《Python利用PySpark和Kafka实现流处理引擎构建指南》本文将深入解剖基于Python的实时处理黄金组合:Kafka(分布式消息队列)与PySpark(分布式计算引擎)的化学反应,并构建一... 目录引言:数据洪流时代的生存法则第一章 Kafka:数据世界的中央神经系统消息引擎核心设计哲学高吞吐