Playing sound specific range

Hi,

I have few questions:

  1. I would like to play a specific range[startTime, endTime] of a sound file, is there an efficient way to do it ? I tried to setLoopPoints and setDelay but I couldn’t make them work. Of course, I could monitor the playback through callback and stop the playing, but I think there might be a better way to do it.

  2. Per the documentation, after playing a sound its channel should be invalid, I don’t see it happens when I call hasHandle on a channel the handle seems valid. Does it make any sense?

Thanks

  1. You can scrub to a position of a playing Sound by calling Channel::setPosition on it’s Channel handle. For setLoopPoints to work the sound’s mode will need to be set to FMOD_LOOP_NORMAL or FMOD_LOOP_BIDI.
  2. Where in the docs does it say after playing a sound the channel should be invalid? After playing a sound the channel should be valid if playSound was succesful.

Hi Jeff,

Thanks.

  1. Channel::setPosition will work on the “start”, but the problem is how to accurately end the playback on endTime; I thought about starting some timer, but would like to avoid managing multiple timers. Is there some more elegant way to deal with this? Maybe I could register to some callbacks? I did check the channel callback, didn’t look like it could help.

  2. I saw it in the below book… I think I saw it also in the documentation, but not sure.

I believe setLoopPoints should be sample accurate, and then you would just need to set the loop count to 0 with Channel::setLoopCount to make sure it only plays once.

That book is correct, the channel will be invalid only after the sound has stopped or completed it’s playback, but will be valid until either of those two things occur.

  1. Well, it doesn’t seem like setLoopPoints is doing the trick. It does loop, but after the count is reached, the sound is playing without stopping. It looks like I will have to monitor the playback :frowning: Any idea?

  2. Yeah, that’s what I meant - that post-playback(complete/stopped) the channel’s handle cannot be re-used and should be invalid? I don’t see this happening… how do I check if the handle is valid?

  1. You are right, sorry for the oversight there. I think your original solution of having callbacks is the best way to go, though I am finding it is off by 5-30ms which isn’t ideal. I have added a task to our backlog to implement a call for sample-accurate playback within a given time range.
    Here is a rough example of you can implement such a callback:
FMOD_RESULT F_CALLBACK SyncCallback(FMOD_CHANNELCONTROL* channelcontrol, FMOD_CHANNELCONTROL_TYPE controltype, FMOD_CHANNELCONTROL_CALLBACK_TYPE callbacktype, void* commanddata1, void* commanddata2)
{
    if (callbacktype == FMOD_CHANNELCONTROL_CALLBACK_SYNCPOINT)
    { 
        FMOD::ChannelGroup *cc = (FMOD::ChannelGroup*)channelcontrol;
        return cc->stop();
    }
    return FMOD_OK;
}

FMOD_RESULT FMOD_Play_Sound_Range(FMOD::System *system, FMOD::Sound *sound, int start, FMOD_TIMEUNIT starttimeunit, int end, FMOD_TIMEUNIT endtimeunit)
{
    FMOD_RESULT     result;
    FMOD_SYNCPOINT *endpoint;
    FMOD::Channel  *channel;
    int             numsyncpoints;

    // Remove existing syncpoints
    result = sound->getNumSyncPoints(&numsyncpoints);
    ERRCHECK(result);
    for (int i = 0; i < numsyncpoints; ++i)
	{
		FMOD_SYNCPOINT* syncpoint;
		result = sound->getSyncPoint(i, &syncpoint);
		ERRCHECK(result);
		result = sound->deleteSyncPoint(syncpoint);
		ERRCHECK(result);
	}
    // Add a single syncpoint for the end time
    result = sound->addSyncPoint(end, FMOD_TIMEUNIT_MS, "END", &endpoint);
    ERRCHECK(result);
 
	result = system->playSound(sound, 0, false, &channel);
	ERRCHECK(result);

    // Set start time
	result = channel->setPosition(start, FMOD_TIMEUNIT_MS);
	ERRCHECK(result);
	result = channel->setCallback(SyncCallback);
	ERRCHECK(result);

    return FMOD_OK;
}
  1. The easiest way is to try and call something on the handle I suppose, if it returns FMOD_ERR_INVALID_HANDLE.
1 Like