问题陈述:
我的应用程序中有一组声音效果,存储为.m4a
我想要以各种速度和音调播放的文件(AAC 格式,48 KHz,16 位),而无需将所有变体预先生成为单独的文件。
虽然.rate
的财产AVAudioPlayer
对象可以改变播放速度,它始终保持原始音高,这不是我想要的。相反,我只是想更快或更慢地播放声音样本,并提高或降低音调以匹配 - 就像加速或减慢老式卷轴录音机一样。换句话说,我需要某种方法来从本质上改变音频采样率,例如 +2 半音(快 12%)、–5 半音(慢 33%)、+12 半音(快 2 倍)等。
问题:
有没有什么方法可以从线性 PCM 音频数据中获取AVAudioPlayer
对象,使用不同的 iOS 框架应用采样率转换,并将生成的音频数据填充到新的AVAudioPlayer
对象,然后可以正常播放吗?
可能的途径:
我正在阅读AudioConverterConvertComplexBuffer
。尤其kAudioConverterSampleRateConverterComplexity_Mastering
, and kAudioConverterQuality_Max
, and AudioConverterFillComplexBuffer()
吸引了我的注意。所以这个音频转换框架看起来是可能的。这是我应该进一步探索的途径吗?
要求:
实际上我不需要立即开始播放。如果采样率转换产生轻微延迟,那也没关系。我的所有样本都是 4 秒或更短,因此我可以想象任何动态重采样都会很快发生,大约为 1/10 秒或更短。 (不过,超过 1/2 就太多了。)
如果有更简单的方法使用 iOS 提供的转换框架来实现这一点,我真的不想涉足 OpenAL 或 Core Audio 之类的重量级内容。然而,如果有一个simple使用 OpenAL 或 Core Audio 解决这个问题,我很乐意考虑这一点。我所说的“简单”是指可以用 50-100 行代码实现的东西,并且不需要启动额外的线程来将数据提供给声音设备。我宁愿让一切自动处理 - 这就是为什么我愿意在播放之前转换音频剪辑。
我想在这里避免使用任何第三方库,因为这不是火箭科学,而且我知道它一定可以通过原生 iOS 框架以某种方式实现。
再次,我需要调整音调和播放速率一起,而不是分开。因此,如果播放速度减慢 2 倍,人声就会变得非常低沉且缓慢。如果播放速度加快 2-3 倍,人声听起来就像是一只快速说话的花栗鼠。换句话说,我绝对不想在保持音频持续时间相同的情况下改变音高,因为当音高向上弯曲超过几个半音时,该操作会导致不受欢迎的“尖细”声音。我只是想加快整个过程的速度,并让音调升高作为自然的副作用,就像老式录音机过去所做的那样。
需要在 iOS 6 及更高版本中工作,尽管 iOS 5 支持将是一个不错的奖励。
Jack Wu提到的论坛链接有一个建议,其中涉及直接覆盖AIFF头数据。这可能有效,但您将需要 AIFF 文件,因为它依赖于要写入的 AIFF 标头的特定范围。这也需要在创建 AVAudioPlayer 之前完成,这意味着一旦运行就无法修改音高。
如果您愿意采用 AudioUnits 路线,完整的简单解决方案可能约为 200 行(请注意,这假设具有一个函数的代码样式最多需要 7 行,每行一个参数)。有一个 Varispeed AudioUnit,它通过将音高锁定到速率来完全满足您的需求。您基本上需要查看 API、文档和一些示例 AudioUnit 代码来熟悉,然后:
- 创建/初始化音频图和流格式(约 100 行)
- 创建 RemoteIO AudioUnit 并将其添加到图中(
kAudioUnitSubType_RemoteIO
)(输出到扬声器)
- 创建并添加一个变速单元,并连接变速单元的输出(
kAudioUnitSubType_Varispeed
) 到 RemoteIO 单元的输入
- 创建 AudioFilePlayer 并将其添加到图表中(
kAudioUnitSubType_AudioFilePlayer
) 单元读取文件并将其连接到变速单元
- 启动图表开始播放
- 当你想改变音高时,通过AudioUnitSetParameter进行,音高和播放速率的改变将在播放时生效
请注意,还有一个 TimePitch 音频单元,它也允许独立控制音调和速率。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)