问题陈述:
我的应用程序中有一组声音效果存储为.m4a
文件(AAC格式,48 KHz,16位),我希望以各种速度和音高播放,而不必预先播放将所有变体生成为单独的文件。
虽然.rate
对象的AVAudioPlayer
属性可以改变播放速度,但它始终保持原始音高,这不是我想要的。相反,我只是想要更快或更慢地播放声音样本并让音调上下移动以匹配 - 就像加速或减慢老式卷轴到磁带录音机一样。换句话说,我需要一些方法来基本上改变音频采样率,如+2半音(快12%),-5半音(慢33%),+ 12半音(快2倍)等等。
问题:
是否有某种方式从AVAudioPlayer
对象获取线性PCM音频数据,使用不同的iOS框架应用采样率转换,并将生成的音频数据填充到新的AVAudioPlayer
对象中,然后正常播放?
可能的途径:
我正在阅读AudioConverterConvertComplexBuffer
。特别是kAudioConverterSampleRateConverterComplexity_Mastering
,kAudioConverterQuality_Max
和AudioConverterFillComplexBuffer()
引起了我的注意。所以这个音频转换框架看起来很可能。这是我应该进一步探索的途径吗?
要求:
我实际上不需要立即开始播放。如果采样率转换引起轻微延迟,那很好。我所有的样本都是4秒或更短的时间,所以我认为任何即时重新采样都会很快发生,大约为1/10秒或更短。 (但是,超过1/2会是太多了。)
如果使用iOS提供的转换框架有更简单的方法,我真的不想进入OpenAL或Core Audio等重量级的东西。但是,如果使用OpenAL或Core Audio存在简单解决此问题的解决方案,我很乐意考虑这一点。 “简单”是指可以在50-100行代码中实现的东西,并且不需要启动额外的线程来将数据提供给声音设备。我宁愿自动处理所有事情 - 这就是为什么我愿意在播放前转换音频片段。
我想在这里避免使用任何第三方库,因为这不是火箭科学,我知道必须以某种方式使用原生iOS框架。
同样,我需要一起调整音高和播放速率,而不是单独调整。因此,如果播放速度减慢了2倍,那么人声会变得非常深沉且说话速度慢。如果播放速度加快2-3倍,那么人类的声音听起来就像一个快速说话的花栗鼠。换句话说,我绝对不希望在保持音频持续时间相同的同时改变音调,因为当向上弯曲音调超过一对半音时,该操作导致不期望的“细小”声音。我只想加快整个过程的速度,并将音调调高为一种自然的副作用,就像过去常用的老式录音机一样。
需要在iOS 6及更高版本中运行,虽然iOS 5支持将是一个不错的奖励。
答案 0 :(得分:2)
Jack Wu提到的论坛链接有一个建议,涉及直接覆盖AIFF标题数据。这可能有效,但您需要拥有AIFF文件,因为它依赖于要写入的特定范围的AIFF标头。这也需要在创建AVAudioPlayer之前完成,这意味着一旦它运行就不能修改音高。
如果你愿意去AudioUnits路线,一个完整的简单解决方案可能是〜200行(请注意,这假设具有一个功能的代码样式最多需要7行,每行有一个参数)。有一个Varispeed AudioUnit,它通过锁定音高来完成您想要的速度。您基本上需要查看API,docs和一些示例AudioUnit代码才能熟悉,然后:
kAudioUnitSubType_RemoteIO
)(此输出到发言人)kAudioUnitSubType_Varispeed
)连接到RemoteIO Unit的输入kAudioUnitSubType_AudioFilePlayer
)单元以读取文件并将其连接到varispeed单元请注意,还有一个TimePitch音频单元,可以独立控制音高和速率。
答案 1 :(得分:2)
对于iOS 7,您需要查看名为audioTimePitchAlgorithm
的AVPlayerItem的时间间距算法(AVAudioTimePitchAlgorithmVarispeed
)。不幸的是,早期系统无法使用此功能。