Add MxMiniaudio wrapper to fix resource issues

This commit is contained in:
Christian Semmler 2025-05-19 15:31:18 -07:00
parent 70536c50bd
commit 7b8d36e01d
8 changed files with 66 additions and 30 deletions

View File

@ -2,10 +2,9 @@
#define LEGO3DSOUND_H #define LEGO3DSOUND_H
#include "decomp.h" #include "decomp.h"
#include "mxminiaudio.h"
#include "mxtypes.h" #include "mxtypes.h"
#include <miniaudio.h>
class LegoActor; class LegoActor;
class LegoROI; class LegoROI;

View File

@ -62,8 +62,8 @@ class LegoCacheSound : public MxCore {
// [library:audio] WAVE_FORMAT_PCM (audio in .SI files only used this format) // [library:audio] WAVE_FORMAT_PCM (audio in .SI files only used this format)
static const MxU32 g_supportedFormatTag = 1; static const MxU32 g_supportedFormatTag = 1;
ma_audio_buffer m_buffer; MxMiniaudio<ma_audio_buffer> m_buffer;
ma_sound m_cacheSound; MxMiniaudio<ma_sound> m_cacheSound;
undefined m_unk0x0c[4]; // 0x0c undefined m_unk0x0c[4]; // 0x0c
Lego3DSound m_sound; // 0x10 Lego3DSound m_sound; // 0x10
MxU8* m_data; // 0x40 MxU8* m_data; // 0x40

View File

@ -63,16 +63,16 @@ MxResult LegoCacheSound::Create(
ma_audio_buffer_config_init(format, p_pwfx.m_channels, bufferSizeInFrames, m_data, NULL); ma_audio_buffer_config_init(format, p_pwfx.m_channels, bufferSizeInFrames, m_data, NULL);
config.sampleRate = p_pwfx.m_samplesPerSec; config.sampleRate = p_pwfx.m_samplesPerSec;
if (ma_audio_buffer_init(&config, &m_buffer) != MA_SUCCESS) { if (m_buffer.Init(ma_audio_buffer_init, &config) != MA_SUCCESS) {
return FAILURE; return FAILURE;
} }
if (ma_sound_init_from_data_source( if (m_cacheSound.Init(
ma_sound_init_from_data_source,
SoundManager()->GetEngine(), SoundManager()->GetEngine(),
&m_buffer, &m_buffer,
MxOmni::IsSound3D() ? 0 : MA_SOUND_FLAG_NO_SPATIALIZATION, MxOmni::IsSound3D() ? 0 : MA_SOUND_FLAG_NO_SPATIALIZATION,
NULL, nullptr
&m_cacheSound
) != MA_SUCCESS) { ) != MA_SUCCESS) {
return FAILURE; return FAILURE;
} }
@ -108,8 +108,8 @@ void LegoCacheSound::CopyData(MxU8* p_data, MxU32 p_dataSize)
// FUNCTION: BETA10 0x1006685b // FUNCTION: BETA10 0x1006685b
void LegoCacheSound::Destroy() void LegoCacheSound::Destroy()
{ {
ma_sound_uninit(&m_cacheSound); m_cacheSound.Destroy(ma_sound_uninit);
ma_audio_buffer_uninit(&m_buffer); m_buffer.Destroy(ma_audio_buffer_uninit);
delete[] m_data; delete[] m_data;
Init(); Init();

View File

@ -0,0 +1,38 @@
#ifndef MXMINIAUDIO_H
#define MXMINIAUDIO_H
#include "mxtypes.h"
#include <miniaudio.h>
#include <utility>
template <typename T>
class MxMiniaudio : public T {
public:
MxMiniaudio() : m_initialized(false) {}
template <typename Fn, typename... Args>
ma_result Init(Fn ma_init, Args&&... args)
{
ma_result result = ma_init(std::forward<Args>(args)..., this);
if (result == MA_SUCCESS) {
m_initialized = true;
}
return result;
}
template <typename Fn>
void Destroy(Fn ma_uninit)
{
if (m_initialized) {
ma_uninit(this);
m_initialized = false;
}
}
private:
bool m_initialized;
};
#endif // MXMINIAUDIO_H

View File

@ -4,9 +4,9 @@
#include "decomp.h" #include "decomp.h"
#include "mxatom.h" #include "mxatom.h"
#include "mxaudiomanager.h" #include "mxaudiomanager.h"
#include "mxminiaudio.h"
#include <SDL3/SDL_audio.h> #include <SDL3/SDL_audio.h>
#include <miniaudio.h>
// VTABLE: LEGO1 0x100dc128 // VTABLE: LEGO1 0x100dc128
// VTABLE: BETA10 0x101c1ce8 // VTABLE: BETA10 0x101c1ce8
@ -44,7 +44,7 @@ class MxSoundManager : public MxAudioManager {
int p_totalAmount int p_totalAmount
); );
ma_engine m_engine; MxMiniaudio<ma_engine> m_engine;
SDL_AudioStream* m_stream; SDL_AudioStream* m_stream;
undefined m_unk0x38[4]; undefined m_unk0x38[4];
}; };

View File

@ -2,10 +2,9 @@
#define MXWAVEPRESENTER_H #define MXWAVEPRESENTER_H
#include "decomp.h" #include "decomp.h"
#include "mxminiaudio.h"
#include "mxsoundpresenter.h" #include "mxsoundpresenter.h"
#include <miniaudio.h>
// VTABLE: LEGO1 0x100d49a8 // VTABLE: LEGO1 0x100d49a8
// SIZE 0x6c // SIZE 0x6c
class MxWavePresenter : public MxSoundPresenter { class MxWavePresenter : public MxSoundPresenter {
@ -92,15 +91,15 @@ class MxWavePresenter : public MxSoundPresenter {
// [library:audio] // [library:audio]
// If MxDSAction::looping is set, we keep the entire audio in memory and use `m_ab`. // If MxDSAction::looping is set, we keep the entire audio in memory and use `m_ab`.
// In (most) other cases, data is streamed through the ring buffer `m_rb`. // In (most) other cases, data is streamed through the ring buffer `m_rb`.
ma_pcm_rb m_rb; MxMiniaudio<ma_pcm_rb> m_rb;
struct { struct {
ma_audio_buffer m_buffer; MxMiniaudio<ma_audio_buffer> m_buffer;
MxU8* m_data; MxU8* m_data;
MxU32 m_length; MxU32 m_length;
MxU32 m_offset; MxU32 m_offset;
} m_ab; } m_ab;
ma_sound m_sound; MxMiniaudio<ma_sound> m_sound;
MxU32 m_chunkLength; // 0x5c MxU32 m_chunkLength; // 0x5c
MxBool m_started; // 0x65 MxBool m_started; // 0x65
MxBool m_is3d; // 0x66 MxBool m_is3d; // 0x66

View File

@ -58,7 +58,7 @@ void MxSoundManager::Destroy(MxBool p_fromDestructor)
SDL_DestroyAudioStream(m_stream); SDL_DestroyAudioStream(m_stream);
} }
ma_engine_uninit(&m_engine); m_engine.Destroy(ma_engine_uninit);
Init(); Init();
m_criticalSection.Leave(); m_criticalSection.Leave();
@ -88,7 +88,7 @@ MxResult MxSoundManager::Create(MxU32 p_frequencyMS, MxBool p_createThread)
engineConfig.channels = MxOmni::IsSound3D() ? 2 : 1; engineConfig.channels = MxOmni::IsSound3D() ? 2 : 1;
engineConfig.sampleRate = g_sampleRate; engineConfig.sampleRate = g_sampleRate;
if (ma_engine_init(&engineConfig, &m_engine) != MA_SUCCESS) { if (m_engine.Init(ma_engine_init, &engineConfig) != MA_SUCCESS) {
goto done; goto done;
} }

View File

@ -40,9 +40,9 @@ MxResult MxWavePresenter::AddToManager()
// FUNCTION: LEGO1 0x100b1b10 // FUNCTION: LEGO1 0x100b1b10
void MxWavePresenter::Destroy(MxBool p_fromDestructor) void MxWavePresenter::Destroy(MxBool p_fromDestructor)
{ {
ma_sound_uninit(&m_sound); m_sound.Destroy(ma_sound_uninit);
ma_pcm_rb_uninit(&m_rb); m_rb.Destroy(ma_pcm_rb_uninit);
ma_audio_buffer_uninit(&m_ab.m_buffer); m_ab.m_buffer.Destroy(ma_audio_buffer_uninit);
delete[] m_ab.m_data; delete[] m_ab.m_data;
if (m_waveFormat) { if (m_waveFormat) {
@ -145,18 +145,18 @@ void MxWavePresenter::StartingTickle()
ma_audio_buffer_config_init(format, channels, sizeInFrames, m_ab.m_data, NULL); ma_audio_buffer_config_init(format, channels, sizeInFrames, m_ab.m_data, NULL);
config.sampleRate = sampleRate; config.sampleRate = sampleRate;
if (ma_audio_buffer_init(&config, &m_ab.m_buffer) != MA_SUCCESS) { if (m_ab.m_buffer.Init(ma_audio_buffer_init, &config) != MA_SUCCESS) {
goto done; goto done;
} }
} }
else { else {
if (ma_pcm_rb_init( if (m_rb.Init(
ma_pcm_rb_init,
format, format,
channels, channels,
ma_calculate_buffer_size_in_frames_from_milliseconds(g_rbSizeInMilliseconds, sampleRate), ma_calculate_buffer_size_in_frames_from_milliseconds(g_rbSizeInMilliseconds, sampleRate),
NULL, nullptr,
NULL, nullptr
&m_rb
) != MA_SUCCESS) { ) != MA_SUCCESS) {
goto done; goto done;
} }
@ -164,12 +164,12 @@ void MxWavePresenter::StartingTickle()
ma_pcm_rb_set_sample_rate(&m_rb, sampleRate); ma_pcm_rb_set_sample_rate(&m_rb, sampleRate);
} }
if (ma_sound_init_from_data_source( if (m_sound.Init(
ma_sound_init_from_data_source,
MSoundManager()->GetEngine(), MSoundManager()->GetEngine(),
m_action->IsLooping() ? (ma_data_source*) &m_ab.m_buffer : (ma_data_source*) &m_rb, m_action->IsLooping() ? (ma_data_source*) &m_ab.m_buffer : (ma_data_source*) &m_rb,
m_is3d ? 0 : MA_SOUND_FLAG_NO_SPATIALIZATION, m_is3d ? 0 : MA_SOUND_FLAG_NO_SPATIALIZATION,
NULL, nullptr
&m_sound
) != MA_SUCCESS) { ) != MA_SUCCESS) {
goto done; goto done;
} }