Merge pull request #8273 from Robyt3/Sound-Various-Fixes

Fix crashes and memory leaks related to editor map sounds and opus file decoding, refactoring
This commit is contained in:
Dennis Felsing 2024-04-27 15:45:55 +00:00 committed by GitHub
commit 516315e0e2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 42 additions and 27 deletions

View file

@ -292,14 +292,15 @@ CSample *CSound::AllocSample()
return nullptr; return nullptr;
CSample *pSample = &m_aSamples[m_FirstFreeSampleIndex]; CSample *pSample = &m_aSamples[m_FirstFreeSampleIndex];
m_FirstFreeSampleIndex = pSample->m_NextFreeSampleIndex; if(pSample->m_pData != nullptr || pSample->m_NextFreeSampleIndex == SAMPLE_INDEX_USED)
pSample->m_NextFreeSampleIndex = SAMPLE_INDEX_USED;
if(pSample->m_pData != nullptr)
{ {
char aError[64]; char aError[128];
str_format(aError, sizeof(aError), "Sample was not unloaded (index=%d, duration=%f)", pSample->m_Index, pSample->TotalTime()); str_format(aError, sizeof(aError), "Sample was not unloaded (index=%d, next=%d, duration=%f, data=%p)",
pSample->m_Index, pSample->m_NextFreeSampleIndex, pSample->TotalTime(), pSample->m_pData);
dbg_assert(false, aError); dbg_assert(false, aError);
} }
m_FirstFreeSampleIndex = pSample->m_NextFreeSampleIndex;
pSample->m_NextFreeSampleIndex = SAMPLE_INDEX_USED;
return pSample; return pSample;
} }
@ -341,29 +342,36 @@ void CSound::RateConvert(CSample &Sample) const
bool CSound::DecodeOpus(CSample &Sample, const void *pData, unsigned DataSize) const bool CSound::DecodeOpus(CSample &Sample, const void *pData, unsigned DataSize) const
{ {
OggOpusFile *pOpusFile = op_open_memory((const unsigned char *)pData, DataSize, nullptr); int OpusError = 0;
OggOpusFile *pOpusFile = op_open_memory((const unsigned char *)pData, DataSize, &OpusError);
if(pOpusFile) if(pOpusFile)
{ {
const int NumChannels = op_channel_count(pOpusFile, -1); const int NumChannels = op_channel_count(pOpusFile, -1);
const int NumSamples = op_pcm_total(pOpusFile, -1); // per channel! if(NumChannels > 2)
Sample.m_Channels = NumChannels;
if(Sample.m_Channels > 2)
{ {
op_free(pOpusFile);
dbg_msg("sound/opus", "file is not mono or stereo."); dbg_msg("sound/opus", "file is not mono or stereo.");
return false; return false;
} }
Sample.m_pData = (short *)calloc((size_t)NumSamples * NumChannels, sizeof(short)); const int NumSamples = op_pcm_total(pOpusFile, -1); // per channel!
if(NumSamples < 0)
{
op_free(pOpusFile);
dbg_msg("sound/opus", "failed to get number of samples, error %d", NumSamples);
return false;
}
short *pSampleData = (short *)calloc((size_t)NumSamples * NumChannels, sizeof(short));
int Pos = 0; int Pos = 0;
while(Pos < NumSamples) while(Pos < NumSamples)
{ {
const int Read = op_read(pOpusFile, Sample.m_pData + Pos * NumChannels, NumSamples * NumChannels, nullptr); const int Read = op_read(pOpusFile, pSampleData + Pos * NumChannels, (NumSamples - Pos) * NumChannels, nullptr);
if(Read < 0) if(Read < 0)
{ {
free(Sample.m_pData); free(pSampleData);
op_free(pOpusFile);
dbg_msg("sound/opus", "op_read error %d at %d", Read, Pos); dbg_msg("sound/opus", "op_read error %d at %d", Read, Pos);
return false; return false;
} }
@ -372,15 +380,19 @@ bool CSound::DecodeOpus(CSample &Sample, const void *pData, unsigned DataSize) c
Pos += Read; Pos += Read;
} }
op_free(pOpusFile);
Sample.m_pData = pSampleData;
Sample.m_NumFrames = Pos; Sample.m_NumFrames = Pos;
Sample.m_Rate = 48000; Sample.m_Rate = 48000;
Sample.m_Channels = NumChannels;
Sample.m_LoopStart = -1; Sample.m_LoopStart = -1;
Sample.m_LoopEnd = -1; Sample.m_LoopEnd = -1;
Sample.m_PausedAt = 0; Sample.m_PausedAt = 0;
} }
else else
{ {
dbg_msg("sound/opus", "failed to decode sample"); dbg_msg("sound/opus", "failed to decode sample, error %d", OpusError);
return false; return false;
} }
@ -459,10 +471,7 @@ bool CSound::DecodeWV(CSample &Sample, const void *pData, unsigned DataSize) con
const unsigned int SampleRate = WavpackGetSampleRate(pContext); const unsigned int SampleRate = WavpackGetSampleRate(pContext);
const int NumChannels = WavpackGetNumChannels(pContext); const int NumChannels = WavpackGetNumChannels(pContext);
Sample.m_Channels = NumChannels; if(NumChannels > 2)
Sample.m_Rate = SampleRate;
if(Sample.m_Channels > 2)
{ {
dbg_msg("sound/wv", "file is not mono or stereo."); dbg_msg("sound/wv", "file is not mono or stereo.");
s_pWVBuffer = nullptr; s_pWVBuffer = nullptr;
@ -498,6 +507,8 @@ bool CSound::DecodeWV(CSample &Sample, const void *pData, unsigned DataSize) con
#endif #endif
Sample.m_NumFrames = NumSamples; Sample.m_NumFrames = NumSamples;
Sample.m_Rate = SampleRate;
Sample.m_Channels = NumChannels;
Sample.m_LoopStart = -1; Sample.m_LoopStart = -1;
Sample.m_LoopEnd = -1; Sample.m_LoopEnd = -1;
Sample.m_PausedAt = 0; Sample.m_PausedAt = 0;

View file

@ -1379,12 +1379,17 @@ void CEditor::DoToolbarSounds(CUIRect ToolBar)
if(pSelectedSound->m_SoundId != m_ToolbarPreviewSound && m_ToolbarPreviewSound >= 0 && Sound()->IsPlaying(m_ToolbarPreviewSound)) if(pSelectedSound->m_SoundId != m_ToolbarPreviewSound && m_ToolbarPreviewSound >= 0 && Sound()->IsPlaying(m_ToolbarPreviewSound))
Sound()->Stop(m_ToolbarPreviewSound); Sound()->Stop(m_ToolbarPreviewSound);
m_ToolbarPreviewSound = pSelectedSound->m_SoundId; m_ToolbarPreviewSound = pSelectedSound->m_SoundId;
}
else
{
m_ToolbarPreviewSound = -1;
}
if(m_ToolbarPreviewSound >= 0)
{
static int s_PlayPauseButton, s_StopButton, s_SeekBar = 0; static int s_PlayPauseButton, s_StopButton, s_SeekBar = 0;
DoAudioPreview(ToolBarBottom, &s_PlayPauseButton, &s_StopButton, &s_SeekBar, m_ToolbarPreviewSound); DoAudioPreview(ToolBarBottom, &s_PlayPauseButton, &s_StopButton, &s_SeekBar, m_ToolbarPreviewSound);
} }
else
m_ToolbarPreviewSound = -1;
} }
static void Rotate(const CPoint *pCenter, CPoint *pPoint, float Rotation) static void Rotate(const CPoint *pCenter, CPoint *pPoint, float Rotation)
@ -8705,11 +8710,10 @@ void CEditor::OnClose()
void CEditor::OnDialogClose() void CEditor::OnDialogClose()
{ {
if(m_FilePreviewSound >= 0) Graphics()->UnloadTexture(&m_FilePreviewImage);
{
Sound()->UnloadSample(m_FilePreviewSound); Sound()->UnloadSample(m_FilePreviewSound);
m_FilePreviewSound = -1; m_FilePreviewSound = -1;
} m_FilePreviewState = PREVIEW_UNLOADED;
} }
void CEditor::LoadCurrentMap() void CEditor::LoadCurrentMap()

View file

@ -10,7 +10,7 @@ public:
explicit CEditorSound(CEditor *pEditor); explicit CEditorSound(CEditor *pEditor);
~CEditorSound(); ~CEditorSound();
int m_SoundId = 0; int m_SoundId = -1;
char m_aName[IO_MAX_PATH_LENGTH] = ""; char m_aName[IO_MAX_PATH_LENGTH] = "";
void *m_pData = nullptr; void *m_pData = nullptr;