views:

237

answers:

3

I'm trying to play only part of a sound using FMOD, say frames 50000-100000 of a 200000 frame file. I have found a couple of ways to seek forward (i.e. to start playback at frame 50000) but I have not found a way to make sure the sound stops playing at 100000. Is there any way FMOD can natively do this without having to add lbsndfile or the like into the picture?

I should also mention that I am using the streaming option. I have to assume that these sounds are arbitrarily large and cannot be comfortably/quickly loaded into memory.

+1  A: 

You should be able to use the streaming callback to stop the stream when you get to the desired point.

Option 1: When you create the stream, set lenbytes to an even divisor of the number of frames you wish to play. In your example, set 'lenbytes' to 5000, then keep a counter in the callback. When you get to 10, stop the stream.

Option 2: use FSOUND_Stream_AddSyncPoint with pcmoffset set to your desired stopping point. Register a callback with FSOUND_Stream_SetSyncCallback. Stop the stream in the callback.

AShelly
Thanks for this. Just to confirm, both these methods are inexact right? They depend on when *exactly* the stop stream code is reached. There isn't any way to play precisely a certain interval?
Yuvi Masory
+1  A: 

You can use Channel::setDelay for sample accurate starting and stopping of sounds. Use FMOD_DELAYTYPE_DSPCLOCK_START to set the start time of the sound and FMOD_DELAYTYPE_DSPCLOCK_END to set the end time.

Check out the docs for Channel::setDelay, FMOD_DELAYTYPE, System::getDSPClock.

Pete
+1  A: 

To start playback at sample 50,000 and end at 100,000 you could do the following assuming the sound file sample rate and the system sample rate are the same. As DSP clock works in system output samples you may need to do some maths to adjust your end sample in terms of output rate. See Sound::getDefaults for sound sample rate and System::getSoftwareFormat for system rate.

unsigned int sysHi, sysLo;

// ... create sound, play sound paused ...

// Seek the data to the desired start offset
channel->setPosition(50000, FMOD_TIMEUNIT_PCM);

// For accurate sample playback get the current system "tick"
system->getDSPClock(&sysHi, &sysLo);

// Set start offset to a couple of "mixes" in the future, 2048 samples is far enough in the future to avoid issues with mixer timings
FMOD_64BIT_ADD(sysHi, sysLo, 0, 2048);
channel->setDelay(FMOD_DELAYTYPE_DSPCLOCK_START, sysHi, sysLo);

// Set end offset for 50,000 samples from our start time, which means the end sample will be 100,000
FMOD_64BIT_ADD(sysHi, sysLo, 0, 50000);
channel->setDelay(FMOD_DELAYTYPE_DSPCLOCK_END, sysHi, sysLo);

// ... unpause sound ...
Mathew Block