diff --git a/src/audio.cpp b/src/audio.cpp index d342fbbf..0918c6c8 100644 --- a/src/audio.cpp +++ b/src/audio.cpp @@ -459,6 +459,24 @@ bool NxAudioEngine::canPlayMusic(const char* name) return getFilenameFullPath(filename, name, NxAudioEngineLayer::NXAUDIOENGINE_MUSIC); } +void NxAudioEngine::cleanOldAudioSources() +{ + if (trace_all || trace_music) ffnx_trace("NxAudioEngine::%s: %d elements in the list before cleaning\n", __func__, _audioSourcesToDeleteLater.size()); + + std::list::iterator it = _audioSourcesToDeleteLater.begin(); + while (it != _audioSourcesToDeleteLater.end()) { + if (!_engine.isValidVoiceHandle((*it).handle)) { + delete (*it).audioSource; + it = _audioSourcesToDeleteLater.erase(it); + } + else { + ++it; + } + } + + if (trace_all || trace_music) ffnx_trace("NxAudioEngine::%s: %d elements in the list after cleaning\n", __func__, _audioSourcesToDeleteLater.size()); +} + SoLoud::AudioSource* NxAudioEngine::loadMusic(const char* name, bool isFullPath, const char* format) { SoLoud::AudioSource* music = nullptr; @@ -480,6 +498,8 @@ SoLoud::AudioSource* NxAudioEngine::loadMusic(const char* name, bool isFullPath, { if (trace_all || trace_music) ffnx_trace("NxAudioEngine::%s: %s\n", __func__, filename); + cleanOldAudioSources(); + if (_openpsf_loaded && SoLoud::OpenPsf::is_our_path(filename)) { SoLoud::OpenPsf* openpsf = new SoLoud::OpenPsf(); music = openpsf; @@ -593,6 +613,9 @@ bool NxAudioEngine::playMusic(const char* name, uint32_t id, int channel, MusicO music.handle = _engine.playBackground(*audioSource, initialVolume, options.offsetSeconds > 0); music.id = id; + // Keep audioSource pointer somewhere to delete it after musicHandle is stopped + _audioSourcesToDeleteLater.push_back(NxAudioEngineMusicAudioSource(music.handle, audioSource)); + if (options.offsetSeconds > 0) { if (trace_all || trace_music) ffnx_info("%s: seek to time %fs\n", __func__, options.offsetSeconds); _engine.seek(music.handle, options.offsetSeconds); @@ -630,9 +653,12 @@ void NxAudioEngine::playSynchronizedMusics(const std::vector& names for (const std::string &name: names) { SoLoud::AudioSource* audioSource = loadMusic(name.c_str()); + if (audioSource != nullptr) { SoLoud::handle musicHandle = _engine.playBackground(*audioSource, -1.0f, true); _engine.addVoiceToGroup(groupHandle, musicHandle); + // Keep audioSource pointer somewhere to delete it after musicHandle is stopped + _audioSourcesToDeleteLater.push_back(NxAudioEngineMusicAudioSource(musicHandle, audioSource)); } } diff --git a/src/audio.h b/src/audio.h index 99821bdc..d9f85c6c 100644 --- a/src/audio.h +++ b/src/audio.h @@ -87,6 +87,15 @@ class NxAudioEngine float wantedMusicVolume; }; + struct NxAudioEngineMusicAudioSource + { + NxAudioEngineMusicAudioSource(SoLoud::handle handle, SoLoud::AudioSource* audioSource) : + handle(handle), + audioSource(audioSource) {} + SoLoud::handle handle; + SoLoud::AudioSource* audioSource; + }; + struct NxAudioEngineVoice { NxAudioEngineVoice() : @@ -141,11 +150,13 @@ class NxAudioEngine // MUSIC NxAudioEngineMusic _musics[2]; std::stack _musicStack; // For resuming + std::list _audioSourcesToDeleteLater; float _previousMusicMasterVolume = -1.0f; float _musicMasterVolume = -1.0f; SoLoud::time _lastVolumeFadeEndTime = 0.0; + void cleanOldAudioSources(); SoLoud::AudioSource* loadMusic(const char* name, bool isFullPath = false, const char* format = nullptr); void overloadPlayArgumentsFromConfig(char* name, uint32_t *id, MusicOptions *MusicOptions); void backupMusic(int channelSource);