【问题标题】:swift AVFoundation pitched audio memory issueswift AVFoundation 音频内存问题
【发布时间】:2016-06-22 15:20:01
【问题描述】:

您好,对于 swift 和一般编程来说还是新手。

我有这个以指定音高播放一段音频的功能。它被一个 NStimer 调用,所以每秒播放一次。 (函数包含在 SoundPlayer 类中,然后设置 NStimer 并在 viewController 中使用)

func playPitchedAudio(audioFile: AVAudioFile, pitch: Float){
    audioEngine.stop()
    audioEngine.reset()

    let audioPlayerNode = AVAudioPlayerNode()
    let changePitchEffect = AVAudioUnitTimePitch()

    changePitchEffect.pitch = pitch

    audioEngine.attachNode(audioPlayerNode)
    audioEngine.attachNode(changePitchEffect)

    audioEngine.connect(audioPlayerNode, to: changePitchEffect, format: nil)

    audioEngine.connect(changePitchEffect, to: audioEngine.outputNode, format: nil)

    audioPlayerNode.scheduleFile(audioFile, atTime: nil, completionHandler: nil)

    do {
        try audioEngine.start()
    } catch {
        print("error")
    }

    audioPlayerNode.play()

}

它运行良好且工作正常,但每次调用时都会向内存添加几 MB 并且永远不会重新获得空间。对内存泄漏进行了一些研究,但找不到任何对我的具体情况有帮助的东西,所以希望有人能指出我正确的方向。

我认为这与创建一个新节点有关,并且每次调用 TimePitch 时都会将它们移动到包含该函数的类中,但出现“libc++abi.dylib:以 NSException 类型的未捕获异常终止”错误当声音第二次尝试播放时。

非常感谢任何帮助,谢谢!

额外的东西。

// defined in class to be used by function
var pitchedAudioPlayer = AVAudioPlayerNode()
var audioEngine = AVAudioEngine()

//Timer Start 
self.timer.invalidate()
self.timer = NSTimer.scheduledTimerWithTimeInterval(tempo, target: self,     selector: #selector(ViewController.timeTriggerPointer), userInfo: nil, repeats: true)

//Timer calls... (along with some other unrelated stuff)
func timeTriggerPointer() {
    soundPlayer.playPitchedAudio(pitchFilePath, pitch: -1000.0)
}

解决方案 -

import AVFoundation

class SoundPlayer {
    var pitchedAudioPlayer = AVAudioPlayerNode()
    var audioEngine = AVAudioEngine()

    let audioPlayerNode = AVAudioPlayerNode()
    let changePitchEffect = AVAudioUnitTimePitch()

    init() {
        audioEngine.attachNode(audioPlayerNode)
        audioEngine.attachNode(changePitchEffect)

        audioEngine.connect(audioPlayerNode, to: changePitchEffect, format: nil)
        audioEngine.connect(changePitchEffect, to: audioEngine.outputNode, format: nil)
    }

    func playPitchedAudio(audioFile: AVAudioFile, pitch: Float){
        audioPlayerNode.stop()

        changePitchEffect.pitch = pitch

        audioPlayerNode.scheduleFile(audioFile, atTime: nil,     completionHandler: nil)



        do {
            try audioEngine.start()
        } catch {
            print("error")
        }

        audioPlayerNode.play()
    }
}

【问题讨论】:

  • 有什么问题?是泄漏还是崩溃?
  • 对不起,泄漏是问题所在。崩溃是我修复泄漏的失败尝试。
  • 如何插入?将是问题。我不确定我是否有泄漏,但是当我运行计时器时,内存使用量不断增加,直到大约 120mb,然后崩溃。当我使用 AVAudioPlayer 时,该应用程序运行良好(但这不允许改变音高),所以肯定是这个功能导致了它。我不知道如何追踪泄漏,我尝试过使用仪器,但在这个阶段它有点超出我的能力,并且似乎指向我没有编写的代码,所以并没有真正帮助我。不知道如何直接在 Xcode 中进行。感谢您的帮助!
  • 您阅读我的回答了吗(如下)?这不是泄漏。只是您创建对象,直到内存不足。停止这样做,一切都会好起来的。

标签: swift audio memory pitch


【解决方案1】:

“泄漏”是一项技术含量很高的事情:一块永远无法释放的未引用内存(因为它是未引用的)。我怀疑你有泄漏。您只是拥有越来越多的对象,仅此而已。

您一遍又一遍地重复此代码(每次计时器触发一次):

let audioPlayerNode = AVAudioPlayerNode()
let changePitchEffect = AVAudioUnitTimePitch()
audioEngine.attachNode(audioPlayerNode)
audioEngine.attachNode(changePitchEffect)

但是,音频引擎本身仍然存在(它在函数外部声明,作为视图控制器的属性)。因此,每次计时器触发时,您都会向同一个音频引擎添加另外两个节点。节点占用内存,因此您的内存不断增加。这里没有惊喜。如果您不希望这种情况发生,请不要这样做。

我认为这与每次调用时创建一个新节点和 TimePitch 有关

给你。所以你已经解决了你自己的问题。

想一想你想要做什么。您有一个带有节点的音频引擎。每次运行时唯一可能改变的是 AVAudioUnitTimePitch 节点的音高和要播放的文件。因此,请事先创建整个音频引擎和节点,并将其保留在原处。保留对 AVAudioUnitTimePitch 的引用作为属性。在计时器功能中,只需更改音高值!

let theTimePitchNode = AVAudioUnitTimePitch()
// and you have also added that node to the engine in your setup
func playPitchedAudio(audioFile: AVAudioFile, pitch: Float){

    audioPlayerNode.stop()

    theTimePitchNode.pitch = pitch
    audioPlayerNode.scheduleFile(audioFile, atTime: nil, completionHandler: nil)

    do {
        try audioEngine.start()
    } catch {
        print("error")
    }

    audioPlayerNode.play()

}

【讨论】:

  • 感谢您澄清我对泄漏的错误理解!这有帮助。所以我理解了这个问题,但我尝试的修复没有奏效!生病尝试一些其他的东西。
  • 但是你没有显示你尝试的修复,那么我怎么知道你做错了什么?我已经修改了我的答案,以显示您需要在此处遵循的策略。
  • 所以我试过这个.. 但声音现在只播放一次(在第一次计时器击中)并且内存问题仍然存在。 (在问题中添加了代码)
  • 您的新代码毫无意义。你的playPitchedAudio 函数在inside 你的init 函数???这很古怪。
  • 抱歉,这里只是一个格式错误,而不是实际代码。现已修复
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多