我怎样才能使用AVAudioPlayer播放audio更快*和*更高音?

问题陈述:

我在我的应用程序中存储了一系列以.m4a文件(AAC格式,48 KHz,16位)存储的声音效果,我希望以各种速度和音高播放,而无需预先生成所有变体文件。

虽然AVAudioPlayer对象的AVAudioPlayer属性可以改变播放速度,但它始终保持原始音高,这不是我想要的。 相反,我只是想要更快或更慢地播放声音样本,并使音高向上或向下匹配 – 就像加速或减慢旧式的卷轴式磁带录音机一样。 换句话说,我需要一些方法来改变audio采样率,如+2个半音(快12%),-5个半音(慢33%),+ 12个半音(快两倍)等等。

题:

有什么方法从AVAudioPlayer对象中获取线性PCMaudio数据,使用不同的iOS框架应用采样率转换,并将生成的audio数据填充到新的AVAudioPlayer对象中,然后可以正常播放?

可能的途径:

我正在读AudioConverterConvertComplexBuffer 。 特别是kAudioConverterSampleRateConverterComplexity_MasteringkAudioConverterQuality_MaxAudioConverterFillComplexBuffer()引起了我的注意。 所以看起来这个audio转换框架是可能的。 这是我应该进一步探索的途径吗?

要求:

  1. 我其实不需要立即开始播放。 如果采样率转换稍微延迟,那没问题。 我所有的样品都是4秒或更less,所以我想可以快速进行任何即时重采样,大约在1/10秒或更短。 (尽pipe如此,超过1/2将会太多。)

  2. 如果有更简单的方法来使用iOS提供的转换框架,我真的宁愿不进入OpenAL或Core Audio等重量级的东西。 但是,如果使用OpenAL或Core Audio的这个问题有一个简单的解决scheme,我很乐意考虑这个问题。 我所说的“简单”是指可以用50-100行代码实现的东西,并且不需要启动额外的线程将数据传送到声音设备。 我宁愿将所有的东西都自动处理 – 这就是为什么我愿意在播放前转换audio剪辑。

  3. 我想在这里避免任何第三方库,因为这不是火箭科学,我知道它本来可以在iOS框架下实现。

  4. 再次,我需要一起调整音高和播放速度,而不是分开 。 所以,如果播放速度减慢了2倍,人声就会变得非常深沉而缓慢。 如果播放速度加快2-3倍,人声就像一个快速通话的花栗鼠。 换句话说,我绝对不希望在保持audio持续时间不变的情况下改变音调,因为当向上弯曲音高超过几个半音时,该操作导致不希望的“细小”的声音。 我只是想加快整个过程,把音调作为一个自然的副作用,就像老式的录音机以前那样。

  5. 需要在iOS 6或更高版本上工作,但iOS 5支持将是一个不错的奖励。

论坛链接Jack Wu提到了一个build议,它直接覆盖了AIFF标题数据。 这可能会起作用,但是您将需要具有AIFF文件,因为它依赖于AIFF头的特定范围来写入。 在创buildAVAudioPlayer之前,这也需要完成,这意味着一旦它运行,就不能修改音高。

如果你愿意去AudioUnits路线,一个完整简单的解决scheme大概是200行(注意,这里假定代码风格有一个函数最多7行,每行有一个参数)。 有一个Varispeed AudioUnit,它正是你想locking沥青的速度。 你基本上需要看API,文档和一些示例AudioUnit代码来熟悉,然后:

  1. 创build/初始化audiographics和stream格式(〜100行)
  2. 创build并添加一个RemoteIOaudio单元( kAudioUnitSubType_RemoteIO )(输出到扬声器)
  3. 创build并添加一个变速单元,并将变速单元( kAudioUnitSubType_Varispeed )的输出连接到RemoteIO单元的input
  4. 创build并添加一个AudioFilePlayer( kAudioUnitSubType_AudioFilePlayer )单元来读取文件并将其连接到变速单元
  5. 启动graphics开始播放
  6. 当您想要改变音调时,通过AudioUnitSetParameter进行,音高和播放速率的改变将在播放时生效

请注意,还有一个TimePitchaudio单元可以独立控制音高和速率。

对于iOS 7,您需要查看名为AVAudioTimePitchAlgorithmVarispeed AVPlayerItem的时间间隔algorithm( audioTimePitchAlgorithm )。 不幸的是,这个function在早期的系统上不可用。