当我添加一束(20-40)的样本同时在演奏和彼此重叠时,有时会开始变形,然后开始出现一些波动,振荡和咔嗒声。当样本正在播放时,应用程序崩溃时会发生类似的声音-听起来像是突然的,嘎吱作响的停止。

注意起伏在0:05到0:10之间开始;讨厌的点击从0:15开始。

Listen Here

如何使它更平滑?我正在生成播放4-8秒的.wav文件的AKPlayer对象(从4.1开始)。这些进入AKBoosters,再进入AKMixer,再进入最终的AKMixer进行输出。

编辑:

许多PenAudioNodes被插入到AudioReceiver单例的混音器中。

这是我的AudioReceiver单例:

class AudioReceiver {
    static var sharedInstance = AudioReceiver()
    private var audioNodes = [UUID : AudioNode]()
    private let mixer = AKMixer()
    private let queue = DispatchQueue(label: "audio-queue")

    //MARK: - Setup & Teardown

    init() {
        AudioKit.output = mixer //peakLimiter
        AudioKit.start()
    }

    //MARK: - Public

    func audioNodeBegan(_ message : AudioNodeMessage) {
        queue.async {
            var audioNode: AudioNode?
            switch message.senderType {
            case .pen:
                audioNode = PenAudioNode()
            case .home:
                audioNode = LoopingAudioNode(with: AudioHelper.homeLoopFile())
            default:
                break
            }
            if let audioNode = audioNode {
                self.audioNodes[message.senderId] = audioNode
                self.mixer.connect(input: audioNode.output)
                audioNode.start(message)
            }
        }
    }

    func audioNodeMoved(_ message : AudioNodeMessage) {
        queue.async {
            if let audioNode = self.audioNodes[message.senderId] {
                audioNode.update(message)
            }
        }
    }

    func audioNodeEnded(_ message : AudioNodeMessage) {
        queue.async {
            if let audioNode = self.audioNodes[message.senderId] {
                audioNode.stop(message)
            }
            self.audioNodes[message.senderId] = nil
        }
    }
}

这是我的PenAudioNode:
class PenAudioNode {
    fileprivate var mixer: AKMixer?
    fileprivate var playersBoosters = [AKPlayer : AKBooster]()
    fileprivate var finalOutput: AKNode?
    fileprivate let file: AKAudioFile = AudioHelper.randomBellSampleFile()

    //MARK: - Setup & Teardown

    init() {
        mixer = AKMixer()
        finalOutput = mixer!
    }
}

extension PenAudioNode: AudioNode {
    var output: AKNode {
        return finalOutput!
    }

    func start(_ message: AudioNodeMessage) {
    }

    func update(_ message: AudioNodeMessage) {
        if let velocity = message.velocity {
            let newVolume = Swift.min((velocity / 50) + 0.1, 1)
            mixer!.volume = newVolume
        }
        if let isClimactic = message.isClimactic, isClimactic {
            let player = AKPlayer(audioFile: file)
            player.completionHandler = { [weak self] in
                self?.playerCompleted(player)
            }
            let booster = AKBooster(player)
            playersBoosters[player] = booster
            booster.rampTime = 1
            booster.gain = 0
            mixer!.connect(input: booster)
            player.play()
            booster.gain = 1
        }
    }

    func stop(_ message: AudioNodeMessage) {
        for (_, booster) in playersBoosters {
            booster.gain = 0
        }
        DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + 1) {
            self.mixer!.stop()
            self.output.disconnectOutput()
        }
    }

    private func playerCompleted(_ player: AKPlayer) {
        playersBoosters.removeValue(forKey: player)
    }
}

最佳答案

这听起来像您没有释放对象,并且最终使音频引擎过载,图中连接的处理节点实例过多。特别是不释放AKBoosters会引起这样的问题。我不能真正说出代码在做什么,但是如果生成对象而没有正确释放它们,则会导致音频混乱。

您希望尽可能节省对象,并确保使用的是基于AKNode的绝对最小数量的处理。

有多种调试方法,但是您可以首先打印出AVAudioEngine的当前状态:

AudioKit.engine.description

这将显示您在任何给定时刻在图中连接了多少个节点。

10-04 12:51