如果 iOS 核心音频单元同时连接到输入单元和输出单元,是否有回调?
Is there a Callback for an iOS Core Audio Unit, if the unit is connected to both an input unit and output unit?
我有一个音频单元,它位于另外两个单元之间。也就是说,我的单元有另一个单元分配给它的输入节点,它有另一个单元分配给它的输出节点。
我想访问输入我的设备的 AudioBufferList。我想在回调中访问此缓冲区列表。但是,如果我的单元的输入总线已经连接到另一个音频单元,那么我的 RenderCallback 永远不会被调用。
我可以使用什么回调来访问给定单元的传入音频缓冲区?
AURenderCallbackStruct splitterCallback;
splitterCallback.inputProc = (AURenderCallback) SplitterCallback;
splitterCallback.inputProcRefCon = (__bridge void*) self;
status = AudioUnitSetProperty(splitterAuUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input,
0, &splitterCallback, sizeof(splitterCallback));
AudioUnitElement genericOutputBus = 0;
AudioUnitConnection genericOutToIoUnitIn;
genericOutToIoUnitIn.sourceAudioUnit = genericAuUnit;
genericOutToIoUnitIn.sourceOutputNumber = genericOutputBus;
genericOutToIoUnitIn.destInputNumber = ioUnitOutputElement;
AudioUnitSetProperty (
splitterAuUnit, // connection destination
kAudioUnitProperty_MakeConnection, // property key
kAudioUnitScope_Input, // destination scope
ioUnitOutputElement, // destination element
&genericOutToIoUnitIn, // connection definition
sizeof (genericOutToIoUnitIn)
);
// Callback
static OSStatus SplitterCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
@autoreleasepool {
NSLog(@"splitterCallback"); // This is never called. :(
}
}
这是在 AUGraph API 中注册回调而不破坏 API 的核心音频过程。它在 OSX 中进行了测试,但是 API 的这一部分对于 iOS 也是通用的。假设你想听输出单元输入的信号,一个单元 "upstream" 就是 splitterAuUnit
。我将通过以下方式注册回调 MyRenderProc()
:
AudioUnitAddRenderNotify(splitterAuUnit,
MyRenderProc,
&player);
在回调中检查渲染操作和 post 渲染错误很重要:
if (*ioActionFlags & kAudioUnitRenderAction_PostRender){
static int TEMP_kAudioUnitRenderAction_PostRenderError = (1 << 8);
if (!(*ioActionFlags & TEMP_kAudioUnitRenderAction_PostRenderError)){
Float32* data = (Float32 *)ioData->mBuffers[0].mData; //just for one channel!
// … …
}
}
我有一个音频单元,它位于另外两个单元之间。也就是说,我的单元有另一个单元分配给它的输入节点,它有另一个单元分配给它的输出节点。
我想访问输入我的设备的 AudioBufferList。我想在回调中访问此缓冲区列表。但是,如果我的单元的输入总线已经连接到另一个音频单元,那么我的 RenderCallback 永远不会被调用。
我可以使用什么回调来访问给定单元的传入音频缓冲区?
AURenderCallbackStruct splitterCallback;
splitterCallback.inputProc = (AURenderCallback) SplitterCallback;
splitterCallback.inputProcRefCon = (__bridge void*) self;
status = AudioUnitSetProperty(splitterAuUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input,
0, &splitterCallback, sizeof(splitterCallback));
AudioUnitElement genericOutputBus = 0;
AudioUnitConnection genericOutToIoUnitIn;
genericOutToIoUnitIn.sourceAudioUnit = genericAuUnit;
genericOutToIoUnitIn.sourceOutputNumber = genericOutputBus;
genericOutToIoUnitIn.destInputNumber = ioUnitOutputElement;
AudioUnitSetProperty (
splitterAuUnit, // connection destination
kAudioUnitProperty_MakeConnection, // property key
kAudioUnitScope_Input, // destination scope
ioUnitOutputElement, // destination element
&genericOutToIoUnitIn, // connection definition
sizeof (genericOutToIoUnitIn)
);
// Callback
static OSStatus SplitterCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
@autoreleasepool {
NSLog(@"splitterCallback"); // This is never called. :(
}
}
这是在 AUGraph API 中注册回调而不破坏 API 的核心音频过程。它在 OSX 中进行了测试,但是 API 的这一部分对于 iOS 也是通用的。假设你想听输出单元输入的信号,一个单元 "upstream" 就是 splitterAuUnit
。我将通过以下方式注册回调 MyRenderProc()
:
AudioUnitAddRenderNotify(splitterAuUnit,
MyRenderProc,
&player);
在回调中检查渲染操作和 post 渲染错误很重要:
if (*ioActionFlags & kAudioUnitRenderAction_PostRender){
static int TEMP_kAudioUnitRenderAction_PostRenderError = (1 << 8);
if (!(*ioActionFlags & TEMP_kAudioUnitRenderAction_PostRenderError)){
Float32* data = (Float32 *)ioData->mBuffers[0].mData; //just for one channel!
// … …
}
}