I’m implementing a gapless media player (on flac streams) using the subsound/sentence api (I create a sentence with 2 subsounds and loop it indefinitely, changing the non active subsound whenever I reach the end of a Stream).
When subsound0 is active, everything is fine: getPosition with FMOD_TIMEUNIT_SEQUENCE_MS returns the position of the active Stream, and setPosition with the same parameter allows me to seek Inside the Stream.
When subsound1 is active (detected with _currentChannel->getPosition(&newCurrentIndex, FMOD_TIMEUNIT_SENTENCE_SUBSOUND | FMOD_TIMEUNIT_BUFFERED))
– if I do not change the Stream affected to subsound0, everything is fine as well
– if I change the Stream affected to subsound0 (to prepare the next track to be played gaplessly), weirdness occurs :
-getPosition with FMOD_TIMEUNIT_SEQUENCE_MS returns wrong value (most of the time it’s "duration of old track in subsound0" + "actual position in subsound1" but not always).
-setPosition with FMOD_TIMEUNIT_SEQUENCE_MS make playback switch to somewhere in the track in subsound0 (it seems not to be random, but I don’t know where exactly it goes).
-sometimes, mostly when the old track in subsound0 was long (5+ minutes), the sound in subsound1 is not played to its end (but playback rolls back to the beginning of the new track in subsound0)
- sferquel asked 5 years ago
Hi, thanks for the answer.
I managed to do something with setDelays, but as I need to support seeking, I did this (this is called when I am within the 2 last seconds of the current track and the scheduling is invalidated when sound is paused or seeked) :
if(_currentChannel == nullptr || _nextSoundScheduled)
uint32 startTimeHi, startTimeLo; _fmodSys->getDSPClock(&startTimeHi, &startTimeLo); int32 sampleRate; _fmodSys->getSoftwareFormat(&sampleRate, nullptr, nullptr, nullptr, nullptr, nullptr); float frequency; uint32 currentLength_pcm; auto fmodRes = _currentSound->getDefaults(&frequency, 0, 0, 0); FmodErrorToEx(fmodRes); fmodRes = _currentSound->getLength(&currentLength_pcm, FMOD_TIMEUNIT_PCM); FmodErrorToEx(fmodRes); uint32 currentPos_pcm; fmodRes = _currentChannel->getPosition(&currentPos_pcm, FMOD_TIMEUNIT_PCM); FmodErrorToEx(fmodRes); uint64 currentLength_Samples = (uint64)currentLength_pcm * (uint64)sampleRate; uint64 currentPos_Samples = (uint64)currentPos_pcm * (uint64)sampleRate; uint32 currentLength_dsp = unsigned int((currentLength_Samples / frequency) + 0.5f); uint32 currentPos_dsp = unsigned int((currentPos_Samples / frequency) + 0.5f); uint32 currentRemaining_dsp = currentLength_dsp - currentPos_dsp; FMOD_64BIT_ADD(startTimeHi, startTimeLo, 0, currentRemaining_dsp); fmodRes = _fmodSys->playSound(FMOD_CHANNEL_FREE, _nextSound.get(), true, &_nextChannel); FmodErrorToEx(fmodRes); fmodRes = _nextChannel->setDelay(FMOD_DELAYTYPE_DSPCLOCK_START, startTimeHi, startTimeLo); FmodErrorToEx(fmodRes); _nextChannel->setPaused(false); _nextSoundScheduled = true;
However, I sometimes get a perceptible gap (even if my audio files are FLAC and correctly cut). It is not always the case, but it happens.
Do you have a sample that supports seeking as well as gapless playback ?
in v4.44.05 getDelay(FMOD_DELAYTYPE_DSPCLOCK_END) still returns 0 (even without setting its position while playing), and the perceived gap is even worse than in previous version.
Do you have a reliable sample of gapless playing with an unbounded count of sounds using a Rolling subsounds mechanism or something equivalent ? I really need this feature as well as seeking Inside the tracks and retrieving correct playback position.
I can’t say for sure, but for the last "weirdness" item, I have the feeling that the track in subsound1 is truncated by an amount of "duration of old track in subsound0" – "duration of new track in subsound0".
For example I have the following tracklist (durations):
track 1 (2:30)
track 2 (4:20)
track 3 (6:20)
track 4 (3:00)
track 5 (4:20)
with subsound rolling playback (subsound0 is reset as sound as subsound1 is reached)
track 1 : everything fine
track 2 : get/setPosition do weird things
track 3 : everything fine
track 4 : get/setPosition do weird things, track is truncated after about 1 min (not measured accurately)
track 5 : everything fine
Maybe I’m doing something wrong, but I don’t see where… If it’s a bug, I hope this test scenario can help !
Sentencing has some known issues, and has been removed from the upcoming FMOD studio lowlevel API. Use Channel::setDelay() as a better solution to your problem.
See this knowledge base entry for sample code for seamless stitching of audio viewtopic.php?f=18&t=14630.
Please login first to submit.