Windows (x64), C++
FMOD: 2.03.09
I have a working setup with the Core API:
CHECKFMODERR(FMOD::System_Create(&system));
CHECKFMODERR(system->setSoftwareChannels(MAX_SOUNDS_SLOTS));
CHECKFMODERR(system->init(MAX_SOUNDS_SLOTS, FMOD_INIT_NORMAL, nullptr));
CHECKFMODERR(system->set3DSettings(1.0f, DISTANCEFACTOR, 1.0f));
// per frame:
CHECKFMODERR(system->update());
When I switch to the Studio API (but still play sounds via low-level System::playSound):
CHECKFMODERR(FMOD::Studio::System::create(&studiosystem));
CHECKFMODERR(studiosystem->getCoreSystem(&system));
CHECKFMODERR(system->setSoftwareChannels(MAX_SOUNDS_SLOTS));
CHECKFMODERR(studiosystem->initialize(MAX_SOUNDS_SLOTS, FMOD_STUDIO_INIT_NORMAL, FMOD_INIT_NORMAL, nullptr));
CHECKFMODERR(system->set3DSettings(1.0f, DISTANCEFACTOR, 1.0f));
// per frame:
CHECKFMODERR(studiosystem->update());
Observed:
- After a short sound naturally finishes, any calls on the channel (e.g., channel->getPaused, channel->isPlaying) sometimes do not return FMOD_OK. With pure Core init I get FMOD_OK and isPlaying=false in the same situation.
- Virtualization behaves differently: channels become virtual more often / seem to “disappear” earlier, even though I did not change virtualization settings.
Questions:
- Is it expected that the lifetime/validity of low-level channels (FMOD::Channel) differs when initialized via Studio API vs pure Core init? In my case, this is critical (see the code below).
- Can Studio API be configured to behave as close as possible to Core (same/near virtualization behavior and the same return codes after a sound ends)?
Additional notes:
- Channels are created with system->playSound (not Studio events).
- With Core API the current logic is stable; issues appear immediately after switching Init/Update to Studio.
Small code excerpt where the issue manifests (cleanup after completion):
bool paused = true;
FMOD_RESULT status = PlayingSounds[i].channel->getPaused(&paused);
if (status != FMOD_OK) {
core.Trace("PlayingSounds[%d].channel 0x%08X %s paused %d status %d",
i, PlayingSounds[i].channel, PlayingSounds[i].Name.c_str(), paused, status);
i = FreeSound(i);
continue;
}
if (paused) continue;
bool is_playing;
status = CHECKFMODERR(PlayingSounds[i].channel->isPlaying(&is_playing));
if (!is_playing || status != FMOD_OK) {
if (PlayingSounds[i].aliasLoopIdx != -1)
AliasRandomLoopSound(i);
else {
PlayingSounds[i].channel = nullptr;
if (i <= 1 && OGG_sound[i] != nullptr) {
CHECKFMODERR(OGG_sound[i]->release());
OGG_sound[i] = nullptr;
}
i = FreeSound(i);
int32_t soundId = (i + 1) | (PlayingSounds[i].stamp << 16);
core.Event("SoundEnded", "l", soundId);
}
}
In Core, checking the paused state worked fine, but in Studio, sounds that have finished playing immediately return FMOD_ERR_INVALID_HANDLE. Even if I rewrite this logic, the channel becomes completely inaccessible, including losing info like its last 3D coordinates, which is important for restarting a random sound from a specific list at the same location.