AURemoteIO::IOThread EXC_BAD_ACCESS - ios

I am using AudioGraph.eqRenderInput is a callback function.
static OSStatus eqRenderInput(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
{
#autoreleasepool {
NSLog(#"--method = %s--current thread:%#",__func__,[NSThread currentThread]);
MyAudioController *mycon = (__bridge MyAudioController *)inRefCon;
AudioUnit mixUNIT = mycon->mixUnit;
AudioUnitRender(mixUNIT, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
int bufferCount = ioData->mNumberBuffers;
NSLog(#"current thread:%#----bufferCount=%d",[NSThread currentThread],bufferCount);
// Fill the provided AudioBufferList with the data from the AudioBufferList output by the audio data output
for (int bufferIndex = 0; bufferIndex < bufferCount; bufferIndex++) {
NSData *tmpData = [NSData dataWithBytes:ioData->mBuffers[bufferIndex].mData length:ioData->mBuffers[bufferIndex].mDataByteSize];
[mycon->mixMArray addObject:tmpData]; // this line carsh
NSLog(#"mchannel = %d---bufferIndex = %d",ioData->mBuffers[bufferIndex].mNumberChannels,bufferIndex);
}
}
}
mixMArray class is NSMutableArray,
[mycon->mixMArray addObject:tmpData];this line crash,
error message is exec bad access code = 1 adddress = 0xf42e8.

Related

How to merge two Audio Units into AudioBufferList for AURenderCallback

Please see code below. All I want to, is to merge bufflist1 and bufflist2, then inset to ioData. But I don't know how.
OSStatus PlayCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData) {
ALNPlayer *player = (__bridge ALNPlayer *)inRefCon;
OSStatus status;
player->buffList->mBuffers[0].mDataByteSize = CONST_BUFFER_SIZEV3;
//read audio1 data to bufflist1
status = AudioConverterFillComplexBuffer(player->audioConverter1, lyInInputDataProcV1, inRefCon, &inNumberFrames, player->buffList1, NULL);
//read audio2 data to bufflist2
status = AudioConverterFillComplexBuffer(player->audioConverter2, lyInInputDataProcV2, inRefCon, &inNumberFrames, player->buffList2, NULL);
//below is copy bufferlist1 to ioData
//and now i want to merge bufflist1 and buflist2,then inset to iodata. But I don't know how.
memcpy(ioData->mBuffers[0].mData, player->buffList->mBuffers[0].mData, player->buffList->mBuffers[0].mDataByteSize);
}

iOS - How to solve echo problems with speex?

My App call to the intercom has an echo, I have used the native method, but it is useless, I want to use the echo cancellation of speex, but I have encountered some problems, in the echo cancellation of speex, need three parameters, ref, echo and End, I only have the bufferList.mBuffers[0].mData variable, I don't know what the other two parameters are to be substituted for?
OSStatus recordingCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimestamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) {
AudioProcessor *audioProcessor = (__bridge AudioProcessor *)inRefCon;
AudioBufferList bufferList;
bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0].mData = NULL;
OSStatus status = AudioUnitRender(audioProcessor.audioUnit, ioActionFlags, inTimestamp, inBusNumber, inNumberFrames, &bufferList);
if (status != noErr) {
return status;
}
SpeexEchoState *echo_state = speex_echo_state_init(bufferList.mBuffers[0].mDataByteSize, 882);
SpeexPreprocessState *den = speex_preprocess_state_init(bufferList.mBuffers[0].mDataByteSize, 44100);
short *ref_buf = (short*)bufferList.mBuffers[0].mData;
short *echo_buf = (short*)malloc(bufferList.mBuffers[0].mDataByteSize);
short *endbuf = (short*)malloc(bufferList.mBuffers[0].mDataByteSize);
speex_echo_cancellation(echo_state,
(spx_int16_t*)ref_buf,
(spx_int16_t*)echo_buf,
(spx_int16_t*)endbuf);
speex_preprocess_run(den, (spx_int16_t*)endbuf);
[audioProcessor.delegate processAudioData:endbuf dataSize:bufferList.mBuffers[0].mDataByteSize];
free(ref_buf);
free(echo_buf);
free(endbuf);
return noErr;
}
If you build-in AEC is not working, it means that there is a good chance that your echo behavior is not trivial and you should look for more robust solutions than Speex. Google for echo cancellation software to find few alternatives.

AudioUnit noise if there is no output buffer

I am trying to implement playing pcm audio received from remote server via socket. Here was my previous question link. This works fine as I use circular buffer to always feed in the incoming buffer.
However I have a problem that there is a huge noise sound that is being produced if I have no buffer supplied to my output. This happens when I begin to use AudioOutputUnitStart(_audioUnit) and when there is no buffer to play.
I suspect I have to fix this in my OutputRenderCallback function below or may be there is something else I need to do :
static OSStatus OutputRenderCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData){
Test *output = (__bridge Test*)inRefCon;
TPCircularBuffer *circularBuffer = [output outputShouldUseCircularBuffer];
if( !circularBuffer ){
SInt32 *left = (SInt32*)ioData->mBuffers[0].mData;
for(int i = 0; i < inNumberFrames; i++ ){
left[ i ] = 0.0f;
}
return noErr;
};
int32_t bytesToCopy = ioData->mBuffers[0].mDataByteSize;
SInt16* outputBuffer = ioData->mBuffers[0].mData;
uint32_t availableBytes;
SInt16 *sourceBuffer = TPCircularBufferTail(circularBuffer, &availableBytes);
int32_t amount = MIN(bytesToCopy,availableBytes);
memcpy(outputBuffer, sourceBuffer, amount);
TPCircularBufferConsume(circularBuffer,amount);
return noErr;
}
I highly appreciate you help.Thanks.
An audio unit callback requires that you always put the requested amount of samples in the AudioBufferList buffers. Your code does not do that if the amount (from that available circular buffer) is less.
So put something in the output buffer always, as your code does if there is no circular buffer.
BTW: calling a method:
[output outputShouldUseCircularBuffer]
inside a callback is a violation of Apple's rules for real-time audio.
I am posting my answer incase someone else stumbles at the same point as I was. I am new to objective c so incase someone has a better solution. I do welcome any suggestions.
As #hotpaw2 suggested the AudioBufferList needs to be feed with samples and in my case when my circularBuffer had nothing inside of it. I had to feed the AudioBufferList with frames being set to 0.0f
static OSStatus OutputRenderCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData){
Test *output = (__bridge Test*)inRefCon;
TPCircularBuffer *circularBuffer = [output outputShouldUseCircularBuffer];
int32_t bytesToCopy = ioData->mBuffers[0].mDataByteSize;
SInt16* outputBuffer = ioData->mBuffers[0].mData;
uint32_t availableBytes;
SInt16 *sourceBuffer = TPCircularBufferTail(circularBuffer, &availableBytes);
int32_t amount = MIN(bytesToCopy,availableBytes);
if (amount>0) {
memcpy(outputBuffer, sourceBuffer, amount);
TPCircularBufferConsume(circularBuffer,amount);
}
else{
SInt32 *left = (SInt32*)ioData->mBuffers[0].mData;
for(int i = 0; i < inNumberFrames; i++ ){
left[ i ] = 0.0f;
}
return noErr;
}
return noErr; }

AURemoteIO::IOThread(18):EXE_BAD_ACCESS (Code1, address 0X20)

I am using following function to render the incoming audio.
static OSStatus audioUnitRenderCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberOfFrames,
AudioBufferList *ioData{
// App is crashing at this :
AudioUnitIO *SELF = (__bridge AudioUnitIO *)inRefCon;
// MICROPHONE: take the sound received, render it into bytes and hand them to the delegate
AudioUnitRender(SELF->g_audioUnit,
ioActionFlags,
inTimeStamp,
g_inputBus,
inNumberOfFrames,
ioData);
if (!SELF->recordingAudio) {
memset(ioData->mBuffers[0].mData, 0, ioData->mBuffers[0].mDataByteSize);
// Some other code goes here
}
I am getting the crash as mentioned in question. Am I missing something?

Convert sound in Core Audio (iOS): 1 buffer 2 channels to 2 buffers and each has 1 channel?

I used OrigamiEngine to play flac files. But the problem is I need to convert its output data (it used standard Core Audio with a custom static function) in this file.
Code:
static OSStatus Sound_Renderer(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData) {
ORGMOutputUnit *output = (ORGMOutputUnit *)inRefCon;
OSStatus err = noErr;
void *readPointer = ioData->mBuffers[0].mData;
int amountToRead, amountRead;
amountToRead = inNumberFrames * (output->_format.mBytesPerPacket);
amountRead = [output readData:(readPointer) amount:amountToRead];
if (amountRead < amountToRead) {
int amountRead2;
amountRead2 = [output readData:(readPointer+amountRead) amount:amountToRead-amountRead];
amountRead += amountRead2;
}
ioData->mBuffers[0].mDataByteSize = amountRead;
ioData->mBuffers[0].mNumberChannels = output->_format.mChannelsPerFrame;
ioData->mNumberBuffers = 1;
return err;
}
So ioData has 1 buffer and 2 channels but I need vice versa - 2 buffers when each of them contains 1 channel. Or simply:
LRLRLR... -> LLL... + RRR...
UPDATED
In general I need to achieve something like the following:
ioData->mBuffers[0].mDataByteSize = ...;
ioData->mBuffers[0].mNumberChannels = 1;
ioData->mBuffers[1].mDataByteSize = ...;
ioData->mBuffers[1].mNumberChannels = 1;
ioData->mNumberBuffers = 2;

Resources