     // MARK: Lifecycle
 
     /// This function should be called from Node subclasses as soon as a valid AU is obtained
-    public func associate(with avAudioUnit: AVAudioUnit, identifier: String) {
-        self.avAudioUnit = avAudioUnit
-        parameter = avAudioUnit.auAudioUnit.parameterTree?[identifier]
+    public func associate(with avAudioNode: AVAudioNode, identifier: String) {
+        self.avAudioNode = avAudioNode
+        parameter = avAudioNode.auAudioUnit.parameterTree?[identifier]
         assert(parameter != nil)
     }
 

            guard let automationBaseAddress = automationPtr.baseAddress else { return }

            guard let observer = ParameterAutomationGetRenderObserver(parameter.address,
                                                                      avAudioUnit.auAudioUnit.scheduleParameterBlock,
                                                                      Float(Settings.sampleRate),
                                                                      Float(lastTime.sampleTime),
                                                                      automationBaseAddress,
                                                                      events.count) else { return }

            renderObserverToken = avAudioUnit.auAudioUnit.token(byAddingRenderObserver: observer)
        }
    }

    /// Automate to a new value using a ramp.
    public func ramp(to value: AUValue, duration: Float) {
        let paramBlock = avAudioUnit.auAudioUnit.scheduleParameterBlock
        paramBlock(AUEventSampleTimeImmediate,
                   AUAudioFrameCount(duration * Float(Settings.sampleRate)),
                   parameter.address,

    /// - Parameter events: automation curve
    /// - Parameter startTime: optional time to start automation
    public func automate(events: [AutomationEvent], startTime: AVAudioTime? = nil) {
        var lastRenderTime = avAudioNode.lastRenderTime ?? AVAudioTime(sampleTime: 0, atRate: Settings.sampleRate)

        if !lastRenderTime.isSampleTimeValid {
            if let engine = avAudioNode.engine, engine.isInManualRenderingMode {
                lastRenderTime = AVAudioTime(sampleTime: engine.manualRenderingSampleTime, atRate: Settings.sampleRate)
            } else {
                lastRenderTime = AVAudioTime(sampleTime: 0, atRate: Settings.sampleRate)
