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