6

I'm trying to set up an audio unit capable of mono input and stereo output. Intend on playing a sine wave tone through the left channel output and a different sign wave periodically through the right channel out.

I am receiving the error,

'NSInternalInconsistencyException', reason: ' Error initialing unit: -50;

when I attempt to initialize my audio unit here,

// Initialize audio unit
OSErr err = AudioUnitInitialize(self.ioUnit);
NSAssert1(err == noErr, @"Error initializing unit: %hd", err);

I believe it has to do with how I am setting up the audio unit,

// Audio component description
AudioComponentDescription desc;
desc.componentType          = kAudioUnitType_Output;
desc.componentSubType       = kAudioUnitSubType_RemoteIO;
desc.componentManufacturer  = kAudioUnitManufacturer_Apple;
desc.componentFlags         = 0;
desc.componentFlagsMask     = 0;

// Get component
AudioComponent inputComponent = AudioComponentFindNext(NULL, &desc);

// Get Audio units
AudioComponentInstanceNew(inputComponent, &ioUnit);

// Enable input, which disabled by default. Output enable by default
UInt32 enableInput = 1;
AudioUnitSetProperty(ioUnit,
                     kAudioOutputUnitProperty_EnableIO,
                     kAudioUnitScope_Input,
                     kInputBus,
                     &enableInput,
                     sizeof(enableInput));

AudioStreamBasicDescription monoStreamFormat;
monoStreamFormat.mSampleRate          = 44100.00;
monoStreamFormat.mFormatID            = kAudioFormatLinearPCM;
monoStreamFormat.mFormatFlags         = kAudioFormatFlagsAudioUnitCanonical;
monoStreamFormat.mBytesPerPacket      = 2;
monoStreamFormat.mBytesPerFrame       = 2;
monoStreamFormat.mFramesPerPacket     = 1;
monoStreamFormat.mChannelsPerFrame    = 1;
monoStreamFormat.mBitsPerChannel      = 16;

// Apply format to input of ioUnit
AudioUnitSetProperty(ioUnit,
                     kAudioUnitProperty_StreamFormat,
                     kAudioUnitScope_Input,
                     kInputBus,
                     &monoStreamFormat,
                     sizeof(monoStreamFormat));


AudioStreamBasicDescription stereoStreamFormat;
stereoStreamFormat.mSampleRate          = 44100.00;
stereoStreamFormat.mFormatID            = kAudioFormatLinearPCM;
stereoStreamFormat.mFormatFlags         = kAudioFormatFlagsAudioUnitCanonical;
stereoStreamFormat.mBytesPerPacket      = 4;
stereoStreamFormat.mBytesPerFrame       = 4;
stereoStreamFormat.mFramesPerPacket     = 1;
stereoStreamFormat.mChannelsPerFrame    = 2;
stereoStreamFormat.mBitsPerChannel      = 32;

// Apply format to output of ioUnit
AudioUnitSetProperty(ioUnit,
                     kAudioUnitProperty_StreamFormat,
                     kAudioUnitScope_Output,
                     kOutputBus,
                     &stereoStreamFormat,
                     sizeof(stereoStreamFormat));

// Set input callback
AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = inputCallback;
callbackStruct.inputProcRefCon = (__bridge void *)(self);
AudioUnitSetProperty(ioUnit,
                     kAudioUnitProperty_SetRenderCallback,
                     kAudioUnitScope_Global,
                     kInputBus,
                     &callbackStruct,
                     sizeof(callbackStruct));

// Set output callback
callbackStruct.inputProc = outputCallback;
callbackStruct.inputProcRefCon = (__bridge void *)(self);
AudioUnitSetProperty(ioUnit,
                     kAudioUnitProperty_SetRenderCallback,
                     kAudioUnitScope_Global,
                     kOutputBus,
                     &callbackStruct,
                     sizeof(callbackStruct));

but I couldn't find anything on the error code -50 it's giving back so I'm not sure what it doesn't like. I'm on a deadline so any help it greatly appreciated.

mickben
  • 385
  • 4
  • 11

2 Answers2

2

kAudioFormatFlagsAudioUnitCanonical is 32-bit 8.24 fixed point format. That means mBytesPerFrame should be 4 for mono and 8 for stereo, and mBitsPerChannel should be 32 for both stereo and mono. Setting it to 16-bits for would probably produce this error.

That said, I doubt you want 8.24. You probably want kAudioFormatFlagsCanonical to get standard 16-bit audio. Or, if you want 32 bit, go with 32-bit float (kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved). Easier to deal with the math during your processing.

Also, you are setting the formats on the virtual inputs and outputs rather than the client inputs and outputs, which I don't think is what you want. The API here is rather confusing, but to set client input format, use kAudioUnitScope_Input, kOutputBus. The logic here is that you're setting the format of the output of the internal Core Audio input converter unit, which, from the perspective of your code, is the input audio. Confusing, I know. See Audio Unit docs for more detail. Likewise, to set client output format, use kAudioUnitScope_Output, kInputBus.

Adam Bryant
  • 545
  • 3
  • 13
  • Thanks for the response. I will make those changes to the IO formats and see if it fixes my error (you're right that the naming is counterintuitive for the IO formats). – mickben Apr 16 '14 at 17:03
  • I'm assuming based on your response that I also need to switch `kOutputBus` with `kInputBus` when setting up my IO callbacks as well. – mickben Apr 16 '14 at 17:14
  • Sorry, I made a mistake. mBytesPerFrame should be 8 for stereo with 8.24. – Adam Bryant Apr 16 '14 at 17:24
  • I'm not sure. I think so. I've only ever set up a single callback, which I think is all you need really. You get input samples, process them, and then output them, all in the same callback. So it would be kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, kOutputBus. – Adam Bryant Apr 16 '14 at 17:28
  • Note that for enabling input, you *do* use input scope and input bus however. – Adam Bryant Apr 16 '14 at 17:29
  • I made the changes you suggested and I took your advice about changing from `kAudioFormatFlagsAudioUnitCanonical` and I'm now using `kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked`. The error is gone and I'm now getting input but no output. I'm going to mark your answer as the accepted answer. I'm hoping I can continue picking your brain. Are you on IRC or any other chat service? I don't want to take up to much of your time, but my deadline for this is today and any help I can get it greatly appreciated. – mickben Apr 16 '14 at 17:52
  • Glad it helped. Post another question to stack overflow if you can't find the answer elsewhere on here. I'll keep an eye out... – Adam Bryant Apr 16 '14 at 17:53
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/50809/discussion-between-studmuf-and-adam-bryant) – mickben Apr 16 '14 at 17:57
  • Did you ever get this fixed? – Surz Jun 30 '17 at 00:37
0

32 bits per channel is too many bits to fit 2 channels into 4 bytes. Try 16.

hotpaw2
  • 70,107
  • 14
  • 90
  • 153