EXC_BAD_ACCESS error (isolated project included)

Dear FMOD Support,

I stumbled upon a bug which seems to be caused by the FMOD engine, and not by me.

It seems to be caused by a conditional transition region, in combination with a “system.update()” call.

I have included the FMOD project, and example code (modified from the simple event example).

Here is how to reproduce:

  1. Copy “DontCallUs.bank” to the resource directory of the examples
  2. Replace “simple event.cpp” with my copy (copy-paste below)
  3. Run the example on a real iPhone (I used iPhone5). It does NOT happen in the simulator!
  4. Press “A” to start event.

Your help would be very much appreciated.

Mark

simple event.cpp

#include "fmod_studio.hpp"
#include "fmod.hpp"
#include "common.h"
#include <stdio.h>

FMOD::Studio::System pSystem;
FMOD::Studio::Bank masterBank;
FMOD::Studio::EventInstance eventInstance;

void startAudio() {
    
    //Load Bank
    ERRCHECK( pSystem.loadBank(Common_MediaPath("DontCallUs.bank"), &masterBank) );
    
    //Load event
    FMOD::Studio::ID loopingAmbienceID = {0};
    ERRCHECK( FMOD::Studio::parseID("{6fea8e2b-6d94-419e-b211-9e83aafbf7fe}", &loopingAmbienceID) );
    
    FMOD::Studio::EventDescription loopingAmbienceDescription;
    ERRCHECK( pSystem.getEvent(&loopingAmbienceID, FMOD_STUDIO_LOAD_BEGIN_NOW, &loopingAmbienceDescription) );
    
    ERRCHECK( loopingAmbienceDescription.createInstance(&eventInstance) );
    
    //Start event
    ERRCHECK( eventInstance.start());
}

const char* drawStatus() {
    int position = 0;
    float volume = 0.0;
    bool paused = false;
    const char* playbackeStateStr;
    const char* loadingStateStr;
    
    if(eventInstance.isValid()) {
        eventInstance.getTimelinePosition(&position);
        eventInstance.getVolume(&volume);
        eventInstance.getPaused(&paused);
    
        FMOD_STUDIO_PLAYBACK_STATE playbackState;
        eventInstance.getPlaybackState(&playbackState);
        switch (playbackState) {
            case FMOD_STUDIO_PLAYBACK_IDLE:
                playbackeStateStr = "IDLE"; break;
            case FMOD_STUDIO_PLAYBACK_PLAYING:
                playbackeStateStr = "PLAYING"; break;
            case FMOD_STUDIO_PLAYBACK_STOPPED:
                playbackeStateStr = "STOPPED"; break;
            case FMOD_STUDIO_PLAYBACK_SUSTAINING:
                playbackeStateStr = "SUSTAINING"; break;
        }
    
        FMOD_STUDIO_LOADING_STATE loadingState;
        eventInstance.getLoadingState(&loadingState);
        switch (loadingState) {
            case FMOD_STUDIO_LOADING_STATE_LOADED:
                loadingStateStr = "LOADED"; break;
            case FMOD_STUDIO_LOADING_STATE_LOADING:
                loadingStateStr = "LOADING"; break;
            case FMOD_STUDIO_LOADING_STATE_UNLOADED:
                loadingStateStr = "UNLOADED"; break;
            case FMOD_STUDIO_LOADING_STATE_UNLOADING:
                loadingStateStr = "UNLOADING"; break;
        }
    } else {
        playbackeStateStr = "...";
        loadingStateStr = "...";
    }
    
    FMOD::System* system;
    pSystem.getLowLevelSystem(&system);
    int channels;
    system->getChannelsPlaying(&channels);
    
    Common_Draw("Loading: %s; Pos: %i; Vol: %f; Paused: %s; Playback: %s; Used Channels: %i",loadingStateStr,position,volume,(paused?"Yes":"No"),playbackeStateStr,channels);

}

int FMOD_Main()
{
    // Init FMOD::STUDIO::SYSTEM
    void *extraDriverData = 0;
    Common_Init(&extraDriverData);    
    ERRCHECK( FMOD::Studio::System::create(&pSystem) );
    ERRCHECK( pSystem.initialize(32, FMOD_STUDIO_INIT_NORMAL, FMOD_INIT_NORMAL, extraDriverData) );

    do
    {
        Common_Update();
        
        if (Common_BtnPress(BTN_ACTION1))
        {     
            startAudio();
        }
        

        ERRCHECK( pSystem.update() );

        Common_Draw("==================================================");
        Common_Draw("Crash with conditional transition region ");
        Common_Draw("==================================================");
        Common_Draw("");
        Common_Draw("Press %s to CRASH", Common_BtnStr(BTN_ACTION1));
        Common_Draw("Press %s to quit", Common_BtnStr(BTN_QUIT));
        Common_Draw("", Common_BtnStr(BTN_QUIT));
        drawStatus();

        Common_Sleep(50);
    } while (!Common_BtnPress(BTN_QUIT));

    ERRCHECK( pSystem.release() );

    Common_Close();

    return 0;
}

Thanks for the straightforward repro! We have reproduced the bug here - it looks like an unaligned read in the mixer code. We’re investigating the best way to fix this, and will get back to you soon.

Any updates or work-a-rounds?

My goal is to jump to a point in the timeline (Marker A,B or C) given a game-parameter. I guess I can work-a-round by setting the timeline position directly.

Questions:

  • Can I retrieve marker position using the API? (Or do I have to look it up in FMOD studio and hard code it?)
  • How can I calculate the length of one measure? Using this length, I can jump to the correct location in the next section. (i.e jump from 3rd beat somewhere in section A, to the 3rd beat of the first measure of section B)

Thanks for your help!

Unfortunately due to the nature of this bug, setting the timeline position directly won’t really help. We’re still looking into this, and should have an update shortly - sorry for the delay!

Just to update you, we have diagnosed this crash and have a fix in place for our next release.
If you would like a preview version with that fix please contact me at support@fmod.org.

Thanks for your patience on this issue, we have tracked down the problem and have a fix for it. This will require an updated version of FMOD to resolve which we hope to make available on Monday. If you could send an e-mail to support@fmod.org I can take care of your issues personally and ensure you get a fixed version ASAP.