I have this AUGraph configuration
AudioUnitGraph 0x2505000:
Member Nodes:
node 1: 'aufx' 'ipeq' 'appl', instance 0x15599530 O
node 2: 'aufx' 'rvb2' 'appl', instance 0x1566ffd0 O
node 3: 'aufc' 'conv' 'appl', instance 0x15676900 O
node 4: 'aumx' 'mcmx' 'appl', instance 0x15676a30 O
node 5: 'aumx' 'mcmx' 'appl', instance 0x15677ac0 O
node 6: 'aumx' 'mcmx' 'appl', instance 0x15678a40 O
node 7: 'auou' 'rioc' 'appl', instance 0x15679a20 O
node 8: 'augn' 'afpl' 'appl', instance 0x1558b710 O
Connections:
node 7 bus 1 => node 5 bus 0 [ 1 ch, 44100 Hz, 'lpcm' (0x00000C2C) 8.24-bit little-endian signed integer, deinterleaved]
node 5 bus 0 => node 3 bus 0 [ 2 ch, 44100 Hz, 'lpcm' (0x00000C2C) 8.24-bit little-endian signed integer, deinterleaved]
node 3 bus 0 => node 2 bus 0 [ 2 ch, 44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
node 2 bus 0 => node 6 bus 0 [ 1 ch, 44100 Hz, 'lpcm' (0x00000C2C) 8.24-bit little-endian signed integer, deinterleaved]
node 8 bus 0 => node 4 bus 0 [ 1 ch, 44100 Hz, 'lpcm' (0x00000C2C) 8.24-bit little-endian signed integer, deinterleaved]
node 4 bus 0 => node 6 bus 1 [ 2 ch, 44100 Hz, 'lpcm' (0x00000C2C) 8.24-bit little-endian signed integer, deinterleaved]
node 6 bus 0 => node 1 bus 0 [ 2 ch, 44100 Hz, 'lpcm' (0x00000C2C) 8.24-bit little-endian signed integer, deinterleaved]
node 1 bus 0 => node 7 bus 0 [ 2 ch, 0 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
CurrentState:
mLastUpdateError=0, eventsToProcess=F, isInitialized=F, isRunning=F
and the error
AUGraphInitialize err = -10868
since I have connected a reverb unit between two mixer units even if I have created a converter unit:
OSStatus err = noErr;
UInt32 micBus = 0;
UInt32 filePlayerBus = 1;
//// ionode:1 ----> vfxNode:0 bus 0
err = AUGraphConnectNodeInput(processingGraph, ioNode, 1, vfxNode, 0);
if (err) { NSLog(@"ioNode:1 ---> vfxNode:0 err = %ld", err); }
//// vfxNode:0 ---> convertNode:0
err = AUGraphConnectNodeInput(processingGraph, vfxNode, 0, convertNode, 0);
//// convertNode:0 ---> vfxRevNode:0
err = AUGraphConnectNodeInput(processingGraph, convertNode, 0, vfxRevNode, 0);
//// vfxRevNode:0 ---> mixerNode:0
err = AUGraphConnectNodeInput(processingGraph, vfxRevNode, 0, mixerNode, micBus );
//if (err) { NSLog(@"vfxRevNode:0 ---> mixerNode:0 err = %ld", err); }
//// vfxNode:0 ----> mixerNode:0
//err = AUGraphConnectNodeInput(processingGraph, vfxNode, 0, mixerNode, micBus );
if (err) { NSLog(@"vfxNode:0 ---> mixerNode:0 err = %ld", err); }
//// audioPlayerNode:0 ----> fxNode:0
err = AUGraphConnectNodeInput(processingGraph, audioPlayerNode, 0, fxNode, 0);
if (err) { NSLog(@"audioPlayerNode:0 ---> fxNode:0 err = %ld", err); }
//// fxNode:0 ----> mixerNode:1
err = AUGraphConnectNodeInput(processingGraph, fxNode, 0, mixerNode, filePlayerBus);
if (err) { NSLog(@"fxNode:0 ---> mixerNode:1 err = %ld", err); }
///// mixerNode:0 ----> eqNode:0
err = AUGraphConnectNodeInput(processingGraph, mixerNode, 0, eqNode, 0);
if (err) { NSLog(@"mixerNode:0 ---> eqNode:0 err = %ld", err); }
//// eqNode:0 ----> ioNode:0
err = AUGraphConnectNodeInput(processingGraph, eqNode, 0, ioNode, 0);
if (err) { NSLog(@"eqNode:0 ---> ioNode:0 err = %ld", err); }
Here are the nodes:
////
//// EQ NODE
////
err = AUGraphAddNode(processingGraph, &EQUnitDescription, &eqNode);
if (err) { NSLog(@"eqNode err = %ld", err); }
////
//// REV NODE
////
err = AUGraphAddNode(processingGraph, &ReverbUnitDescription, &vfxRevNode);
if (err) { NSLog(@"vfxRevNode err = %ld", err); }
////
//// FORMAT CONVERTER NODE
////
err = AUGraphAddNode (processingGraph, &convertUnitDescription, &convertNode);
if (err) { NSLog(@"convertNode err = %ld", err); }
////
//// FX NODE
////
err = AUGraphAddNode(processingGraph, &FXUnitDescription, &fxNode);
if (err) { NSLog(@"fxNode err = %ld", err); }
////
//// VFX NODE
////
err = AUGraphAddNode(processingGraph, &VFXUnitDescription, &vfxNode);
if (err) { NSLog(@"vfxNode err = %ld", err); }
///
/// MIXER NODE
///
err = AUGraphAddNode (processingGraph, &MixerUnitDescription, &mixerNode );
if (err) { NSLog(@"mixerNode err = %ld", err); }
///
/// OUTPUT NODE
///
err = AUGraphAddNode(processingGraph, &iOUnitDescription, &ioNode);
if (err) { NSLog(@"outputNode err = %ld", err); }
////
/// PLAYER NODE
///
err = AUGraphAddNode(processingGraph, &playerUnitDescription, &audioPlayerNode);
if (err) { NSLog(@"audioPlayerNode err = %ld", err); }
and the component descriptions:
OSStatus err = noErr;
err = NewAUGraph(&processingGraph);
// OUTPUT unit
AudioComponentDescription iOUnitDescription;
iOUnitDescription.componentType = kAudioUnitType_Output;
iOUnitDescription.componentSubType = kAudioUnitSubType_RemoteIO;//kAudioUnitSubType_VoiceProcessingIO;//kAudioUnitSubType_RemoteIO;
iOUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
iOUnitDescription.componentFlags = 0;
iOUnitDescription.componentFlagsMask = 0;
// MIXER unit
AudioComponentDescription MixerUnitDescription;
MixerUnitDescription.componentType = kAudioUnitType_Mixer;
MixerUnitDescription.componentSubType = kAudioUnitSubType_MultiChannelMixer;
MixerUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
MixerUnitDescription.componentFlags = 0;
MixerUnitDescription.componentFlagsMask = 0;
// PLAYER unit
AudioComponentDescription playerUnitDescription;
playerUnitDescription.componentType = kAudioUnitType_Generator;
playerUnitDescription.componentSubType = kAudioUnitSubType_AudioFilePlayer;
playerUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
// EQ unit
AudioComponentDescription EQUnitDescription;
EQUnitDescription.componentType = kAudioUnitType_Effect;
EQUnitDescription.componentSubType = kAudioUnitSubType_AUiPodEQ;
EQUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
EQUnitDescription.componentFlags = 0;
EQUnitDescription.componentFlagsMask = 0;
// Reverb unit
AudioComponentDescription ReverbUnitDescription;
ReverbUnitDescription.componentType = kAudioUnitType_Effect;
ReverbUnitDescription.componentSubType = kAudioUnitSubType_Reverb2;
ReverbUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
ReverbUnitDescription.componentFlags = 0;
ReverbUnitDescription.componentFlagsMask = 0;
// Format Converter between VFX and Reverb units
AudioComponentDescription convertUnitDescription;
convertUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
convertUnitDescription.componentType = kAudioUnitType_FormatConverter;
convertUnitDescription.componentSubType = kAudioUnitSubType_AUConverter;
convertUnitDescription.componentFlags = 0;
convertUnitDescription.componentFlagsMask = 0;
// FX unit
AudioComponentDescription FXUnitDescription;
FXUnitDescription.componentType = kAudioUnitType_Mixer;
FXUnitDescription.componentSubType = kAudioUnitSubType_MultiChannelMixer;
FXUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
FXUnitDescription.componentFlags = 0;
FXUnitDescription.componentFlagsMask = 0;
// VFX unit
AudioComponentDescription VFXUnitDescription;
VFXUnitDescription.componentType = kAudioUnitType_Mixer;
VFXUnitDescription.componentSubType = kAudioUnitSubType_MultiChannelMixer;
VFXUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
VFXUnitDescription.componentFlags = 0;
VFXUnitDescription.componentFlagsMask = 0;
I created the setup of the converter node to have as input the input node stream format (that is a mixer unit) and the output node stream format as output format (that is the reverb)
OSStatus err = noErr;
err = AUGraphNodeInfo(processingGraph, convertNode, NULL, &convertUnit);
if (err) { NSLog(@"setupConverterUnit error = %ld", err); }
// set converter input format to vfxunit format
AudioStreamBasicDescription asbd = {0};
size_t bytesPerSample;
bytesPerSample = sizeof(SInt16);
asbd.mFormatID = kAudioFormatLinearPCM;
asbd.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
asbd.mBitsPerChannel = 8 * bytesPerSample;
asbd.mFramesPerPacket = 1;
asbd.mChannelsPerFrame = 1;
asbd.mBytesPerPacket = bytesPerSample * asbd.mFramesPerPacket;
asbd.mBytesPerFrame = bytesPerSample * asbd.mChannelsPerFrame;
asbd.mSampleRate = sampleRate;
err = AudioUnitSetProperty(convertUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &asbd, sizeof(asbd));
if (err) { NSLog(@"setupConverterUnit kAudioUnitProperty_StreamFormat error = %ld", err); }
// set converter output format to reverb format
UInt32 streamFormatSize = sizeof(monoStreamFormat);
err = AudioUnitSetProperty(convertUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &monoStreamFormat, streamFormatSize);
if (err) { NSLog(@"setupConverterUnit kAudioUnitProperty_StreamFormat error = %ld", err); }
The reverb unit is configured as follows:
OSStatus err = noErr;
err = AUGraphNodeInfo(processingGraph, vfxRevNode, NULL, &vfxRevUnit);
if (err) { NSLog(@"setupReverbUnit err = %ld", err); }
UInt32 size = sizeof(mReverbPresetArray);
err = AudioUnitGetProperty(vfxRevUnit, kAudioUnitProperty_FactoryPresets, kAudioUnitScope_Global, 0, &mReverbPresetArray, &size);
if (err) { NSLog(@"kAudioUnitProperty_FactoryPresets err = %ld", err); }
printf("setupReverbUnit Preset List:\n");
UInt8 count = CFArrayGetCount(mReverbPresetArray);
for (int i = 0; i < count; ++i) {
AUPreset *aPreset = (AUPreset*)CFArrayGetValueAtIndex(mReverbPresetArray, i);
CFShow(aPreset->presetName);
}
and the input mixer unit as
OSStatus err;
err = AUGraphNodeInfo(processingGraph, vfxNode, NULL, &vfxUnit);
if (err) { NSLog(@"setVFxUnit err = %ld", err); }
UInt32 busCount = 1;
err = AudioUnitSetProperty (
vfxUnit,
kAudioUnitProperty_ElementCount,
kAudioUnitScope_Input,
0,
&busCount,
sizeof (busCount)
);
AudioStreamBasicDescription asbd = {0};
size_t bytesPerSample;
bytesPerSample = sizeof(SInt16);
asbd.mFormatID = kAudioFormatLinearPCM;
asbd.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
asbd.mBitsPerChannel = 8 * bytesPerSample;
asbd.mFramesPerPacket = 1;
asbd.mChannelsPerFrame = 1;
asbd.mBytesPerPacket = bytesPerSample * asbd.mFramesPerPacket;
asbd.mBytesPerFrame = bytesPerSample * asbd.mChannelsPerFrame;
asbd.mSampleRate = sampleRate;
err = AudioUnitSetProperty (
vfxUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
0,
&asbd,
sizeof (asbd)
);
So far no way to make it works. I need the reverb unit to be there since I need it on the mic input only before entering the next mixer units.
Where I'm wrong with AudioStreamBasicDescription on the converter ?
EDIT What happens is that there is no sound. The audio graph is not being initialized and it comes out with the error
AUGraphInitialize err = -10868
The graph described here can be depicted in this way
A mic input connected to vfxNode to get the render callback. This was connected to a mixer on bus 0. A song player node connected to another mixer where there is a second render callback that processes the audio in playback. This is connected to bus 1 of the last mixer in the chain. A eq node connects the mixer to the ouput ioNode.
When using a converter node between the fx mixer (vfxNode) and the reverb there is no sound anymore:
//// vfxNode:0 ---> convertNode:0
err = AUGraphConnectNodeInput(processingGraph, vfxNode, 0, convertNode, 0);
//// convertNode:0 ---> vfxRevNode:0
err = AUGraphConnectNodeInput(processingGraph, convertNode, 0, vfxRevNode, 0);
//// vfxRevNode:0 ---> mixerNode:0
err = AUGraphConnectNodeInput(processingGraph, vfxRevNode, 0, mixerNode, micBus );
//if (err) { NSLog(@"vfxRevNode:0 ---> mixerNode:0 err = %ld", err); }
Having no reverb node hence no converter node everything works properly:
//// ionode:1 ----> vfxNode:0 bus 0
err = AUGraphConnectNodeInput(processingGraph, ioNode, 1, vfxNode, 0);
if (err) { NSLog(@"ioNode:1 ---> vfxNode:0 err = %ld", err); }
//// vfxNode:0 ----> mixerNode:0
err = AUGraphConnectNodeInput(processingGraph, vfxNode, 0, mixerNode, micBus );
if (err) { NSLog(@"vfxNode:0 ---> mixerNode:0 err = %ld", err); }