In my iOS app I use open-source code (a mix of C++ and Objective-C) in a .mm file to find the max frequency of sound recorded by the mic. However, I'm getting a bad access error about 10% of the time and have no idea how to deal with it, as I'm using a language I'm not familiar with.
The NSLog output is as follows:
ERROR: [0x19932f310] >aurioc> 806: failed: -50 (enable 3, outf< 2 ch, 44100 Hz, Int8.24, non-inter> inf< 2 ch, 44100 Hz, Int8.24, non-inter>)
2015-06-29 12:31:15.396 XXX[547:138175] error = couldn't setup remote i/o unit
Here is where the error occurs:
AudioToolbox`AUInputElement::PullInput:
0x182a821ec <+0>: stp x24, x23, [sp, #-64]!
0x182a821f0 <+4>: stp x22, x21, [sp, #16]
0x182a821f4 <+8>: stp x20, x19, [sp, #32]
0x182a821f8 <+12>: stp x29, x30, [sp, #48]
0x182a821fc <+16>: add x29, sp, #48
0x182a82200 <+20>: mov x20, x4
0x182a82204 <+24>: mov x23, x3
0x182a82208 <+28>: mov x21, x2
0x182a8220c <+32>: mov x22, x1
0x182a82210 <+36>: mov x19, x0
0x182a82214 <+40>: ldr w8, [x19, #164]
0x182a82218 <+44>: cbnz w8, 0x182a82224 ; <+56>
0x182a8221c <+48>: movn w0, #0x2a7b
0x182a82220 <+52>: b 0x182a822ac ; <+192>
0x182a82224 <+56>: cmp w8, #1
0x182a82228 <+60>: b.eq 0x182a82248 ; <+92>
0x182a8222c <+64>: ldrb w8, [x19, #160]
0x182a82230 <+68>: cbz w8, 0x182a82248 ; <+92>
0x182a82234 <+72>: add x0, x19, #120
0x182a82238 <+76>: add x1, x19, #80
0x182a8223c <+80>: mov x2, x20
0x182a82240 <+84>: bl 0x182a810e4 ; AUBufferList::PrepareBuffer(CAStreamBasicDescription const&, unsigned int)
0x182a82244 <+88>: b 0x182a82258 ; <+108>
0x182a82248 <+92>: add x0, x19, #120
0x182a8224c <+96>: add x1, x19, #80
0x182a82250 <+100>: mov x2, x20
0x182a82254 <+104>: bl 0x182a811e4 ; AUBufferList::PrepareNullBuffer(CAStreamBasicDescription const&, unsigned int)
0x182a82258 <+108>: mov x5, x0
0x182a8225c <+112>: ldr w8, [x19, #164]
0x182a82260 <+116>: cmp w8, #1
0x182a82264 <+120>: b.ne 0x182a82284 ; <+152>
0x182a82268 <+124>: ldr x0, [x19, #184]
0x182a8226c <+128>: ldr w3, [x19, #192]
0x182a82270 <+132>: mov x1, x22
0x182a82274 <+136>: mov x2, x21
0x182a82278 <+140>: mov x4, x20
0x182a8227c <+144>: bl 0x18298f0ec ; AudioUnitRender
0x182a82280 <+148>: b 0x182a8229c ; <+176>
0x182a82284 <+152>: ldp x8, x0, [x19, #168]
0x182a82288 <+156>: mov x1, x22
0x182a8228c <+160>: mov x2, x21
0x182a82290 <+164>: mov x3, x23
0x182a82294 <+168>: mov x4, x20
0x182a82298 <+172>: blr x8
0x182a8229c <+176>: ldr w8, [x19, #164] // EXC_BAD_ACCESS HERE
0x182a822a0 <+180>: cmp w8, #0
0x182a822a4 <+184>: movn w8, #0x2a7b
0x182a822a8 <+188>: csel w0, w8, w0, eq
0x182a822ac <+192>: ldp x29, x30, [sp, #48]
0x182a822b0 <+196>: ldp x20, x19, [sp, #32]
0x182a822b4 <+200>: ldp x22, x21, [sp, #16]
0x182a822b8 <+204>: ldp x24, x23, [sp], #64
0x182a822bc <+208>: ret
The thing is, this error does not happen in the demo app using the open-source code, so I figure it must be something I added. The only code I added was to the view controller, the code between the three asterisks (***) in here:
#import "LightsViewController.h"
#import "mo_audio.h" //stuff that helps set up low-level audio
#import "FFTHelper.h"
#define SAMPLE_RATE 44100 //22050 //44100
#define FRAMESIZE 512
#define NUMCHANNELS 2
#define kOutputBus 0
#define kInputBus 1
/// Nyquist Maximum Frequency
const Float32 NyquistMaxFreq = SAMPLE_RATE/2.0;
/// caculates HZ value for specified index from a FFT bins vector
Float32 frequencyHerzValue(long frequencyIndex, long fftVectorSize, Float32 nyquistFrequency ) {
return ((Float32)frequencyIndex/(Float32)fftVectorSize) * nyquistFrequency;
}
// The Main FFT Helper
FFTHelperRef *fftConverter = NULL;
//Accumulator Buffer=====================
// CHANGE "SAMPLE RATE" (?) HERE, I.E., HOW OFTEN THE METHOD IS RUN THAT SAMPLES THE MAX HZ
const UInt32 accumulatorDataLenght = 2048; //16384; //32768; 65536; 131072;
UInt32 accumulatorFillIndex = 0;
Float32 *dataAccumulator = nil;
static void initializeAccumulator() {
dataAccumulator = (Float32*) malloc(sizeof(Float32)*accumulatorDataLenght);
accumulatorFillIndex = 0;
}
static void destroyAccumulator() {
if (dataAccumulator!=NULL) {
free(dataAccumulator);
dataAccumulator = NULL;
}
accumulatorFillIndex = 0;
}
static BOOL accumulateFrames(Float32 *frames, UInt32 lenght) { //returned YES if full, NO otherwise.
// float zero = 0.0;
// vDSP_vsmul(frames, 1, &zero, frames, 1, lenght);
if (accumulatorFillIndex>=accumulatorDataLenght) { return YES; } else {
memmove(dataAccumulator+accumulatorFillIndex, frames, sizeof(Float32)*lenght);
accumulatorFillIndex = accumulatorFillIndex+lenght;
if (accumulatorFillIndex>=accumulatorDataLenght) { return YES; }
}
return NO;
}
static void emptyAccumulator() {
accumulatorFillIndex = 0;
memset(dataAccumulator, 0, sizeof(Float32)*accumulatorDataLenght);
}
//=======================================
//==========================Window Buffer
const UInt32 windowLength = accumulatorDataLenght;
Float32 *windowBuffer= NULL;
//=======================================
/// max value from vector with value index (using Accelerate Framework)
static Float32 vectorMaxValueACC32_index(Float32 *vector, unsigned long size, long step, unsigned long *outIndex) {
Float32 maxVal;
vDSP_maxvi(vector, step, &maxVal, outIndex, size);
return maxVal;
}
///returns HZ of the strongest frequency.
static Float32 strongestFrequencyHZ(Float32 *buffer, FFTHelperRef *fftHelper, UInt32 frameSize, Float32 *freqValue) {
Float32 *fftData = computeFFT(fftHelper, buffer, frameSize);
fftData[0] = 0.0;
unsigned long length = frameSize/2.0;
Float32 max = 0;
unsigned long maxIndex = 0;
max = vectorMaxValueACC32_index(fftData, length, 1, &maxIndex);
if (freqValue!=NULL) { *freqValue = max; }
Float32 HZ = frequencyHerzValue(maxIndex, length, NyquistMaxFreq);
return HZ;
}
__weak UILabel *labelToUpdate = nil;
int value;
#pragma mark MAIN CALLBACK
void AudioCallback( Float32 * buffer, UInt32 frameSize, void * userData )
{
//take only data from 1 channel
Float32 zero = 0.0;
vDSP_vsadd(buffer, 2, &zero, buffer, 1, frameSize*NUMCHANNELS);
if (accumulateFrames(buffer, frameSize)==YES) { //if full
//windowing the time domain data before FFT (using Blackman Window)
if (windowBuffer==NULL) { windowBuffer = (Float32*) malloc(sizeof(Float32)*windowLength); }
vDSP_blkman_window(windowBuffer, windowLength, 0);
vDSP_vmul(dataAccumulator, 1, windowBuffer, 1, dataAccumulator, 1, accumulatorDataLenght);
//=========================================
Float32 maxHZValue = 0;
Float32 maxHZ = strongestFrequencyHZ(dataAccumulator, fftConverter, accumulatorDataLenght, &maxHZValue);
//NSLog(@" max HZ = %0.3f ", maxHZ);
dispatch_async(dispatch_get_main_queue(), ^{ //update UI only on main thread
***//labelToUpdate.text = [NSString stringWithFormat:@"%0.3f HZ",maxHZ];
if (maxHZ > 18950.0f) {
if (maxHZ < 19050.0f) {
value = 0;
} else if (maxHZ < 19150.0f) {
value = 1;
} else if (maxHZ < 19450.0f) {
value = 2;
}
}
});***
emptyAccumulator(); //empty the accumulator when finished
}
memset(buffer, 0, sizeof(Float32)*frameSize*NUMCHANNELS);
}
@interface LightsViewController ()
@property int hzValue;
@property NSTimer *timerWhiteAndOrage;
@property NSTimer *timerRedAndBlue;
@property NSTimer *methodTimer;
@end
@implementation LightsViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
//labelToUpdate = HZValueLabel;
_hzValue = value;
//initialize stuff
fftConverter = FFTHelperCreate(accumulatorDataLenght);
initializeAccumulator();
[self initMomuAudio];
NSTimer *timer = [NSTimer
scheduledTimerWithTimeInterval:(NSTimeInterval)(0.05f)
target:self
selector:@selector(didReceiveNewMaxHz)
userInfo:nil
repeats:TRUE];
timer.fireDate = [NSDate dateWithTimeIntervalSinceNow:(NSTimeInterval) 0.1f];
_methodTimer = timer;
}
-(void) initMomuAudio {
bool result = false;
result = MoAudio::init( SAMPLE_RATE, FRAMESIZE, NUMCHANNELS, false);
if (!result) { NSLog(@" MoAudio init ERROR"); }
result = MoAudio::start( AudioCallback, NULL );
if (!result) { NSLog(@" MoAudio start ERROR"); }
}
-(void) dealloc {
destroyAccumulator();
FFTHelperRelease(fftConverter);
}
@end
Aucun commentaire:
Enregistrer un commentaire