簡體   English   中英

iOS Swift中簡單的低延遲音頻播放

[英]Simple low-latency audio playback in iOS Swift

我是iOS的初學者,我正在嘗試用Swift設計一個鼓組應用程序。 我用一個按鈕設計了一個視圖並編寫了下面的代碼,但它有一些問題:

  1. 當我像滾筒一樣快速觸摸按鈕時,有些聲音會丟失。
  2. 仍處於“鼓聲”中,每次觸摸按鈕時聲音都會中斷,而不是讓樣本播放直到結束。 例如,鈸卷很糟糕。 即使我再次觸摸按鈕,我也希望聽到每個樣本完全響起。
  3. 觸摸和聲音之間存在延遲。 我知道AVAudioPlayer不是低延遲音頻的最佳選擇,但作為初學者,很難學習OpenAL ,沒有代碼示例的AudioUnitSwift教程。 問題與此類似: 我應該使用哪種框架在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()
}

如果您需要極低的延遲,我發現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的值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]

我花了一個下午嘗試通過玩AVAudioPlayer和AVAudioSession來解決這個問題,但我無法隨心所欲。 (不幸的是,這里設置IO緩沖持續時間似乎沒有幫助。)我也嘗試過AudioToolbox,但我發現結果表現幾乎相同 - 相關用戶操作之間明顯可察覺的延遲和音頻。

在搜索了一下互聯網之后,我發現了這個:

www.rockhoppertech.com/blog/swift-avfoundation/

AVAudioEngine部分結果非常有用。 下面的代碼是一個輕微的重做:

import UIKit
import AVFoundation

class ViewController: UIViewController {

var engine = AVAudioEngine()
var playerNode = AVAudioPlayerNode()
var mixerNode: AVAudioMixerNode?
var audioFile: AVAudioFile?

@IBOutlet var button: UIButton!

override func viewDidLoad() {
    super.viewDidLoad()

    engine.attach(playerNode)
    mixerNode = engine.mainMixerNode

    engine.connect(playerNode, to: mixerNode!, format: mixerNode!.outputFormat(forBus: 0))

    do {
        try engine.start()
    }

    catch let error {
        print("Error starting engine: \(error.localizedDescription)")
    }

    let url = Bundle.main.url(forResource: "click_04", withExtension: ".wav")

    do {
        try audioFile = AVAudioFile(forReading: url!)
    }

    catch let error {
        print("Error opening audio file: \(error.localizedDescription)")
    }
}

@IBAction func playSound(_ sender: Any) {

    engine.connect(playerNode, to: engine.mainMixerNode, format: audioFile?.processingFormat)
    playerNode.scheduleFile(audioFile!, at: nil, completionHandler: nil)

    if engine.isRunning{
        playerNode.play()
    } else {
        print ("engine not running")
    }
}

}

這可能不完美,因為我是一個Swift新手並且之前沒有使用過AVAudioEngine。 但它似乎確實有效!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM