有没有办法使用 AVAudioPlayerNode 从头开始​​重播声音?

Posted

技术标签:

【中文标题】有没有办法使用 AVAudioPlayerNode 从头开始​​重播声音?【英文标题】:Is there a way to replay a sound from the beginning using AVAudioPlayerNode? 【发布时间】:2017-11-15 08:40:04 【问题描述】:

我设置了一堆音频节点

var audioPlayers = [AVAudioPlayerNode]()

var engine = AVAudioEngine()

var player = AVAudioPlayerNode()


@IBAction func key(_ sender: UIButton) 
        audioPlayers[someindex].play()


func createPlayers() 

        for key in constructedArrayOfNotes 
            player = AVAudioPlayerNode()


            player.volume = 0.5

            let reverb = AVAudioUnitReverb()
            reverb.loadFactoryPreset(AVAudioUnitReverbPreset.cathedral)

            reverb.wetDryMix = 50

            let audiopath = Bundle.main.path(forResource: key, ofType: "mp3",inDirectory: directory)!
            let url = NSURL.fileURL(withPath: audiopath)

            do 
                let file = try! AVAudioFile.init(forReading: url)
                let buffer = AVAudioPCMBuffer(pcmFormat: file.processingFormat, frameCapacity: AVAudioFrameCount(file.length))
                try file.read(into: buffer!)
                engine.attach(player)
                engine.attach(reverb)



                engine.connect(player, to: reverb, format: buffer!.format)
                engine.connect(reverb, to: engine.mainMixerNode, format: buffer!.format)
                player.scheduleFile(file, at: nil, completionHandler: nil)



                audioPlayers.append(player)
             catch 
                print("error")
            


        





override func viewDidLoad() 

    createPlayers()
    engine.prepare()
    try! engine.start()

    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

有没有办法让我从头开始重播存储在 AVAudioPlayerNode 中的音频文件?目前,当我按下 IBAction 时,声音会播放,但我无法重播。我正在尝试做相当于 AVAudioPlayer.starttime = 0

【问题讨论】:

【参考方案1】:

回答您提出的问题:

AVAudioPlayerNode没有seek功能,需要重新调度文件。

一种简洁的方法是在创建音频文件时保留对它们的引用。然后,在您的关键功能中重新安排文件并播放。

var audioPlayers = [AVAudioPlayerNode]()
var audioFiles = [AVAudioFile]() // Populate in same loop you create the players.

@IBAction func key(_ sender: UIButton) 
    let player = audioPlayers[sender.tag]
    let audioFile = audioFiles[sender.tag]
    player.scheduleFile(audioFile, at: nil, completionHandler: nil)
    player.play()

根据假设提供建议:)

对于作为按钮目标的键功能,我假设您希望在按下按钮时播放不同的音频文件。如果您不介意从按下按钮到音频开始播放之间会有一点延迟,或者,如果您正在处理非常长的音频文件,那么您当前的方法就可以了。但是,如果无法接受不可预测的延迟时间,您有几个选择。

安排音频 AVAudioBuffers 而不是文件,开始播放时的延迟时间要少得多。您将使用我上面概述的相同方法,但不是存储 AVAudioFile 和调度,而是存储和调度 AVAudioBuffer。

如果您要制作打击垫或键盘样式的采样器,则需要将延迟降至最低。 AVAudioUnitSampler 非常适合这个。它能够实现非常低延迟的音频,并且可以配置为将文件映射到键。设置起来有点困难,但如果时间很重要,那么值得付出努力。

【讨论】:

不幸的是,当我再次按下按钮时,我仍然无法播放我想要的相同声音。我希望它从一开始就重播声音。我想知道也许 play(at:...) 函数可以解决问题,但它需要一个 AVAudioTime 参数,我不知道如何构造一个。

以上是关于有没有办法使用 AVAudioPlayerNode 从头开始​​重播声音?的主要内容,如果未能解决你的问题,请参考以下文章

AVAudioPlayerNode lastRenderTime

AVAudioPlayerNode音量更改不会立即应用

以编程方式淡出 AVAudioPlayerNode 的音量

播放完成后在 AVAudioPlayerNode 上调用 stop() 会导致崩溃

AVAudioEngine 录制在 AVAudioPlayerNode 中播放的声音

AVAudioEngine & AVAudioPlayerNode didFinish 方法,如 AVAudioPlayer