Question

AUParamInfo() doesn't seem to exist in the iOS7 frameworks (CoreAudio, AudioUnit, AudioToolbox). I'm wondering what would be the way to get all parameters for a unit. That is, without knowing what type or subtype of unit it is, since if not the answer would be to look up in the Audio Unit Parameters Reference.

Was it helpful?

Solution

Greg's answer is right in the sense that kAudioUnitProperty_ParameterList is the right property ID to query to eventually get all parameters of a unit. However, the way to get all parameters is a bit more involved:

  1. Use AudioUnitGetPropertyInfo to see if the property is available and if it is, get back its data size (data size for the whole info which might be a collection, not for a single element of whatever type the property is, mind you).
  2. Use AudioUnitGetProperty proper to get the property back. Also, at this point, if the property you got back is a collection of elements as opposed to a single one, you'll have to call AudioUnitGetProperty once for each element. Specifically, you'll call it dataSize / sizeof(TypeToHoldSingleInstanceOfYourProperty) times.

    //  Get number of parameters in this unit (size in bytes really):
    UInt32 parameterListSize = 0;
    AudioUnitGetPropertyInfo(_audioUnit, kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0, &parameterListSize, NULL);
    
    //  Get ids for the parameters:
    AudioUnitParameterID *parameterIDs = malloc(parameterListSize);
    AudioUnitGetProperty(_audioUnit, kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0, parameterIDs, &parameterListSize);
    
    AudioUnitParameterInfo parameterInfo_t;
    UInt32 parameterInfoSize = sizeof(AudioUnitParameterInfo);
    UInt32 parametersCount = parameterListSize / sizeof(AudioUnitParameterID);
    for(UInt32 pIndex = 0; pIndex < parametersCount; pIndex++){
        AudioUnitGetProperty(_audioUnit, kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global, parameterIDs[pIndex], &parameterInfo_t, &parameterInfoSize);
        // do whatever you want with each parameter...
    }
    

OTHER TIPS

Not sure if this will be helpful, but the documentation states:

To get parameter information from an audio unit, a host application first gets the value of the audio unit’s kAudioUnitProperty_ParameterList property, a property provided for you by superclasses in the SDK. This property’s value is a list of the defined parameter IDs for the audio unit. The host can then query the kAudioUnitProperty_ParameterInfo property for each parameter ID.

(from the Audio Unit Programming Guide)

Here is a Swift 5 version proposal

1 - Define a convenient structure to store our info

/// Swifty AudioUnit parameters array

struct AudioUnitParameter: CustomStringConvertible {
    var id: Int
    var name: String = ""
    var minValue: Float
    var maxValue: Float
    var defaultValue: Float
    var unit: Int

    init(_ info: AudioUnitParameterInfo, id: UInt32) {
        self.id = Int(id)
        if let cfName = info.cfNameString?.takeUnretainedValue() {
            name = String(cfName)
        }
        minValue = Float(info.minValue)
        maxValue = Float(info.maxValue)
        defaultValue = Float(info.defaultValue)
        unit = Int(info.unit.rawValue)
    }
    
    var description: String {
        "Parameter [id: \(id)] :  \(name) [\(minValue)..\(maxValue)] \(unit)"
    }
}

2 - Add a convenient parameters getter on the AudioUnit class

extension AudioUnit {
    
    /// Returns an array with audioUnit parameters descriptions
    var parameters: [AudioUnitParameter] {
        
        var out = [AudioUnitParameter]()
        
        //  Get number of parameters in this unit (size in bytes really):
        var parameterListSize: UInt32 = 0
        let parameterSize = MemoryLayout<AudioUnitParameterID>.size
        AudioUnitGetPropertyInfo(self, kAudioUnitProperty_ParameterList,
                                 kAudioUnitScope_Global,
                                 0, &parameterListSize, nil);
        
        let numberOfParameters = Int(parameterListSize) / parameterSize

        //  Get ids for the parameters:
        let parameterIds = UnsafeMutablePointer<UInt32>.allocate(capacity: Int(parameterListSize))
        AudioUnitGetProperty(self, kAudioUnitProperty_ParameterList,
                             kAudioUnitScope_Global,
                             0, parameterIds, &parameterListSize);

        var info = AudioUnitParameterInfo()
        var infoSize = UInt32(MemoryLayout<AudioUnitParameterInfo>.size)
        
        for i in 0 ..< numberOfParameters {
            let id = parameterIds[i]
            AudioUnitGetProperty(self, kAudioUnitProperty_ParameterInfo,
                                 kAudioUnitScope_Global,
                                 id, &info, &infoSize);
            out += [AudioUnitParameter(info, id: id)]
        }
        return out
    }
}

Usage:

if let params = myDLSSynthAudioUnit.parameters {
    params.forEach { print($0) }
}
Property [0] :  Tuning [-1200.0..1200.0] 9
Property [1] :  Volume [-120.0..40.0] 13
Property [2] :  Reverb Volume [-120.0..40.0] 13

We can also implement a string getter for the Unit integer code. Just copy all the parameters from the Apple AudioUnitParameterUnit.

extension AudioUnitParameterUnit {
    var name: String { ["Generic", "Indexed", "Boolean", "Percent", ... ][rawValue] }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top