Implementing fmod syncpoints (and callbacks) in android

Hi! I would like to have a simple example code to implement syncpoints for an audio file along with setting up callbacks for the same(FMOD Core api, Android).

What I tried is,

FMOD_SYNCPOINT **point = nullptr;
result = sound->addSyncPoint(1154, FMOD_TIMEUNIT_MS, "Good", point);
ERRCHECK(result);

Until here, everything works fine and a syncpoint is created. But ,

char *name = NULL;
FMOD_SYNCPOINT **point2 = NULL;
sound->getSyncPoint(0, point2);
result = sound->getSyncPointInfo(*point2, name, 64, 0, FMOD_TIMEUNIT_MS);

this leads to app crashing.

Even setting callback like this,

result = channel->setCallback(mycallback);
ERRCHECK(result);

throws an error – an invalid object handle was used.

My callback function is as follows–

FMOD_RESULT F_CALLBACK mycallback(FMOD_CHANNELCONTROL *chanControl, FMOD_CHANNELCONTROL_TYPE controlType, FMOD_CHANNELCONTROL_CALLBACK_TYPE callbackType, void *commandData1, void *commandData2)
{
    if (controlType == FMOD_CHANNELCONTROL_CHANNEL)
    {
        FMOD::Channel *pChannel = (FMOD::Channel *)chanControl;
        if(callbackType == FMOD_CHANNELCONTROL_CALLBACK_SYNCPOINT){
            
            FMOD::Sound *sound;
            pChannel->getCurrentSound(&sound);
        }
       
    }
    else
    {
        FMOD::ChannelGroup *group = (FMOD::ChannelGroup *)chanControl;
        // ChannelGroup specific functions here...
    }

    return FMOD_OK;
}

I request, to please provide me with a brief sample code to solve these errors or a brief code containing complete implementation of syncpoints along with setting a callback to a channel.

Thanx, in advance.

Hi,

You seem to be running into two issues:

  1. You’re creating a double pointer for your second FMOD_SYNCPOINT object, which is throwing a read access violation as you’re trying to dereference a null pointer when passing *point2 to sound->getSyncPointInfo. You should be creating a single pointer, and addressing it as needed when passing it to functions. For example:
FMOD_SYNCPOINT *point2 = NULL;
sound->getSyncPoint(0, &point2);
result = sound->getSyncPointInfo(point2, name, 64, 0, FMOD_TIMEUNIT_MS);
  1. As you’ve already noted in a DM to @Connor_FMOD, you need to be playing your sound before setting the callback on the channel - this is because the channel itself is created when you call System::playSound. I’ve flagged a documentation change internally regarding this.

The rest of your code is working fine for me. If you do run into any issues after resolving the above, feel free to let me know.

It is quite strange after using the above code in my callback function the app crashes and restarts for the first time and for the second time it crashes completely.
Here is the exact code of my callbank function:-

FMOD_RESULT F_CALLBACK mycallback(FMOD_CHANNELCONTROL *chanControl, FMOD_CHANNELCONTROL_TYPE controlType, FMOD_CHANNELCONTROL_CALLBACK_TYPE callbackType, void *commandData1, void *commandData2)
{
    if (controlType == FMOD_CHANNELCONTROL_CHANNEL)
    {
        FMOD::Channel *pChannel = (FMOD::Channel *)chanControl;
        if(callbackType == FMOD_CHANNELCONTROL_CALLBACK_SYNCPOINT){
            //Common_Draw(bol[(int)(size_t)commandData1].data());
            FMOD::Sound *tempSound;
            pChannel->getCurrentSound(&tempSound);
            FMOD_SYNCPOINT *tempPoint;
            result = tempSound->getSyncPoint((int)(size_t)commandData1, &tempPoint);
            ERRCHECK(result);
            char *name;
            result = tempSound->getSyncPointInfo(tempPoint, name, 64, 0, FMOD_TIMEUNIT_MS);
            ERRCHECK(result);
            Common_Draw(name);
        }
        // Channel specific functions here...
    }

There’s two issues with the callback code:

  1. You’re attempting to assign a value to result without defining it in the callback.
  2. You’re passing a char* name to getSyncPointInfo() without initializing it. You’ll want to initialize it to match the namelen argument you’re passing to getSyncPointInfo() i.e. char name[64];

To elaborate on needing to define result even though it’s defined outside of it - you should consider the callback to be removed from the rest of your code. If you want to access a variable that is outside the callback, you should pass it to the object you’re setting the callback on (i.e. the channel) as user data with ChannelControl::setUserData, and access it from within the callback by calling ChannelControl::getUserData on chanControl.

Yes! That surely helped me out. Thanx

No problem!