Question

I'm trying to use a remote IO connection and route the audio input through the built in filter effect (iOS 5 only) and then back out of the hardware. I can make it route straight from the input to the output but I can't get the filter to work. I'm not sure whether it's the filter Audio Unit or the routing that I've got wrong.

This bit is just my attempt at setting up the filter and changing the routing so that the data is processed by it.

Any help is appreciated.

// ******* BEGIN FILTER ********

NSLog(@"Begin filter");

// Creates Audio Component Description - Output Filter    
AudioComponentDescription filterCompDesc;
filterCompDesc .componentType = kAudioUnitType_Effect;
filterCompDesc.componentSubType = kAudioUnitSubType_LowPassFilter;
filterCompDesc.componentManufacturer = kAudioUnitManufacturer_Apple;
filterCompDesc.componentFlags = 1;
filterCompDesc.componentFlagsMask = 1;


// Create Filter Unit
AudioUnit lpFilterUnit;
AudioComponent filterComponent = AudioComponentFindNext(NULL, &filterCompDesc);
setupErr = AudioComponentInstanceNew(filterComponent, &lpFilterUnit);
NSAssert(setupErr == noErr, @"No instance of filter");

AudioUnitElement bus2 = 2;
setupErr = AudioUnitSetProperty(lpFilterUnit, kAudioUnitSubType_LowPassFilter, kAudioUnitScope_Output, bus2, &oneFlag, sizeof(oneFlag));

AudioUnitElement bus3 = 3;
setupErr = AudioUnitSetProperty(lpFilterUnit, kAudioUnitSubType_LowPassFilter, kAudioUnitScope_Input, bus3, &oneFlag, sizeof(oneFlag));



// ******** END FILTER ******** //


AudioUnitConnection hardInToLP;
hardInToLP.sourceAudioUnit    = remoteIOunit;
hardInToLP.sourceOutputNumber = 1;
hardInToLP.destInputNumber    = 3;

setupErr = AudioUnitSetProperty (
                      remoteIOunit,                     // connection destination
                      kAudioUnitProperty_MakeConnection,  // property key
                      kAudioUnitScope_Input,              // destination scope
                      bus3,                // destination element
                      &hardInToLP,                // connection definition
                      sizeof (hardInToLP)
                      );

AudioUnitConnection LPToHardOut;
LPToHardOut.sourceAudioUnit    = lpFilterUnit;
LPToHardOut.sourceOutputNumber = 1;
LPToHardOut.destInputNumber    = 3;

setupErr = AudioUnitSetProperty (
                      remoteIOunit,                     // connection destination
                      kAudioUnitProperty_MakeConnection,  // property key
                      kAudioUnitScope_Input,              // destination scope
                      bus3,                // destination element
                      &hardInToLP,                // connection definition
                      sizeof (hardInToLP)
                      );


/*
// Sets up the Audio Units Connection - new instance called connection
AudioUnitConnection connection;

// Connect Audio Input's out to Audio Out's in
connection.sourceAudioUnit = remoteIOunit;
connection.sourceOutputNumber = bus1;
connection.destInputNumber = bus0;


setupErr = AudioUnitSetProperty(remoteIOunit, kAudioUnitProperty_MakeConnection, kAudioUnitScope_Input, bus0, &connection, sizeof(connection));
*/ 

NSAssert(setupErr == noErr, @"No RIO connection");
Was it helpful?

Solution

A couple things going on here:

  • You're gonna help yourself a lot if you do an assert (or some sort of check-error-and-log-it) after every call that can return an OSStatus. That way you'll figure out how far you're getting. Probably also want to log the actual OSStatus value when it's != noErr, and then look it up (start in "Audio Unit Component Services Reference" in Xcode documentation viewer).
  • After you create the filter AudioUnit, I don't get what you're doing with the AudioUnitSetProperty() calls. The second parameter should be the name of a property (something that starts with kAudioUnitProperty...). That's almost certainly returning an error right there.
  • remoteIOunit only has two buses, and they have special meanings. bus 1 is input from the mic, bus 0 is output to hardware. Trying to connect to remote io input scope bus 3 is probably going to be another error

Suggest you roll back to when you had audio pass-through working. That would mean you had just remoteIO, and a connection from output scope / bus 1 to input scope / bus 0.

Then create the filter unit. Change your connections so you connect:

  • remoteIO output scope bus 1 to filter input scope bus 0
  • filter output scope bus 0 to remoteIO input scope bus 0

The other thing that's going to be a problem is that all these iOS 5 filters seem to want to use floating-point LPCM formats, which is not the canonical format your other units will default to. You may have to get the stream format from the filter unit (input or output scope are probably the same?) and then set that as the format that remoteIO output scope / bus 1 produces and remoteIO input scope / bus 0 accepts. Another option would be to introduce AUConverter units before and after the filter unit.

OTHER TIPS

The first answer given here just saved me a lot more frustration. No where does the Apple documentation tell you that the file formats for the Effect units require floating point. I couldn't figure out why it kept failing to play my audio properly until I read this post. I followed the advice above and retrieved the stream format from the low pass filter unit, and used that to set up two converter units that I created (ie. set the output format of the pre filter converter, and the input format of the post filter converter. Once I did that and connected all the nodes together it started working as expected.

im trying to use a low pass filter and when trying to do as suggested aka set the format i keep getting an error "the operation could not be completed" what in this code is faulty? After retrieving the lowpassUnit I also check for errors but there are none.

result = AudioUnitSetProperty(lowpassUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &stereoStreamFormat, sizeof (stereoStreamFormat));
    if (noErr != result)
{
    NSLog(@"%@", [NSError errorWithDomain:NSOSStatusErrorDomain code:result        userInfo:nil]);
    return;
}

PS: If anyone knows of proper Audio unit documentation please share as the official documentation is really lacking

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top