gpt4 book ai didi

c++ - 以编程方式实时更改音频文件的速度

转载 作者:行者123 更新时间:2023-11-28 05:05:46 24 4
gpt4 key购买 nike

环境

  • 硬件:Raspberry Pi x
  • 操作系统:Raspbian Jessie Lite
  • 语言:Qt5/C++

目标

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

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

一些想法

QtMultimedia 中的 QMediaPlayer 具有应该执行此操作的 playbackRate 属性。不幸的是,我一直无法让 QtMultimedia 在我的系统中运行。

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

您将如何实现这一目标?

最佳答案

我不知道其中有多少转化为 C++。我在这个问题上所做的工作使用 Java。不过,该算法的某些内容应该有所帮助。

示例数据(组成):

sample    value
0 0.0
1 0.3
2 0.5
3 0.6
4 0.2
5 -0.1
6 -0.4

在正常速度下,我们向输出线发送一系列值,其中样本数每输出一帧递增 1。

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

要做到这一点,事实证明线性插值对音频非常有效。可以使用更复杂的曲线拟合算法,但保真度的增加被认为是不值得的。

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

sample    value
0 0.0
0.5 0.15
1 0.3
1.5 0.4
2 0.5
2.5 0.55
3 0.6
etc.

如果你想播放 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.

我通过一个“光标”对其进行编码,该光标在每个样本帧中递增,递增量决定了播放的“速度”。游标指向一个数组,就像整数索引一样,但它是一个 float (或 double )。如果游标的值有小数部分,则小数部分用于在整数部分指向的样本值和整数部分加一之间进行插值。

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

audioValue = A * 0.75 + B * 0.25

定义速度增量的精确度非常高。我认为 Java 的 float 足以满足此目的。

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

以下是演示这两种策略的链接,其中通过 slider 控件实时更改声音的播放速度。

SlidersTest.jar

这是 jar 文件的可运行拷贝,其中还包含源代码,并通过 Java 8 执行。您还可以重命名文件 SlidersTest.zip,然后深入查看上下文中的源代码。

但也可以直接在我为最近编写并开源的代码发布的页面的以下两个部分中导航到源文件的链接:见AudioCue.javaSlidersTest.java

AudioCue.java 是一个长文件。相关部分在文件末尾的内部类:类AudioCuePlayer,平滑算法,查看setter方法setSpeed,大约是3/4的下来的路。抱歉,我没有行号。

关于c++ - 以编程方式实时更改音频文件的速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44818752/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com