当前位置:  开发笔记 > IOS > 正文

iOS Swift中简单的低延迟音频播放

如何解决《iOSSwift中简单的低延迟音频播放》经验,为你挑选了1个好方法。

我是iOS的初学者,我正在尝试用Swift设计一个鼓组应用程序.我用一个按钮设计了一个视图并编写了下面的代码,但它有一些问题:

    当我像滚筒一样快速触摸按钮时,有些声音会丢失.

    仍处于"鼓声"中,每次触摸按钮时声音都会中断,而不是让样本播放直到结束.例如,钹卷很糟糕.即使我再次触摸按钮,我也希望听到每个样本完全响起.

    触摸和声音之间存在延迟.我知道这AVAudioPlayer是不是低延迟音频的最佳选择,但作为一个初学者,它很难学OpenAL,AudioUnit没有代码示例或教程Swift.问题与此类似:我应该使用哪种框架在iOS中播放低延迟的音频文件(WAV,MP3,AIFF)?.

代码:

override func viewDidLoad() {
    super.viewDidLoad()

    // Enable multiple touch for the button
    for v in view.subviews {
        if v.isKindOfClass(UIButton) {
            v.multipleTouchEnabled = true
        }
    }

    // Init audio
    audioURL = NSBundle.mainBundle().URLForResource("snareDrum", withExtension: "wav")!
    do {
        player = try AVAudioPlayer(contentsOfURL: audioURL)
        player?.prepareToPlay()
    } catch {
        print("AVAudioPlayer Error")
    }
}

override func viewDidDisappear(animated: Bool) {
    super.viewDidDisappear(animated)

    player?.stop()
    player = nil
}

@IBAction func playSound(sender: UIButton) {
    player?.currentTime = 0
    player?.play()
}

小智.. 6

如果您需要极低的延迟,我发现AVAudioSession单例上有一个非常简单的解决方案(在应用程序启动时会自动实例化):

首先,使用此类方法获取对应用程序的AVAudioSession单例的引用:

(来自AVAudioSession类参考):

获得共享音频会话

声明SWIFT

class func sharedInstance() -> AVAudioSession

然后,尝试使用此实例方法将首选IO缓冲区持续时间设置为非常短的(例如.002):

设置首选音频I/O缓冲持续时间,以秒为单位.

声明SWIFT

func setPreferredIOBufferDuration(_ duration: NSTimeInterval) throws

参数

duration 要使用的音频I/O缓冲持续时间(以秒为单位).

outError 在输入时,指向错误对象的指针.如果发生错误,则将指针设置为描述错误的NSError对象.如果您不想要错误信息,请传入零.返回值如果请求成功,则返回true,否则返回false.

讨论

此方法请求更改I/O缓冲区持续时间.要确定更改是否生效,请使用IOBufferDuration属性.详情请参见配置音频会话.


请记住上面的注释 - IOBufferDuration属性是否实际设置为传递给func setPrefferedIOBufferDuration(_ duration: NSTimeInterval) throws方法的值,取决于不返回错误的函数,以及我不完全清楚的其他因素.另外 - 在我的测试中 - 我发现如果你将这个值设置为一个非常低的值,那么值(或接近它的值)确实会被设置,但是当播放文件时(例如使用AVAudioPlayerNode)声音不会玩了.没有错误,只是没有声音.这显然是个问题.我还没有发现如何测试这个问题,除非注意到在实际设备上测试时听不到声音.我会调查一下.但就目前而言,我建议将首选持续时间设置为不小于.002或.0015..0015的值似乎适用于我正在测试的iPad Air(型号A1474).虽然低至.0012似乎在我的iPhone 6S上运行良好.

从CPU开销角度考虑的另一件事是音频文件的格式.未压缩格式在播放时将具有非常低的CPU开销.Apple建议您使用CAF文件以获得最高质量和最低开销.对于压缩文件和最低开销,您应该使用IMA4压缩:

(来自iOS多媒体编程指南):

iOS中的首选音频格式对于未压缩(最高质量)音频,请使用打包在CAF文件中的16位小端线性PCM音频数据.您可以使用afconvert命令行工具在Mac OS X中将音频文件转换为此格式,如下所示:

/usr/bin/afconvert -f caff -d LEI16 {INPUT} {OUTPUT}

当您需要同时播放多个声音时,为了减少内存使用量,请使用IMA4(IMA/ADPCM)压缩.这样可以减小文件大小,但在解压缩过程中对CPU的影响最小.与线性PCM数据一样,在CAF文件中打包IMA4数据.

您也可以使用afconvert转换为IMA4:

/usr/bin/afconvert -f AIFC -d ima4 [file]



1> 小智..:

如果您需要极低的延迟,我发现AVAudioSession单例上有一个非常简单的解决方案(在应用程序启动时会自动实例化):

首先,使用此类方法获取对应用程序的AVAudioSession单例的引用:

(来自AVAudioSession类参考):

获得共享音频会话

声明SWIFT

class func sharedInstance() -> AVAudioSession

然后,尝试使用此实例方法将首选IO缓冲区持续时间设置为非常短的(例如.002):

设置首选音频I/O缓冲持续时间,以秒为单位.

声明SWIFT

func setPreferredIOBufferDuration(_ duration: NSTimeInterval) throws

参数

duration 要使用的音频I/O缓冲持续时间(以秒为单位).

outError 在输入时,指向错误对象的指针.如果发生错误,则将指针设置为描述错误的NSError对象.如果您不想要错误信息,请传入零.返回值如果请求成功,则返回true,否则返回false.

讨论

此方法请求更改I/O缓冲区持续时间.要确定更改是否生效,请使用IOBufferDuration属性.详情请参见配置音频会话.


请记住上面的注释 - IOBufferDuration属性是否实际设置为传递给func setPrefferedIOBufferDuration(_ duration: NSTimeInterval) throws方法的值,取决于不返回错误的函数,以及我不完全清楚的其他因素.另外 - 在我的测试中 - 我发现如果你将这个值设置为一个非常低的值,那么值(或接近它的值)确实会被设置,但是当播放文件时(例如使用AVAudioPlayerNode)声音不会玩了.没有错误,只是没有声音.这显然是个问题.我还没有发现如何测试这个问题,除非注意到在实际设备上测试时听不到声音.我会调查一下.但就目前而言,我建议将首选持续时间设置为不小于.002或.0015..0015的值似乎适用于我正在测试的iPad Air(型号A1474).虽然低至.0012似乎在我的iPhone 6S上运行良好.

从CPU开销角度考虑的另一件事是音频文件的格式.未压缩格式在播放时将具有非常低的CPU开销.Apple建议您使用CAF文件以获得最高质量和最低开销.对于压缩文件和最低开销,您应该使用IMA4压缩:

(来自iOS多媒体编程指南):

iOS中的首选音频格式对于未压缩(最高质量)音频,请使用打包在CAF文件中的16位小端线性PCM音频数据.您可以使用afconvert命令行工具在Mac OS X中将音频文件转换为此格式,如下所示:

/usr/bin/afconvert -f caff -d LEI16 {INPUT} {OUTPUT}

当您需要同时播放多个声音时,为了减少内存使用量,请使用IMA4(IMA/ADPCM)压缩.这样可以减小文件大小,但在解压缩过程中对CPU的影响最小.与线性PCM数据一样,在CAF文件中打包IMA4数据.

您也可以使用afconvert转换为IMA4:

/usr/bin/afconvert -f AIFC -d ima4 [file]

推荐阅读
mobiledu2402851173
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有