When I use AUGraph to implemention record and play, I want to get audio data through RenderCallback.There is a problem in remote io unit callback with error kAudioConverterErr_InvalidInputSize(1768846202),I don't know how to solve it.
Is there any other way to get audio data?
NSAssert(NewAUGraph(&_auGraph) == noErr, @"NewAUGraph failed");
const AudioComponentDescription ioComponentDesc = {
.componentType = kAudioUnitType_Output,
.componentSubType = kAudioUnitSubType_RemoteIO,
.componentManufacturer = kAudioUnitManufacturer_Apple,
.componentFlags = 0,
.componentFlagsMask = 0
};
AUGraphAddNode(_auGraph, &ioComponentDesc, &_ioNode);
const AudioComponentDescription effectComponent = {
.componentType = kAudioUnitType_Effect,
.componentSubType = kAudioUnitSubType_Reverb2,
.componentManufacturer = kAudioUnitManufacturer_Apple,
.componentFlags = 0,
.componentFlagsMask = 0
};
AUGraphAddNode(_auGraph, &effectComponent, &_reverbNode);
const AudioComponentDescription inConvertComponentDesc = {
.componentType = kAudioUnitType_FormatConverter,
.componentSubType = kAudioUnitSubType_AUConverter,
.componentManufacturer = kAudioUnitManufacturer_Apple,
.componentFlags = 0,
.componentFlagsMask = 0
};
AUGraphAddNode(_auGraph, &inConvertComponentDesc, &_inConvertNode);
const AudioComponentDescription outConvertComponentDesc = {
.componentType = kAudioUnitType_FormatConverter,
.componentSubType = kAudioUnitSubType_AUConverter,
.componentManufacturer = kAudioUnitManufacturer_Apple,
.componentFlags = 0,
.componentFlagsMask = 0
};
AUGraphAddNode(_auGraph, &outConvertComponentDesc, &_outConvertNode);
NSAssert(AUGraphOpen(_auGraph) == noErr, @"AUGraphOpen failed");
AUGraphNodeInfo(_auGraph, _ioNode, NULL, &_ioUnit);
AUGraphNodeInfo(_auGraph, _reverbNode, NULL, &_reverbUnit);
AUGraphNodeInfo(_auGraph, _inConvertNode, NULL, &_inConvertUnit);
AUGraphNodeInfo(_auGraph, _outConvertNode, NULL, &_outConvertUnit);
UInt32 enable = 1;
AudioUnitElement inputBus = 1;
AudioUnitElement outputBus = 0;
AudioUnitSetProperty(_ioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, inputBus, &enable, sizeof(enable));
AudioUnitSetProperty(_ioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, outputBus, &enable, sizeof(enable));
AudioStreamBasicDescription absd;
memset(&absd, 0, sizeof(absd));
absd.mSampleRate = 44100;
absd.mFormatID = kAudioFormatLinearPCM;
absd.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
absd.mBitsPerChannel = 16;
absd.mChannelsPerFrame = 2;
absd.mBytesPerFrame = absd.mBitsPerChannel / 8 * absd.mChannelsPerFrame;
absd.mFramesPerPacket = 1;
absd.mBytesPerPacket = absd.mBytesPerFrame;
AudioUnitSetProperty(_ioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, inputBus, &absd, sizeof(absd));
AudioUnitSetProperty(_ioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, outputBus, &absd, sizeof(absd));
AURenderCallbackStruct callback = {0};
callback.inputProc = audioUnitRenderCallback;
callback.inputProcRefCon = (__bridge void *)self;
AudioUnitSetProperty(_ioUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input,
outputBus,
&callback,
sizeof(callback));
OSStatus status;
AudioStreamBasicDescription reverbABSD;
memset(&reverbABSD, 0, sizeof(reverbABSD));
reverbABSD.mSampleRate = 44100;
reverbABSD.mFormatID = kAudioFormatLinearPCM;
reverbABSD.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
reverbABSD.mBitsPerChannel = 32;
reverbABSD.mChannelsPerFrame = 2;
reverbABSD.mBytesPerFrame = reverbABSD.mBitsPerChannel / 8;
reverbABSD.mFramesPerPacket = 1;
reverbABSD.mBytesPerPacket = reverbABSD.mBytesPerFrame;
AudioUnitSetProperty(_reverbUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &reverbABSD, sizeof(reverbABSD));
AudioUnitSetProperty(_reverbUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &reverbABSD, sizeof(reverbABSD));
AudioUnitSetParameter(_reverbUnit, kReverb2Param_Gain, kAudioUnitScope_Global, 0, 20, 0);
AudioUnitSetParameter(_reverbUnit, kReverb2Param_DryWetMix, kAudioUnitScope_Global, 0, 50, 0);
status = AudioUnitSetProperty(_outConvertUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &reverbABSD, sizeof(reverbABSD));
status = AudioUnitSetProperty(_outConvertUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &absd, sizeof(absd));
AUGraphConnectNodeInput(_auGraph, _ioNode, 1, _inConvertNode, 0);
AUGraphConnectNodeInput(_auGraph, _inConvertNode, 0, _reverbNode, 0);
AUGraphConnectNodeInput(_auGraph, _reverbNode, 0, _outConvertNode, 0);
static OSStatus audioUnitRenderCallback(void * inRefCon,
AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * __nullable ioData)
{
XLAudioCaptureGraph *THIS = (__bridge XLAudioCaptureGraph *)inRefCon;
memset(ioData->mBuffers[0].mData, 0, ioData->mBuffers[0].mDataByteSize);
OSStatus status = AudioUnitRender(THIS.outConvertUnit, ioActionFlags, inTimeStamp, 0, inNumberFrames, ioData);
}
The audioUnitRenderCallback status return kAudioConverterErr_InvalidInputSize.