AUHostMusicalContextBlock "An audio unit accessing this property should cache it in realtime-safe storage before beginning to render."

Viewed 108

When using the AVFoundation MusicalContextBlock parameter Apple says:

"An audio unit accessing this property should cache it in realtime-safe storage before beginning to render."

What does this mean?

I am trying to implement the callback that allows audio units to retrieve timing information. However. I am getting spotty results. Namely if I set the MusicalContextBlock on several AudioUnits, only the last one accesses the callback successfully. The others do not call it. It is as if the most recent audio unit "takes over" the function.

  public func contextBlock() -> AUHostMusicalContextBlock {
        func getMusicalContext(currentTempo : UnsafeMutablePointer<Double>?,
                               timeSignatureNumerator : UnsafeMutablePointer<Double>?,
                               timeSignatureDenominator : UnsafeMutablePointer<Int>?,
                               currentBeatPosition: UnsafeMutablePointer<Double>?,
                               sampleOffsetToNextBeat : UnsafeMutablePointer<Int>?,
                               currentMeasureDownbeatPosition: UnsafeMutablePointer<Double>?) -> Bool {
            if self.delegate == nil { return false }
            let context = self.delegate!.musicalContext
            currentTempo?.pointee = context.currentTempo
            timeSignatureNumerator?.pointee = context.timeSignatureNumerator
            timeSignatureDenominator?.pointee = context.timeSignatureDenominator
            currentBeatPosition?.pointee = context.currentBeatPosition
            sampleOffsetToNextBeat?.pointee = context.sampleOffsetToNextBeat
            currentMeasureDownbeatPosition?.pointee = context.currentMeasureDownbeatPosition
            return true
        }
        return getMusicalContext
    }

    public func instrument(description: AudioComponentDescription) -> AVAudioUnitMIDIInstrument{
        let plugin = AVAudioUnitMIDIInstrument(audioComponentDescription: description)
        plugin.auAudioUnit.musicalContextBlock = contextBlock()
        return plugin
    }
1 Answers

I'm not sure what goes on here.

Audio Units that want to use the musicalContextBlock will most probably want to use it it the render function. But they are not supposed to access that property directly within the render function.

An AudioUnit can implement allocateRenderResourcesAndReturnError, that the host is supposed to call before each render. There it can safely check if musicalContextBlock is set, and if so, store it at location to be used later, in the render function.

Are you sure you call allocateRenderResourcesAndReturnError on each AudioUnit before doing a render?

Related