I am trying to work out how to fade out and pause the sound, then unpause it.
I customised the basic ‘3d’ example (for iOS) with this code:
if (Common_BtnPress(BTN_ACTION2))
{
bool paused;
channel2->setVolume(1.0);
channel2->setPaused(false);
channel2->setDelay(0, 0);
ERRCHECK(result);
}
if (Common_BtnPress(BTN_MORE))
{
unsigned long long parentclock;
channel2->getDSPClock(nullptr, &parentclock);
unsigned long long fadepoint = parentclock + 44100;
channel2->addFadePoint(parentclock, 1.0);
channel2->addFadePoint(fadepoint, 0.0);
channel2->setDelay(0, fadepoint, false);
}
As you can see, the ‘B’ button unpauses the sound. (I also paused everything to begin with. The ‘E’ button fades out and sets a delay for pausing the sound. Both those actions
On pressing the ‘B’ button again, it doesn’t unpause it.
I read in the documentation
False: When dspclock_end is reached, behaves like ChannelControl::setPaused has been called, a subsequent dspclock_start allows it to resume.
…but I don’t fully understand what it’s asking me to do. I’ve tried lots of combinations of setDelay
but it won’t unpause.
Any help would be greatly appreciated.
Some further digging. In order to unpause a sound which has been paused with addFadePoint
and setDelay
, you have to have another call to both addFadePoint
and setDelay
, like this.
unsigned long long dspclock;
unsigned long long parentclock;
channel2->getDSPClock(&dspclock, &parentclock);
channel2->addFadePoint(parentclock, 1.0f);
channel2->setDelay(0, 0, false);
channel2->setPaused(false);
However, I am still stuck here because pausing a sound like this:
unsigned long long parentclock;
channel2->getDSPClock(nullptr, &parentclock);
unsigned long long fadepoint = parentclock + 132300;
channel2->addFadePoint(parentclock, 1.0);
channel2->addFadePoint(fadepoint, 0.0);
channel2->setDelay(0, fadepoint, false);
A subsequent call to getPaused
(after the fade) returns false
(incorrect, as it should have paused with the setDelay
call?)
…and a call to isPlaying
returns true
. So how do we tell when we’ve paused a sound after fading?
I figured it out, but be prepared for a very circuitous answer. This functions just checks if a sound is actively playing on the channel.
We have to check:
- if the channel is ‘playing’ (active)
- if the sound is paused
- if there are any delays set
- if there are any future fade points
code
bool isPlaying() {
// check if the channel is inactive
bool isplaying = false;
result = channel->isPlaying(&isplaying);
if ((result != FMOD_OK) && (result != FMOD_ERR_INVALID_HANDLE)) {
LOGE("fmod:: Error getting isPlaying status because: %s\n", FMOD_ErrorString(result));
}
if (!isplaying) {
return false;
}
// check if the sound is paused
bool paused = true;
result = channel->getPaused(&paused);
if (paused) {
return false;
}
// check for scheduled fades
unsigned long long dspclock_start = 0;
unsigned long long dspclock_end = 0;
result = channel->getDelay(&dspclock_start, &dspclock_end, 0);
if ((result != FMOD_OK) && (result != FMOD_ERR_INVALID_HANDLE)) {
LOGE("fmod:: Error getting delay because: %s\n", FMOD_ErrorString(result));
}
if (dspclock_start > 0 || dspclock_end > 0) {
// it's set to either play in the future or stop in the future
// or a fade has been performed
// if a fade's been performed, there won't be any fade points
// need to check if there's an active fade
unsigned int numpoints;
result = channel->getFadePoints(&numpoints, 0, 0);
if ((result != FMOD_OK) && (result != FMOD_ERR_INVALID_HANDLE)) {
LOGE("fmod:: Error getting fade points because: %s\n", FMOD_ErrorString(result));
}
if (numpoints) {
// we're in a fade
return true;
}
return false;
}
return true;
}
In the documentation it states for the stopchannels
argument that:
False: When dspclock_end
is reached, behaves like ChannelControl::setPaused has been called, a subsequent dspclock_start
allows it to resume.
However, the word ‘like’ here encapsulates quite a lot of assumptions, and quite a bit of extra code to actually figure out what the state of the channel is. It’s difficult to work out if it’s actually playing sound or not if setDelay
and/or addFadePoints
has been called.
I hope this may help others in the future when they’re trying to work out if a sound has completed fading, has been paused with setDelay
or has been manually paused with setPaused
.
ChannelControl::isPlaying is working as intended, calling play on a sound means it is ‘playing’ until it is stopped. Even if it is paused it is still ‘playing’.
A Channel is considered playing after System::playSound or System::playDSP, even if it is paused.
You could also use ChannelControl::getAudibility
which goes to zero when delayed and paused and should be one for everything else.
Thanks for the reply, and the tip about getAudibility
- that’s helpful.
The issue I had was that the call to setDelay
did not pause it. Even though the sound had ‘paused’ when it came to the clock time, calling setPaused(false)
did not unpause it. You had to check if there was a delay set using getDelay
then unset it using setDelay(0, 0)
.
Then setVolume
did not work, because of the previous fade point. You had to check if there were fade points set using getFadePoints
, then remove them and set another fade point at the volume you wanted.
It sounds like getAudibility
might circumvent all of this, though! Thanks
1 Like