3

I'm trying to make an inter-app audio iOS app and it looks like I'm having trouble the AudioOutputUnitPublish method. Here's the method:

- (void)publishOutputAudioUnit {
    AudioComponentDescription desc = {kAudioUnitType_RemoteInstrument, 
                                     'iasp','rfoo', 0, 1};
    OSStatus result = AudioOutputUnitPublish(&desc, CFSTR("MyMusicApp"), 
                                             1, outputUnit);
    if (result != noErr) 
        NSLog(@"AudioOutputUnitPublish instrument result: %d", (int)result);

    desc = { kAudioUnitType_RemoteGenerator, 'iasp', 'rfoo', 0, 1 };
    result = AudioOutputUnitPublish(&desc, CFSTR("MyMusicApp"), 1, outputUnit);
    if (result != noErr) 
        NSLog(@"AudioOutputUnitPublish generator result: %d", (int)result);
}

Here is my plist info:

<key>AudioComponents</key>
<array>
    <dict>
        <key>manufacturer</key>
        <string>rfoo</string>
        <key>name</key>
        <string>MyMusicApp</string>
        <key>subtype</key>
        <string>iasp</string>
        <key>type</key>
        <string>aurg</string>
        <key>version</key>
        <integer>1</integer>
    </dict>
    <dict>
        <key>manufacturer</key>
        <string>rfoo</string>
        <key>name</key>
        <string>MyMusicApp</string>
        <key>subtype</key>
        <string>iasp</string>
        <key>type</key>
        <string>auri</string>
        <key>version</key>
        <integer>1</integer>
    </dict>
</array>

This is the result I'm getting:

AudioOutputUnitPublish instrument result: -50
AudioOutputUnitPublish generator result: -50

I know OSStatus code -50 means there's an invalid parameter... but I can't seem to figure out which one is invalid. Can anyone help me debug here? Thanks!


EDIT :

Just wanted to post more code so others could help me out more:

I have two audio units and hopefully a third one - MIDISynth (inactive as of now), MultiChannelMixer, and RemoteIO audio unit. I have a render callback attached to the mixer audio unit. I'm guessing I'm connecting something wrong in my AUGraph (none of the examples I've seen have attached an audio rendering callback to the audio unit so this might be where I'm doing something wrong). Hopefully someone can spot out what I'm doing wrong!

Here's the code:

- (AUGraph)createAUGraphWithSynth:(AudioUnit *)sUnit mixUnit:(AudioUnit *)mixUnit remoteUnit:(AudioUnit *)remUnit {
    // Initializations
    AUGraph graph = 0;
    OSStatus result = noErr;
    // Create graph nodes
    AUNode mixerNode, ioNode;

    // Create Component Descriptor
    AudioComponentDescription cd;
    cd.componentManufacturer    = kAudioUnitManufacturer_Apple;
    cd.componentFlags           = 0;
    cd.componentFlagsMask       = 0;

    // Init AUGraph
    Check(result = NewAUGraph(&graph));

    // Init Mixer unit
    cd.componentType    = kAudioUnitType_Mixer;
    cd.componentSubType = kAudioUnitSubType_MultiChannelMixer;
    Check(result = AUGraphAddNode(graph, &cd, &mixerNode));

    // Init io Unit
    cd.componentType    = kAudioUnitType_Output;
    cd.componentSubType = kAudioUnitSubType_RemoteIO;
    Check(result = AUGraphAddNode(graph, &cd, &ioNode));

    // Open AUGraph
    Check(AUGraphOpen(graph));

    // Get mixer unit
    Check(AUGraphNodeInfo(graph, mixerNode, NULL, mixUnit));

    // Get io unit
    Check(AUGraphNodeInfo(graph, ioNode, NULL, remUnit));

    // Set number of input busses
    UInt32 numBuses = 1;
    UInt32 size = sizeof(numBuses);
    Check(AudioUnitSetProperty(*mixUnit,
                               kAudioUnitProperty_ElementCount,
                               kAudioUnitScope_Input,
                               0, &numBuses, size));

    AudioStreamBasicDescription desc;
    const int four_bytes_per_float = 4;
    const int eight_bits_per_byte = 8;

    for (int i = 0; i < numBuses; ++i) {
        AURenderCallbackStruct callbackStruct;
        callbackStruct.inputProc        = outputCallback;
        callbackStruct.inputProcRefCon  = (__bridge void *)self;
    
        Check(AUGraphSetNodeInputCallback(graph, mixerNode, i, &callbackStruct));

        UInt32 size = sizeof(desc);
        Check(AudioUnitGetProperty(*mixUnit,
                                   kAudioUnitProperty_StreamFormat,
                                   kAudioUnitScope_Input,
                                   0, &desc, &size));
    
        memset(&desc, 0, sizeof(desc));
    

        desc.mSampleRate        = SAMPLE_RATE;
        desc.mFormatID          = kAudioFormatLinearPCM;
        desc.mFormatFlags       = kAudioFormatFlagsNativeFloatPacked 
                                | kAudioFormatFlagIsNonInterleaved;
        desc.mBytesPerPacket    = four_bytes_per_float;
        desc.mFramesPerPacket   = 1;
        desc.mBytesPerFrame     = four_bytes_per_float;
        desc.mBitsPerChannel    = four_bytes_per_float * eight_bits_per_byte;
        desc.mChannelsPerFrame  = 2;
        Check(AudioUnitSetProperty(*remUnit,
                                   kAudioUnitProperty_StreamFormat,
                                   kAudioUnitScope_Input,
                                   0, &desc, sizeof(desc)));

    }

    Check(AudioUnitSetProperty(*mixUnit,
                               kAudioUnitProperty_StreamFormat,
                               kAudioUnitScope_Output,
                               0, &desc, sizeof(desc)));

    Check(AudioUnitGetProperty(*mixUnit,
                               kAudioUnitProperty_StreamFormat,
                               kAudioUnitScope_Output,
                               0, &desc, &size));

    memset(&desc, 0, sizeof(desc));

    desc.mSampleRate        = SAMPLE_RATE;
    desc.mFormatID          = kAudioFormatLinearPCM;
    desc.mFormatFlags       = kAudioFormatFlagsNativeFloatPacked 
                            | kAudioFormatFlagIsNonInterleaved;
    desc.mBytesPerPacket    = four_bytes_per_float;
    desc.mFramesPerPacket   = 1;
    desc.mBytesPerFrame     = four_bytes_per_float;
    desc.mBitsPerChannel    = four_bytes_per_float * eight_bits_per_byte;
    desc.mChannelsPerFrame  = 2;
     
    Check(AudioUnitSetProperty(*mixUnit,
                               kAudioUnitProperty_StreamFormat,
                               kAudioUnitScope_Output,
                               0, &desc, sizeof(desc)));

    // Must configure remote io unit:
    Check(AudioUnitSetProperty(*remUnit,
                               kAudioUnitProperty_StreamFormat,
                               kAudioUnitScope_Output,
                               1, &desc, sizeof(desc)));

     // Connect nodes (synth->output)
     Check(AUGraphConnectNodeInput(graph, mixerNode, 0, ioNode, 0));

     return graph;
 }
Community
  • 1
  • 1
yun
  • 1,243
  • 11
  • 30

1 Answers1

3

The last field in the AudioComponentDescription, componentFlagsMask, should be 0, not 1. (See the documentation. It looks like at least one tutorial misidentifies this field as the component version.)

Whether this is the sole cause of the problem I'm not sure. The rest of the code looks OK, but I guess it's possible there may be issues elsewhere in the project, eg. with the capabilities.

walkytalky
  • 9,453
  • 2
  • 36
  • 44
  • Hi walkytalky, thanks for getting back to me. I set it to 0 but I'm still getting the same -50 error :( - I've enabled Inter-App Audio and Background Modes for Audio... Is there something else I'm missing? – yun Feb 19 '16 at 16:02
  • 1
    In that case I'd guess `outputUnit` hasn't been properly initialised. Is that meant to be set via the `remUnit` parameter in your graph creation method? If you step through it, does that actually happen? – walkytalky Feb 22 '16 at 11:57
  • yup it looks like I'm attaching it incorrectly, let me get back to you on that after I fix it... – yun Feb 22 '16 at 14:33
  • I didn't have all the settings apparently - I did not set bundle display name in my plist. Took me forever to find out but now it is publishing! Thanks for the help. – yun Feb 22 '16 at 15:26