0

I've built a convenience wrapper for defining/creating AudioKit effects:

public struct SQEffect {
    public var type: EffectType = .delay
    public var node: AKNode!
    public var usesSync: Bool = false
    public var dryWetMixer: AKDryWetMixer? = nil
    public var parameters: [String] = []
    
    public init(input: AKNode, type: EffectType, useSync: Bool) {
        self.type = type
        switch type {
        case .autopan:
            node = AKOperationEffect(input) { input, parameters in
                let oscillator = AKOperation.sineWave(frequency: parameters[speedIndex], amplitude: parameters[depthIndex])
                return input.pan(oscillator)
            }
            parameters = ["speed", "depth"]
        case .delay:
            var delTime = 0.33
            if useSync == true {
                let tempo = SequencerController.sharedInstance.currentTempo
                let beatDur = (60000 / tempo) / 1000
                // we'll make the default a dotted-eighth
                delTime = 0.75 * beatDur
            }
            node = AKOperationEffect(input) { input, params in
                return input.smoothDelay(time: params[0], feedback: params[1], samples: 1_024, maximumDelayTime: 10.0)
            }
            (node as! AKOperationEffect).parameters = [delTime, 0.1]
            dryWetMixer = AKDryWetMixer(input, node)
            parameters = ["time", "feedback", "dryWet_balance"]
        case .notchPeak:
            node = AKEqualizerFilter(input, centerFrequency: 250, bandwidth: 200.0, gain: 5.0)
            parameters = ["centreFreq", "bandwidth", "gain"]
        case .lowPass:
            node = AKLowPassFilter(input, cutoffFrequency: 600.0, resonance: -20.0)
            parameters = ["cutoffFreq", "resonance"]
        case .chorus:
            node = AKChorus(input, frequency: 50.0, depth: 0.3, feedback: 0.0, dryWetMix: 0.0)
            parameters = ["freq", "depth", "feedback", "dryWetMix"]
        case .flanger:
            node = AKFlanger(input, frequency: 50.0, depth: 0.3, feedback: 0.2, dryWetMix: 0.0)
            parameters = ["freq", "depth", "feedback", "dryWetMix"]
        case .reverb:
            // NOTE: We could replace this with another reverb (AKReverb2) at some point, for greater control.
            node = AKReverb(input, dryWetMix: 0.0)
            (node as! AKReverb).loadFactoryPreset(.cathedral)
            parameters = ["factoryPreset", "dryWetMix"]
        }
        self.usesSync = useSync
    }
    
    // do other stuff...
}

The custom init() is leaking memory, specifically reported by Instruments in AKOperationEffect and AKEqualizerFilter. Is there anything obvious I'm doing wrong here?

jbm
  • 1,248
  • 10
  • 22
  • When you say it's leaking memory, do you mean that during some operation, memory steadily grows, or do you mean that Instruments is reporting a single leak event? Instruments reports small false-positive leak events all the time, and many parts of Cocoa leak small and bounded amounts of memory. Unless you're seeing memory *steadily* leaking, this is unlikely something you should pursue. Getting the output of `leaks` to zero is not really a thing in a complex project. – Rob Napier Sep 16 '20 at 16:09
  • Ah, okay, good to know! I've been trying to debug memory pressure warnings and happened to see a bunch of "Root Leaks" reported when instantiating those effects, but I'll dig deeper. – jbm Sep 16 '20 at 16:45

0 Answers0