0

I have an AudioUnit with correspondent Callback working properly, But now, I need to send it to a RemoteIO, cause i'm implementing some framework who needs an RemoteIO AudioUnit to work.

THen... I need the same output i'm getting with this audiounit mixer but with another audiounit with type kAudioUnitSubType_RemoteIO.

Please, help!

EDIT ... This is the code I'm trying... EDIT 2- iOUnitDescription Added

AudioComponentDescription iOUnitDescription;
iOUnitDescription.componentType          = kAudioUnitType_Output;
iOUnitDescription.componentSubType       = kAudioUnitSubType_RemoteIO;
iOUnitDescription.componentManufacturer  = kAudioUnitManufacturer_Apple;
iOUnitDescription.componentFlags         = 0;
iOUnitDescription.componentFlagsMask     = 0;


AudioComponent foundIoUnitReference = AudioComponentFindNext (
                                                              NULL,
                                                              &iOUnitDescription
                                                              );
AudioComponentInstanceNew (
                           foundIoUnitReference,
                           &audioUnit
                           );

result = AudioUnitSetProperty (
                               audioUnit,
                               kAudioUnitProperty_StreamFormat,
                               kAudioUnitScope_Input,
                               guitarBus,
                               &stereoStreamFormat,
                               sizeof (stereoStreamFormat)
                               );

if (noErr != result) {[self printErrorMessage: @"AudioUnitSetProperty (set mixer unit guitar input bus stream format)" withStatus: result];return;}
result = AudioUnitSetProperty (
                               audioUnit,
                               kAudioUnitProperty_SampleRate,
                               kAudioUnitScope_Output,
                               0,
                               &graphSampleRate,
                               sizeof (graphSampleRate)
                               );
if (noErr != result) {[self printErrorMessage: @"AudioUnitSetProperty (set AUDIOUNIT unit output stream format)" withStatus: result]; return;}


AudioUnitElement mixerUnitOutputBus  = 0;
AudioUnitElement ioUnitOutputElement = 0;

AudioUnitConnection mixerOutToIoUnitIn;
mixerOutToIoUnitIn.sourceAudioUnit    = mixerUnit;
mixerOutToIoUnitIn.sourceOutputNumber = mixerUnitOutputBus;
mixerOutToIoUnitIn.destInputNumber    = ioUnitOutputElement;

AudioUnitSetProperty (
                      audioUnit,                     // connection destination
                      kAudioUnitProperty_MakeConnection,  // property key
                      kAudioUnitScope_Input,              // destination scope
                      ioUnitOutputElement,                // destination element
                      &mixerOutToIoUnitIn,                // connection definition
                      sizeof (mixerOutToIoUnitIn)
                      );
Fischer
  • 1,513
  • 4
  • 17
  • 38
  • Post some code of your AudioUnit setup, it's literally a case of adding the additional AudioUnit and making the correct connections. – MDB983 Aug 02 '14 at 14:30

1 Answers1

2

I really need more info. From the above, i see you have a mixer somewhere, a guitarBus which presumably is your input (and seemingly a stream). What is the definition of &iOUnitDescription. More importantly, where are you hooking your renderCallback to, what are you doing in the callback and what does the framework expect?

Typically, when i need to process Audio, I build my own graph; I make this it's own class for better portability. This should be a good starting point for you

Here is how I implement such a solution.

 // header file

  @interface MDMixerGraph : NSObject{
    AUGraph graph;
    AudioUnit mixerUnit;
    AudioUnit inputUnit;
    AudioUnit rioUnit;
   }
  -(void) setupAUGraph;
  @end

  // implementation

  @implementation MDMixerGraph

  // exception Helper 
  void MDThrowOnError(OSStatus status){
  if (status != noErr) {
      @throw [NSException exceptionWithName:@"MDMixerException"
                                   reason:[NSString stringWithFormat:@"Status Error %d).", (int)status]
                                    userInfo:nil];
     }
  }


   // helper method for setting up graph nodes
   OSStatus MDAdAUGraphdNode(OSType inComponentType, OSType inComponentSubType, AUGraph inGraph, AUNode *outNode)
   {
     AudioComponentDescription desc;
     desc.componentType = inComponentType;
     desc.componentSubType = inComponentSubType;
     desc.componentFlags = 0;
     desc.componentFlagsMask = 0;
     desc.componentManufacturer = kAudioUnitManufacturer_Apple;
     return AUGraphAddNode(inGraph, &desc, outNode);
   }

   // setup method to init and start AUGraph
   -(void) setupAUGraph{

    //Create the Graph
    MDThrowOnError(NewAUGraph(&graph));

   // setup AU Units
   // Add Audio Units (Nodes) to the graph
   AUNode inputNode, rioNode, mixerNode;

//Input Node -- this may need to be a different type to accept your Stream (not enough info above) 
MDThrowOnError(MDAdAUGraphdNode(kAudioUnitType_Output, kAudioUnitSubType_RemoteIO, graph, &inputUnit));

//Remote IO Node - your output node
MDThrowOnError(MDAdAUGraphdNode(kAudioUnitType_Output, kAudioUnitSubType_RemoteIO, graph, &rioNode));

//mixerNode - Depending on output and input change the mixer sub-type here
// you can configure additional nodes depending on your needs for inputs and outputs
MDThrowOnError(MDAdAUGraphdNode(kAudioUnitType_Mixer, kAudioUnitSubType_AU3DMixerEmbedded, graph, &mixerNode));

// open graph
MDThrowOnError(AUGraphOpen(graph));

// we need a ref to the Audio Units so lets grab all of them here

MDThrowOnError(AUGraphNodeInfo(graph, inputNode, NULL, &inputUnit));
MDThrowOnError(AUGraphNodeInfo(graph, rioNode, NULL, &rioUnit));
MDThrowOnError(AUGraphNodeInfo(graph, mixerNode, NULL, &mixerUnit));

// setup the connections here, input to output of the graph.
/// the graph looks like inputNode->mixerNode->rioNode

MDThrowOnError(AUGraphConnectNodeInput(graph, inputNode, 0, mixerNode, 0));
MDThrowOnError(AUGraphConnectNodeInput(graph, mixerNode, 0, rioNode, 0));

// Init the graph

MDThrowOnError(AUGraphInitialize(graph));

//do any other setup here for your stream    

// Finally, Start the graph

MDThrowOnError(AUGraphStart(graph));

}

In your View Controller extension you simply;

  // define the MDMixerGraph Class
  // @property (nonatomic) MDMixerGraph *mixer;

And in the implementation

  self.mixer = [[MDMixerGraph alloc]init];
 [self.mixer setupAUGraph];

And you have reference to the rioUnit to pass to your framework (self.mixer.rioUnit); Without knowing more about your requirements connection/processing this is the best i can do for you.

Cheers!

MDB983
  • 2,444
  • 17
  • 20
  • Thanks for your answer. I added the definition of &iOUnitDescription and the way to call the render callback on the question. In the callback I'm Mixing samples, not getting input, so the guitarBus is not really a guitar, is the bus for percussion samples. – Fischer Aug 02 '14 at 17:50
  • Really I'm using the base of Mixerhost sample, this part of code is the same. The render callback works good, everything works good, but I need to get a RemoteIO audiounit with the output of the mixer audio unit – Fischer Aug 02 '14 at 17:54
  • Try to understand the code rather than copying it ... if you look closely at the MixerHost Code you'll see the graph setup is similar to my code above. You simply need to "Expose" the ioNode. As i have above, declare a AudioUnit rioUnit in the header. Then get the reference (again as i have done above)... the code using MixerHose name would be result = AUGraphNodeInfo ( processingGraph, ioNode, NULL, &rioUnit ); -- you can pass rioUnit to your framework – MDB983 Aug 02 '14 at 19:27
  • Just to Clarify, The mixer already connects to a RemoteIO Unit, You simply need to make it visible so you can pass it to your framework. You do this with the AUGraphNodeInfo. – MDB983 Aug 02 '14 at 19:35