lundi 1 décembre 2014

error after stopping AudioUnit Recording

I'm trying to grab audio input from the iPhone's microphone by using this code:



@property (nonatomic) AudioUnit rioUnit;
@property (nonatomic) CAStreamBasicDescription outputCASBD;

(...)

// set our required format - LPCM non-interleaved 32 bit floating point
CAStreamBasicDescription outFormat = CAStreamBasicDescription(44100, // sample rate
kAudioFormatLinearPCM, // format id
4, // bytes per packet
1, // frames per packet
4, // bytes per frame
1, // channels per frame
32, // bits per channel
kAudioFormatFlagIsFloat | kAudioFormatFlagIsNonInterleaved);

try {
// Open the output unit
AudioComponentDescription desc;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_RemoteIO;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;

AudioComponent comp = AudioComponentFindNext(NULL, &desc);

AudioComponentInstanceNew(comp, &_rioUnit);

UInt32 one = 1;
XThrowIfError(AudioUnitSetProperty(_rioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &one, sizeof(one)), "couldn't enable input on the remote I/O unit");

AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = renderInput;
callbackStruct.inputProcRefCon = (__bridge void*)self;
XThrowIfError(AudioUnitSetProperty(_rioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &callbackStruct, sizeof(callbackStruct)), "couldn't set remote i/o render callback");

XThrowIfError(AudioUnitSetProperty(_rioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &outFormat, sizeof(outFormat)), "couldn't set the remote I/O unit's output client format");
XThrowIfError(AudioUnitSetProperty(_rioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &outFormat, sizeof(outFormat)), "couldn't set the remote I/O unit's input client format");

XThrowIfError(AudioUnitInitialize(_rioUnit), "couldn't initialize the remote I/O unit");
XThrowIfError(AudioOutputUnitStart(_rioUnit), "couldn't start the remote I/O unit");
}
catch (CAXException &e) {
char buf[256];
fprintf(stderr, "Error: %s (%s)\n", e.mOperation, e.FormatError(buf));
}
catch (...) {
fprintf(stderr, "An unknown error occurred\n");
}

// Allocate our own buffers (1 channel, 16 bits per sample, thus 16 bits per frame, thus 2 bytes per frame).
// Practice learns the buffers used contain 512 frames, if this changes it will be fixed in processAudio.
// will need float for accellerate fft (input is 16 bit signed integer) so make space...
_tempBuffer.mNumberChannels = outFormat.mChannelsPerFrame;
_tempBuffer.mDataByteSize = 512 * outFormat.mBytesPerFrame * 2;
_tempBuffer.mData = malloc( self.tempBuffer.mDataByteSize );


All is good, up to the point where I want to stop listening to the Mic input.


I'm doing this:



AudioOutputUnitStop(_rioUnit);
AudioUnitUninitialize(_rioUnit);
AudioComponentInstanceDispose(_rioUnit);
_rioUnit = nil;


But I get an error from inside the callback function defined for kAudioOutputUnitProperty_SetInputCallback.


The error is: AURemoteIO::IOThread (14): EXC_BAD_ACCESS (code=1, address=0x8000000c)


It appears to me that AudioUnit's InputCallback is still being called, even though I am Stopping it, Unitializing and Disposing of its instance.


Why is this happening and how can I prevent the InputCallback from being called after I Stop, Unitialize and Dispose of its instance?




Aucun commentaire:

Enregistrer un commentaire