有没有办法以编程方式获取 iOS 中音频单元的所有参数?

Posted

技术标签:

【中文标题】有没有办法以编程方式获取 iOS 中音频单元的所有参数?【英文标题】:is there a way to programmatically get all the parameters of an Audio Unit in iOS? 【发布时间】:2013-10-04 21:13:28 【问题描述】:

AUParamInfo() 似乎不存在于 ios7 框架(CoreAudio、AudioUnit、AudioToolbox)中。我想知道获取一个单元的所有参数的方法是什么。也就是说,不知道它是什么类型或子类型的单元,因为如果不是,答案将是在音频单元参数参考中查找。

【问题讨论】:

【参考方案1】:

Greg 的回答是正确的,因为 kAudioUnitProperty_ParameterList 是要查询以最终获取单元的所有参数的正确属性 ID。但是,获取所有参数的方式有点复杂:

    使用AudioUnitGetPropertyInfo 查看属性是否可用,如果可用,则返回其数据大小(可能是一个集合的整个信息的数据大小,而不是属性是任何类型的单个元素的数据大小,请注意你)。

    正确使用AudioUnitGetProperty 来取回该属性。此外,此时,如果您返回的属性是元素集合而不是单个元素,则您必须为每个元素调用一次AudioUnitGetProperty。具体来说,你可以称它为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...
    
    

【讨论】:

【参考方案2】:

不确定这是否会有所帮助,但文档指出:

要从音频单元获取参数信息,主机应用程序 首先获取音频单元的值 kAudioUnitProperty_ParameterList 属性,为您提供的一个属性 通过 SDK 中的超类。这个属性的值是一个列表 为音频单元定义的参数 ID。然后主机可以查询 每个参数 ID 的 kAudioUnitProperty_ParameterInfo 属性。

(来自Audio Unit Programming Guide)

【讨论】:

实际上,我似乎无法让它工作。我实例化了一个远程 I/O 音频单元,但执行AudioUnitParameterID *parameterIds; UInt32 numberOfParameters = 0; AudioUnitGetProperty(_audioUnit, kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0, &amp;parameterIds, &amp;numberOfParameters); 之类的操作没有返回任何结果。有什么想法吗? @SaldaVonSchwartz 你在其他 AU 上试过了吗? RemoteIO 好像没有参数。【参考方案3】:

这是一个 Swift 5 版本提案

1 - 定义一个方便的结构来存储我们的信息

/// 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 - 在 AudioUnit 类上添加一个方便的参数获取器

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
    

用法:

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

我们还可以为 Unit 整数代码实现一个字符串 getter。只需从 Apple AudioUnitParameterUnit 复制所有参数即可。

extension AudioUnitParameterUnit 
    var name: String  ["Generic", "Indexed", "Boolean", "Percent", ... ][rawValue] 

【讨论】:

以上是关于有没有办法以编程方式获取 iOS 中音频单元的所有参数?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法以编程方式向 UICollectionView 单元格添加填充?

有没有办法以编程方式访问 iOS 图像描述器?

在 ios 中以编程方式获取墙纸

如何以编程方式更改 iOS 设备音量?

以编程方式在 iOS 中录制的音频无法在 Windows 中播放

以编程方式获取所有存储过程的简单方法