Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 多文件播放器上的核心音频声音测量_Swift_Swift3_Callback_Core Audio_Audiounit - Fatal编程技术网

Swift 多文件播放器上的核心音频声音测量

Swift 多文件播放器上的核心音频声音测量,swift,swift3,callback,core-audio,audiounit,Swift,Swift3,Callback,Core Audio,Audiounit,我有一个AUGraph设置,其中有两个文件播放器音频单元输入多通道混音器单元,然后再输入远程I/O输出。这个设置工作得很好 现在我一直在努力添加一个回调,这样我就可以计算出各个文件播放器的音量 private let meteringCallback: AURenderCallback = { ( inRefCon, ioActionFlags, inTimeStamp, inBusNumber, frameCount, ioData ) ->

我有一个AUGraph设置,其中有两个文件播放器音频单元输入多通道混音器单元,然后再输入远程I/O输出。这个设置工作得很好

现在我一直在努力添加一个回调,这样我就可以计算出各个文件播放器的音量

private let meteringCallback: AURenderCallback = { (
    inRefCon,
    ioActionFlags,
    inTimeStamp,
    inBusNumber,
    frameCount,
    ioData ) -> OSStatus in

    var status = noErr

    var track: AUTrack = unsafeBitCast(inRefCon, to: AUTrack.self)

    status = AudioUnitRender(track.fileAU!,
                             ioActionFlags,
                             inTimeStamp,
                             inBusNumber,
                             frameCount,
                             ioData!);

    var samples = [Float]()
    let ptr = ioData!.pointee.mBuffers.mData?.assumingMemoryBound(to: Float.self)
    samples.append(contentsOf: UnsafeBufferPointer(start: ptr, count: Int(frameCount)))

    // ... fancy algorithm calculating DB value ...
}
AUTrack simple保存有关该特定轨迹的信息。将整个类实例传递给回调(在示例中通常是这样做的)在这里没有意义,因为有多个文件播放器

private let meteringCallback: AURenderCallback = { (
    inRefCon,
    ioActionFlags,
    inTimeStamp,
    inBusNumber,
    frameCount,
    ioData ) -> OSStatus in

    var status = noErr

    var track: AUTrack = unsafeBitCast(inRefCon, to: AUTrack.self)

    status = AudioUnitRender(track.fileAU!,
                             ioActionFlags,
                             inTimeStamp,
                             inBusNumber,
                             frameCount,
                             ioData!);

    var samples = [Float]()
    let ptr = ioData!.pointee.mBuffers.mData?.assumingMemoryBound(to: Float.self)
    samples.append(contentsOf: UnsafeBufferPointer(start: ptr, count: Int(frameCount)))

    // ... fancy algorithm calculating DB value ...
}
现在我需要将这个回调设置在某个地方,这样我就可以捕获每个文件播放器输入到混合器中的值。然而,当我尝试这样做时,我不断得到一个-10877(无效元素)错误

我尝试用这个设置计量回调

// Set metering callback
var meteringCallbackStruct = AURenderCallbackStruct(inputProc: meteringCallback,
                                                    inputProcRefCon: &self.tracks[1])
status = AudioUnitSetProperty(self.tracks[1].fileAU!,
                          kAudioUnitProperty_SetRenderCallback,
                          kAudioUnitScope_Output,
                          0,
                          &meteringCallbackStruct,
                     UInt32(MemoryLayout<AURenderCallbackStruct>.size))
//设置计数回调
var meteringCallbackStruct=AURenderCallbackStruct(inputProc:meteringCallback,
inputProcRefCon:&self.tracks[1])
状态=AudioUnitSetProperty(self.tracks[1].fileAU!,
kAudioUnitProperty_SetRenderCallback,
考迪翁镜输出,
0,
&meteringCallbackStruct,
UInt32(内存大小))
我不太确定如何解决这个问题


除非我以某种方式将样本传回混合装置,否则这个回调不会“吃掉”样本吗?

您不应该用Swift进行回调。渲染线程处理只能在C/C++中完成

您可以使用:

它使用与呈现回调相同的函数签名。它被称为“渲染前”和“渲染后”,您需要处理渲染后。您可以从ioActionFlags获取此信息

int isPostRender = ioActionFlags & kAudioUnitRenderAction_PostRender;
但是,由于您使用的是多通道混音器,因此内置了输入级监控,因此不需要回调

您首先像这样启用它

//AudioUnit mixer; kAudioUnitSubType_MultiChannelMixer 

//Call Before AudioUnitInitialize()
UInt32 meteringMode = 1;
AudioUnitSetProperty(mixer, kAudioUnitProperty_MeteringMode, kAudioUnitScope_Input, 0, &meteringMode, sizeof(meteringMode));
然后在处理过程中,您可以通过读取参数来获得级别

int channel = 0;

AudioUnitParameterValue averageDecibles;
AudioUnitGetParameter(mixer, kMultiChannelMixerParam_PreAveragePower, kAudioUnitScope_Input, channel, &averageDecibles);

AudioUnitParameterValue peakHoldDecibles;
AudioUnitGetParameter(mixer, kMultiChannelMixerParam_PrePeakHoldLevel, kAudioUnitScope_Input, channel, &peakHoldDecibles);
Swift:

var meteringMode: UInt32 = 1;
let propSize = UInt32(MemoryLayout<UInt32>.size)
AudioUnitSetProperty(mixer, kAudioUnitProperty_MeteringMode, kAudioUnitScope_Input, 0, &meteringMode, propSize);

var averageDecibles: AudioUnitParameterValue = 0
AudioUnitGetParameter(mixer, kMultiChannelMixerParam_PreAveragePower, kAudioUnitScope_Input, channel, &averageDecibles);

var peakHoldDecibles: AudioUnitParameterValue = 0
AudioUnitGetParameter(mixer, kMultiChannelMixerParam_PrePeakHoldLevel, kAudioUnitScope_Input, channel, &peakHoldDecibles);
var计量模式:UInt32=1;
让propSize=UInt32(MemoryLayout.size)
AudioUnitSetProperty(混音器、kAudioUnitProperty_计量模式、kAudioUnitScope_输入、0和计量模式、propSize);
var averageDecibles:AudioUnitParameterValue=0
AudioUnitGetParameter(混音器、K多通道混音器参数、平均功率、音频范围、输入、通道和平均小数);
var peakHoldDecibles:AudioUnitParameterValue=0
AudioUnitGetParameter(混音器、kMultiChannelMixerParam\u预峰值保持电平、kAudioUnitScope\u输入、通道和峰值分辨率);

非常感谢您。这对我来说是一个很大的帮助,我已经写了一半自己的混音器了。我不敢相信我在头文件中漏掉了这些参数:D