以编程方式实时更改音频文件的速度 环境 硬件:覆盆子皮x O.S.:Raspbian Jessie Lite 语言:Qt5/C++ 目标

以编程方式实时更改音频文件的速度 环境 硬件:覆盆子皮x O.S.:Raspbian Jessie Lite 语言:Qt5/C++ 目标,c++,audio,C++,Audio,执行音频文件(wav或更好的mp3),平稳地、连续地改变其速度。音高应根据速度(播放速率)变化。 我的应用程序每秒更新几次包含所需速度的变量:即1.0=正常速度。要求的范围约为0.2。。3.0,分辨率为0.01 音频可能是音乐,预期格式:单声道,16位,11.025赫兹。 没有关于延迟的具体限制:低于500毫秒是可以接受的 一些想法 QtMultimedia中的QMediaPlayer具有playbackRate属性,该属性正好可以执行此操作。不幸的是,我一直无法使多媒体在我的系统中工作 也可以

执行音频文件(wav或更好的mp3),平稳地、连续地改变其速度。音高应根据速度(播放速率)变化。 我的应用程序每秒更新几次包含所需速度的变量:即1.0=正常速度。要求的范围约为0.2。。3.0,分辨率为0.01

音频可能是音乐,预期格式:单声道,16位,11.025赫兹。 没有关于延迟的具体限制:低于500毫秒是可以接受的

一些想法 QtMultimedia中的QMediaPlayer具有playbackRate属性,该属性正好可以执行此操作。不幸的是,我一直无法使多媒体在我的系统中工作

也可以使用外部播放器,并使用管道或任何IPC发送数据


<>你怎么会做到这一点?

< p>我不知道这有多少转化为C++。我在这个问题上所做的工作使用Java。尽管如此,算法的某些方面还是应该有所帮助

示例数据(组成):

在正常速度下,我们向输出行发送一系列值,其中每个输出帧的采样数增加1

如果我们的速度变慢了,比如说半速,那么在到达媒体数据中的同一点之前,我们应该输出两倍的值。换句话说,我们需要在输出中包括不存在的中间采样帧位置0.5、1.5、2.5…处的值

要做到这一点,事实证明线性插值对音频效果相当好。可以使用更复杂的曲线拟合算法,但保真度的提高不值得费心

因此,我们最终得到如下流(对于半速):

如果要回放3/4速度,则输出中使用的位置和值如下:

sample    value
0          0.0
0.75       0.225
1.5        0.4
2.25       0.525
3          0.6
3.75       0.525
etc.
我通过一个“光标”对其进行编码,该光标在每个采样帧中递增,递增量决定播放的“速度”。光标指向数组,就像整数索引一样,但它是一个浮点(或双精度)。如果光标的值有一个小数部分,则该小数部分用于在整数部分指向的采样值和整数部分加1之间插值

例如,如果光标为6.25,soundData[6]的值为A,soundData[6+1]的值为B,则声音值为:

audioValue = A * 0.75 + B * 0.25
您可以定义速度增量的精度非常高。我认为Java的浮动被认为足以达到这个目的

至于保持动态变化的速度增量平稳,我将通过一系列4096个步骤(大约1/10秒,44100 fps)对新速度进行调整。更改请求通常是异步的,例如来自GUI的,并且随着时间的推移以某种不可预测的方式分布。平滑算法应能够根据每个新的速度请求重新计算和更新自身

下面的链接演示了这两种策略,其中声音的播放速度通过滑块控件实时改变

这是jar文件的可运行副本,它也包含源代码,并通过Java8执行。您还可以重命名文件SlidersTest.zip,然后在上下文中深入查看源代码

但是,在我最近编写并开放源代码的这段代码中,我发布的页面的以下两个部分也可以直接导航到源文件的链接: 看见 看


java是一个长文件。相关部分在文件末尾的内部类中:类AudioCuePlayer,对于平滑算法,请检查setter方法setSpeed,它大约是下降的3/4。对不起,我没有行号。

我不知道这有多少转化为C++。我在这个问题上所做的工作使用Java。尽管如此,算法的某些方面还是应该有所帮助

示例数据(组成):

在正常速度下,我们向输出行发送一系列值,其中每个输出帧的采样数增加1

如果我们的速度变慢了,比如说半速,那么在到达媒体数据中的同一点之前,我们应该输出两倍的值。换句话说,我们需要在输出中包括不存在的中间采样帧位置0.5、1.5、2.5…处的值

要做到这一点,事实证明线性插值对音频效果相当好。可以使用更复杂的曲线拟合算法,但保真度的提高不值得费心

因此,我们最终得到如下流(对于半速):

如果要回放3/4速度,则输出中使用的位置和值如下:

sample    value
0          0.0
0.75       0.225
1.5        0.4
2.25       0.525
3          0.6
3.75       0.525
etc.
我通过一个“光标”对其进行编码,该光标在每个采样帧中递增,递增量决定播放的“速度”。光标指向数组,就像整数索引一样,但它是一个浮点(或双精度)。如果光标的值有一个小数部分,则该小数部分用于在整数部分指向的采样值和整数部分加1之间插值

例如,如果光标为6.25,soundData[6]的值为A,soundData[6+1]的值为B,则声音值为:

audioValue = A * 0.75 + B * 0.25
您可以定义速度增量的精度非常高。我认为Java的浮动被认为足以达到这个目的

至于保持动态变化的速度增量平稳,我将通过一系列4096个步骤(大约1/10秒,44100 fps)对新速度进行调整。更改请求通常是异步的,例如来自GUI的,并且随着时间的推移以某种不可预测的方式分布。平滑算法应能够根据每个新的速度请求重新计算和更新自身

Fol