0

My iOS app (using openFrameworks) crashes 30-40% of the time on launch on this line:

    if(soundInputPtr!=NULL) soundInputPtr->audioIn(tempBuffer, ioData->mBuffers[i].mDataByteSize/2, 1);

which is inside the larger function in ofxiPhoneSoundStream.m

static OSStatus recordingCallback(void *inRefCon, 
                              AudioUnitRenderActionFlags *ioActionFlags, 
                              const AudioTimeStamp *inTimeStamp, 
                              UInt32 inBusNumber, 
                              UInt32 inNumberFrames, 
                                  AudioBufferList *ioData) {

I am doing audio setup with ofSoundStreamSetup(0, 1, this, 44100, 256, 4); in setup().

In the simulator this crash happens 100% of the time. Any idea (a) what's happening or (b) how to debug it?

Update: Stack trace:

Thread 11 AURemoteIO::IOThread, Queue : (null)

#0  0x00008ff2 in Gameplay::listen() at /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/usr/include/c++/4.2.1/bits/basic_string.h:238
#1  0x003178bc in recordingCallback(void*, unsigned long*, AudioTimeStamp const*, unsigned long, unsigned long, AudioBufferList*) at /Developer/of_007_iphone/libs/openFrameworks/sound/ofxiPhoneSoundStream.mm:143
#2  0x019447e4 in AUIOHelper::NotifyInputAvailable(AudioTimeStamp const&, unsigned long, AudioBufferList const&) ()
#3  0x0192baf1 in AURemoteIO::PerformIO(unsigned int, unsigned int, XAudioTimeStamp const&, XAudioTimeStamp const&, int&) ()
#4  0x0192bbc1 in AURIOCallbackReceiver_PerformIO ()
#5  0x0191b3bf in _XPerformIO ()
#6  0x01861c11 in mshMIGPerform ()
#7  0x018e4180 in MSHMIGDispatchMessage ()
#8  0x019297ba in AURemoteIO::IOThread::Run() ()
#9  0x0192e8e1 in AURemoteIO::IOThread::Entry(void*) ()
#10 0x01836972 in CAPThread::Entry(CAPThread*) ()
#11 0x97bf7259 in _pthread_start ()
#12 0x97bf70de in thread_start ()

And then Thread 11 AURemoteIO::IOThread: Program received signal: "EXC_BAD_ACCESS"

As requested, recordingCallback():

static OSStatus recordingCallback(void *inRefCon, 
                                  AudioUnitRenderActionFlags *ioActionFlags, 
                                  const AudioTimeStamp *inTimeStamp, 
                                  UInt32 inBusNumber, 
                                  UInt32 inNumberFrames, 
                                  AudioBufferList *ioData) {


    AudioBufferList list;

    // redundant
    list.mNumberBuffers = 1;
    list.mBuffers[0].mData = sampleBuffer;
    list.mBuffers[0].mDataByteSize = 2 * inNumberFrames;
    list.mBuffers[0].mNumberChannels = 1;

    ioData = &list;
    //printf("No buffers: %d, buffer length: %d bus number: %d\n", ioData->mNumberBuffers, ioData->mBuffers[0].mDataByteSize, inBusNumber);


    // Then:
    // Obtain recorded samples

    OSStatus status = AudioUnitRender(audioUnit, ioActionFlags, inTimeStamp, 1, inNumberFrames, ioData);
    checkStatus(status);
    if(status!=noErr) return status;
    if(ioData->mNumberBuffers>0) {
        int i = 0;
        short int *buffer = (short int *) list.mBuffers[i].mData;
        for(int j = 0; j < ioData->mBuffers[i].mDataByteSize/2; j++) {
            // go through each sample and turn it into a float
            tempBuffer[j] = (float)buffer[j]/32767.f;

        }
        done = true;


      // THIS LINE IS LINE 143
        if(soundInputPtr!=NULL) soundInputPtr->audioIn(tempBuffer, ioData->mBuffers[i].mDataByteSize/2, 1); 

    }
    return noErr;
}

Line 143 marked above, also: if(soundInputPtr!=NULL) soundInputPtr->audioIn(tempBuffer, ioData->mBuffers[i].mDataByteSize/2, 1);

Added:

Gameplay::listen() is just a max/min tracker-- it used to do more, but I realized those functions were better moved to audioRecieved(). In fact, no other code is calling this function:

void Gameplay::listen() {

  // track extremes for XML purpose
  if (pitchAvg > move.highestPitch) move.highestPitch = pitchAvg;
  if ((pitchAvg < move.lowestPitch) && pitchAvg != 0) move.lowestPitch = pitchAvg;
  if (ampAvg > move.loudestVol) move.loudestVol = ampAvg;
  if ((ampAvg < move.softestVol) && ampAvg > 0.15) move.softestVol = ampAvg;
}
buildsucceeded
  • 4,203
  • 4
  • 34
  • 72
  • Post the output of the crashes. – WrightsCS Sep 08 '11 at 21:51
  • Please also add the source for `Gameplay::listen` (which I'm assuming is the function pointed to by `soundInputPtr->audioIn`; you may want to verify that with `NSLog`). EDIT: Actually, looking at your other question, I see `audioIn` appears to be a method somewhere else, so the `Gameplay::listen` crash is a different (possibly related, possibly unrelated) crash. – Peter Hosey Sep 10 '11 at 21:39

1 Answers1

1

Read the stack trace and go where it tells you.

#0  0x00008ff2 in Gameplay::listen() at /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/usr/include/c++/4.2.1/bits/basic_string.h:238

In my copy of that file, that code reads as follows:

  void
  _M_dispose(const _Alloc& __a)
  {
#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
    if (__builtin_expect(this != &_S_empty_rep(), false))
#endif
      if (__gnu_cxx::__exchange_and_add_dispatch(&this->_M_refcount,
                             -1) <= 0)
        //Line 238:
        _M_destroy(__a);
  }  // XXX MT

Looking elsewhere in the file, that method is called by basic_string's destructor to release the string's private storage (_M_rep()).

For Objective-C objects, a crash like that generally indicates that the object itself (in this case, the string) was trashed, usually by over-releasing it. But I don't know how applicable that is to C++ objects; a lot of things work differently in C++ vs. Objective-C.

We can probably tell you more if you show us the code for recordingCallback, making sure to include line 143 of that file (again, see the stack trace for why I'm pointing there).

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
  • Added a `!= NULL` check on the pointer to the start and end of the audio buffer before I do anything with it. That seems to solve the crash. Can you help me understand why the stacktrace was pointing me into the `listen()` function when that function wasn't directly implicated in the crash? – buildsucceeded Sep 12 '11 at 13:37
  • @ickydog: Is `move` an Objective-C object, or a C++ object that overloads the `.` operator? If not, I can't see how it was part of the crash given the code you've added to your question. Is that method different now (i.e., in the code you posted) from the version that crashed? – Peter Hosey Sep 12 '11 at 13:57
  • `move` is just a struct that holds values for `col`, `row` and `error`. Code posted is what crashed, although from what I understand `EXC_BAD_ACCESS` can sometimes point at unrelated code because a pointer has been incremented beyond its allocated scope in the, erm, program memory? – buildsucceeded Sep 12 '11 at 14:14
  • @ickydog: `EXC_BAD_ACCESS` means you tried to access memory that didn't belong to you. Sometimes it means you tried to go outside of something that did; sometimes it means that it had belonged to you in the past but then you freed it (e.g., over-release of a Cocoa object); sometimes it means that you overwrote a pointer. It's technically possible for wrong code to be implicated, but fantastically unlikely; you'd need to smash the stack in a way that doesn't just leave garbage the debugger/crash reporter can't make sense of. – Peter Hosey Sep 12 '11 at 18:51